nitpicker: Domain-specific coordinate constraints

This patch introduces a way to tweak the coordinate systems per
domain. The 'origin' attribute denotes the origin of the coordinate
system. Valid values are "top_left", "top_right", "bottom_left",
"bottom_right", and "pointer". Furthermore, the screen dimensions as
reported to the nitpicker client can be tweaked per domain using the
'width' and 'height' attributes. If the specified value is positive,
it is taken as literal boundary. If the value is negative, the size
if deducted by the specified amount from the physical screen area.
This commit is contained in:
Norman Feske 2014-07-08 16:19:21 +02:00
parent 1745453315
commit 6a237a6c55
6 changed files with 99 additions and 44 deletions

View File

@ -30,7 +30,7 @@ struct Background : private Texture_base, Session, View
*/
Background(Area size)
:
Texture_base(Area(0, 0)), Session(Genode::Session_label(""), 0),
Texture_base(Area(0, 0)), Session(Genode::Session_label("")),
View(*this, View::NOT_TRANSPARENT, View::BACKGROUND, 0),
color(25, 37, 50)
{

View File

@ -35,7 +35,7 @@ class Chunky_menubar : public Texture<PT>,
Chunky_menubar(PT *pixels, Area size)
:
Texture<PT>(pixels, 0, size),
Session(Genode::Session_label(""), 0),
Session(Genode::Session_label("")),
View(*this, View::NOT_TRANSPARENT, View::NOT_BACKGROUND, 0),
_canvas(pixels, size)
{

View File

@ -40,7 +40,12 @@ class Domain_registry
/**
* Origin of the domain's coordiate system
*/
enum Origin { ORIGIN_POINTER, ORIGIN_SCREEN };
enum Origin {
ORIGIN_POINTER,
ORIGIN_TOP_LEFT,
ORIGIN_TOP_RIGHT,
ORIGIN_BOTTOM_LEFT,
ORIGIN_BOTTOM_RIGHT };
private:
@ -49,16 +54,31 @@ class Domain_registry
Xray _xray;
Origin _origin;
unsigned _layer;
Point _offset;
Point _area;
friend class Domain_registry;
Entry(Name const &name, Color color, Xray xray, Origin origin,
unsigned layer)
unsigned layer, Point offset, Point area)
:
_name(name), _color(color), _xray(xray), _origin(origin),
_layer(layer)
_layer(layer), _offset(offset), _area(area)
{ }
Point _corner(Area screen_area) const
{
switch (_origin) {
case ORIGIN_POINTER: return Point(0, 0);
case ORIGIN_TOP_LEFT: return Point(0, 0);
case ORIGIN_TOP_RIGHT: return Point(screen_area.w(), 0);
case ORIGIN_BOTTOM_LEFT: return Point(0, screen_area.h());
case ORIGIN_BOTTOM_RIGHT: return Point(screen_area.w(),
screen_area.h());
}
return Point(0, 0);
}
public:
bool has_name(Name const &name) const { return name == _name; }
@ -70,6 +90,24 @@ class Domain_registry
bool xray_opaque() const { return _xray == XRAY_OPAQUE; }
bool xray_no() const { return _xray == XRAY_NO; }
bool origin_pointer() const { return _origin == ORIGIN_POINTER; }
Point phys_pos(Point pos, Area screen_area) const
{
return pos + _corner(screen_area) + _offset;
}
Area screen_area(Area phys_screen_area) const
{
int const w = _area.x() > 0
? _area.x()
: Genode::max(0, (int)phys_screen_area.w() + _area.x());
int const h = _area.y() > 0
? _area.y()
: Genode::max(0, (int)phys_screen_area.h() + _area.y());
return Area(w, h);
}
};
static Entry::Xray _xray(Genode::Xml_node domain)
@ -95,15 +133,18 @@ class Domain_registry
{
char const * const attr_name = "origin";
Entry::Origin const default_origin = Entry::ORIGIN_SCREEN;
Entry::Origin const default_origin = Entry::ORIGIN_TOP_LEFT;
if (!domain.has_attribute(attr_name))
return default_origin;
Genode::Xml_node::Attribute const attr = domain.attribute(attr_name);
if (attr.has_value("screen")) return Entry::ORIGIN_SCREEN;
if (attr.has_value("pointer")) return Entry::ORIGIN_POINTER;
if (attr.has_value("top_left")) return Entry::ORIGIN_TOP_LEFT;
if (attr.has_value("top_right")) return Entry::ORIGIN_TOP_RIGHT;
if (attr.has_value("bottom_left")) return Entry::ORIGIN_BOTTOM_LEFT;
if (attr.has_value("bottom_right")) return Entry::ORIGIN_BOTTOM_RIGHT;
if (attr.has_value("pointer")) return Entry::ORIGIN_POINTER;
PWRN("invalid value of origin attribute");
return default_origin;
@ -138,10 +179,16 @@ class Domain_registry
unsigned const layer = domain.attribute_value("layer", ~0UL);
Point const offset(domain.attribute_value("xpos", 0L),
domain.attribute_value("ypos", 0L));
Point const area(domain.attribute_value("width", 0L),
domain.attribute_value("height", 0L));
Entry::Color const color = domain.attribute_value("color", WHITE);
_entries.insert(new (_alloc) Entry(name, color, _xray(domain),
_origin(domain), layer));
_origin(domain), layer, offset, area));
}
private:

