mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
nitpicker: Reduce superfluous refresh operations
This commit is contained in:
parent
65e283142a
commit
1ac343fabd
@ -104,6 +104,8 @@ class Chunky_menubar : public Texture<PT>,
|
|||||||
session_label.string(), WHITE, "", session_color);
|
session_label.string(), WHITE, "", session_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
View &view() override { return *this; }
|
||||||
|
|
||||||
using Menubar::state;
|
using Menubar::state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1164,6 +1164,8 @@ void Nitpicker::Main::handle_input(unsigned)
|
|||||||
framebuffer.refresh(rect.x1(), rect.y1(),
|
framebuffer.refresh(rect.x1(), rect.y1(),
|
||||||
rect.w(), rect.h()); });
|
rect.w(), rect.h()); });
|
||||||
|
|
||||||
|
user_state.mark_all_views_as_clean();
|
||||||
|
|
||||||
/* deliver framebuffer synchronization events */
|
/* deliver framebuffer synchronization events */
|
||||||
if (!user_state.kill()) {
|
if (!user_state.kill()) {
|
||||||
for (::Session *s = session_list.first(); s; s = s->next())
|
for (::Session *s = session_list.first(); s; s = s->next())
|
||||||
|
@ -43,6 +43,8 @@ struct Menubar : Menubar_state
|
|||||||
virtual void state(Menubar_state) = 0;
|
virtual void state(Menubar_state) = 0;
|
||||||
|
|
||||||
Menubar_state state() const { return *this; }
|
Menubar_state state() const { return *this; }
|
||||||
|
|
||||||
|
virtual View &view() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,7 +41,7 @@ User_state::User_state(Global_keys &global_keys, Area view_stack_size, Menubar &
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
void User_state::_update_all()
|
void User_state::_update_menubar()
|
||||||
{
|
{
|
||||||
Menubar_state state(*this, "", BLACK);
|
Menubar_state state(*this, "", BLACK);
|
||||||
|
|
||||||
@ -51,6 +51,14 @@ void User_state::_update_all()
|
|||||||
_input_receiver->color());
|
_input_receiver->color());
|
||||||
|
|
||||||
_menubar.state(state);
|
_menubar.state(state);
|
||||||
|
|
||||||
|
refresh_view(_menubar.view(), _menubar.view().abs_geometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void User_state::_update_all()
|
||||||
|
{
|
||||||
|
_update_menubar();
|
||||||
update_all_views();
|
update_all_views();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,5 +284,5 @@ void User_state::focused_session(::Session *session)
|
|||||||
if (!_global_key_sequence)
|
if (!_global_key_sequence)
|
||||||
_input_receiver = session;
|
_input_receiver = session;
|
||||||
|
|
||||||
_update_all();
|
_update_menubar();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ class User_state : public Mode, public View_stack
|
|||||||
*/
|
*/
|
||||||
bool _global_key_sequence = false;
|
bool _global_key_sequence = false;
|
||||||
|
|
||||||
|
void _update_menubar();
|
||||||
void _update_all();
|
void _update_all();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -92,6 +92,7 @@ class View : public Same_buffer_list_elem,
|
|||||||
Point _buffer_off; /* offset to the visible buffer area */
|
Point _buffer_off; /* offset to the visible buffer area */
|
||||||
Session &_session; /* session that created the view */
|
Session &_session; /* session that created the view */
|
||||||
char _title[TITLE_LEN];
|
char _title[TITLE_LEN];
|
||||||
|
Dirty_rect _dirty_rect;
|
||||||
|
|
||||||
Genode::List<View_parent_elem> _children;
|
Genode::List<View_parent_elem> _children;
|
||||||
|
|
||||||
@ -154,7 +155,13 @@ class View : public Same_buffer_list_elem,
|
|||||||
void remove_child(View const &child) { _children.remove(&child); }
|
void remove_child(View const &child) { _children.remove(&child); }
|
||||||
|
|
||||||
template <typename FN>
|
template <typename FN>
|
||||||
void for_each_child(FN const &fn) const {
|
void for_each_child(FN const &fn) {
|
||||||
|
for (View_parent_elem *e = _children.first(); e; e = e->next())
|
||||||
|
fn(*static_cast<View *>(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FN>
|
||||||
|
void for_each_const_child(FN const &fn) const {
|
||||||
for (View_parent_elem const *e = _children.first(); e; e = e->next())
|
for (View_parent_elem const *e = _children.first(); e; e = e->next())
|
||||||
fn(*static_cast<View const *>(e));
|
fn(*static_cast<View const *>(e));
|
||||||
}
|
}
|
||||||
@ -242,6 +249,23 @@ class View : public Same_buffer_list_elem,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark part of view as dirty
|
||||||
|
*
|
||||||
|
* \param rect dirty rectangle in absolute coordinates
|
||||||
|
*/
|
||||||
|
void mark_as_dirty(Rect rect) { _dirty_rect.mark_as_dirty(rect); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return dirty-rectangle information
|
||||||
|
*/
|
||||||
|
Dirty_rect dirty_rect() const { return _dirty_rect; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset dirty rectangle
|
||||||
|
*/
|
||||||
|
void mark_as_clean() { _dirty_rect = Dirty_rect(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _VIEW_H_ */
|
#endif /* _VIEW_H_ */
|
||||||
|
@ -209,8 +209,9 @@ void View_stack::draw_rec(Canvas_base &canvas, View const *view, Rect rect) cons
|
|||||||
if (next && left.valid()) draw_rec(canvas, next, left);
|
if (next && left.valid()) draw_rec(canvas, next, left);
|
||||||
|
|
||||||
/* draw current view */
|
/* draw current view */
|
||||||
{
|
view->dirty_rect().flush([&] (Rect const &dirty_rect) {
|
||||||
Clip_guard clip_guard(canvas, clipped);
|
|
||||||
|
Clip_guard clip_guard(canvas, Rect::intersect(clipped, dirty_rect));
|
||||||
|
|
||||||
/* draw background if view is transparent */
|
/* draw background if view is transparent */
|
||||||
if (view->uses_alpha())
|
if (view->uses_alpha())
|
||||||
@ -218,7 +219,7 @@ void View_stack::draw_rec(Canvas_base &canvas, View const *view, Rect rect) cons
|
|||||||
|
|
||||||
view->frame(canvas, _mode);
|
view->frame(canvas, _mode);
|
||||||
view->draw(canvas, _mode);
|
view->draw(canvas, _mode);
|
||||||
}
|
});
|
||||||
|
|
||||||
/* draw areas at the bottom/right of the current view */
|
/* draw areas at the bottom/right of the current view */
|
||||||
if (next && right.valid()) draw_rec(canvas, next, right);
|
if (next && right.valid()) draw_rec(canvas, next, right);
|
||||||
@ -226,14 +227,32 @@ void View_stack::draw_rec(Canvas_base &canvas, View const *view, Rect rect) cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void View_stack::refresh_view(View const &view, Rect const rect)
|
void View_stack::refresh_view(View &view, Rect const rect)
|
||||||
{
|
{
|
||||||
/* clip argument agains view outline */
|
/* rectangle constrained to view geometry */
|
||||||
Rect const intersection = Rect::intersect(rect, _outline(view));
|
Rect const view_rect = Rect::intersect(rect, _outline(view));
|
||||||
|
|
||||||
_dirty_rect.mark_as_dirty(intersection);
|
for (View *v = _first_view(); v; v = v->view_stack_next()) {
|
||||||
|
|
||||||
view.for_each_child([&] (View const &child) { refresh_view(child, rect); });
|
Rect const intersection = Rect::intersect(view_rect, _outline(*v));
|
||||||
|
|
||||||
|
if (intersection.valid())
|
||||||
|
_mark_view_as_dirty(*v, intersection);
|
||||||
|
}
|
||||||
|
|
||||||
|
view.for_each_child([&] (View &child) { refresh_view(child, rect); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void View_stack::refresh(Rect const rect)
|
||||||
|
{
|
||||||
|
for (View *v = _first_view(); v; v = v->view_stack_next()) {
|
||||||
|
|
||||||
|
Rect const intersection = Rect::intersect(rect, _outline(*v));
|
||||||
|
|
||||||
|
if (intersection.valid())
|
||||||
|
refresh_view(*v, intersection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -241,10 +260,19 @@ void View_stack::geometry(View &view, Rect const rect)
|
|||||||
{
|
{
|
||||||
Rect const old_outline = _outline(view);
|
Rect const old_outline = _outline(view);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Refresh area covered by the original view geometry.
|
||||||
|
*
|
||||||
|
* We specify the whole geometry to also cover the refresh of child
|
||||||
|
* views. The 'refresh_view' function takes care to constrain the
|
||||||
|
* refresh to the actual view geometry.
|
||||||
|
*/
|
||||||
refresh_view(view, Rect(Point(), _size));
|
refresh_view(view, Rect(Point(), _size));
|
||||||
|
|
||||||
|
/* change geometry */
|
||||||
view.geometry(Rect(rect));
|
view.geometry(Rect(rect));
|
||||||
|
|
||||||
|
/* refresh new view geometry */
|
||||||
refresh_view(view, Rect(Point(), _size));
|
refresh_view(view, Rect(Point(), _size));
|
||||||
|
|
||||||
Rect const compound = Rect::compound(old_outline, _outline(view));
|
Rect const compound = Rect::compound(old_outline, _outline(view));
|
||||||
@ -263,14 +291,14 @@ void View_stack::buffer_offset(View &view, Point const buffer_off)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void View_stack::stack(View const &view, View const *neighbor, bool behind)
|
void View_stack::stack(View &view, View const *neighbor, bool behind)
|
||||||
{
|
{
|
||||||
_views.remove(&view);
|
_views.remove(&view);
|
||||||
_views.insert(&view, _target_stack_position(neighbor, behind));
|
_views.insert(&view, _target_stack_position(neighbor, behind));
|
||||||
|
|
||||||
_place_labels(view.abs_geometry());
|
_place_labels(view.abs_geometry());
|
||||||
|
|
||||||
_dirty_rect.mark_as_dirty(_outline(view));
|
_mark_view_as_dirty(view, _outline(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -279,7 +307,7 @@ void View_stack::title(View &view, const char *title)
|
|||||||
view.title(title);
|
view.title(title);
|
||||||
_place_labels(view.abs_geometry());
|
_place_labels(view.abs_geometry());
|
||||||
|
|
||||||
_dirty_rect.mark_as_dirty(_outline(view));
|
_mark_view_as_dirty(view, _outline(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -298,7 +326,7 @@ View *View_stack::find_view(Point p)
|
|||||||
|
|
||||||
void View_stack::remove_view(View const &view, bool redraw)
|
void View_stack::remove_view(View const &view, bool redraw)
|
||||||
{
|
{
|
||||||
view.for_each_child([&] (View const &child) { remove_view(child); });
|
view.for_each_const_child([&] (View const &child) { remove_view(child); });
|
||||||
|
|
||||||
/* remember geometry of view to remove */
|
/* remember geometry of view to remove */
|
||||||
Rect rect = _outline(view);
|
Rect rect = _outline(view);
|
||||||
@ -306,5 +334,5 @@ void View_stack::remove_view(View const &view, bool redraw)
|
|||||||
/* exclude view from view stack */
|
/* exclude view from view stack */
|
||||||
_views.remove(&view);
|
_views.remove(&view);
|
||||||
|
|
||||||
_dirty_rect.mark_as_dirty(rect);
|
refresh(rect);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,8 @@ class View_stack
|
|||||||
void _mark_view_as_dirty(View &view, Rect rect)
|
void _mark_view_as_dirty(View &view, Rect rect)
|
||||||
{
|
{
|
||||||
_dirty_rect.mark_as_dirty(rect);
|
_dirty_rect.mark_as_dirty(rect);
|
||||||
|
|
||||||
|
view.mark_as_dirty(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -96,7 +98,8 @@ class View_stack
|
|||||||
void size(Area size)
|
void size(Area size)
|
||||||
{
|
{
|
||||||
_size = size;
|
_size = size;
|
||||||
_dirty_rect.mark_as_dirty(Rect(Point(0, 0), _size));
|
|
||||||
|
update_all_views();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,8 +127,23 @@ class View_stack
|
|||||||
*/
|
*/
|
||||||
void update_all_views()
|
void update_all_views()
|
||||||
{
|
{
|
||||||
_place_labels(Rect(Point(), _size));
|
Rect const whole_screen(Point(), _size);
|
||||||
_dirty_rect.mark_as_dirty(Rect(Point(), _size));
|
|
||||||
|
_place_labels(whole_screen);
|
||||||
|
_dirty_rect.mark_as_dirty(whole_screen);
|
||||||
|
|
||||||
|
for (View *view = _first_view(); view; view = view->view_stack_next())
|
||||||
|
view->mark_as_dirty(_outline(*view));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mark all view-local dirty rectangles a clean
|
||||||
|
*/
|
||||||
|
void mark_all_views_as_clean()
|
||||||
|
{
|
||||||
|
for (View *view = _first_view(); view; view = view->view_stack_next())
|
||||||
|
view->mark_as_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,7 +168,7 @@ class View_stack
|
|||||||
rect.p2() + offset),
|
rect.p2() + offset),
|
||||||
view->abs_geometry());
|
view->abs_geometry());
|
||||||
|
|
||||||
_mark_view_as_dirty(*view, r);
|
refresh_view(*view, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +177,17 @@ class View_stack
|
|||||||
*
|
*
|
||||||
* \param view view that should be updated on screen
|
* \param view view that should be updated on screen
|
||||||
*/
|
*/
|
||||||
void refresh_view(View const &view, Rect);
|
void refresh_view(View &view, Rect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh entire view
|
||||||
|
*/
|
||||||
|
void refresh_view(View &view) { refresh_view(view, _outline(view)); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh area
|
||||||
|
*/
|
||||||
|
void refresh(Rect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define view geometry
|
* Define view geometry
|
||||||
@ -186,7 +214,7 @@ class View_stack
|
|||||||
* bottom of the view stack, specify neighbor = 0 and
|
* bottom of the view stack, specify neighbor = 0 and
|
||||||
* behind = false.
|
* behind = false.
|
||||||
*/
|
*/
|
||||||
void stack(View const &view, View const *neighbor = 0, bool behind = true);
|
void stack(View &view, View const *neighbor = 0, bool behind = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set view title
|
* Set view title
|
||||||
|
Loading…
x
Reference in New Issue
Block a user