genode/repos/os/src/server/nitpicker/domain_registry.h

264 lines
7.0 KiB
C++

/*
* \brief Domain registry
* \author Norman Feske
* \date 2014-06-12
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DOMAIN_REGISTRY_
#define _DOMAIN_REGISTRY_
#include "types.h"
namespace Nitpicker { class Domain_registry; }
class Nitpicker::Domain_registry
{
public:
class Entry : public List<Entry>::Element
{
public:
typedef String<64> Name;
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 };
/**
* Origin of the domain's coordiate system
*/
enum Origin {
ORIGIN_POINTER,
ORIGIN_TOP_LEFT,
ORIGIN_TOP_RIGHT,
ORIGIN_BOTTOM_LEFT,
ORIGIN_BOTTOM_RIGHT };
private:
Name _name;
Color _color;
Label _label;
Content _content;
Hover _hover;
Focus _focus;
Origin _origin;
unsigned _layer;
Point _offset;
Point _area;
friend class Domain_registry;
Entry(Name const &name, Color color, Label label,
Content content, Hover hover, Focus focus,
Origin origin, unsigned layer, Point offset, Point area)
:
_name(name), _color(color), _label(label),
_content(content), _hover(hover), _focus(focus),
_origin(origin), _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; }
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; }
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; }
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()
: max(0, (int)phys_screen_area.w() + _area.x());
int const h = _area.y() > 0
? _area.y()
: max(0, (int)phys_screen_area.h() + _area.y());
return Area(w, h);
}
};
static Entry::Label _label(Xml_node domain)
{
typedef String<32> Value;
Value const value = domain.attribute_value("label", Value("yes"));
if (value == "no") return Entry::LABEL_NO;
if (value == "yes") return Entry::LABEL_YES;
warning("invalid value of label attribute in <domain>");
return Entry::LABEL_YES;
}
static Entry::Content _content(Xml_node domain)
{
typedef String<32> Value;
Value const value = domain.attribute_value("content", Value("tinted"));
if (value == "client") return Entry::CONTENT_CLIENT;
if (value == "tinted") return Entry::CONTENT_TINTED;
return Entry::CONTENT_TINTED;
}
static Entry::Hover _hover(Xml_node domain)
{
typedef String<32> Value;
Value const value = domain.attribute_value("hover", Value("focused"));
if (value == "focused") return Entry::HOVER_FOCUSED;
if (value == "always") return Entry::HOVER_ALWAYS;
warning("invalid value of hover attribute in <domain>");
return Entry::HOVER_FOCUSED;
}
static Entry::Focus _focus(Xml_node domain)
{
typedef 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;
warning("invalid value of focus attribute in <domain>");
return Entry::FOCUS_NONE;
}
static Entry::Origin _origin(Xml_node domain)
{
typedef String<32> Value;
Value const value = domain.attribute_value("origin", Value("top_left"));
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;
warning("invalid value of origin attribute in <domain>");
return Entry::ORIGIN_BOTTOM_LEFT;
}
void _insert(Xml_node domain)
{
Entry::Name const name = domain.attribute_value("name", Entry::Name());
if (!name.valid()) {
error("no valid domain name specified");
return;
}
if (lookup(name)) {
error("domain name \"", name, "\" is not unique");
return;
}
if (!domain.has_attribute("layer")) {
error("no layer specified for domain \"", name, "\"");
return;
}
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));
Color const color = domain.attribute_value("color", white());
_entries.insert(new (_alloc) Entry(name, color, _label(domain),
_content(domain), _hover(domain),
_focus(domain),
_origin(domain), layer, offset, area));
}
private:
List<Entry> _entries { };
Allocator &_alloc;
public:
Domain_registry(Allocator &alloc, Xml_node config)
:
_alloc(alloc)
{
char const *type = "domain";
if (!config.has_sub_node(type))
return;
Xml_node domain = config.sub_node(type);
for (;; domain = domain.next(type)) {
_insert(domain);
if (domain.last(type))
break;
}
}
~Domain_registry()
{
while (Entry *e = _entries.first()) {
_entries.remove(e);
destroy(_alloc, e);
}
}
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_ */