mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-25 05:19:57 +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
|
* \author Norman Feske
|
||||||
* \date 2015-09-16
|
* \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 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");
|
_focused = attribute_has_value(window_node, "focused", "yes");
|
||||||
_has_alpha = attribute_has_value(window_node, "has_alpha", "yes");
|
_has_alpha = attribute_has_value(window_node, "has_alpha", "yes");
|
||||||
|
@ -29,6 +29,82 @@ class Decorator::Window : public Window_base
|
|||||||
{
|
{
|
||||||
private:
|
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;
|
Window_title _title;
|
||||||
|
|
||||||
bool _focused = false;
|
bool _focused = false;
|
||||||
@ -41,9 +117,6 @@ class Decorator::Window : public Window_base
|
|||||||
static unsigned const _border_size = 4;
|
static unsigned const _border_size = 4;
|
||||||
static unsigned const _title_height = 16;
|
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 _bright = { 255, 255, 255, 64 };
|
||||||
Color _dark = { 0, 0, 0, 127 };
|
Color _dark = { 0, 0, 0, 127 };
|
||||||
@ -54,7 +127,6 @@ class Decorator::Window : public Window_base
|
|||||||
|
|
||||||
Area const _icon_size { 16, 16 };
|
Area const _icon_size { 16, 16 };
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intensity of the title-bar radient in percent. A value of 0 produces
|
* 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
|
* 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,
|
Window(unsigned id, Nitpicker::Session_client &nitpicker,
|
||||||
Animator &animator, Config const &config)
|
Animator &animator, Config const &config)
|
||||||
:
|
:
|
||||||
Window_base(id, nitpicker, _border()),
|
Window_base(id),
|
||||||
|
_nitpicker(nitpicker),
|
||||||
_animator(animator), _config(config)
|
_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()
|
void adapt_to_changed_config()
|
||||||
{
|
{
|
||||||
_base_color = _config.base_color(_title);
|
_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;
|
virtual void draw_behind(Canvas_base &, Window_base const &, Rect) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Nitpicker::Session_client &_nitpicker;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Geometry of content
|
* Geometry of content
|
||||||
*/
|
*/
|
||||||
@ -100,114 +97,22 @@ class Decorator::Window_base : public Window_list::Element
|
|||||||
*/
|
*/
|
||||||
unsigned const _id;
|
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:
|
public:
|
||||||
|
|
||||||
Window_base(unsigned id, Nitpicker::Session_client &nitpicker,
|
Window_base(unsigned id) : _id(id) { }
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long id() const { return _id; }
|
unsigned long id() const { return _id; }
|
||||||
Rect geometry() const { return _geometry; }
|
Rect geometry() const { return _geometry; }
|
||||||
|
|
||||||
bool is_in_front_of(Window_base const &neighbor) const
|
void geometry(Rect geometry) { _geometry = geometry; }
|
||||||
{
|
|
||||||
return _neighbor == neighbor.frontmost_view();
|
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
|
* 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
|
* decorations haven't been redrawn already. If we updated the
|
||||||
* nitpicker views at this point, we would reveal not-yet-drawn pixels.
|
* nitpicker views at this point, we would reveal not-yet-drawn pixels.
|
||||||
*/
|
*/
|
||||||
virtual bool update(Xml_node window_node)
|
virtual bool update(Xml_node window_node) = 0;
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
/*
|
virtual void update_nitpicker_views() { }
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report information about element at specified position
|
* Report information about element at specified position
|
||||||
|
Loading…
x
Reference in New Issue
Block a user