vbox_pointer: provide a 'Report' service for shape reports

Issue #2585
This commit is contained in:
Christian Prochaska 2017-11-28 18:40:27 +01:00 committed by Christian Helmuth
parent 5099d00eb3
commit 78b38cd65b
8 changed files with 282 additions and 419 deletions

View File

@ -76,7 +76,6 @@ set config {
<config>
<policy label="pointer -> hover" report="nitpicker -> hover"/>
<policy label="pointer -> xray" report="null"/>
<policy label="pointer -> focus" report="nitpicker -> focus"/>
</config>
<route>
<service name="ROM"> <parent/> </service>
@ -92,11 +91,9 @@ set config {
<config>
<report focus="yes" hover="yes" xray="yes"/>
<domain name="pointer" layer="1" content="client" label="no" origin="pointer"/>
<domain name="smiley" layer="3" content="client" label="no" hover="always" focus="click"/>
<domain name="default" layer="3" content="client" label="yes" hover="always" focus="click"/>
<policy label_prefix="pointer" domain="pointer"/>
<policy label_prefix="test-domain-smiley" domain="smiley"/>
<default-policy domain="default"/>
<background color="#00426f"/> <!-- indigo -->
@ -113,23 +110,6 @@ set config {
</route>
</start>
<start name="report_rom_shapes">
<binary name="report_rom"/>
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config>
<policy label="pointer -> arrow" report="shape-arrow -> shape"/>
<policy label="pointer -> blade" report="shape-blade -> shape"/>
<policy label="pointer -> bladex" report="shape-bladex -> shape"/>
<policy label="pointer -> smiley" report="shape-smiley -> shape"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="shape-arrow">
<binary name="test-vbox_pointer"/>
<resource name="RAM" quantum="2M"/>
@ -139,7 +119,9 @@ set config {
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Report"> <child name="report_rom_shapes"/> </service>
<service name="Report" label="shape">
<child name="pointer" label="test-label-arrow -> testnit"/>
</service>
</route>
</start>
<start name="shape-blade">
@ -151,7 +133,9 @@ set config {
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Report"> <child name="report_rom_shapes"/> </service>
<service name="Report" label="shape">
<child name="pointer" label="test-label-blade -> testnit"/>
</service>
</route>
</start>
<start name="shape-bladex">
@ -163,7 +147,9 @@ set config {
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Report"> <child name="report_rom_shapes"/> </service>
<service name="Report" label="shape">
<child name="pointer" label="test-label-bladex -> testnit"/>
</service>
</route>
</start>
<start name="shape-smiley-config">
@ -197,7 +183,9 @@ set config {
<route>
<service name="ROM" label="smiley.config">
<child name="shape-smiley-config"/> </service>
<service name="Report"> <child name="report_rom_shapes"/> </service>
<service name="Report" label="shape">
<child name="pointer" label="test-label-smiley -> testnit"/>
</service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
@ -208,22 +196,13 @@ set config {
<start name="pointer">
<binary name="vbox_pointer"/>
<resource name="RAM" quantum="1M"/>
<config>
<policy domain="smiley" rom="smiley"/>
<policy label="test-label-arrow" rom="arrow"/>
<policy label="test-label-blade" rom="blade"/>
<policy label="test-label-bladex" rom="bladex"/>
</config>
<provides> <service name="Report"/> </provides>
<route>
<service name="PD"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
<service name="ROM" label="xray"> <child name="report_rom_nitpicker"/> </service>
<service name="ROM" label="hover"> <child name="report_rom_nitpicker"/> </service>
<service name="ROM" label="arrow"> <child name="report_rom_shapes"/> </service>
<service name="ROM" label="blade"> <child name="report_rom_shapes"/> </service>
<service name="ROM" label="bladex"> <child name="report_rom_shapes"/> </service>
<service name="ROM" label="smiley"> <child name="report_rom_shapes"/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
@ -241,7 +220,7 @@ set config {
<service name="Nitpicker"> <child name="nitpicker"/> </service>
</route>
</start>
<start name="test-domain-smiley">
<start name="test-label-smiley">
<binary name="testnit"/>
<resource name="RAM" quantum="2M"/>
<route>
@ -277,18 +256,6 @@ set config {
<service name="Nitpicker"> <child name="nitpicker"/> </service>
</route>
</start>
<start name="test-label-blade2">
<binary name="testnit"/>
<resource name="RAM" quantum="2M"/>
<route>
<service name="PD"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
</route>
</start>
<start name="test-label-bladex">
<binary name="testnit"/>
<resource name="RAM" quantum="2M"/>

View File

@ -113,12 +113,6 @@ append config_of_app {
<config>
<policy label="vbox_pointer -> hover" report="nitpicker -> hover"/>
<policy label="vbox_pointer -> xray" report="nitpicker -> xray"/>}
for { set i 1} { $i <= $use_vms } { incr i} {
append config_of_app "
<policy label=\"vbox_pointer -> shape$i\" report=\"vbox$i -> shape\"/>"
}
append config_of_app {
<policy label="usb_report_filter -> devices" report="usb_drv -> devices"/>
<policy label="usb_report_filter -> usb_drv_config" report="usb_drv -> config"/>
@ -154,23 +148,10 @@ append config_of_app {
<start name="vbox_pointer" priority="-1">
<resource name="RAM" quantum="2M"/>
<config>}
for { set i 1} { $i <= $use_vms } { incr i} {
append config_of_app "
<policy label=\"nit_fb$i\" rom=\"shape$i\"/>"
}
append config_of_app {
</config>
<provides> <service name="Report"/> </provides>
<route>
<service name="Nitpicker"> <child name="nitpicker"/> </service>}
for { set i 1} { $i <= $use_vms } { incr i} {
append config_of_app "
<service name=\"ROM\" label=\"shape$i\"> <child name=\"report_rom\"/> </service>"
}
append config_of_app {
<service name="ROM" label="hover"> <child name="report_rom"/> </service>
<service name="ROM" label="xray"> <child name="report_rom"/> </service>
@ -313,7 +294,10 @@ for { set i 1} { $i <= $use_vms } { incr i} {
<service name="Block"> <child name="part_blk"/> </service>}
append config_of_app "
<service name=\"Framebuffer\"> <child name=\"nit_fb${i}\" /> </service>
<service name=\"Input\"> <child name=\"nit_fb${i}\" /> </service>"
<service name=\"Input\"> <child name=\"nit_fb${i}\" /> </service>
<service name=\"Report\" label=\"shape\">
<child name=\"vbox_pointer\" label=\"nit_fb${i} -> \"/>
</service>"
append config_of_app {
<service name="Report"><child name="report_rom" /></service>
<service name="ROM" label="usb_devices"> <child name="report_rom" /> </service>

View File

@ -159,8 +159,6 @@ append_if [expr $use_gui] config {
<config>
<policy label="vbox_pointer -> hover" report="nitpicker -> hover"/>
<policy label="vbox_pointer -> xray" report="nitpicker -> xray"/>
<policy label="vbox_pointer -> shape1" report="vbox1 -> shape"/>
<policy label="vbox_pointer -> shape2" report="vbox2 -> shape"/>
</config>
</start>
@ -192,14 +190,8 @@ append_if [expr $use_gui] config {
<start name="vbox_pointer" priority="-1">
<resource name="RAM" quantum="2M"/>
<config>
<policy label="nit_fb1" rom="shape1"/>
<policy label="nit_fb2" rom="shape2"/>
</config>
<route>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
<service name="ROM" label="shape1"> <child name="report_rom"/> </service>
<service name="ROM" label="shape2"> <child name="report_rom"/> </service>
<service name="ROM" label="hover"> <child name="report_rom"/> </service>
<service name="ROM" label="xray"> <child name="report_rom"/> </service>
<any-service> <parent/> </any-service>
@ -251,6 +243,7 @@ append_if [expr $use_gui] config {
</config>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
<service name="Report" label="shape"> <child name="vbox_pointer" label="nit_fb2 -> "/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Framebuffer"> <child name="nit_fb2" /> </service>
<service name="Input"> <child name="nit_fb2" /> </service>
@ -283,6 +276,7 @@ append_if [expr $use_bridge] config {
<service name="Nic"> <child name="nic_bridge"/> </service>}
append_if [expr $use_gui] config {
<service name="Report" label="shape"> <child name="vbox_pointer" label="nit_fb1 -> "/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Framebuffer"> <child name="nit_fb1" /> </service>
<service name="Input"> <child name="nit_fb1" /> </service>}

View File

@ -17,12 +17,19 @@
#include <base/component.h>
#include <base/heap.h>
#include <base/attached_rom_dataspace.h>
#include <os/pixel_alpha8.h>
#include <os/pixel_rgb565.h>
#include <os/pixel_rgb888.h>
#include <os/surface.h>
#include <os/texture_rgb888.h>
#include <nitpicker_session/connection.h>
#include <report_rom/report_service.h>
#include <vbox_pointer/dither_painter.h>
#include <vbox_pointer/shape_report.h>
/* local includes */
#include "util.h"
#include "policy.h"
#include "rom_registry.h"
#include "big_mouse.h"
namespace Vbox_pointer { class Main; }
@ -48,15 +55,13 @@ void convert_default_pointer_data_to_pixels(PT *pixel, Nitpicker::Area size)
}
class Vbox_pointer::Main : public Vbox_pointer::Pointer_updater
class Vbox_pointer::Main : public Rom::Reader
{
private:
Genode::Env &_env;
typedef Vbox_pointer::String String;
typedef Vbox_pointer::String String;
typedef Vbox_pointer::Policy Policy;
typedef Vbox_pointer::Policy_registry Policy_registry;
Genode::Env &_env;
Genode::Attached_rom_dataspace _hover_ds { _env, "hover" };
Genode::Attached_rom_dataspace _xray_ds { _env, "xray" };
@ -71,12 +76,15 @@ class Vbox_pointer::Main : public Vbox_pointer::Pointer_updater
Nitpicker::Session::View_handle _view = _nitpicker.create_view();
Genode::Heap _heap { _env.ram(), _env.rm() };
Genode::Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
Policy_registry _policy_registry { *this, _env, _heap };
Rom::Registry _rom_registry { _sliced_heap, _env.ram(), _env.rm(), *this };
bool _verbose = _config.xml().attribute_value("verbose", false);
Report::Root _report_root { _env, _sliced_heap, _rom_registry, _verbose };
String _hovered_label;
String _hovered_domain;
bool _xray = false;
bool _default_pointer_visible = false;
@ -84,22 +92,38 @@ class Vbox_pointer::Main : public Vbox_pointer::Pointer_updater
Nitpicker::Area _current_pointer_size;
Genode::Dataspace_capability _pointer_ds;
Genode::Attached_ram_dataspace _texture_pixel_ds { _env.ram(), _env.rm(),
Vbox_pointer::MAX_WIDTH *
Vbox_pointer::MAX_HEIGHT *
sizeof(Genode::Pixel_rgb888) };
Genode::Attached_ram_dataspace _texture_alpha_ds { _env.ram(), _env.rm(),
Vbox_pointer::MAX_WIDTH *
Vbox_pointer::MAX_HEIGHT };
void _resize_nitpicker_buffer_if_needed(Nitpicker::Area pointer_size);
void _show_default_pointer();
void _show_shape_pointer(Policy *p);
void _show_shape_pointer(Shape_report &shape_report);
void _update_pointer();
void _handle_hover();
void _handle_xray();
public:
/**
* Reader interface
*/
void notify_module_changed() override
{
_update_pointer();
}
void notify_module_invalidated() override
{
_update_pointer();
}
Main(Genode::Env &);
/*******************************
** Pointer_updater interface **
*******************************/
void update_pointer(Policy &policy) override;
};
@ -150,24 +174,57 @@ void Vbox_pointer::Main::_show_default_pointer()
}
void Vbox_pointer::Main::_show_shape_pointer(Policy *p)
void Vbox_pointer::Main::_show_shape_pointer(Shape_report &shape_report)
{
Nitpicker::Area shape_size { shape_report.width, shape_report.height };
Nitpicker::Point shape_hot { (int)-shape_report.x_hot, (int)-shape_report.y_hot };
try {
_resize_nitpicker_buffer_if_needed(p->shape_size());
_resize_nitpicker_buffer_if_needed(shape_size);
} catch (...) {
error(__func__, ": could not resize the pointer buffer "
"for ", p->shape_size(), " pixels");
"for ", shape_size, " pixels");
throw;
}
if (p->shape_visible()) {
Genode::Attached_dataspace ds { _env.rm(), _pointer_ds };
p->draw_shape(ds.local_addr<Genode::Pixel_rgb565>());
if (shape_report.visible) {
using namespace Genode;
/* import shape into texture */
Texture<Pixel_rgb888>
texture(_texture_pixel_ds.local_addr<Pixel_rgb888>(),
_texture_alpha_ds.local_addr<unsigned char>(),
shape_size);
for (unsigned int y = 0; y < shape_size.h(); y++) {
/* import the RGBA-encoded line into the texture */
unsigned char *shape = shape_report.shape;
unsigned char *line = &shape[y * shape_size.w() * 4];
texture.rgba(line, shape_size.w(), y);
}
/* draw texture */
Attached_dataspace ds { _env.rm(), _pointer_ds };
Pixel_rgb565 *pixel = ds.local_addr<Pixel_rgb565>();
Pixel_alpha8 *alpha =
reinterpret_cast<Pixel_alpha8 *>(pixel + shape_size.count());
Surface<Pixel_rgb565> pixel_surface(pixel, shape_size);
Surface<Pixel_alpha8> alpha_surface(alpha, shape_size);
Dither_painter::paint(pixel_surface, texture);
Dither_painter::paint(alpha_surface, texture);
}
_nitpicker.framebuffer()->refresh(0, 0, p->shape_size().w(), p->shape_size().h());
_nitpicker.framebuffer()->refresh(0, 0, shape_size.w(), shape_size.h());
Nitpicker::Rect geometry(p->shape_hot(), p->shape_size());
Nitpicker::Rect geometry(shape_hot, shape_size);
_nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(_view, geometry);
_nitpicker.execute();
@ -177,16 +234,42 @@ void Vbox_pointer::Main::_show_shape_pointer(Policy *p)
void Vbox_pointer::Main::_update_pointer()
{
Policy *policy = nullptr;
if (_xray
|| !(policy = _policy_registry.lookup(_hovered_label, _hovered_domain))
|| (policy->shape_visible() && !policy->shape_valid()))
if (_xray) {
_show_default_pointer();
else
return;
}
try {
Rom::Readable_module &shape_module =
_rom_registry.lookup(*this, _hovered_label);
try {
_show_shape_pointer(policy);
} catch (...) { _show_default_pointer(); }
Shape_report shape_report;
shape_module.read_content(*this, (char*)&shape_report, sizeof(shape_report));
if (shape_report.visible) {
if ((shape_report.width == 0) ||
(shape_report.height == 0) ||
(shape_report.width > MAX_WIDTH) ||
(shape_report.height > MAX_HEIGHT))
throw Genode::Exception();
_show_shape_pointer(shape_report);
}
} catch (...) {
_rom_registry.release(*this, shape_module);
throw;
}
_rom_registry.release(*this, shape_module);
} catch (...) {
_show_default_pointer();
}
}
@ -203,12 +286,13 @@ void Vbox_pointer::Main::_handle_hover()
Genode::Xml_node node(_hover_ds.local_addr<char>());
String hovered_label = read_string_attribute(node, "label", String());
String hovered_domain = read_string_attribute(node, "domain", String());
/* update pointer if hovered domain or label changed */
if (hovered_label != _hovered_label || hovered_domain != _hovered_domain) {
if (_verbose)
Genode::log("hovered_label: ", hovered_label);
/* update pointer if hovered label changed */
if (hovered_label != _hovered_label) {
_hovered_label = hovered_label;
_hovered_domain = hovered_domain;
_update_pointer();
}
}
@ -240,15 +324,6 @@ void Vbox_pointer::Main::_handle_xray()
}
}
void Vbox_pointer::Main::update_pointer(Policy &policy)
{
/* update pointer if shape-changing policy is hovered */
if (&policy == _policy_registry.lookup(_hovered_label, _hovered_domain))
_update_pointer();
}
Vbox_pointer::Main::Main(Genode::Env &env) : _env(env)
{
/*
@ -261,8 +336,6 @@ Vbox_pointer::Main::Main(Genode::Env &env) : _env(env)
_nitpicker.buffer(mode, true /* use alpha */);
_policy_registry.update(_config.xml());
/* register signal handlers */
_hover_ds.sigh(_hover_signal_handler);
_xray_ds.sigh(_xray_signal_handler);
@ -274,6 +347,9 @@ Vbox_pointer::Main::Main(Genode::Env &env) : _env(env)
_handle_hover();
_handle_xray();
_update_pointer();
/* announce 'Report' service */
env.parent().announce(env.ep().manage(_report_root));
}

View File

@ -1,224 +0,0 @@
/*
* \brief VirtualBox pointer policies implementation
* \author Christian Prochaska
* \author Christian Helmuth
* \date 2015-06-08
*/
/*
* Copyright (C) 2015-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.
*/
/* Genode includes */
#include <base/attached_rom_dataspace.h>
#include <base/attached_ram_dataspace.h>
#include <os/pixel_alpha8.h>
#include <os/pixel_rgb888.h>
#include <os/surface.h>
#include <os/texture_rgb888.h>
#include <vbox_pointer/dither_painter.h>
/* local includes */
#include "policy.h"
/******************************
** Entry in policy registry **
******************************/
class Vbox_pointer::Policy_entry : public Vbox_pointer::Policy,
public Genode::List<Policy_entry>::Element
{
private:
Genode::Env &_env;
String _label;
String _domain;
Pointer_updater &_updater;
Genode::Attached_ram_dataspace _texture_pixel_ds { _env.ram(), _env.rm(),
Vbox_pointer::MAX_WIDTH *
Vbox_pointer::MAX_HEIGHT *
sizeof(Genode::Pixel_rgb888) };
Genode::Attached_ram_dataspace _texture_alpha_ds { _env.ram(), _env.rm(),
Vbox_pointer::MAX_WIDTH *
Vbox_pointer::MAX_HEIGHT };
Genode::Attached_rom_dataspace _shape_ds;
Genode::Signal_handler<Policy_entry> _shape_signal_handler {
_env.ep(), *this, &Policy_entry::_import_shape };
bool _shape_visible;
Nitpicker::Area _shape_size;
Nitpicker::Point _shape_hot;
void _import_shape()
{
using namespace Genode;
_shape_ds.update();
if (!_shape_ds.valid())
return;
if (_shape_ds.size() < sizeof(Vbox_pointer::Shape_report))
return;
Vbox_pointer::Shape_report *shape_report =
_shape_ds.local_addr<Vbox_pointer::Shape_report>();
_shape_visible = shape_report->visible;
if (!_shape_visible
|| shape_report->width == 0 || shape_report->height == 0
|| shape_report->width > Vbox_pointer::MAX_WIDTH
|| shape_report->height > Vbox_pointer::MAX_HEIGHT) {
_shape_size = Nitpicker::Area();
_shape_hot = Nitpicker::Point();
_updater.update_pointer(*this);
return;
}
_shape_size = Nitpicker::Area(shape_report->width, shape_report->height);
_shape_hot = Nitpicker::Point(-shape_report->x_hot, -shape_report->y_hot);
Texture<Pixel_rgb888>
texture(_texture_pixel_ds.local_addr<Pixel_rgb888>(),
_texture_alpha_ds.local_addr<unsigned char>(),
_shape_size);
for (unsigned int y = 0; y < _shape_size.h(); y++) {
/* import the RGBA-encoded line into the texture */
unsigned char *shape = shape_report->shape;
unsigned char *line = &shape[y * _shape_size.w() * 4];
texture.rgba(line, _shape_size.w(), y);
}
_updater.update_pointer(*this);
}
public:
Policy_entry(Genode::Env &env, String const &label,
String const &domain, String const &rom,
Pointer_updater &updater)
:
_env(env), _label(label), _domain(domain), _updater(updater),
_shape_ds(_env, rom.string())
{
_import_shape();
_shape_ds.sigh(_shape_signal_handler);
}
/**
* Return similarity of policy label and the passed label
*/
Genode::size_t match_label(String const &other) const
{
if (_label.length() > 1 && other.length() > 1) {
/* length of string w/o null byte */
Genode::size_t const len = _label.length() - 1;
if (Genode::strcmp(other.string(), _label.string(), len) == 0)
return len;
}
return 0;
}
/**
* Return if policy domain and passed domain match exactly
*/
bool match_domain(String const &other) const
{
return _domain.length() > 1 && _domain == other;
}
/**********************
** Policy interface **
**********************/
Nitpicker::Area shape_size() const override { return _shape_size; }
Nitpicker::Point shape_hot() const override { return _shape_hot; }
bool shape_visible() const override { return _shape_visible; }
bool shape_valid() const override { return _shape_size.valid(); }
void draw_shape(Genode::Pixel_rgb565 *pixel) override
{
using namespace Genode;
if (!_shape_size.valid())
return;
Pixel_alpha8 *alpha =
reinterpret_cast<Pixel_alpha8 *>(pixel + _shape_size.count());
Surface<Pixel_rgb565> pixel_surface(pixel, _shape_size);
Surface<Pixel_alpha8> alpha_surface(alpha, _shape_size);
Texture<Pixel_rgb888>
texture(_texture_pixel_ds.local_addr<Pixel_rgb888>(),
_texture_alpha_ds.local_addr<unsigned char>(),
_shape_size);
Dither_painter::paint(pixel_surface, texture);
Dither_painter::paint(alpha_surface, texture);
}
};
/**************
** Registry **
**************/
void Vbox_pointer::Policy_registry::update(Genode::Xml_node config)
{
/* TODO real update should flush at least */
config.for_each_sub_node("policy", [&] (Genode::Xml_node policy) {
String const label = read_string_attribute(policy, "label", String());
String const domain = read_string_attribute(policy, "domain", String());
String const rom = read_string_attribute(policy, "rom", String());
if (!label.valid() && !domain.valid())
Genode::warning("policy does not declare label/domain attribute");
else if (!rom.valid())
Genode::warning("policy does not declare shape rom");
else
insert(new (_alloc) Policy_entry(_env, label, domain, rom, _updater));
});
}
Vbox_pointer::Policy * Vbox_pointer::Policy_registry::lookup(String const &label,
String const &domain)
{
/* try label similarity matching first */
unsigned similarity = 0;
Policy_entry *match = nullptr;
for (Policy_entry *p = first(); p; p = p->next()) {
unsigned s = p->match_label(label);
if (s > similarity) {
similarity = s;
match = p;
}
}
if (match) return match;
/* then match domains */
for (Policy_entry *p = first(); p; p = p->next())
if (p->match_domain(domain))
return p;
return nullptr;
}

View File

@ -1,71 +0,0 @@
/*
* \brief VirtualBox pointer policies
* \author Christian Helmuth
* \date 2015-06-08
*/
/*
* Copyright (C) 2015-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 _VBOX_POINTER_POLICY_H_
#define _VBOX_POINTER_POLICY_H_
/* Genode includes */
#include <os/pixel_rgb565.h>
#include <nitpicker_session/nitpicker_session.h>
#include <vbox_pointer/shape_report.h>
#include <util/list.h>
/* local includes */
#include "util.h"
namespace Vbox_pointer {
struct Pointer_updater;
struct Policy;
struct Policy_entry;
struct Policy_registry;
}
struct Vbox_pointer::Pointer_updater
{
virtual void update_pointer(Policy &initiator) = 0;
};
struct Vbox_pointer::Policy
{
virtual Nitpicker::Area shape_size() const = 0;
virtual Nitpicker::Point shape_hot() const = 0;
virtual bool shape_visible() const = 0;
virtual bool shape_valid() const = 0;
virtual void draw_shape(Genode::Pixel_rgb565 *pixel) = 0;
};
class Vbox_pointer::Policy_registry : private Genode::List<Policy_entry>
{
private:
Pointer_updater &_updater;
Genode::Env &_env;
Genode::Allocator &_alloc;
public:
Policy_registry(Pointer_updater &updater, Genode::Env &env,
Genode::Allocator &alloc)
: _updater(updater), _env(env), _alloc(alloc) { }
void update(Genode::Xml_node config);
Policy * lookup(String const &label, String const &domain);
};
#endif /* _VBOX_POINTER_POLICY_H_ */

View File

@ -0,0 +1,137 @@
/*
* \brief Registry of ROM modules
* \author Norman Feske
* \date 2014-01-11
*/
/*
* 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 _ROM_REGISTRY_H_
#define _ROM_REGISTRY_H_
/* Genode includes */
#include <report_rom/rom_registry.h>
#include <os/session_policy.h>
namespace Rom { struct Registry; }
struct Rom::Registry : Registry_for_reader, Registry_for_writer, Genode::Noncopyable
{
private:
Genode::Allocator &_md_alloc;
Genode::Ram_session &_ram;
Genode::Region_map &_rm;
Reader &_reader;
Module_list _modules;
struct Read_write_policy : Module::Read_policy, Module::Write_policy
{
bool read_permitted(Module const &,
Writer const &,
Reader const &) const override
{
/*
* The pointer application is always allowed to read the ROM content.
*/
return true;
}
bool write_permitted(Module const &, Writer const &) const override
{
/*
* Because the report-session label is used as the module name
* for the writer, each report session refers to a distinct
* module. Report client can write to their respective modules
* at any time.
*/
return true;
}
} _read_write_policy;
Module &_lookup(Module::Name const name, bool create_if_not_found)
{
for (Module *m = _modules.first(); m; m = m->next())
if (m->_has_name(name))
return *m;
if (!create_if_not_found)
throw Genode::Service_denied();
/* module does not exist yet, create one */
/* XXX proper accounting for the used memory is missing */
/* XXX if we run out of memory, the server will abort */
Module * const module = new (&_md_alloc)
Module(_ram, _rm, name, _read_write_policy, _read_write_policy);
_modules.insert(module);
return *module;
}
void _try_to_destroy(Module const &module)
{
if (module._in_use())
return;
_modules.remove(&module);
Genode::destroy(&_md_alloc, const_cast<Module *>(&module));
}
public:
Registry(Genode::Allocator &md_alloc,
Genode::Ram_session &ram, Genode::Region_map &rm,
Reader &reader)
:
_md_alloc(md_alloc), _ram(ram), _rm(rm), _reader(reader)
{ }
Module &lookup(Writer &writer, Module::Name const &name) override
{
Module &module = _lookup(name, true);
module._register(writer);
/*
* Enforce invariant that each module can have only one writer at a
* time.
*/
if (module._num_writers() > 1) {
release(writer, module);
throw Genode::Service_denied();
}
module._register(_reader);
return module;
}
void release(Writer &writer, Module &module) override
{
module._unregister(_reader);
module._unregister(writer);
_try_to_destroy(module);
}
Readable_module &lookup(Reader &reader, Module::Name const &rom_label) override
{
return _lookup(rom_label, false);
}
void release(Reader &reader, Readable_module &module) override
{
_try_to_destroy(static_cast<Module&>(module));
}
};
#endif /* _ROM_REGISTRY_H_ */

View File

@ -1,3 +1,3 @@
TARGET = vbox_pointer
SRC_CC = main.cc policy.cc
SRC_CC = main.cc
LIBS += base