mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +00:00
decorator: generalize include/decorator/window.h
This change makes it possible to reuse the generic window decorator classes in include/decorator/ for decorators of a different structure. E.g., instead of painting decorations on a single nitpicker session, each window may paint its decorations into additional window-specific nitpicker sessions.
This commit is contained in:
parent
493386ed27
commit
acb0ddd9ef
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Accessor for the default font
|
||||
* \brief Accessor for textures
|
||||
* \author Norman Feske
|
||||
* \date 2015-09-16
|
||||
*/
|
||||
|
@ -205,7 +205,35 @@ static bool attribute_has_value(Genode::Xml_node node,
|
||||
|
||||
bool Decorator::Window::update(Genode::Xml_node window_node)
|
||||
{
|
||||
bool updated = Window_base::update(window_node);
|
||||
bool updated = false;
|
||||
|
||||
/*
|
||||
* Detect the need to bring the window to the top of the global
|
||||
* view stack.
|
||||
*/
|
||||
unsigned const topped_cnt = attribute(window_node, "topped", 0UL);
|
||||
if (topped_cnt != _topped_cnt) {
|
||||
|
||||
_global_to_front = true;
|
||||
_topped_cnt = topped_cnt;
|
||||
_nitpicker_stacking_up_to_date = false;
|
||||
|
||||
updated |= true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect geometry changes
|
||||
*/
|
||||
Rect new_geometry = rect_attribute(window_node);
|
||||
if (new_geometry.p1() != geometry().p1()
|
||||
|| new_geometry.p2() != geometry().p2()) {
|
||||
|
||||
geometry(new_geometry);
|
||||
|
||||
_nitpicker_views_up_to_date = false;
|
||||
|
||||
updated |= true;
|
||||
}
|
||||
|
||||
_focused = attribute_has_value(window_node, "focused", "yes");
|
||||
_has_alpha = attribute_has_value(window_node, "has_alpha", "yes");
|
||||
|
@ -29,6 +29,82 @@ class Decorator::Window : public Window_base
|
||||
{
|
||||
private:
|
||||
|
||||
Nitpicker::Session_client &_nitpicker;
|
||||
|
||||
/*
|
||||
* Flag indicating that the current window position has been propagated
|
||||
* to the window's corresponding nitpicker views.
|
||||
*/
|
||||
bool _nitpicker_views_up_to_date = false;
|
||||
|
||||
/*
|
||||
* Flag indicating that the stacking position of the window within the
|
||||
* window stack has changed. The new stacking position must be
|
||||
* propagated to nitpicker.
|
||||
*/
|
||||
bool _nitpicker_stacking_up_to_date = false;
|
||||
|
||||
Nitpicker::Session::View_handle _neighbor;
|
||||
|
||||
struct Nitpicker_view
|
||||
{
|
||||
Nitpicker::Session_client &_nitpicker;
|
||||
Nitpicker::Session::View_handle _handle { _nitpicker.create_view() };
|
||||
|
||||
typedef Nitpicker::Session::Command Command;
|
||||
|
||||
Nitpicker_view(Nitpicker::Session_client &nitpicker, unsigned id = 0)
|
||||
:
|
||||
_nitpicker(nitpicker)
|
||||
{
|
||||
/*
|
||||
* We supply the window ID as label for the anchor view.
|
||||
*/
|
||||
if (id) {
|
||||
char buf[128];
|
||||
Genode::snprintf(buf, sizeof(buf), "%d", id);
|
||||
|
||||
_nitpicker.enqueue<Command::Title>(_handle, buf);
|
||||
}
|
||||
}
|
||||
|
||||
~Nitpicker_view()
|
||||
{
|
||||
_nitpicker.destroy_view(_handle);
|
||||
}
|
||||
|
||||
Nitpicker::Session::View_handle handle() const { return _handle; }
|
||||
|
||||
void stack(Nitpicker::Session::View_handle neighbor)
|
||||
{
|
||||
_nitpicker.enqueue<Command::To_front>(_handle, neighbor);
|
||||
}
|
||||
|
||||
void place(Rect rect)
|
||||
{
|
||||
_nitpicker.enqueue<Command::Geometry>(_handle, rect);
|
||||
Point offset = Point(0, 0) - rect.p1();
|
||||
_nitpicker.enqueue<Command::Offset>(_handle, offset);
|
||||
}
|
||||
};
|
||||
|
||||
Nitpicker_view _bottom_view { _nitpicker },
|
||||
_right_view { _nitpicker },
|
||||
_left_view { _nitpicker },
|
||||
_top_view { _nitpicker };
|
||||
|
||||
Nitpicker_view _content_view { _nitpicker, id() };
|
||||
|
||||
static Border _init_border() {
|
||||
return Border(_border_size + _title_height,
|
||||
_border_size, _border_size, _border_size); }
|
||||
|
||||
Border const _border { _init_border() };
|
||||
|
||||
bool _global_to_front = false;
|
||||
|
||||
unsigned _topped_cnt = 0;
|
||||
|
||||
Window_title _title;
|
||||
|
||||
bool _focused = false;
|
||||
@ -41,9 +117,6 @@ class Decorator::Window : public Window_base
|
||||
static unsigned const _border_size = 4;
|
||||
static unsigned const _title_height = 16;
|
||||
|
||||
static Border _border() {
|
||||
return Border(_border_size + _title_height,
|
||||
_border_size, _border_size, _border_size); }
|
||||
|
||||
Color _bright = { 255, 255, 255, 64 };
|
||||
Color _dark = { 0, 0, 0, 127 };
|
||||
@ -54,7 +127,6 @@ class Decorator::Window : public Window_base
|
||||
|
||||
Area const _icon_size { 16, 16 };
|
||||
|
||||
|
||||
/*
|
||||
* Intensity of the title-bar radient in percent. A value of 0 produces
|
||||
* no gradient. A value of 100 creates a gradient from white over
|
||||
@ -329,10 +401,78 @@ class Decorator::Window : public Window_base
|
||||
Window(unsigned id, Nitpicker::Session_client &nitpicker,
|
||||
Animator &animator, Config const &config)
|
||||
:
|
||||
Window_base(id, nitpicker, _border()),
|
||||
Window_base(id),
|
||||
_nitpicker(nitpicker),
|
||||
_animator(animator), _config(config)
|
||||
{ }
|
||||
|
||||
void stack(Nitpicker::Session::View_handle neighbor) override
|
||||
{
|
||||
_neighbor = neighbor;
|
||||
_nitpicker_stacking_up_to_date = false;
|
||||
}
|
||||
|
||||
Nitpicker::Session::View_handle frontmost_view() const override
|
||||
{
|
||||
return _bottom_view.handle();
|
||||
}
|
||||
|
||||
Rect outer_geometry() const override
|
||||
{
|
||||
return Rect(geometry().p1() - Point(_border.left, _border.top),
|
||||
geometry().p2() + Point(_border.right, _border.bottom));
|
||||
}
|
||||
|
||||
void border_rects(Rect *top, Rect *left, Rect *right, Rect *bottom) const
|
||||
{
|
||||
outer_geometry().cut(geometry(), top, left, right, bottom);
|
||||
}
|
||||
|
||||
bool is_in_front_of(Window_base const &neighbor) const override
|
||||
{
|
||||
return _neighbor == neighbor.frontmost_view();
|
||||
}
|
||||
|
||||
void update_nitpicker_views() override
|
||||
{
|
||||
if (!_nitpicker_views_up_to_date) {
|
||||
|
||||
/* update view positions */
|
||||
Rect top, left, right, bottom;
|
||||
border_rects(&top, &left, &right, &bottom);
|
||||
|
||||
_content_view.place(geometry());
|
||||
_top_view .place(top);
|
||||
_left_view .place(left);
|
||||
_right_view .place(right);
|
||||
_bottom_view .place(bottom);
|
||||
|
||||
_nitpicker_views_up_to_date = true;
|
||||
}
|
||||
|
||||
if (!_nitpicker_stacking_up_to_date) {
|
||||
|
||||
/*
|
||||
* Bring the view to the global top of the view stack if the
|
||||
* 'topped' counter changed. Otherwise, we refer to a
|
||||
* session-local neighbor for the restacking operation.
|
||||
*/
|
||||
Nitpicker::Session::View_handle neighbor = _neighbor;
|
||||
if (_global_to_front) {
|
||||
neighbor = Nitpicker::Session::View_handle();
|
||||
_global_to_front = false;
|
||||
}
|
||||
|
||||
_content_view.stack(neighbor);
|
||||
_top_view.stack(_content_view.handle());
|
||||
_left_view.stack(_top_view.handle());
|
||||
_right_view.stack(_left_view.handle());
|
||||
_bottom_view.stack(_right_view.handle());
|
||||
|
||||
_nitpicker_stacking_up_to_date = true;
|
||||
}
|
||||
}
|
||||
|
||||
void adapt_to_changed_config()
|
||||
{
|
||||
_base_color = _config.base_color(_title);
|
||||
|
@ -85,11 +85,8 @@ class Decorator::Window_base : public Window_list::Element
|
||||
virtual void draw_behind(Canvas_base &, Window_base const &, Rect) const = 0;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Nitpicker::Session_client &_nitpicker;
|
||||
|
||||
/*
|
||||
* Geometry of content
|
||||
*/
|
||||
@ -100,114 +97,22 @@ class Decorator::Window_base : public Window_list::Element
|
||||
*/
|
||||
unsigned const _id;
|
||||
|
||||
/*
|
||||
* Flag indicating that the current window position has been propagated
|
||||
* to the window's corresponding nitpicker views.
|
||||
*/
|
||||
bool _nitpicker_views_up_to_date = false;
|
||||
|
||||
/*
|
||||
* Flag indicating that the stacking position of the window within the
|
||||
* window stack has changed. The new stacking position must be
|
||||
* propagated to nitpicker.
|
||||
*/
|
||||
bool _nitpicker_stacking_up_to_date = false;
|
||||
|
||||
unsigned _topped_cnt = 0;
|
||||
|
||||
bool _global_to_front = false;
|
||||
|
||||
Nitpicker::Session::View_handle _neighbor;
|
||||
|
||||
Border const _border;
|
||||
|
||||
struct Nitpicker_view
|
||||
{
|
||||
Nitpicker::Session_client &_nitpicker;
|
||||
Nitpicker::Session::View_handle _handle { _nitpicker.create_view() };
|
||||
|
||||
typedef Nitpicker::Session::Command Command;
|
||||
|
||||
Nitpicker_view(Nitpicker::Session_client &nitpicker, unsigned id = 0)
|
||||
:
|
||||
_nitpicker(nitpicker)
|
||||
{
|
||||
/*
|
||||
* We supply the window ID as label for the anchor view.
|
||||
*/
|
||||
if (id) {
|
||||
char buf[128];
|
||||
Genode::snprintf(buf, sizeof(buf), "%d", id);
|
||||
|
||||
_nitpicker.enqueue<Command::Title>(_handle, buf);
|
||||
}
|
||||
}
|
||||
|
||||
~Nitpicker_view()
|
||||
{
|
||||
_nitpicker.destroy_view(_handle);
|
||||
}
|
||||
|
||||
Nitpicker::Session::View_handle handle() const { return _handle; }
|
||||
|
||||
void stack(Nitpicker::Session::View_handle neighbor)
|
||||
{
|
||||
_nitpicker.enqueue<Command::To_front>(_handle, neighbor);
|
||||
}
|
||||
|
||||
void place(Rect rect)
|
||||
{
|
||||
_nitpicker.enqueue<Command::Geometry>(_handle, rect);
|
||||
Point offset = Point(0, 0) - rect.p1();
|
||||
_nitpicker.enqueue<Command::Offset>(_handle, offset);
|
||||
}
|
||||
};
|
||||
|
||||
Nitpicker_view _bottom_view, _right_view, _left_view, _top_view;
|
||||
Nitpicker_view _content_view;
|
||||
|
||||
public:
|
||||
|
||||
Window_base(unsigned id, Nitpicker::Session_client &nitpicker,
|
||||
Border border)
|
||||
:
|
||||
_nitpicker(nitpicker), _id(id), _border(border),
|
||||
_bottom_view(nitpicker),
|
||||
_right_view(nitpicker),
|
||||
_left_view(nitpicker),
|
||||
_top_view(nitpicker),
|
||||
_content_view(nitpicker, _id)
|
||||
{ }
|
||||
|
||||
void stack(Nitpicker::Session::View_handle neighbor)
|
||||
{
|
||||
_neighbor = neighbor;
|
||||
_nitpicker_stacking_up_to_date = false;
|
||||
}
|
||||
|
||||
Nitpicker::Session::View_handle frontmost_view() const
|
||||
{
|
||||
return _bottom_view.handle();
|
||||
}
|
||||
|
||||
Rect outer_geometry() const
|
||||
{
|
||||
return Rect(_geometry.p1() - Point(_border.left, _border.top),
|
||||
_geometry.p2() + Point(_border.right, _border.bottom));
|
||||
}
|
||||
|
||||
void border_rects(Rect *top, Rect *left, Rect *right, Rect *bottom) const
|
||||
{
|
||||
outer_geometry().cut(_geometry, top, left, right, bottom);
|
||||
}
|
||||
Window_base(unsigned id) : _id(id) { }
|
||||
|
||||
unsigned long id() const { return _id; }
|
||||
Rect geometry() const { return _geometry; }
|
||||
|
||||
bool is_in_front_of(Window_base const &neighbor) const
|
||||
{
|
||||
return _neighbor == neighbor.frontmost_view();
|
||||
}
|
||||
void geometry(Rect geometry) { _geometry = geometry; }
|
||||
|
||||
virtual Rect outer_geometry() const = 0;
|
||||
|
||||
virtual void stack(Nitpicker::Session::View_handle neighbor) = 0;
|
||||
|
||||
virtual Nitpicker::Session::View_handle frontmost_view() const = 0;
|
||||
|
||||
virtual bool is_in_front_of(Window_base const &neighbor) const = 0;
|
||||
|
||||
/**
|
||||
* Draw window elements
|
||||
@ -227,79 +132,9 @@ class Decorator::Window_base : public Window_list::Element
|
||||
* decorations haven't been redrawn already. If we updated the
|
||||
* nitpicker views at this point, we would reveal not-yet-drawn pixels.
|
||||
*/
|
||||
virtual bool update(Xml_node window_node)
|
||||
{
|
||||
bool result = false;
|
||||
virtual bool update(Xml_node window_node) = 0;
|
||||
|
||||
/*
|
||||
* Detect the need to bring the window to the top of the global
|
||||
* view stack.
|
||||
*/
|
||||
unsigned const topped_cnt = attribute(window_node, "topped", 0UL);
|
||||
if (topped_cnt != _topped_cnt) {
|
||||
|
||||
_global_to_front = true;
|
||||
_topped_cnt = topped_cnt;
|
||||
_nitpicker_stacking_up_to_date = false;
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect geometry changes
|
||||
*/
|
||||
Rect new_geometry = rect_attribute(window_node);
|
||||
if (new_geometry.p1() != _geometry.p1()
|
||||
|| new_geometry.p2() != _geometry.p2()) {
|
||||
|
||||
_geometry = new_geometry;
|
||||
|
||||
_nitpicker_views_up_to_date = false;
|
||||
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void update_nitpicker_views()
|
||||
{
|
||||
if (!_nitpicker_views_up_to_date) {
|
||||
|
||||
/* update view positions */
|
||||
Rect top, left, right, bottom;
|
||||
border_rects(&top, &left, &right, &bottom);
|
||||
|
||||
_content_view.place(_geometry);
|
||||
_top_view .place(top);
|
||||
_left_view .place(left);
|
||||
_right_view .place(right);
|
||||
_bottom_view .place(bottom);
|
||||
|
||||
_nitpicker_views_up_to_date = true;
|
||||
}
|
||||
|
||||
if (!_nitpicker_stacking_up_to_date) {
|
||||
|
||||
/*
|
||||
* Bring the view to the global top of the view stack if the
|
||||
* 'topped' counter changed. Otherwise, we refer to a
|
||||
* session-local neighbor for the restacking operation.
|
||||
*/
|
||||
Nitpicker::Session::View_handle neighbor = _neighbor;
|
||||
if (_global_to_front) {
|
||||
neighbor = Nitpicker::Session::View_handle();
|
||||
_global_to_front = false;
|
||||
}
|
||||
|
||||
_content_view.stack(neighbor);
|
||||
_top_view.stack(_content_view.handle());
|
||||
_left_view.stack(_top_view.handle());
|
||||
_right_view.stack(_left_view.handle());
|
||||
_bottom_view.stack(_right_view.handle());
|
||||
|
||||
_nitpicker_stacking_up_to_date = true;
|
||||
}
|
||||
}
|
||||
virtual void update_nitpicker_views() { }
|
||||
|
||||
/**
|
||||
* Report information about element at specified position
|
||||
|
Loading…
x
Reference in New Issue
Block a user