From 17454533154eb7754ec394b29cece251b79d6e86 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 2 Jul 2014 22:00:15 +0200 Subject: [PATCH] nitpicker: Layers and client-side mouse cursor This patch introduces a mandatory layer attribute to domains. The layer ordering is superimposed on the stacking order of the views. The top-most layer can be assigned to a pointer-managing client. An example for such a pointer is located at os/src/app/pointer. It replaces the formerly built-in nitpicker mouse cursor. The new layering mechanism replaces the former "stay-top" session argument. So the Nitpicker::Connection no longer takes the stay-top flag as the first argument. --- .../os/include/nitpicker_session/connection.h | 9 +-- repos/os/run/demo.run | 15 +++- .../nitpicker => app/pointer}/big_mouse.h | 0 repos/os/src/app/pointer/main.cc | 66 +++++++++++++++ repos/os/src/app/pointer/target.mk | 3 + repos/os/src/server/nitpicker/background.h | 4 +- .../os/src/server/nitpicker/chunky_menubar.h | 5 +- .../os/src/server/nitpicker/domain_registry.h | 26 ++++-- repos/os/src/server/nitpicker/main.cc | 48 ++++++----- repos/os/src/server/nitpicker/mouse_cursor.h | 81 ------------------- .../os/src/server/nitpicker/pointer_origin.h | 46 +++++++++++ repos/os/src/server/nitpicker/session.h | 10 +-- repos/os/src/server/nitpicker/user_state.cc | 8 +- repos/os/src/server/nitpicker/user_state.h | 6 +- repos/os/src/server/nitpicker/view.h | 7 +- repos/os/src/server/nitpicker/view_stack.cc | 65 ++++++++++----- repos/os/src/server/nitpicker/view_stack.h | 2 + 17 files changed, 233 insertions(+), 168 deletions(-) rename repos/os/src/{server/nitpicker => app/pointer}/big_mouse.h (100%) create mode 100644 repos/os/src/app/pointer/main.cc create mode 100644 repos/os/src/app/pointer/target.mk delete mode 100644 repos/os/src/server/nitpicker/mouse_cursor.h create mode 100644 repos/os/src/server/nitpicker/pointer_origin.h diff --git a/repos/os/include/nitpicker_session/connection.h b/repos/os/include/nitpicker_session/connection.h index abef3ec6e..d743f8448 100644 --- a/repos/os/include/nitpicker_session/connection.h +++ b/repos/os/include/nitpicker_session/connection.h @@ -34,7 +34,7 @@ class Nitpicker::Connection : public Genode::Connection, /** * Create session and return typed session capability */ - Session_capability _connect(bool stay_top, char const *label) + Session_capability _connect(char const *label) { enum { ARGBUF_SIZE = 128 }; char argbuf[ARGBUF_SIZE]; @@ -50,9 +50,6 @@ class Nitpicker::Connection : public Genode::Connection, enum { SESSION_METADATA = 36*1024 }; Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", SESSION_METADATA); - if (stay_top) - Arg_string::set_arg(argbuf, sizeof(argbuf), "stay_top", "yes"); - return session(argbuf); } @@ -61,10 +58,10 @@ class Nitpicker::Connection : public Genode::Connection, /** * Constructor */ - Connection(bool stay_top = false, char const *label = "") + Connection(char const *label = "") : /* establish nitpicker session */ - Genode::Connection(_connect(stay_top, label)), + Genode::Connection(_connect(label)), Session_client(cap()), /* request frame-buffer and input sub sessions */ diff --git a/repos/os/run/demo.run b/repos/os/run/demo.run index e23f91a7b..bfc6922dc 100644 --- a/repos/os/run/demo.run +++ b/repos/os/run/demo.run @@ -5,7 +5,8 @@ set build_components { core init drivers/timer - server/nitpicker server/liquid_framebuffer app/launchpad app/scout + server/nitpicker app/pointer + server/liquid_framebuffer app/launchpad app/scout test/nitpicker server/nitlog drivers/framebuffer drivers/pci drivers/input } @@ -119,8 +120,11 @@ append config { - - + + + + + @@ -129,6 +133,9 @@ append config { + + + @@ -163,7 +170,7 @@ close $launchpad_config_fd set boot_modules { core init timer - nitpicker liquid_fb launchpad scout + nitpicker pointer liquid_fb launchpad scout testnit nitlog launchpad.config } diff --git a/repos/os/src/server/nitpicker/big_mouse.h b/repos/os/src/app/pointer/big_mouse.h similarity index 100% rename from repos/os/src/server/nitpicker/big_mouse.h rename to repos/os/src/app/pointer/big_mouse.h diff --git a/repos/os/src/app/pointer/main.cc b/repos/os/src/app/pointer/main.cc new file mode 100644 index 000000000..8ec8d30d0 --- /dev/null +++ b/repos/os/src/app/pointer/main.cc @@ -0,0 +1,66 @@ +/* + * \brief Minimalistic nitpicker pointer + * \author Norman Feske + * \date 2014-07-02 + */ + +/* + * 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. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include + +/* local includes */ +#include "big_mouse.h" + + +template +void convert_cursor_data_to_pixels(PT *pixel, Nitpicker::Area size) +{ + unsigned char *alpha = (unsigned char *)(pixel + size.count()); + + for (unsigned y = 0; y < size.h(); y++) { + for (unsigned x = 0; x < size.w(); x++) { + + /* the source is known to be in RGB565 format */ + Genode::Pixel_rgb565 src = + *(Genode::Pixel_rgb565 *)(&big_mouse.pixels[y][x]); + + unsigned const i = y*size.w() + x; + pixel[i] = PT(src.r(), src.g(), src.b()); + alpha[i] = src.r() ? 255 : 0; + } + } +} + + +int main(int, char **) +{ + static Nitpicker::Connection nitpicker; + + Nitpicker::Area const cursor_size(big_mouse.w, big_mouse.h); + + Framebuffer::Mode const mode(cursor_size.w(), cursor_size.h(), + Framebuffer::Mode::RGB565); + nitpicker.buffer(mode, true); + + static Genode::Attached_dataspace ds(nitpicker.framebuffer()->dataspace()); + + convert_cursor_data_to_pixels(ds.local_addr(), cursor_size); + + Nitpicker::Session::View_handle view = nitpicker.create_view(); + Nitpicker::Rect geometry(Nitpicker::Point(0, 0), cursor_size); + nitpicker.enqueue(view, geometry); + nitpicker.enqueue(view); + nitpicker.execute(); + + Genode::sleep_forever(); +} diff --git a/repos/os/src/app/pointer/target.mk b/repos/os/src/app/pointer/target.mk new file mode 100644 index 000000000..9fa442a31 --- /dev/null +++ b/repos/os/src/app/pointer/target.mk @@ -0,0 +1,3 @@ +TARGET = pointer +SRC_CC = main.cc +LIBS += base diff --git a/repos/os/src/server/nitpicker/background.h b/repos/os/src/server/nitpicker/background.h index 6adb91b35..8f79362fc 100644 --- a/repos/os/src/server/nitpicker/background.h +++ b/repos/os/src/server/nitpicker/background.h @@ -30,8 +30,8 @@ struct Background : private Texture_base, Session, View */ Background(Area size) : - Texture_base(Area(0, 0)), Session(Genode::Session_label(""), 0, false), - View(*this, View::NOT_STAY_TOP, View::NOT_TRANSPARENT, View::BACKGROUND, 0), + Texture_base(Area(0, 0)), Session(Genode::Session_label(""), 0), + View(*this, View::NOT_TRANSPARENT, View::BACKGROUND, 0), color(25, 37, 50) { View::geometry(Rect(Point(0, 0), size)); diff --git a/repos/os/src/server/nitpicker/chunky_menubar.h b/repos/os/src/server/nitpicker/chunky_menubar.h index abae95c8a..e9286ee67 100644 --- a/repos/os/src/server/nitpicker/chunky_menubar.h +++ b/repos/os/src/server/nitpicker/chunky_menubar.h @@ -35,9 +35,8 @@ class Chunky_menubar : public Texture, Chunky_menubar(PT *pixels, Area size) : Texture(pixels, 0, size), - Session(Genode::Session_label(""), 0, false), - View(*this, View::STAY_TOP, View::NOT_TRANSPARENT, - View::NOT_BACKGROUND, 0), + Session(Genode::Session_label(""), 0), + View(*this, View::NOT_TRANSPARENT, View::NOT_BACKGROUND, 0), _canvas(pixels, size) { View::geometry(Rect(Point(0, 0), size)); diff --git a/repos/os/src/server/nitpicker/domain_registry.h b/repos/os/src/server/nitpicker/domain_registry.h index fe9e5758f..3cc7e54b1 100644 --- a/repos/os/src/server/nitpicker/domain_registry.h +++ b/repos/os/src/server/nitpicker/domain_registry.h @@ -44,16 +44,19 @@ class Domain_registry private: - Name _name; - Color _color; - Xray _xray; - Origin _origin; + Name _name; + Color _color; + Xray _xray; + Origin _origin; + unsigned _layer; friend class Domain_registry; - Entry(Name const &name, Color color, Xray xray, Origin origin) + Entry(Name const &name, Color color, Xray xray, Origin origin, + unsigned layer) : - _name(name), _color(color), _xray(xray), _origin(origin) + _name(name), _color(color), _xray(xray), _origin(origin), + _layer(layer) { } public: @@ -62,6 +65,8 @@ class Domain_registry Color color() const { return _color; } + unsigned layer() const { return _layer; } + bool xray_opaque() const { return _xray == XRAY_OPAQUE; } bool xray_no() const { return _xray == XRAY_NO; } bool origin_pointer() const { return _origin == ORIGIN_POINTER; } @@ -126,10 +131,17 @@ class Domain_registry return; } + if (!domain.has_attribute("layer")) { + PERR("no layer specified for domain \"%s\"", name.string()); + return; + } + + unsigned const layer = domain.attribute_value("layer", ~0UL); + Entry::Color const color = domain.attribute_value("color", WHITE); _entries.insert(new (_alloc) Entry(name, color, _xray(domain), - _origin(domain))); + _origin(domain), layer)); } private: diff --git a/repos/os/src/server/nitpicker/main.cc b/repos/os/src/server/nitpicker/main.cc index 793a2d64c..9fb099868 100644 --- a/repos/os/src/server/nitpicker/main.cc +++ b/repos/os/src/server/nitpicker/main.cc @@ -34,10 +34,9 @@ /* local includes */ #include "input.h" -#include "big_mouse.h" #include "background.h" #include "clip_guard.h" -#include "mouse_cursor.h" +#include "pointer_origin.h" #include "chunky_menubar.h" #include "domain_registry.h" @@ -638,11 +637,10 @@ class Nitpicker::Session_component : public Genode::Rpc_object, Framebuffer::Session &framebuffer, int v_offset, bool provides_default_bg, - bool stay_top, Allocator &session_alloc, size_t ram_quota) : - ::Session(label, v_offset, stay_top), + ::Session(label, v_offset), _session_alloc(&session_alloc, ram_quota), _framebuffer(framebuffer), _framebuffer_session_component(view_stack, *this, framebuffer, *this), @@ -729,7 +727,6 @@ class Nitpicker::Session_component : public Genode::Rpc_object, view = new (_view_alloc) View(*this, - stay_top() ? View::STAY_TOP : View::NOT_STAY_TOP, View::NOT_TRANSPARENT, View::NOT_BACKGROUND, &(*parent)); @@ -748,7 +745,6 @@ class Nitpicker::Session_component : public Genode::Rpc_object, try { view = new (_view_alloc) View(*this, - stay_top() ? View::STAY_TOP : View::NOT_STAY_TOP, View::NOT_TRANSPARENT, View::NOT_BACKGROUND, nullptr); } @@ -921,8 +917,6 @@ class Nitpicker::Root : public Genode::Root_component int const v_offset = _default_v_offset; - bool const stay_top = Arg_string::find_arg(args, "stay_top").bool_value(false); - size_t const required_quota = Input::Session_component::ev_ds_size() + Genode::align_addr(sizeof(Session::Command_buffer), 12); @@ -940,7 +934,7 @@ class Nitpicker::Root : public Genode::Root_component Session_component *session = new (md_alloc()) Session_component(Session_label(args), _view_stack, _mode, _pointer_origin, *ep(), _framebuffer, - v_offset, provides_default_bg, stay_top, + v_offset, provides_default_bg, *md_alloc(), unused_quota); session->apply_session_policy(_domain_registry); @@ -1068,9 +1062,7 @@ struct Nitpicker::Main /* * Create view stack with default elements */ - Area mouse_size { big_mouse.w, big_mouse.h }; - Mouse_cursor mouse_cursor { (PT const *)&big_mouse.pixels[0][0], - mouse_size, user_state }; + Pointer_origin pointer_origin; Background background = { Area(99999, 99999) }; @@ -1080,7 +1072,7 @@ struct Nitpicker::Main Genode::Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() }; Root np_root = { session_list, *domain_registry, global_keys, - ep.rpc_ep(), user_state, user_state, mouse_cursor, + ep.rpc_ep(), user_state, user_state, pointer_origin, sliced_heap, framebuffer, Framebuffer_screen::MENUBAR_HEIGHT }; Genode::Reporter pointer_reporter = { "pointer" }; @@ -1115,9 +1107,9 @@ struct Nitpicker::Main fb_screen->menubar.state(Menubar_state(user_state, "", BLACK)); user_state.default_background(background); - user_state.stack(mouse_cursor); - user_state.stack(fb_screen->menubar); + user_state.stack(pointer_origin); user_state.stack(background); + user_state.stack(fb_screen->menubar); config()->sigh(config_dispatcher); Signal_transmitter(config_dispatcher).submit(); @@ -1144,19 +1136,19 @@ void Nitpicker::Main::handle_input(unsigned) return; do { - Point const old_mouse_pos = user_state.mouse_pos(); + Point const old_pointer_pos = user_state.pointer_pos(); /* handle batch of pending events */ if (input.is_pending()) import_input_events(ev_buf, input.flush(), user_state); - Point const new_mouse_pos = user_state.mouse_pos(); - Point const menubar_offset = Point(0, Framebuffer_screen::MENUBAR_HEIGHT); - Point const report_pos = new_mouse_pos - menubar_offset; + Point const new_pointer_pos = user_state.pointer_pos(); + Point const menubar_offset = Point(0, Framebuffer_screen::MENUBAR_HEIGHT); + Point const report_pos = new_pointer_pos - menubar_offset; /* report mouse-position updates */ - if (pointer_reporter.is_enabled() && old_mouse_pos != new_mouse_pos - && new_mouse_pos.y() >= 0) + if (pointer_reporter.is_enabled() && old_pointer_pos != new_pointer_pos + && new_pointer_pos.y() >= 0) Genode::Reporter::Xml_generator xml(pointer_reporter, [&] () { @@ -1165,8 +1157,8 @@ void Nitpicker::Main::handle_input(unsigned) }); /* update mouse cursor */ - if (old_mouse_pos != new_mouse_pos) - user_state.geometry(mouse_cursor, Rect(new_mouse_pos, mouse_size)); + if (old_pointer_pos != new_pointer_pos) + user_state.geometry(pointer_origin, Rect(new_pointer_pos, Area())); /* perform redraw and flush pixels to the framebuffer */ user_state.draw(fb_screen->screen).flush([&] (Rect const &rect) { @@ -1226,7 +1218,13 @@ void Nitpicker::Main::handle_config(unsigned) for (::Session *s = session_list.first(); s; s = s->next()) s->apply_session_policy(*domain_registry); - user_state.apply_origin_policy(mouse_cursor); + user_state.apply_origin_policy(pointer_origin); + + /* + * Domains may have changed their layering, resort the view stack with the + * new constrains. + */ + user_state.sort_views_by_layer(); /* redraw */ user_state.update_all_views(); @@ -1251,7 +1249,7 @@ void Nitpicker::Main::handle_fb_mode(unsigned) fb_screen->menubar.state(menubar_state); /* re-insert menu bar behind mouse cursor */ - user_state.stack(fb_screen->menubar, &mouse_cursor); + user_state.stack(fb_screen->menubar, &pointer_origin); /* redraw */ user_state.update_all_views(); diff --git a/repos/os/src/server/nitpicker/mouse_cursor.h b/repos/os/src/server/nitpicker/mouse_cursor.h deleted file mode 100644 index 5c5726df4..000000000 --- a/repos/os/src/server/nitpicker/mouse_cursor.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * \brief Nitpicker mouse cursor - * \author Norman Feske - * \date 2006-08-18 - * - * The Nitpicker mouse cursor is implemented as a transparent - * view that stays always in front of all other views. - */ - -/* - * Copyright (C) 2006-2013 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 _MOUSE_CURSOR_H_ -#define _MOUSE_CURSOR_H_ - -#include - -#include "view.h" -#include "session.h" - -template -class Mouse_cursor : public Texture, - public Session, public View -{ - private: - - View_stack const &_view_stack; - - public: - - /** - * Constructor - */ - Mouse_cursor(PT const *pixels, Area size, View_stack const &view_stack) - : - Texture(pixels, 0, size), - Session(Genode::Session_label(""), 0, false), - View(*this, View::STAY_TOP, View::TRANSPARENT, View::NOT_BACKGROUND, 0), - _view_stack(view_stack) - { } - - - /*********************** - ** Session interface ** - ***********************/ - - void submit_input_event(Input::Event) override { } - void submit_sync() override { } - - - /******************** - ** View interface ** - ********************/ - - /* - * The mouse cursor is always displayed without a surrounding frame. - */ - - int frame_size(Mode const &mode) const override { return 0; } - - void frame(Canvas_base &canvas, Mode const &mode) const override { } - - void draw(Canvas_base &canvas, Mode const &mode) const override - { - Rect const view_rect = abs_geometry(); - - Clip_guard clip_guard(canvas, view_rect); - - /* draw area behind the mouse cursor */ - _view_stack.draw_rec(canvas, view_stack_next(), view_rect); - - /* draw mouse cursor */ - canvas.draw_texture(view_rect.p1(), *this, Texture_painter::MASKED, BLACK, true); - } -}; - -#endif diff --git a/repos/os/src/server/nitpicker/pointer_origin.h b/repos/os/src/server/nitpicker/pointer_origin.h new file mode 100644 index 000000000..04a4e5ee8 --- /dev/null +++ b/repos/os/src/server/nitpicker/pointer_origin.h @@ -0,0 +1,46 @@ +/* + * \brief View that represents the origin of the pointer coordinate system + * \author Norman Feske + * \date 2014-07-02 + */ + +/* + * 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 _POINTER_ORIGIN_H_ +#define _POINTER_ORIGIN_H_ + +#include "view.h" +#include "session.h" + +struct Pointer_origin : Session, View +{ + Pointer_origin() + : + Session(Genode::Session_label(""), 0), + View(*this, View::TRANSPARENT, View::NOT_BACKGROUND, 0) + { } + + + /*********************** + ** Session interface ** + ***********************/ + + void submit_input_event(Input::Event) override { } + void submit_sync() override { } + + + /******************** + ** View interface ** + ********************/ + + int frame_size(Mode const &) const override { return 0; } + void frame(Canvas_base &, Mode const &) const override { } + void draw(Canvas_base &, Mode const &) const override { } +}; + +#endif /* _POINTER_ORIGIN_H_ */ diff --git a/repos/os/src/server/nitpicker/session.h b/repos/os/src/server/nitpicker/session.h index 1a0d955ae..f50c4c059 100644 --- a/repos/os/src/server/nitpicker/session.h +++ b/repos/os/src/server/nitpicker/session.h @@ -42,7 +42,6 @@ class Session : public Session_list::Element View *_background = 0; int _v_offset; unsigned char const *_input_mask = { 0 }; - bool const _stay_top; public: @@ -51,11 +50,10 @@ class Session : public Session_list::Element * * \param label session label * \param v_offset vertical screen offset of session - * \param stay_top true for views that stay always in front */ - Session(Genode::Session_label const &label, int v_offset, bool stay_top) + Session(Genode::Session_label const &label, int v_offset) : - _label(label), _v_offset(v_offset), _stay_top(stay_top) + _label(label), _v_offset(v_offset) { } virtual ~Session() { } @@ -72,6 +70,8 @@ class Session : public Session_list::Element bool origin_pointer() const { return _domain && _domain->origin_pointer(); } + unsigned layer() const { return _domain ? _domain->layer() : ~0UL; } + Texture_base const *texture() const { return _texture; } void texture(Texture_base const *texture, bool uses_alpha) @@ -100,8 +100,6 @@ class Session : public Session_list::Element void background(View *background) { _background = background; } - bool stay_top() const { return _stay_top; } - /** * Return true if session uses an alpha channel */ diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 5c4456ebb..ec80c395d 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -71,7 +71,7 @@ void User_state::handle_event(Input::Event ev) /* * Mangle incoming events */ - int ax = _mouse_pos.x(), ay = _mouse_pos.y(); + int ax = _pointer_pos.x(), ay = _pointer_pos.y(); int rx = 0, ry = 0; /* skip info about relative motion by default */ /* transparently handle absolute and relative motion events */ @@ -94,13 +94,13 @@ void User_state::handle_event(Input::Event ev) /* create the mangled event */ ev = Input::Event(type, keycode, ax, ay, rx, ry); - _mouse_pos = Point(ax, ay); + _pointer_pos = Point(ax, ay); /* count keys */ if (type == Event::PRESS) Mode::inc_key_cnt(); if (type == Event::RELEASE && Mode::drag()) Mode::dec_key_cnt(); - View const * const pointed_view = find_view(_mouse_pos); + View const * const pointed_view = find_view(_pointer_pos); ::Session * const pointed_session = pointed_view ? &pointed_view->session() : 0; /* @@ -268,7 +268,7 @@ void User_state::forget(::Session const &session) Mode::forget(session); if (_pointed_session == &session) { - View * const pointed_view = find_view(_mouse_pos); + View * const pointed_view = find_view(_pointer_pos); _pointed_session = pointed_view ? &pointed_view->session() : nullptr; } diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index 7c93b8bc3..d59ac8b8f 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -40,9 +40,9 @@ class User_state : public Mode, public View_stack Menubar &_menubar; /* - * Current mouse cursor position + * Current pointer position */ - Point _mouse_pos; + Point _pointer_pos; /* * Currently pointed-at session @@ -80,7 +80,7 @@ class User_state : public Mode, public View_stack /** * Accessors */ - Point mouse_pos() { return _mouse_pos; } + Point pointer_pos() { return _pointer_pos; } /** * (Re-)apply origin policy to all views diff --git a/repos/os/src/server/nitpicker/view.h b/repos/os/src/server/nitpicker/view.h index 27aaf82c5..469c4b2ce 100644 --- a/repos/os/src/server/nitpicker/view.h +++ b/repos/os/src/server/nitpicker/view.h @@ -76,13 +76,11 @@ class View : public Same_buffer_list_elem, enum { TITLE_LEN = 32 }; /* max.characters of a title */ - enum Stay_top { NOT_STAY_TOP = 0, STAY_TOP = 1 }; enum Transparent { NOT_TRANSPARENT = 0, TRANSPARENT = 1 }; enum Background { NOT_BACKGROUND = 0, BACKGROUND = 1 }; private: - Stay_top const _stay_top; /* keep view always on top */ Transparent const _transparent; /* background is partly visible */ Background _background; /* view is a background view */ @@ -119,10 +117,10 @@ class View : public Same_buffer_list_elem, public: - View(Session &session, Stay_top stay_top, Transparent transparent, + View(Session &session, Transparent transparent, Background bg, View *parent) : - _stay_top(stay_top), _transparent(transparent), _background(bg), + _transparent(transparent), _background(bg), _parent(parent), _session(session) { title(""); } @@ -250,7 +248,6 @@ class View : public Same_buffer_list_elem, bool same_session_as(View const &other) const { return &_session == &other._session; } bool top_level() const { return _parent == 0; } - bool stay_top() const { return _stay_top; } bool transparent() const { return _transparent || _session.uses_alpha(); } bool background() const { return _background; } Rect label_rect() const { return _label_rect; } diff --git a/repos/os/src/server/nitpicker/view_stack.cc b/repos/os/src/server/nitpicker/view_stack.cc index 3abb559a9..20375fb05 100644 --- a/repos/os/src/server/nitpicker/view_stack.cc +++ b/repos/os/src/server/nitpicker/view_stack.cc @@ -15,24 +15,6 @@ #include "clip_guard.h" -/*************** - ** Utilities ** - ***************/ - -/** - * Get last view with the stay_top attribute - * - * \param view first view of the view stack - */ -static View const *last_stay_top_view(View const *view) -{ - for (; view && view->view_stack_next() && view->view_stack_next()->stay_top(); ) - view = view->view_stack_next(); - - return view; -} - - /************************** ** View stack interface ** **************************/ @@ -79,10 +61,9 @@ Rect View_stack::_outline(View const &view) const View const *View_stack::_target_stack_position(View const *neighbor, bool behind) { - /* find target position in view stack */ - View const *cv = last_stay_top_view(_first_view()); + View const *cv = _first_view(); - for ( ; cv; cv = _next_view(*cv)) { + for (; cv; cv = _next_view(*cv)) { /* bring view to front? */ if (behind && !neighbor) @@ -101,7 +82,7 @@ View const *View_stack::_target_stack_position(View const *neighbor, bool behind break; } - return cv ? cv : last_stay_top_view(_first_view()); + return cv ? cv : _first_view(); } @@ -296,6 +277,9 @@ void View_stack::stack(View &view, View const *neighbor, bool behind) _views.remove(&view); _views.insert(&view, _target_stack_position(neighbor, behind)); + /* enforce stacking constrains dictated by domain layers */ + sort_views_by_layer(); + _place_labels(view.abs_geometry()); _mark_view_as_dirty(view, _outline(view)); @@ -336,3 +320,40 @@ void View_stack::remove_view(View const &view, bool redraw) refresh(rect); } + + +void View_stack::sort_views_by_layer() +{ + Genode::List sorted; + + /* last element of the sorted list */ + View_stack_elem *at = nullptr; + + while (_views.first()) { + + /* find view with the lowest layer */ + unsigned lowest_layer = ~0UL; + View_stack_elem *lowest_view = nullptr; + for (View_stack_elem *v = _views.first(); v; v = v->next()) { + unsigned const layer = static_cast(v)->session().layer(); + if (layer < lowest_layer) { + lowest_layer = layer; + lowest_view = v; + } + } + + if (!lowest_view) + lowest_view = _views.first(); + + /* + * Move lowest view from unsorted list to the end of the sorted + * list. + */ + _views.remove(lowest_view); + sorted.insert(lowest_view, at); + at = lowest_view; + } + + /* replace empty source list by newly sorted list */ + _views = sorted; +} diff --git a/repos/os/src/server/nitpicker/view_stack.h b/repos/os/src/server/nitpicker/view_stack.h index e079ef53e..9db3ac73d 100644 --- a/repos/os/src/server/nitpicker/view_stack.h +++ b/repos/os/src/server/nitpicker/view_stack.h @@ -262,6 +262,8 @@ class View_stack for (View *v = _first_view(); v; v = v->view_stack_next()) v->apply_origin_policy(pointer_origin); } + + void sort_views_by_layer(); }; #endif