View File

@ -505,9 +505,9 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
Point pos = command.geometry.rect.p1();
/* transpose y position of top-level views by vertical session offset */
/* transpose position of top-level views by vertical session offset */
if (view->top_level())
pos = pos + Point(0, v_offset());
pos = ::Session::phys_pos(pos, _view_stack.size());
if (view.is_valid())
_view_stack.geometry(*view, Rect(pos, command.geometry.rect.area()));
@ -635,12 +635,11 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
View &pointer_origin,
Rpc_entrypoint &ep,
Framebuffer::Session &framebuffer,
int v_offset,
bool provides_default_bg,
Allocator &session_alloc,
size_t ram_quota)
:
::Session(label, v_offset),
::Session(label),
_session_alloc(&session_alloc, ram_quota),
_framebuffer(framebuffer),
_framebuffer_session_component(view_stack, *this, framebuffer, *this),
@ -684,13 +683,18 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
{
using namespace Input;
Point const origin_offset =
::Session::phys_pos(Point(0, 0), _view_stack.size());
/*
* Transpose absolute coordinates by session-specific vertical
* offset.
*/
if (e.ax() || e.ay())
e = Event(e.type(), e.code(), e.ax(),
Genode::max(0, e.ay() - v_offset()), e.rx(), e.ry());
e = Event(e.type(), e.code(),
Genode::max(0, e.ax() - origin_offset.x()),
Genode::max(0, e.ay() - origin_offset.y()),
e.rx(), e.ry());
_input_session_component.submit(&e);
}
@ -821,11 +825,12 @@ class Nitpicker::Session_component : public Genode::Rpc_object<Session>,
Framebuffer::Mode mode() override
{
unsigned const width = _framebuffer.mode().width();
unsigned const height = _framebuffer.mode().height()
- ::Session::v_offset();
Area const phys_area(_framebuffer.mode().width(),
_framebuffer.mode().height());
return Framebuffer::Mode(width, height,
Area const session_area = ::Session::screen_area(phys_area);
return Framebuffer::Mode(session_area.w(), session_area.h(),
_framebuffer.mode().format());
}
@ -906,7 +911,6 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
Mode &_mode;
::View &_pointer_origin;
Framebuffer::Session &_framebuffer;
int _default_v_offset;
protected:
@ -915,8 +919,6 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
PINF("create session with args: %s\n", args);
size_t const ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
int const v_offset = _default_v_offset;
size_t const required_quota = Input::Session_component::ev_ds_size()
+ Genode::align_addr(sizeof(Session::Command_buffer), 12);
@ -934,8 +936,7 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
Session_component *session = new (md_alloc())
Session_component(Session_label(args), _view_stack, _mode,
_pointer_origin, *ep(), _framebuffer,
v_offset, provides_default_bg,
*md_alloc(), unused_quota);
provides_default_bg, *md_alloc(), unused_quota);
session->apply_session_policy(_domain_registry);
_session_list.insert(session);
@ -970,13 +971,12 @@ class Nitpicker::Root : public Genode::Root_component<Session_component>
Domain_registry const &domain_registry, Global_keys &global_keys,
Rpc_entrypoint &session_ep, View_stack &view_stack, Mode &mode,
::View &pointer_origin, Allocator &md_alloc,
Framebuffer::Session &framebuffer, int default_v_offset)
Framebuffer::Session &framebuffer)
:
Root_component<Session_component>(&session_ep, &md_alloc),
_session_list(session_list), _domain_registry(domain_registry),
_global_keys(global_keys), _view_stack(view_stack), _mode(mode),
_pointer_origin(pointer_origin), _framebuffer(framebuffer),
_default_v_offset(default_v_offset)
_pointer_origin(pointer_origin), _framebuffer(framebuffer)
{ }
};
@ -1073,7 +1073,7 @@ struct Nitpicker::Main
Root<PT> np_root = { session_list, *domain_registry, global_keys,
ep.rpc_ep(), user_state, user_state, pointer_origin,
sliced_heap, framebuffer, Framebuffer_screen::MENUBAR_HEIGHT };
sliced_heap, framebuffer };
Genode::Reporter pointer_reporter = { "pointer" };
@ -1143,17 +1143,14 @@ void Nitpicker::Main::handle_input(unsigned)
import_input_events(ev_buf, input.flush(), user_state);
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_pointer_pos != new_pointer_pos
&& new_pointer_pos.y() >= 0)
if (pointer_reporter.is_enabled() && old_pointer_pos != new_pointer_pos)
Genode::Reporter::Xml_generator xml(pointer_reporter, [&] ()
{
xml.attribute("xpos", report_pos.x());
xml.attribute("ypos", report_pos.y());
xml.attribute("xpos", new_pointer_pos.x());
xml.attribute("ypos", new_pointer_pos.y());
});
/* update mouse cursor */

