mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
decorator: consider partially transparent windows
This patch changes the window manager, the decorator, and the floating window layouter to propagate the usage of an alpha channel from the client application to the decorator. This way, the decorator can paint the decoration elements behind the affected windows, which would otherwise be skipped.
This commit is contained in:
parent
ea16c19516
commit
785cac7168
@ -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");
|
||||
|
||||
|
@ -117,6 +117,11 @@ class Floating_window_layouter::Window : public List<Window>::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<Window>::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<Window>::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 (...) { }
|
||||
}
|
||||
|
@ -108,11 +108,14 @@ class Wm::Nitpicker::View : public Genode::Weak_object<View>,
|
||||
Point _buffer_offset;
|
||||
Weak_ptr<View> _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<View>,
|
||||
_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<View> 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<Nitpicker::Session>,
|
||||
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<Nitpicker::Session>,
|
||||
Weak_ptr<View> 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<Nitpicker::Session>,
|
||||
*/
|
||||
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<Nitpicker::Session>,
|
||||
_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<Nitpicker::Session>) { }
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user