diff --git a/repos/gems/src/app/decorator/window.h b/repos/gems/src/app/decorator/window.h index bd0a44620..e07b33da3 100644 --- a/repos/gems/src/app/decorator/window.h +++ b/repos/gems/src/app/decorator/window.h @@ -51,6 +51,8 @@ class Decorator::Window : public Window_base Color _base_color() const { return Color(45, 49, 65); } + bool _has_alpha = false; + class Element : public Animator::Item { public: @@ -306,7 +308,7 @@ class Decorator::Window : public Window_base _animator(animator) { } - void draw(Canvas_base &canvas, Rect clip) const override; + void draw(Canvas_base &canvas, Rect clip, Draw_behind_fn const &) const override; bool update(Xml_node window_node) override; @@ -324,7 +326,8 @@ class Decorator::Window : public Window_base void Decorator::Window::draw(Decorator::Canvas_base &canvas, - Decorator::Rect clip) const + Decorator::Rect clip, + Draw_behind_fn const &draw_behind_fn) const { Clip_guard clip_guard(canvas, clip); @@ -334,10 +337,8 @@ void Decorator::Window::draw(Decorator::Canvas_base &canvas, Point p1 = rect.p1(); Point p2 = rect.p2(); - bool const draw_content = false; - - if (draw_content) - canvas.draw_box(geometry(), Color(10, 20, 40)); + if (_has_alpha) + draw_behind_fn.draw_behind(canvas, *this, canvas.clip()); _draw_corner(canvas, Rect(p1, corner), _border_size, true, true, element(Element::TOP_LEFT).color()); @@ -403,6 +404,9 @@ bool Decorator::Window::update(Genode::Xml_node window_node) _focused = window_node.has_attribute("focused") && window_node.attribute("focused").has_value("yes"); + _has_alpha = window_node.has_attribute("has_alpha") + && window_node.attribute("has_alpha").has_value("yes"); + try { Xml_node highlight = window_node.sub_node("highlight"); diff --git a/repos/gems/src/app/floating_window_layouter/main.cc b/repos/gems/src/app/floating_window_layouter/main.cc index c0e6a0953..20b64b9fb 100644 --- a/repos/gems/src/app/floating_window_layouter/main.cc +++ b/repos/gems/src/app/floating_window_layouter/main.cc @@ -117,6 +117,11 @@ class Floating_window_layouter::Window : public List::Element */ Area _requested_size; + /** + * Window may be partially transparent + */ + bool _has_alpha = false; + /* * Number of times the window has been topped. This value is used by * the decorator to detect the need for bringing the window to the @@ -147,6 +152,8 @@ class Floating_window_layouter::Window : public List::Element void position(Point pos) { _geometry = Rect(pos, _geometry.area()); } + void has_alpha(bool has_alpha) { _has_alpha = has_alpha; } + /** * Return true if user drags a window border */ @@ -208,6 +215,9 @@ class Floating_window_layouter::Window : public List::Element xml.node(highlight.name()); }); } + + if (_has_alpha) + xml.attribute("has_alpha", "yes"); }); } @@ -393,6 +403,8 @@ void Floating_window_layouter::Main::import_window_list(Xml_node window_list_xml win->size(area_attribute(node)); win->title(string_attribute(node, "title", Window::Title("untitled"))); + win->has_alpha(node.has_attribute("has_alpha") + && node.attribute("has_alpha").has_value("yes")); } } catch (...) { } } diff --git a/repos/gems/src/server/wm/nitpicker.h b/repos/gems/src/server/wm/nitpicker.h index c92c4d35d..2769bcabc 100644 --- a/repos/gems/src/server/wm/nitpicker.h +++ b/repos/gems/src/server/wm/nitpicker.h @@ -108,11 +108,14 @@ class Wm::Nitpicker::View : public Genode::Weak_object, Point _buffer_offset; Weak_ptr _neighbor_ptr; bool _neighbor_behind; + bool _has_alpha; View(Nitpicker::Session_client &real_nitpicker, - Session_label const &session_label) + Session_label const &session_label, + bool has_alpha) : - _session_label(session_label), _real_nitpicker(real_nitpicker) + _session_label(session_label), _real_nitpicker(real_nitpicker), + _has_alpha(has_alpha) { } /** @@ -204,6 +207,8 @@ class Wm::Nitpicker::View : public Genode::Weak_object, _real_nitpicker.execute(); } } + + bool has_alpha() const { return _has_alpha; } }; @@ -246,9 +251,10 @@ class Wm::Nitpicker::Top_level_view : public View, Top_level_view(Nitpicker::Session_client &real_nitpicker, Session_label const &session_label, + bool has_alpha, Window_registry &window_registry) : - View(real_nitpicker, session_label), + View(real_nitpicker, session_label, has_alpha), _window_registry(window_registry), _window_title(session_label, "") { } @@ -271,6 +277,7 @@ class Wm::Nitpicker::Top_level_view : public View, if (!_win_id.valid()) { _win_id = _window_registry.create(); _window_registry.title(_win_id, _window_title.string()); + _window_registry.has_alpha(_win_id, View::has_alpha()); } _window_registry.size(_win_id, geometry.area()); @@ -334,9 +341,10 @@ class Wm::Nitpicker::Child_view : public View, Child_view(Nitpicker::Session_client &real_nitpicker, Session_label const &session_label, + bool has_alpha, Weak_ptr parent) : - View(real_nitpicker, session_label), _parent(parent) + View(real_nitpicker, session_label, has_alpha), _parent(parent) { try_to_init_real_view(); } @@ -418,6 +426,7 @@ class Wm::Nitpicker::Session_component : public Rpc_object, Click_handler &_click_handler; Signal_context_capability _mode_sigh; Area _requested_size; + bool _has_alpha = false; /* * Command buffer @@ -553,7 +562,7 @@ class Wm::Nitpicker::Session_component : public Rpc_object, Weak_ptr parent_ptr = _view_handle_registry.lookup(parent_handle); Child_view *view = new (_child_view_alloc) - Child_view(_session, _session_label, parent_ptr); + Child_view(_session, _session_label, _has_alpha, parent_ptr); _child_views.insert(view); return *view; @@ -564,7 +573,7 @@ class Wm::Nitpicker::Session_component : public Rpc_object, */ else { Top_level_view *view = new (_top_level_view_alloc) - Top_level_view(_session, _session_label, _window_registry); + Top_level_view(_session, _session_label, _has_alpha, _window_registry); _top_level_views.insert(view); return *view; @@ -873,9 +882,10 @@ class Wm::Nitpicker::Session_component : public Rpc_object, _mode_sigh = sigh; } - void buffer(Framebuffer::Mode mode, bool use_alpha) override + void buffer(Framebuffer::Mode mode, bool has_alpha) override { - _session.buffer(mode, use_alpha); + _session.buffer(mode, has_alpha); + _has_alpha = has_alpha; } void focus(Genode::Capability) { } diff --git a/repos/gems/src/server/wm/window_registry.h b/repos/gems/src/server/wm/window_registry.h index c25fc70b3..22f81d95e 100644 --- a/repos/gems/src/server/wm/window_registry.h +++ b/repos/gems/src/server/wm/window_registry.h @@ -62,6 +62,8 @@ class Wm::Window_registry typedef Genode::String<200> Title; + enum Has_alpha { HAS_ALPHA, HAS_NO_ALPHA }; + private: Id const _id; @@ -70,6 +72,8 @@ class Wm::Window_registry Area _size; + Has_alpha _has_alpha; + friend class Window_registry; Window(Id id) : _id(id) { } @@ -81,8 +85,9 @@ class Wm::Window_registry /* * Accessors for setting attributes */ - void attr(Title const &title) { _title = title; } - void attr(Area size) { _size = size; } + void attr(Title const &title) { _title = title; } + void attr(Area size) { _size = size; } + void attr(Has_alpha has_alpha) { _has_alpha = has_alpha; } void generate_window_list_entry_xml(Xml_generator &xml) const { @@ -91,6 +96,9 @@ class Wm::Window_registry xml.attribute("title", _title.string()); xml.attribute("width", _size.w()); xml.attribute("height", _size.h()); + + if (_has_alpha == HAS_ALPHA) + xml.attribute("has_alpha", "yes"); }); } }; @@ -183,6 +191,11 @@ class Wm::Window_registry void size(Id id, Area size) { _set_attr(id, size); } void title(Id id, Window::Title title) { _set_attr(id, title); } + + void has_alpha(Id id, bool has_alpha) + { + _set_attr(id, has_alpha ? Window::HAS_ALPHA : Window::HAS_NO_ALPHA); + } }; #endif /* _WINDOW_REGISTRY_H_ */ diff --git a/repos/os/include/decorator/window.h b/repos/os/include/decorator/window.h index ae166856f..50e3e55aa 100644 --- a/repos/os/include/decorator/window.h +++ b/repos/os/include/decorator/window.h @@ -66,6 +66,18 @@ class Decorator::Window_base : public Window_list::Element } }; + /** + * Functor for drawing the elements behind a window + * + * This functor is used for drawing the decorations of partially + * transparent windows. It is implemented by the window stack. + */ + struct Draw_behind_fn + { + virtual void draw_behind(Canvas_base &, Window_base const &, Rect) const = 0; + }; + + private: Nitpicker::Session_client &_nitpicker; @@ -195,7 +207,7 @@ class Decorator::Window_base : public Window_list::Element * \param canvas graphics back end * \param clip clipping area to apply */ - virtual void draw(Canvas_base &canvas, Rect clip) const = 0; + virtual void draw(Canvas_base &canvas, Rect clip, Draw_behind_fn const &) const = 0; /** * Update internal window representation from XML model diff --git a/repos/os/include/decorator/window_stack.h b/repos/os/include/decorator/window_stack.h index 95717e035..b9cdcb9e4 100644 --- a/repos/os/include/decorator/window_stack.h +++ b/repos/os/include/decorator/window_stack.h @@ -27,7 +27,7 @@ namespace Decorator { class Window_stack; } -class Decorator::Window_stack +class Decorator::Window_stack : public Window_base::Draw_behind_fn { private: @@ -147,6 +147,16 @@ class Decorator::Window_stack return Window_base::Hover(); } + + + /************************************** + ** Window::Draw_behind_fn interface ** + **************************************/ + + void draw_behind(Canvas_base &canvas, Window_base const &window, Rect clip) const override + { + _draw_rec(canvas, window.next(), clip); + } }; @@ -175,7 +185,7 @@ void Decorator::Window_stack::_draw_rec(Decorator::Canvas_base &canvas, } /* draw current window */ - win->draw(canvas, clipped); + win->draw(canvas, clipped, *this); }