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

232 lines
6.0 KiB
C++

/*
* \brief Nitpicker session interface
* \author Norman Feske
* \date 2006-08-09
*/
/*
* 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 _SESSION_H_
#define _SESSION_H_
/* Genode includes */
#include <util/list.h>
#include <util/string.h>
#include <os/session_policy.h>
/* local includes */
#include "color.h"
#include "canvas.h"
#include "domain_registry.h"
class View;
class Session;
namespace Input { class Event; }
typedef Genode::List<Session> Session_list;
class Session : public Session_list::Element
{
private:
Genode::Session_label const _label;
Domain_registry::Entry const *_domain;
Texture_base const *_texture = { 0 };
bool _uses_alpha = { false };
bool _visible = true;
View *_background = 0;
unsigned char const *_input_mask = { 0 };
public:
/**
* Constructor
*
* \param label session label
*/
explicit Session(Genode::Session_label const &label) : _label(label) { }
virtual ~Session() { }
virtual void submit_input_event(Input::Event ev) = 0;
virtual void submit_sync() = 0;
Genode::Session_label const &label() const { return _label; }
/**
* Return true if session label starts with specified 'selector'
*/
bool matches_session_label(char const *selector) const
{
/*
* Append label separator to match selectors with a trailing
* separator.
*/
char label[Genode::Session_label::capacity() + 4];
Genode::snprintf(label, sizeof(label), "%s ->", _label.string());
return Genode::strcmp(label, selector,
Genode::strlen(selector)) == 0;
}
/**
* Accessors to the domain configuration used in conditions
*/
bool label_visible() const { return !_domain || _domain->label_visible(); }
bool content_client() const { return _domain && _domain->content_client(); }
bool hover_focused() const { return !_domain || _domain->hover_focused(); }
bool hover_always() const { return _domain && _domain->hover_always(); }
bool origin_pointer() const { return _domain && _domain->origin_pointer(); }
unsigned layer() const { return _domain ? _domain->layer() : ~0UL; }
bool visible() const { return _visible; }
void visible(bool visible) { _visible = visible; }
Domain_registry::Entry::Name domain_name() const
{
return _domain ? _domain->name() : Domain_registry::Entry::Name();
}
Texture_base const *texture() const { return _texture; }
void texture(Texture_base const *texture, bool uses_alpha)
{
_texture = texture;
_uses_alpha = uses_alpha;
}
/**
* Set input mask buffer
*
* \param mask input mask buffer containing a byte value per texture
* pixel, which describes the policy of handling user
* input referring to the pixel. If set to zero, the input
* is passed through the view such that it can be handled
* by one of the subsequent views in the view stack. If
* set to one, the input is consumed by the view. If
* 'input_mask' is a null pointer, user input is
* unconditionally consumed by the view.
*/
void input_mask(unsigned char const *mask) { _input_mask = mask; }
Color color() const { return _domain ? _domain->color() : WHITE; }
View *background() const { return _background; }
void background(View *background) { _background = background; }
/**
* Return true if session uses an alpha channel
*/
bool uses_alpha() const { return _texture && _uses_alpha; }
/**
* Calculate session-local coordinate to physical screen position
*
* \param pos coordinate in session-local coordinate system
* \param screen_area session-local screen size
*/
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
*/
unsigned char input_mask_at(Point p) const
{
if (!_input_mask || !_texture) return 0;
/* check boundaries */
if ((unsigned)p.x() >= _texture->size().w()
|| (unsigned)p.y() >= _texture->size().h())
return 0;
return _input_mask[p.y()*_texture->size().w() + p.x()];
}
bool has_same_domain(Session const *s) const
{
return s && (s->_domain == _domain);
}
bool has_focusable_domain()
{
return has_valid_domain()
&& (_domain->focus_click() || _domain->focus_transient());
}
bool has_transient_focusable_domain()
{
return has_valid_domain() && _domain->focus_transient();
}
bool has_valid_domain() const
{
return _domain;
}
void reset_domain()
{
_domain = nullptr;
}
/**
* Set session domain according to the list of configured policies
*
* Select the policy that matches the label. If multiple policies
* match, select the one with the largest number of characters.
*/
void apply_session_policy(Domain_registry const &domain_registry)
{
reset_domain();
try {
Genode::Session_policy policy(_label);
/* read domain attribute */
if (!policy.has_attribute("domain")) {
PERR("policy for label \"%s\" lacks domain declaration",
_label.string());
return;
}
typedef Domain_registry::Entry::Name Domain_name;
char buf[sizeof(Domain_name)];
buf[0] = 0;
try {
policy.attribute("domain").value(buf, sizeof(buf)); }
catch (...) { }
Domain_name name(buf);
_domain = domain_registry.lookup(name);
if (!_domain)
PERR("policy for label \"%s\" specifies nonexistent domain \"%s\"",
_label.string(), name.string());
} catch (...) { PERR("no policy matching label \"%s\"", _label.string()); }
}
};
#endif