2014-06-13 09:37:34 +00:00
|
|
|
/*
|
|
|
|
* \brief Domain registry
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2014-06-12
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Genode Labs GmbH
|
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _DOMAIN_REGISTRY_
|
|
|
|
#define _DOMAIN_REGISTRY_
|
|
|
|
|
|
|
|
#include <util/xml_node.h>
|
|
|
|
#include <util/color.h>
|
|
|
|
|
|
|
|
class Domain_registry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
class Entry : public Genode::List<Entry>::Element
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
typedef Genode::String<64> Name;
|
|
|
|
typedef Genode::Color Color;
|
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
enum Label { LABEL_NO, LABEL_YES };
|
|
|
|
enum Content { CONTENT_CLIENT, CONTENT_TINTED };
|
|
|
|
enum Hover { HOVER_FOCUSED, HOVER_ALWAYS };
|
|
|
|
enum Focus { FOCUS_NONE, FOCUS_CLICK, FOCUS_TRANSIENT };
|
2014-06-19 10:42:24 +00:00
|
|
|
|
2014-07-02 15:37:02 +00:00
|
|
|
/**
|
|
|
|
* Origin of the domain's coordiate system
|
|
|
|
*/
|
2014-07-08 14:19:21 +00:00
|
|
|
enum Origin {
|
|
|
|
ORIGIN_POINTER,
|
|
|
|
ORIGIN_TOP_LEFT,
|
|
|
|
ORIGIN_TOP_RIGHT,
|
|
|
|
ORIGIN_BOTTOM_LEFT,
|
|
|
|
ORIGIN_BOTTOM_RIGHT };
|
2014-07-02 15:37:02 +00:00
|
|
|
|
2014-06-13 09:37:34 +00:00
|
|
|
private:
|
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
Name _name;
|
|
|
|
Color _color;
|
|
|
|
Label _label;
|
|
|
|
Content _content;
|
|
|
|
Hover _hover;
|
|
|
|
Focus _focus;
|
|
|
|
Origin _origin;
|
|
|
|
unsigned _layer;
|
|
|
|
Point _offset;
|
|
|
|
Point _area;
|
2014-06-13 09:37:34 +00:00
|
|
|
|
|
|
|
friend class Domain_registry;
|
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
Entry(Name const &name, Color color, Label label,
|
|
|
|
Content content, Hover hover, Focus focus,
|
|
|
|
Origin origin, unsigned layer, Point offset, Point area)
|
2014-06-13 09:37:34 +00:00
|
|
|
:
|
2015-09-30 09:30:02 +00:00
|
|
|
_name(name), _color(color), _label(label),
|
|
|
|
_content(content), _hover(hover), _focus(focus),
|
|
|
|
_origin(origin), _layer(layer), _offset(offset), _area(area)
|
2014-06-13 09:37:34 +00:00
|
|
|
{ }
|
|
|
|
|
2014-07-08 14:19:21 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-06-13 09:37:34 +00:00
|
|
|
public:
|
|
|
|
|
|
|
|
bool has_name(Name const &name) const { return name == _name; }
|
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
Name name() const { return _name; }
|
|
|
|
Color color() const { return _color; }
|
|
|
|
unsigned layer() const { return _layer; }
|
|
|
|
Content content() const { return _content; }
|
|
|
|
Hover hover() const { return _hover; }
|
2014-07-02 20:00:15 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
bool label_visible() const { return _label == LABEL_YES; }
|
|
|
|
bool content_client() const { return _content == CONTENT_CLIENT; }
|
|
|
|
bool hover_focused() const { return _hover == HOVER_FOCUSED; }
|
|
|
|
bool hover_always() const { return _hover == HOVER_ALWAYS; }
|
|
|
|
bool focus_click() const { return _focus == FOCUS_CLICK; }
|
|
|
|
bool focus_transient() const { return _focus == FOCUS_TRANSIENT; }
|
|
|
|
bool origin_pointer() const { return _origin == ORIGIN_POINTER; }
|
2014-07-08 14:19:21 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2014-06-13 09:37:34 +00:00
|
|
|
};
|
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
static Entry::Label _label(Genode::Xml_node domain)
|
2014-06-19 10:42:24 +00:00
|
|
|
{
|
2015-09-30 09:30:02 +00:00
|
|
|
typedef Genode::String<32> Value;
|
|
|
|
Value const value = domain.attribute_value("label", Value("yes"));
|
2014-06-19 10:42:24 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
if (value == "no") return Entry::LABEL_NO;
|
|
|
|
if (value == "yes") return Entry::LABEL_YES;
|
2014-06-19 10:42:24 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
PWRN("invalid value of label attribute in <domain>");
|
|
|
|
return Entry::LABEL_YES;
|
|
|
|
}
|
2014-06-19 10:42:24 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
static Entry::Content _content(Genode::Xml_node domain)
|
|
|
|
{
|
|
|
|
typedef Genode::String<32> Value;
|
|
|
|
Value const value = domain.attribute_value("content", Value("tinted"));
|
2014-06-19 10:42:24 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
if (value == "client") return Entry::CONTENT_CLIENT;
|
|
|
|
if (value == "tinted") return Entry::CONTENT_TINTED;
|
2014-06-19 10:42:24 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
return Entry::CONTENT_TINTED;
|
2014-06-19 10:42:24 +00:00
|
|
|
}
|
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
static Entry::Hover _hover(Genode::Xml_node domain)
|
2014-07-02 15:37:02 +00:00
|
|
|
{
|
2015-09-30 09:30:02 +00:00
|
|
|
typedef Genode::String<32> Value;
|
|
|
|
Value const value = domain.attribute_value("hover", Value("focused"));
|
2014-07-02 15:37:02 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
if (value == "focused") return Entry::HOVER_FOCUSED;
|
|
|
|
if (value == "always") return Entry::HOVER_ALWAYS;
|
2014-07-02 15:37:02 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
PWRN("invalid value of hover attribute in <domain>");
|
|
|
|
return Entry::HOVER_FOCUSED;
|
|
|
|
}
|
2014-07-02 15:37:02 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
static Entry::Focus _focus(Genode::Xml_node domain)
|
|
|
|
{
|
|
|
|
typedef Genode::String<32> Value;
|
|
|
|
Value const value = domain.attribute_value("focus", Value("none"));
|
|
|
|
|
|
|
|
if (value == "none") return Entry::FOCUS_NONE;
|
|
|
|
if (value == "click") return Entry::FOCUS_CLICK;
|
|
|
|
if (value == "transient") return Entry::FOCUS_TRANSIENT;
|
|
|
|
|
|
|
|
PWRN("invalid value of focus attribute in <domain>");
|
|
|
|
return Entry::FOCUS_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Entry::Origin _origin(Genode::Xml_node domain)
|
|
|
|
{
|
|
|
|
typedef Genode::String<32> Value;
|
|
|
|
Value const value = domain.attribute_value("origin", Value("top_left"));
|
2014-07-02 15:37:02 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
if (value == "top_left") return Entry::ORIGIN_TOP_LEFT;
|
|
|
|
if (value == "top_right") return Entry::ORIGIN_TOP_RIGHT;
|
|
|
|
if (value == "bottom_left") return Entry::ORIGIN_BOTTOM_LEFT;
|
|
|
|
if (value == "bottom_right") return Entry::ORIGIN_BOTTOM_RIGHT;
|
|
|
|
if (value == "pointer") return Entry::ORIGIN_POINTER;
|
2014-07-02 15:37:02 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
PWRN("invalid value of origin attribute in <domain>");
|
|
|
|
return Entry::ORIGIN_BOTTOM_LEFT;
|
2014-07-02 15:37:02 +00:00
|
|
|
}
|
|
|
|
|
2014-06-13 09:37:34 +00:00
|
|
|
void _insert(Genode::Xml_node domain)
|
|
|
|
{
|
|
|
|
char buf[sizeof(Entry::Name)];
|
|
|
|
buf[0] = 0;
|
|
|
|
bool name_defined = false;
|
|
|
|
try {
|
|
|
|
domain.attribute("name").value(buf, sizeof(buf));
|
|
|
|
name_defined = true;
|
|
|
|
} catch (...) { }
|
|
|
|
|
|
|
|
if (!name_defined) {
|
|
|
|
PERR("no valid domain name specified");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry::Name const name(buf);
|
|
|
|
|
|
|
|
if (lookup(name)) {
|
|
|
|
PERR("domain name \"%s\" is not unique", name.string());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-02 20:00:15 +00:00
|
|
|
if (!domain.has_attribute("layer")) {
|
|
|
|
PERR("no layer specified for domain \"%s\"", name.string());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned const layer = domain.attribute_value("layer", ~0UL);
|
|
|
|
|
2014-07-08 14:19:21 +00:00
|
|
|
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));
|
|
|
|
|
2014-06-19 10:42:24 +00:00
|
|
|
Entry::Color const color = domain.attribute_value("color", WHITE);
|
2014-06-13 09:37:34 +00:00
|
|
|
|
2015-09-30 09:30:02 +00:00
|
|
|
_entries.insert(new (_alloc) Entry(name, color, _label(domain),
|
|
|
|
_content(domain), _hover(domain),
|
|
|
|
_focus(domain),
|
2014-07-08 14:19:21 +00:00
|
|
|
_origin(domain), layer, offset, area));
|
2014-06-13 09:37:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Genode::List<Entry> _entries;
|
|
|
|
Genode::Allocator &_alloc;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Domain_registry(Genode::Allocator &alloc, Genode::Xml_node config)
|
|
|
|
:
|
|
|
|
_alloc(alloc)
|
|
|
|
{
|
|
|
|
char const *type = "domain";
|
|
|
|
|
|
|
|
if (!config.has_sub_node(type))
|
|
|
|
return;
|
|
|
|
|
|
|
|
Genode::Xml_node domain = config.sub_node(type);
|
|
|
|
|
|
|
|
for (;; domain = domain.next(type)) {
|
|
|
|
|
|
|
|
_insert(domain);
|
|
|
|
|
|
|
|
if (domain.is_last(type))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~Domain_registry()
|
|
|
|
{
|
2015-06-03 19:35:33 +00:00
|
|
|
while (Entry *e = _entries.first()) {
|
|
|
|
_entries.remove(e);
|
2014-06-13 09:37:34 +00:00
|
|
|
Genode::destroy(_alloc, e);
|
2015-06-03 19:35:33 +00:00
|
|
|
}
|
2014-06-13 09:37:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Entry const *lookup(Entry::Name const &name) const
|
|
|
|
{
|
|
|
|
for (Entry const *e = _entries.first(); e; e = e->next())
|
|
|
|
if (e->has_name(name))
|
|
|
|
return e;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _DOMAIN_REGISTRY_ */
|