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.
This commit is contained in:
Norman Feske 2014-07-02 22:00:15 +02:00
parent 6c4c4e5528
commit 1745453315
17 changed files with 233 additions and 168 deletions

View File

@ -34,7 +34,7 @@ class Nitpicker::Connection : public Genode::Connection<Session>,
/** /**
* Create session and return typed session capability * 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 }; enum { ARGBUF_SIZE = 128 };
char argbuf[ARGBUF_SIZE]; char argbuf[ARGBUF_SIZE];
@ -50,9 +50,6 @@ class Nitpicker::Connection : public Genode::Connection<Session>,
enum { SESSION_METADATA = 36*1024 }; enum { SESSION_METADATA = 36*1024 };
Arg_string::set_arg(argbuf, sizeof(argbuf), "ram_quota", SESSION_METADATA); 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); return session(argbuf);
} }
@ -61,10 +58,10 @@ class Nitpicker::Connection : public Genode::Connection<Session>,
/** /**
* Constructor * Constructor
*/ */
Connection(bool stay_top = false, char const *label = "") Connection(char const *label = "")
: :
/* establish nitpicker session */ /* establish nitpicker session */
Genode::Connection<Session>(_connect(stay_top, label)), Genode::Connection<Session>(_connect(label)),
Session_client(cap()), Session_client(cap()),
/* request frame-buffer and input sub sessions */ /* request frame-buffer and input sub sessions */

View File

@ -5,7 +5,8 @@
set build_components { set build_components {
core init core init
drivers/timer 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 test/nitpicker server/nitlog
drivers/framebuffer drivers/pci drivers/input drivers/framebuffer drivers/pci drivers/input
} }
@ -119,8 +120,11 @@ append config {
<resource name="RAM" quantum="1M"/> <resource name="RAM" quantum="1M"/>
<provides><service name="Nitpicker"/></provides> <provides><service name="Nitpicker"/></provides>
<config> <config>
<domain name="default" color="#ffffff"/> <domain name="pointer" layer="1" xray="no" origin="pointer" />
<policy label="" domain="default"/> <domain name="default" layer="2" />
<policy label="pointer" domain="pointer"/>
<policy label="" domain="default"/>
<global-key name="KEY_SCROLLLOCK" operation="xray" /> <global-key name="KEY_SCROLLLOCK" operation="xray" />
<global-key name="KEY_SYSRQ" operation="kill" /> <global-key name="KEY_SYSRQ" operation="kill" />
@ -129,6 +133,9 @@ append config {
<global-key name="KEY_F12" operation="xray" /> <global-key name="KEY_F12" operation="xray" />
</config> </config>
</start> </start>
<start name="pointer">
<resource name="RAM" quantum="1M"/>
</start>
<start name="launchpad"> <start name="launchpad">
<resource name="RAM" quantum="64M" /> <resource name="RAM" quantum="64M" />
<configfile name="launchpad.config" /> <configfile name="launchpad.config" />
@ -163,7 +170,7 @@ close $launchpad_config_fd
set boot_modules { set boot_modules {
core init core init
timer timer
nitpicker liquid_fb launchpad scout nitpicker pointer liquid_fb launchpad scout
testnit nitlog testnit nitlog
launchpad.config launchpad.config
} }

View File

@ -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 <nitpicker_session/connection.h>
#include <os/surface.h>
#include <os/pixel_rgb565.h>
#include <os/attached_dataspace.h>
#include <base/sleep.h>
/* local includes */
#include "big_mouse.h"
template <typename PT>
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<Genode::Pixel_rgb565>(), cursor_size);
Nitpicker::Session::View_handle view = nitpicker.create_view();
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), cursor_size);
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
nitpicker.enqueue<Nitpicker::Session::Command::To_front>(view);
nitpicker.execute();
Genode::sleep_forever();
}

View File

@ -0,0 +1,3 @@
TARGET = pointer
SRC_CC = main.cc
LIBS += base

View File

