diff --git a/repos/ports/run/vbox_pointer.run b/repos/ports/run/vbox_pointer.run
index 4ad1ac1ba..aef040e03 100644
--- a/repos/ports/run/vbox_pointer.run
+++ b/repos/ports/run/vbox_pointer.run
@@ -76,7 +76,6 @@ set config {
-
@@ -92,11 +91,9 @@ set config {
-
-
@@ -113,23 +110,6 @@ set config {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -139,7 +119,9 @@ set config {
-
+
+
+
@@ -151,7 +133,9 @@ set config {
-
+
+
+
@@ -163,7 +147,9 @@ set config {
-
+
+
+
@@ -197,7 +183,9 @@ set config {
-
+
+
+
@@ -208,22 +196,13 @@ set config {
-
-
-
-
-
-
+
-
-
-
-
@@ -241,7 +220,7 @@ set config {
-
+
@@ -277,18 +256,6 @@ set config {
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/repos/ports/run/vbox_win.inc b/repos/ports/run/vbox_win.inc
index 7759a5ffa..5a9ae42f7 100644
--- a/repos/ports/run/vbox_win.inc
+++ b/repos/ports/run/vbox_win.inc
@@ -113,12 +113,6 @@ append config_of_app {
}
-
-for { set i 1} { $i <= $use_vms } { incr i} {
-append config_of_app "
- shape$i\" report=\"vbox$i -> shape\"/>"
-}
-
append config_of_app {
@@ -154,23 +148,10 @@ append config_of_app {
- }
-
-for { set i 1} { $i <= $use_vms } { incr i} {
-append config_of_app "
- "
-}
-
-append config_of_app {
-
+
}
-for { set i 1} { $i <= $use_vms } { incr i} {
-append config_of_app "
- "
-}
-
append config_of_app {
@@ -313,7 +294,10 @@ for { set i 1} { $i <= $use_vms } { incr i} {
}
append config_of_app "
- "
+
+
+ \"/>
+ "
append config_of_app {
diff --git a/repos/ports/run/virtualbox.run b/repos/ports/run/virtualbox.run
index 1db06bfb6..ad5983a34 100644
--- a/repos/ports/run/virtualbox.run
+++ b/repos/ports/run/virtualbox.run
@@ -159,8 +159,6 @@ append_if [expr $use_gui] config {
-
-
@@ -192,14 +190,8 @@ append_if [expr $use_gui] config {
-
-
-
-
-
-
@@ -251,6 +243,7 @@ append_if [expr $use_gui] config {
+
@@ -283,6 +276,7 @@ append_if [expr $use_bridge] config {
}
append_if [expr $use_gui] config {
+
}
diff --git a/repos/ports/src/app/vbox_pointer/main.cc b/repos/ports/src/app/vbox_pointer/main.cc
index bae7fe5ce..205744780 100644
--- a/repos/ports/src/app/vbox_pointer/main.cc
+++ b/repos/ports/src/app/vbox_pointer/main.cc
@@ -17,12 +17,19 @@
#include
#include
#include
+#include
#include
+#include
+#include
+#include
#include
+#include
+#include
+#include
/* 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());
+ if (shape_report.visible) {
+
+ using namespace Genode;
+
+ /* import shape into texture */
+
+ Texture
+ texture(_texture_pixel_ds.local_addr(),
+ _texture_alpha_ds.local_addr(),
+ 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_alpha8 *alpha =
+ reinterpret_cast(pixel + shape_size.count());
+
+ Surface pixel_surface(pixel, shape_size);
+ Surface 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(_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());
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));
}
diff --git a/repos/ports/src/app/vbox_pointer/policy.cc b/repos/ports/src/app/vbox_pointer/policy.cc
deleted file mode 100644
index ae46bd8de..000000000
--- a/repos/ports/src/app/vbox_pointer/policy.cc
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* local includes */
-#include "policy.h"
-
-
-/******************************
- ** Entry in policy registry **
- ******************************/
-
-class Vbox_pointer::Policy_entry : public Vbox_pointer::Policy,
- public Genode::List::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 _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();
-
- _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
- texture(_texture_pixel_ds.local_addr(),
- _texture_alpha_ds.local_addr(),
- _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 + _shape_size.count());
-
- Surface pixel_surface(pixel, _shape_size);
- Surface alpha_surface(alpha, _shape_size);
-
- Texture
- texture(_texture_pixel_ds.local_addr(),
- _texture_alpha_ds.local_addr(),
- _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;
-}
diff --git a/repos/ports/src/app/vbox_pointer/policy.h b/repos/ports/src/app/vbox_pointer/policy.h
deleted file mode 100644
index b0d2822fa..000000000
--- a/repos/ports/src/app/vbox_pointer/policy.h
+++ /dev/null
@@ -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
-#include
-#include
-#include
-
-/* 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
-{
- 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_ */
diff --git a/repos/ports/src/app/vbox_pointer/rom_registry.h b/repos/ports/src/app/vbox_pointer/rom_registry.h
new file mode 100644
index 000000000..0ccc9a7b7
--- /dev/null
+++ b/repos/ports/src/app/vbox_pointer/rom_registry.h
@@ -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
+#include
+
+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));
+ }
+
+ 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));
+ }
+};
+
+#endif /* _ROM_REGISTRY_H_ */
diff --git a/repos/ports/src/app/vbox_pointer/target.mk b/repos/ports/src/app/vbox_pointer/target.mk
index ba1a6dd90..2280cd9f7 100644
--- a/repos/ports/src/app/vbox_pointer/target.mk
+++ b/repos/ports/src/app/vbox_pointer/target.mk
@@ -1,3 +1,3 @@
TARGET = vbox_pointer
-SRC_CC = main.cc policy.cc
+SRC_CC = main.cc
LIBS += base