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