View File

@ -21,7 +21,7 @@ struct Pointer_origin : Session, View
{
Pointer_origin()
:
Session(Genode::Session_label(""), 0),
Session(Genode::Session_label("")),
View(*this, View::TRANSPARENT, View::NOT_BACKGROUND, 0)
{ }

View File

@ -40,7 +40,6 @@ class Session : public Session_list::Element
Texture_base const *_texture = { 0 };
bool _uses_alpha = { false };
View *_background = 0;
int _v_offset;
unsigned char const *_input_mask = { 0 };
public:
@ -48,13 +47,9 @@ class Session : public Session_list::Element
/**
* Constructor
*
* \param label session label
* \param v_offset vertical screen offset of session
* \param label session label
*/
Session(Genode::Session_label const &label, int v_offset)
:
_label(label), _v_offset(v_offset)
{ }
explicit Session(Genode::Session_label const &label) : _label(label) { }
virtual ~Session() { }
@ -106,9 +101,25 @@ class Session : public Session_list::Element
bool uses_alpha() const { return _texture && _uses_alpha; }
/**
* Return vertical offset of session
* Calculate session-local coordinate to physical screen position
*
* \param pos coordinate in session-local coordinate system
* \param screen_area session-local screen size
*/
int v_offset() const { return _v_offset; }
Point phys_pos(Point pos, Area screen_area) const
{
return _domain ? _domain->phys_pos(pos, screen_area) : Point(0, 0);
}
/**
* Return session-local screen area
*
* \param phys_pos size of physical screen
*/
Area screen_area(Area phys_area) const
{
return _domain ? _domain->screen_area(phys_area) : Area(0, 0);
}
/**
* Return input mask value at specified buffer position