@ -30,8 +30,8 @@ struct Background : private Texture_base, Session, View
*/ */
Background(Area size) Background(Area size)
: :
Texture_base(Area(0, 0)), Session(Genode::Session_label(""), 0, false), Texture_base(Area(0, 0)), Session(Genode::Session_label(""), 0),
View(*this, View::NOT_STAY_TOP, View::NOT_TRANSPARENT, View::BACKGROUND, 0), View(*this, View::NOT_TRANSPARENT, View::BACKGROUND, 0),
color(25, 37, 50) color(25, 37, 50)
{ {
View::geometry(Rect(Point(0, 0), size)); View::geometry(Rect(Point(0, 0), size));

View File

@ -35,9 +35,8 @@ class Chunky_menubar : public Texture<PT>,
Chunky_menubar(PT *pixels, Area size) Chunky_menubar(PT *pixels, Area size)
: :
Texture<PT>(pixels, 0, size), Texture<PT>(pixels, 0, size),
Session(Genode::Session_label(""), 0, false), Session(Genode::Session_label(""), 0),
View(*this, View::STAY_TOP, View::NOT_TRANSPARENT, View(*this, View::NOT_TRANSPARENT, View::NOT_BACKGROUND, 0),
View::NOT_BACKGROUND, 0),
_canvas(pixels, size) _canvas(pixels, size)
{ {
View::geometry(Rect(Point(0, 0), size)); View::geometry(Rect(Point(0, 0), size));

View File

@ -44,16 +44,19 @@ class Domain_registry
private: private:
Name _name; Name _name;
Color _color; Color _color;
Xray _xray; Xray _xray;
Origin _origin; Origin _origin;
unsigned _layer;
friend class Domain_registry; 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: public:
@ -62,6 +65,8 @@ class Domain_registry
Color color() const { return _color; } Color color() const { return _color; }
unsigned layer() const { return _layer; }
bool xray_opaque() const { return _xray == XRAY_OPAQUE; } bool xray_opaque() const { return _xray == XRAY_OPAQUE; }
bool xray_no() const { return _xray == XRAY_NO; } bool xray_no() const { return _xray == XRAY_NO; }
bool origin_pointer() const { return _origin == ORIGIN_POINTER; } bool origin_pointer() const { return _origin == ORIGIN_POINTER; }
@ -126,10 +131,17 @@ class Domain_registry
return; 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); Entry::Color const color = domain.attribute_value("color", WHITE);
_entries.insert(new (_alloc) Entry(name, color, _xray(domain), _entries.insert(new (_alloc) Entry(name, color, _xray(domain),
_origin(domain))); _origin(domain), layer));
} }
private: private:

View File

@ -34,10 +34,9 @@
/* local includes */ /* local includes */
#include "input.h" #include "input.h"
#include "big_mouse.h"
#include "background.h" #include "background.h"
#include "clip_guard.h" #include "clip_guard.h"
#include "mouse_cursor.h" #include "pointer_origin.h"
#include "chunky_menubar.h" #include "chunky_menubar.h"
#include "domain_registry.h" #include "domain_registry.h"
@ -638,11 +637,10 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
Framebuffer::Session &framebuffer, Framebuffer::Session &framebuffer,
int v_offset, int v_offset,
bool provides_default_bg, bool provides_default_bg,
bool stay_top,
Allocator &session_alloc, Allocator &session_alloc,
size_t ram_quota) size_t ram_quota)
: :
::Session(label, v_offset, stay_top), ::Session(label, v_offset),
_session_alloc(&session_alloc, ram_quota), _session_alloc(&session_alloc, ram_quota),
_framebuffer(framebuffer), _framebuffer(framebuffer),
_framebuffer_session_component(view_stack, *this, framebuffer, *this), _framebuffer_session_component(view_stack, *this, framebuffer, *this),
@ -729,7 +727,6 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
view = new (_view_alloc) view = new (_view_alloc)
View(*this, View(*this,
stay_top() ? View::STAY_TOP : View::NOT_STAY_TOP,
View::NOT_TRANSPARENT, View::NOT_BACKGROUND, View::NOT_TRANSPARENT, View::NOT_BACKGROUND,
&(*parent)); &(*parent));
@ -748,7 +745,6 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
try { try {
view = new (_view_alloc) view = new (_view_alloc)
View(*this, View(*this,
stay_top() ? View::STAY_TOP : View::NOT_STAY_TOP,
View::NOT_TRANSPARENT, View::NOT_BACKGROUND, View::NOT_TRANSPARENT, View::NOT_BACKGROUND,
nullptr); nullptr);
} }
@ -921,8 +917,6 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
int const v_offset = _default_v_offset; 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() size_t const required_quota = Input::Session_component::ev_ds_size()
+ Genode::align_addr(sizeof(Session::Command_buffer), 12); + Genode::align_addr(sizeof(Session::Command_buffer), 12);
@ -940,7 +934,7 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
Session_component *session = new (md_alloc()) Session_component *session = new (md_alloc())
Session_component(Session_label(args), _view_stack, _mode, Session_component(Session_label(args), _view_stack, _mode,
_pointer_origin, *ep(), _framebuffer, _pointer_origin, *ep(), _framebuffer,
v_offset, provides_default_bg, stay_top, v_offset, provides_default_bg,
*md_alloc(), unused_quota); *md_alloc(), unused_quota);
session->apply_session_policy(_domain_registry); session->apply_session_policy(_domain_registry);
@ -1068,9 +1062,7 @@ struct Nitpicker::Main
/* /*
* Create view stack with default elements * Create view stack with default elements
*/ */
Area mouse_size { big_mouse.w, big_mouse.h }; Pointer_origin pointer_origin;
Mouse_cursor<PT const> mouse_cursor { (PT const *)&big_mouse.pixels[0][0],
mouse_size, user_state };
Background background = { Area(99999, 99999) }; Background background = { Area(99999, 99999) };
@ -1080,7 +1072,7 @@ struct Nitpicker::Main
Genode::Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() }; Genode::Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() };
Root<PT> np_root = { session_list, *domain_registry, global_keys, Root<PT> 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 }; sliced_heap, framebuffer, Framebuffer_screen::MENUBAR_HEIGHT };
Genode::Reporter pointer_reporter = { "pointer" }; Genode::Reporter pointer_reporter = { "pointer" };
@ -1115,9 +1107,9 @@ struct Nitpicker::Main
fb_screen->menubar.state(Menubar_state(user_state, "", BLACK)); fb_screen->menubar.state(Menubar_state(user_state, "", BLACK));
user_state.default_background(background); user_state.default_background(background);
user_state.stack(mouse_cursor); user_state.stack(pointer_origin);
user_state.stack(fb_screen->menubar);
user_state.stack(background); user_state.stack(background);
user_state.stack(fb_screen->menubar);
config()->sigh(config_dispatcher); config()->sigh(config_dispatcher);
Signal_transmitter(config_dispatcher).submit(); Signal_transmitter(config_dispatcher).submit();
@ -1144,19 +1136,19 @@ void Nitpicker::Main::handle_input(unsigned)
return; return;
do { do {
Point const old_mouse_pos = user_state.mouse_pos(); Point const old_pointer_pos = user_state.pointer_pos();
/* handle batch of pending events */ /* handle batch of pending events */
if (input.is_pending()) if (input.is_pending())
import_input_events(ev_buf, input.flush(), user_state); import_input_events(ev_buf, input.flush(), user_state);
Point const new_mouse_pos = user_state.mouse_pos(); Point const new_pointer_pos = user_state.pointer_pos();
Point const menubar_offset = Point(0, Framebuffer_screen::MENUBAR_HEIGHT); Point const menubar_offset = Point(0, Framebuffer_screen::MENUBAR_HEIGHT);
Point const report_pos = new_mouse_pos - menubar_offset; Point const report_pos = new_pointer_pos - menubar_offset;
/* report mouse-position updates */ /* report mouse-position updates */
if (pointer_reporter.is_enabled() && old_mouse_pos != new_mouse_pos if (pointer_reporter.is_enabled() && old_pointer_pos != new_pointer_pos
&& new_mouse_pos.y() >= 0) && new_pointer_pos.y() >= 0)
Genode::Reporter::Xml_generator xml(pointer_reporter, [&] () Genode::Reporter::Xml_generator xml(pointer_reporter, [&] ()
{ {
@ -1165,8 +1157,8 @@ void Nitpicker::Main::handle_input(unsigned)
}); });
/* update mouse cursor */ /* update mouse cursor */
if (old_mouse_pos != new_mouse_pos) if (old_pointer_pos != new_pointer_pos)
user_state.geometry(mouse_cursor, Rect(new_mouse_pos, mouse_size)); user_state.geometry(pointer_origin, Rect(new_pointer_pos, Area()));
/* perform redraw and flush pixels to the framebuffer */ /* perform redraw and flush pixels to the framebuffer */
user_state.draw(fb_screen->screen).flush([&] (Rect const &rect) { 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()) for (::Session *s = session_list.first(); s; s = s->next())
s->apply_session_policy(*domain_registry); 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 */ /* redraw */
user_state.update_all_views(); user_state.update_all_views();
@ -1251,7 +1249,7 @@ void Nitpicker::Main::handle_fb_mode(unsigned)
fb_screen->menubar.state(menubar_state); fb_screen->menubar.state(menubar_state);
/* re-insert menu bar behind mouse cursor */ /* re-insert menu bar behind mouse cursor */
user_state.stack(fb_screen->menubar, &mouse_cursor); user_state.stack(fb_screen->menubar, &pointer_origin);
/* redraw */ /* redraw */
user_state.update_all_views(); user_state.update_all_views();

View File

@ -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 <nitpicker_gfx/texture_painter.h>
#include "view.h"
#include "session.h"
template <typename PT>
class Mouse_cursor : public Texture<PT>,
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<PT>(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

View File

@ -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_ */

View File

@ -42,7 +42,6 @@ class Session : public Session_list::Element
View *_background = 0; View *_background = 0;
int _v_offset; int _v_offset;
unsigned char const *_input_mask = { 0 }; unsigned char const *_input_mask = { 0 };
bool const _stay_top;
public: public:
@ -51,11 +50,10 @@ class Session : public Session_list::Element
* *
* \param label session label * \param label session label
* \param v_offset vertical screen offset of session * \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() { } virtual ~Session() { }
@ -72,6 +70,8 @@ class Session : public Session_list::Element
bool origin_pointer() const { return _domain && _domain->origin_pointer(); } bool origin_pointer() const { return _domain && _domain->origin_pointer(); }
unsigned layer() const { return _domain ? _domain->layer() : ~0UL; }
Texture_base const *texture() const { return _texture; } Texture_base const *texture() const { return _texture; }
void texture(Texture_base const *texture, bool uses_alpha) 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; } void background(View *background) { _background = background; }
bool stay_top() const { return _stay_top; }
/** /**
* Return true if session uses an alpha channel * Return true if session uses an alpha channel
*/ */

View File

@ -71,7 +71,7 @@ void User_state::handle_event(Input::Event ev)
/* /*
* Mangle incoming events * 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 */ int rx = 0, ry = 0; /* skip info about relative motion by default */
/* transparently handle absolute and relative motion events */ /* transparently handle absolute and relative motion events */
@ -94,13 +94,13 @@ void User_state::handle_event(Input::Event ev)
/* create the mangled event */ /* create the mangled event */
ev = Input::Event(type, keycode, ax, ay, rx, ry); ev = Input::Event(type, keycode, ax, ay, rx, ry);
_mouse_pos = Point(ax, ay); _pointer_pos = Point(ax, ay);
/* count keys */ /* count keys */
if (type == Event::PRESS) Mode::inc_key_cnt(); if (type == Event::PRESS) Mode::inc_key_cnt();
if (type == Event::RELEASE && Mode::drag()) Mode::dec_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; ::Session * const pointed_session = pointed_view ? &pointed_view->session() : 0;
/* /*
@ -268,7 +268,7 @@ void User_state::forget(::Session const &session)
Mode::forget(session); Mode::forget(session);
if (_pointed_session == &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; _pointed_session = pointed_view ? &pointed_view->session() : nullptr;
} }

View File

@ -40,9 +40,9 @@ class User_state : public Mode, public View_stack
Menubar &_menubar; Menubar &_menubar;
/* /*
* Current mouse cursor position * Current pointer position
*/ */
Point _mouse_pos; Point _pointer_pos;
/* /*
* Currently pointed-at session * Currently pointed-at session
@ -80,7 +80,7 @@ class User_state : public Mode, public View_stack
/** /**
* Accessors * Accessors
*/ */
Point mouse_pos() { return _mouse_pos; } Point pointer_pos() { return _pointer_pos; }
/** /**
* (Re-)apply origin policy to all views * (Re-)apply origin policy to all views

View File

@ -76,13 +76,11 @@ class View : public Same_buffer_list_elem,
enum { TITLE_LEN = 32 }; /* max.characters of a title */ 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 Transparent { NOT_TRANSPARENT = 0, TRANSPARENT = 1 };
enum Background { NOT_BACKGROUND = 0, BACKGROUND = 1 }; enum Background { NOT_BACKGROUND = 0, BACKGROUND = 1 };
private: private:
Stay_top const _stay_top; /* keep view always on top */
Transparent const _transparent; /* background is partly visible */ Transparent const _transparent; /* background is partly visible */
Background _background; /* view is a background view */ Background _background; /* view is a background view */
@ -119,10 +117,10 @@ class View : public Same_buffer_list_elem,
public: public:
View(Session &session, Stay_top stay_top, Transparent transparent, View(Session &session, Transparent transparent,
Background bg, View *parent) Background bg, View *parent)
: :
_stay_top(stay_top), _transparent(transparent), _background(bg), _transparent(transparent), _background(bg),
_parent(parent), _session(session) _parent(parent), _session(session)
{ title(""); } { 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 same_session_as(View const &other) const { return &_session == &other._session; }
bool top_level() const { return _parent == 0; } bool top_level() const { return _parent == 0; }
bool stay_top() const { return _stay_top; }
bool transparent() const { return _transparent || _session.uses_alpha(); } bool transparent() const { return _transparent || _session.uses_alpha(); }
bool background() const { return _background; } bool background() const { return _background; }
Rect label_rect() const { return _label_rect; } Rect label_rect() const { return _label_rect; }

View File

@ -15,24 +15,6 @@
#include "clip_guard.h" #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 ** ** 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) View const *View_stack::_target_stack_position(View const *neighbor, bool behind)
{ {
/* find target position in view stack */ View const *cv = _first_view();
View const *cv = last_stay_top_view(_first_view());
for ( ; cv; cv = _next_view(*cv)) { for (; cv; cv = _next_view(*cv)) {
/* bring view to front? */ /* bring view to front? */
if (behind && !neighbor) if (behind && !neighbor)
@ -101,7 +82,7 @@ View const *View_stack::_target_stack_position(View const *neighbor, bool behind
break; 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.remove(&view);
_views.insert(&view, _target_stack_position(neighbor, behind)); _views.insert(&view, _target_stack_position(neighbor, behind));
/* enforce stacking constrains dictated by domain layers */
sort_views_by_layer();
_place_labels(view.abs_geometry()); _place_labels(view.abs_geometry());
_mark_view_as_dirty(view, _outline(view)); _mark_view_as_dirty(view, _outline(view));
@ -336,3 +320,40 @@ void View_stack::remove_view(View const &view, bool redraw)
refresh(rect); refresh(rect);
} }
void View_stack::sort_views_by_layer()
{
Genode::List<View_stack_elem> 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<View *>(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;
}

View File

@ -262,6 +262,8 @@ class View_stack
for (View *v = _first_view(); v; v = v->view_stack_next()) for (View *v = _first_view(); v; v = v->view_stack_next())
v->apply_origin_policy(pointer_origin); v->apply_origin_policy(pointer_origin);
} }
void sort_views_by_layer();
}; };
#endif #endif