From dbebfd624ec38c5b678345b6cf2c6482bf8a8222 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 13 Jun 2014 11:37:34 +0200 Subject: [PATCH] nitpicker: Domain configuration This patch introduces the notion of a "domain" to the nitpicker configuration concept. Session policies always refer to a domain where multiple session policies can refer to the same domain. Thereby a domain provides a way to express the grouping of sessions. This is useful for applications that open multiple nitpicker sessions (such as Qt5 apps that use one nitpicker session per window, menu, etc.). We want to assign all those sessions to a single domain. The configuration looks as follows: ... ... --- repos/os/run/demo.run | 3 + .../os/src/server/nitpicker/domain_registry.h | 119 ++++++++++++++++++ repos/os/src/server/nitpicker/main.cc | 57 +++++---- repos/os/src/server/nitpicker/mode.h | 3 +- repos/os/src/server/nitpicker/session.h | 60 ++++++--- repos/os/src/server/nitpicker/view.cc | 5 +- 6 files changed, 207 insertions(+), 40 deletions(-) create mode 100644 repos/os/src/server/nitpicker/domain_registry.h diff --git a/repos/os/run/demo.run b/repos/os/run/demo.run index 20784afe7e..5c2145f0e7 100644 --- a/repos/os/run/demo.run +++ b/repos/os/run/demo.run @@ -119,6 +119,9 @@ append config { + + + diff --git a/repos/os/src/server/nitpicker/domain_registry.h b/repos/os/src/server/nitpicker/domain_registry.h new file mode 100644 index 0000000000..9321a20d1f --- /dev/null +++ b/repos/os/src/server/nitpicker/domain_registry.h @@ -0,0 +1,119 @@ +/* + * \brief Domain registry + * \author Norman Feske + * \date 2014-06-12 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _DOMAIN_REGISTRY_ +#define _DOMAIN_REGISTRY_ + +#include +#include + +class Domain_registry +{ + public: + + class Entry : public Genode::List::Element + { + public: + + typedef Genode::String<64> Name; + typedef Genode::Color Color; + + private: + + Name _name; + Color _color; + + friend class Domain_registry; + + Entry(Name const &name, Color color) + : + _name(name), _color(color) + { } + + public: + + bool has_name(Name const &name) const { return name == _name; } + + Color color() const { return _color; } + }; + + void _insert(Genode::Xml_node domain) + { + char buf[sizeof(Entry::Name)]; + buf[0] = 0; + bool name_defined = false; + try { + domain.attribute("name").value(buf, sizeof(buf)); + name_defined = true; + } catch (...) { } + + if (!name_defined) { + PERR("no valid domain name specified"); + return; + } + + Entry::Name const name(buf); + + if (lookup(name)) { + PERR("domain name \"%s\" is not unique", name.string()); + return; + } + + Entry::Color const color = domain.attribute_value("color", Entry::Color()); + + _entries.insert(new (_alloc) Entry(name, color)); + } + + private: + + Genode::List _entries; + Genode::Allocator &_alloc; + + public: + + Domain_registry(Genode::Allocator &alloc, Genode::Xml_node config) + : + _alloc(alloc) + { + char const *type = "domain"; + + if (!config.has_sub_node(type)) + return; + + Genode::Xml_node domain = config.sub_node(type); + + for (;; domain = domain.next(type)) { + + _insert(domain); + + if (domain.is_last(type)) + break; + } + } + + ~Domain_registry() + { + while (Entry *e = _entries.first()) + Genode::destroy(_alloc, e); + } + + Entry const *lookup(Entry::Name const &name) const + { + for (Entry const *e = _entries.first(); e; e = e->next()) + if (e->has_name(name)) + return e; + return 0; + } +}; + +#endif /* _DOMAIN_REGISTRY_ */ diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index ef1d97e4dd..e10e7c8378 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -39,6 +39,7 @@ #include "clip_guard.h" #include "mouse_cursor.h" #include "chunky_menubar.h" +#include "domain_registry.h" namespace Input { class Session_component; } namespace Framebuffer { class Session_component; } @@ -895,13 +896,14 @@ class Nitpicker::Root : public Genode::Root_component { private: - Session_list &_session_list; - Global_keys &_global_keys; - Framebuffer::Mode _scr_mode; - View_stack &_view_stack; - Mode &_mode; - Framebuffer::Session &_framebuffer; - int _default_v_offset; + Session_list &_session_list; + Domain_registry const &_domain_registry; + Global_keys &_global_keys; + Framebuffer::Mode _scr_mode; + View_stack &_view_stack; + Mode &_mode; + Framebuffer::Session &_framebuffer; + int _default_v_offset; protected: @@ -933,7 +935,7 @@ class Nitpicker::Root : public Genode::Root_component _framebuffer, v_offset, provides_default_bg, stay_top, *md_alloc(), unused_quota); - session->apply_session_color(); + session->apply_session_policy(_domain_registry); _session_list.insert(session); _global_keys.apply_config(_session_list); @@ -962,17 +964,16 @@ class Nitpicker::Root : public Genode::Root_component /** * Constructor */ - Root(Session_list &session_list, Global_keys &global_keys, - Rpc_entrypoint &session_ep, View_stack &view_stack, - Mode &mode, Allocator &md_alloc, - Framebuffer::Session &framebuffer, + Root(Session_list &session_list, + Domain_registry const &domain_registry, Global_keys &global_keys, + Rpc_entrypoint &session_ep, View_stack &view_stack, Mode &mode, + Allocator &md_alloc, Framebuffer::Session &framebuffer, int default_v_offset) : Root_component(&session_ep, &md_alloc), - _session_list(session_list), _global_keys(global_keys), - _view_stack(view_stack), _mode(mode), - _framebuffer(framebuffer), - _default_v_offset(default_v_offset) + _session_list(session_list), _domain_registry(domain_registry), + _global_keys(global_keys), _view_stack(view_stack), _mode(mode), + _framebuffer(framebuffer), _default_v_offset(default_v_offset) { } }; @@ -1046,6 +1047,13 @@ struct Nitpicker::Main Session_list session_list; + /* + * Construct empty domain registry. The initial version will be replaced + * on the first call of 'handle_config'. + */ + Genode::Volatile_object domain_registry { + *env()->heap(), Genode::Xml_node("") }; + User_state user_state = { global_keys, fb_screen->screen.size(), fb_screen->menubar }; /* @@ -1062,9 +1070,9 @@ struct Nitpicker::Main */ Genode::Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() }; - Root np_root = { session_list, global_keys, ep.rpc_ep(), user_state, - user_state, sliced_heap, framebuffer, - Framebuffer_screen::MENUBAR_HEIGHT }; + Root np_root = { session_list, *domain_registry, global_keys, + ep.rpc_ep(), user_state, user_state, sliced_heap, + framebuffer, Framebuffer_screen::MENUBAR_HEIGHT }; Genode::Reporter pointer_reporter = { "pointer" }; @@ -1196,9 +1204,16 @@ void Nitpicker::Main::handle_config(unsigned) .has_value("yes")); } catch (...) { } - /* update session policies */ + /* update domain registry and session policies */ for (::Session *s = session_list.first(); s; s = s->next()) - s->apply_session_color(); + s->reset_domain(); + + try { + domain_registry.construct(*env()->heap(), config()->xml_node()); } + catch (...) { } + + for (::Session *s = session_list.first(); s; s = s->next()) + s->apply_session_policy(*domain_registry); /* redraw */ user_state.update_all_views(); diff --git a/repos/os/src/server/nitpicker/mode.h b/repos/os/src/server/nitpicker/mode.h index c41c8b5044..cc73a62673 100644 --- a/repos/os/src/server/nitpicker/mode.h +++ b/repos/os/src/server/nitpicker/mode.h @@ -53,7 +53,8 @@ class Mode bool has_key_cnt(unsigned cnt) const { return cnt == _key_cnt; } - Session *focused_session() { return _focused_session; } + Session *focused_session() { return _focused_session; } + Session const *focused_session() const { return _focused_session; } virtual void focused_session(Session *session) { _focused_session = session; } diff --git a/repos/os/src/server/nitpicker/session.h b/repos/os/src/server/nitpicker/session.h index 1f797ea8cc..8dff028d58 100644 --- a/repos/os/src/server/nitpicker/session.h +++ b/repos/os/src/server/nitpicker/session.h @@ -22,6 +22,7 @@ /* local includes */ #include "color.h" #include "canvas.h" +#include "domain_registry.h" class View; class Session; @@ -34,14 +35,14 @@ class Session : public Session_list::Element { private: - Genode::Session_label const _label; - Color _color; - Texture_base const *_texture = { 0 }; - bool _uses_alpha = { false }; - View *_background = 0; - int _v_offset; - unsigned char const *_input_mask = { 0 }; - bool const _stay_top; + Genode::Session_label const _label; + Domain_registry::Entry const *_domain; + Texture_base const *_texture = { 0 }; + bool _uses_alpha = { false }; + View *_background = 0; + int _v_offset; + unsigned char const *_input_mask = { 0 }; + bool const _stay_top; public: @@ -87,7 +88,7 @@ class Session : public Session_list::Element */ void input_mask(unsigned char const *mask) { _input_mask = mask; } - Color color() const { return _color; } + Color color() const { return _domain ? _domain->color() : WHITE; } View *background() const { return _background; } @@ -120,22 +121,51 @@ class Session : public Session_list::Element return _input_mask[p.y()*_texture->size().w() + p.x()]; } + bool has_same_domain(Session const *s) const + { + return s && (s->_domain == _domain); + } + + bool has_valid_domain() const + { + return _domain; + } + + void reset_domain() + { + _domain = nullptr; + } + /** - * Set session color according to the list of configured policies + * Set session domain according to the list of configured policies * * Select the policy that matches the label. If multiple policies * match, select the one with the largest number of characters. */ - void apply_session_color() + void apply_session_policy(Domain_registry const &domain_registry) { - /* use white by default */ - _color = WHITE; + reset_domain(); try { Genode::Session_policy policy(_label); - /* read color attribute */ - policy.attribute("color").value(&_color); + /* read domain attribute */ + if (!policy.has_attribute("domain")) { + PERR("policy for label \"%s\" lacks domain declaration", + _label.string()); + return; + } + + typedef Domain_registry::Entry::Name Domain_name; + char buf[sizeof(Domain_name)]; + buf[0] = 0; + try { + policy.attribute("domain").value(buf, sizeof(buf)); } + catch (...) { } + + Domain_name name(buf); + _domain = domain_registry.lookup(name); + } catch (...) { } } }; diff --git a/repos/os/src/server/nitpicker/view.cc b/repos/os/src/server/nitpicker/view.cc index b07ddb89df..4025491690 100644 --- a/repos/os/src/server/nitpicker/view.cc +++ b/repos/os/src/server/nitpicker/view.cc @@ -79,8 +79,7 @@ void View::frame(Canvas_base &canvas, Mode const &mode) const void View::draw(Canvas_base &canvas, Mode const &mode) const { - /* is this the currently focused view? */ - bool const session_is_focused = mode.is_focused(_session); + bool const is_focused = _session.has_same_domain(mode.focused_session()); Color const frame_color = _session.color(); @@ -88,7 +87,7 @@ void View::draw(Canvas_base &canvas, Mode const &mode) const * Use dimming in x-ray and kill mode, but do not dim the focused view in * x-ray mode. */ - Texture_painter::Mode const op = mode.flat() || (mode.xray() && session_is_focused) + Texture_painter::Mode const op = mode.flat() || (mode.xray() && is_focused) ? Texture_painter::SOLID : Texture_painter::MIXED; Rect const view_rect = abs_geometry();