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:
parent
6c4c4e5528
commit
1745453315
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
66
repos/os/src/app/pointer/main.cc
Normal file
66
repos/os/src/app/pointer/main.cc
Normal 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();
|
||||||
|
}
|
3
repos/os/src/app/pointer/target.mk
Normal file
3
repos/os/src/app/pointer/target.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
TARGET = pointer
|
||||||
|
SRC_CC = main.cc
|
||||||
|
LIBS += base
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
|
46
repos/os/src/server/nitpicker/pointer_origin.h
Normal file
46
repos/os/src/server/nitpicker/pointer_origin.h
Normal 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_ */
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user