mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-01 08:48:20 +00:00
pointer: custom pointer shape support
Make the revised 'vbox_pointer' component the new 'pointer' component. Fixes #2585
This commit is contained in:
parent
18993b5ede
commit
dd98bd67a0
@ -11,10 +11,10 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__VBOX_POINTER__SHAPE_REPORT_H_
|
||||
#define _INCLUDE__VBOX_POINTER__SHAPE_REPORT_H_
|
||||
#ifndef _INCLUDE__POINTER__SHAPE_REPORT_H_
|
||||
#define _INCLUDE__POINTER__SHAPE_REPORT_H_
|
||||
|
||||
namespace Vbox_pointer {
|
||||
namespace Pointer {
|
||||
|
||||
enum {
|
||||
MAX_WIDTH = 100,
|
||||
@ -25,7 +25,7 @@ namespace Vbox_pointer {
|
||||
struct Shape_report;
|
||||
}
|
||||
|
||||
struct Vbox_pointer::Shape_report
|
||||
struct Pointer::Shape_report
|
||||
{
|
||||
bool visible;
|
||||
unsigned int x_hot;
|
||||
@ -35,4 +35,4 @@ struct Vbox_pointer::Shape_report
|
||||
unsigned char shape[MAX_SHAPE_SIZE];
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__VBOX_POINTER__SHAPE_REPORT_H_ */
|
||||
#endif /* _INCLUDE__POINTER__SHAPE_REPORT_H_ */
|
@ -1,2 +1,10 @@
|
||||
SRC_DIR := src/server/nitpicker src/app/pointer
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
||||
|
||||
content: include/pointer include/report_rom
|
||||
|
||||
include/pointer:
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
include/report_rom:
|
||||
$(mirror_from_rep_dir)
|
||||
|
@ -13,8 +13,8 @@ set build_components {
|
||||
server/report_rom
|
||||
server/dynamic_rom
|
||||
server/nitpicker
|
||||
app/vbox_pointer
|
||||
test/vbox_pointer
|
||||
app/pointer
|
||||
test/pointer
|
||||
test/nitpicker
|
||||
}
|
||||
|
||||
@ -57,7 +57,6 @@ set config {
|
||||
<service name="Input"/>
|
||||
</provides>
|
||||
<config buffered="yes" width="1280" height="720" depth="16"/>
|
||||
<!--<config buffered="yes" width="1440" height="900" depth="16"/>-->
|
||||
<route>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
@ -111,7 +110,7 @@ set config {
|
||||
</start>
|
||||
|
||||
<start name="shape-arrow">
|
||||
<binary name="test-vbox_pointer"/>
|
||||
<binary name="test-pointer"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config shape="arrow"/>
|
||||
<route>
|
||||
@ -125,7 +124,7 @@ set config {
|
||||
</route>
|
||||
</start>
|
||||
<start name="shape-blade">
|
||||
<binary name="test-vbox_pointer"/>
|
||||
<binary name="test-pointer"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config shape="blade"/>
|
||||
<route>
|
||||
@ -139,7 +138,7 @@ set config {
|
||||
</route>
|
||||
</start>
|
||||
<start name="shape-bladex">
|
||||
<binary name="test-vbox_pointer"/>
|
||||
<binary name="test-pointer"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config shape="bladex"/>
|
||||
<route>
|
||||
@ -177,7 +176,7 @@ set config {
|
||||
</route>
|
||||
</start>
|
||||
<start name="shape-smiley">
|
||||
<binary name="test-vbox_pointer"/>
|
||||
<binary name="test-pointer"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<configfile name="smiley.config"/>
|
||||
<route>
|
||||
@ -194,7 +193,6 @@ set config {
|
||||
</start>
|
||||
|
||||
<start name="pointer">
|
||||
<binary name="vbox_pointer"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Report"/> </provides>
|
||||
<config shapes="yes" verbose="no"/>
|
||||
@ -283,8 +281,8 @@ set boot_modules {
|
||||
fb_sdl
|
||||
report_rom dynamic_rom
|
||||
nitpicker
|
||||
vbox_pointer
|
||||
test-vbox_pointer
|
||||
pointer
|
||||
test-pointer
|
||||
testnit
|
||||
}
|
||||
|
39
repos/os/src/app/pointer/README
Normal file
39
repos/os/src/app/pointer/README
Normal file
@ -0,0 +1,39 @@
|
||||
Pointer for Nitpicker with optional hover-sensitive shape support
|
||||
|
||||
Per default the standard "big mouse" pointer is rendered on screen.
|
||||
|
||||
Additionally, 'pointer' supports to render "pointer shapes" when hovering
|
||||
Nitpicker sessions for which a shape was reported. This feature must be
|
||||
enabled with the '<config shapes="yes"/>' option. When enabled, the
|
||||
'pointer' component announces a 'Report' service for custom pointer shapes
|
||||
and requests ROM sessions for Nitpicker's 'hover' and 'xray' reports. The
|
||||
mapping between hovered Nitpicker sessions and applications can be achieved
|
||||
with report session label rewriting:
|
||||
|
||||
! <start name="shape-arrow">
|
||||
! <binary name="test-pointer"/>
|
||||
! <resource name="RAM" quantum="2M"/>
|
||||
! <config shape="arrow"/>
|
||||
! <route>
|
||||
! <service name="PD"> <parent/> </service>
|
||||
! <service name="ROM"> <parent/> </service>
|
||||
! <service name="CPU"> <parent/> </service>
|
||||
! <service name="LOG"> <parent/> </service>
|
||||
! <service name="Report" label="shape">
|
||||
! <child name="pointer" label="test-label-arrow -> testnit"/>
|
||||
! </service>
|
||||
! </route>
|
||||
! </start>
|
||||
|
||||
In the example above, which is from 'pointer.run', the 'shape-arrow' component
|
||||
reports an arrow shape with the label "shape". By rewriting the label of the
|
||||
report, the shape will be drawn for the 'test-label-arrow' component, which
|
||||
is reported by Nitpicker with the label 'test-label-arror -> testnit' when
|
||||
hovered.
|
||||
|
||||
When configured with '<config shapes="yes" verbose="yes"/>', the 'pointer'
|
||||
component prints the labels of hovered Nitpicker sessions and received shape
|
||||
reports to the 'LOG' service.
|
||||
|
||||
The most common use cases for pointer shapes are VirtualBox, which reports
|
||||
the guest-pointer shapes if Guest Additions are installed, and Qt applications.
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* \brief Minimalistic nitpicker pointer
|
||||
* \brief Nitpicker pointer with support for VirtualBox-defined shapes
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \author Christian Prochaska
|
||||
* \date 2014-07-02
|
||||
*/
|
||||
|
||||
@ -12,18 +14,29 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <nitpicker_session/connection.h>
|
||||
#include <os/surface.h>
|
||||
#include <os/pixel_rgb565.h>
|
||||
#include <base/attached_dataspace.h>
|
||||
#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 <pointer/dither_painter.h>
|
||||
#include <pointer/shape_report.h>
|
||||
|
||||
/* local includes */
|
||||
#include "util.h"
|
||||
#include "rom_registry.h"
|
||||
#include "big_mouse.h"
|
||||
|
||||
namespace Pointer { class Main; }
|
||||
|
||||
|
||||
template <typename PT>
|
||||
void convert_cursor_data_to_pixels(PT *pixel, Nitpicker::Area size)
|
||||
void convert_default_pointer_data_to_pixels(PT *pixel, Nitpicker::Area size)
|
||||
{
|
||||
unsigned char *alpha = (unsigned char *)(pixel + size.count());
|
||||
|
||||
@ -42,25 +55,324 @@ void convert_cursor_data_to_pixels(PT *pixel, Nitpicker::Area size)
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
class Pointer::Main : public Rom::Reader
|
||||
{
|
||||
static Nitpicker::Connection nitpicker { env, "cursor" };
|
||||
private:
|
||||
|
||||
Nitpicker::Area const cursor_size(big_mouse.w, big_mouse.h);
|
||||
typedef Pointer::String String;
|
||||
|
||||
Framebuffer::Mode const mode(cursor_size.w(), cursor_size.h(),
|
||||
Framebuffer::Mode::RGB565);
|
||||
nitpicker.buffer(mode, true);
|
||||
Genode::Env &_env;
|
||||
|
||||
Genode::Attached_dataspace ds(
|
||||
env.rm(), nitpicker.framebuffer()->dataspace());
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
convert_cursor_data_to_pixels(
|
||||
ds.local_addr<Genode::Pixel_rgb565>(), cursor_size);
|
||||
bool _verbose = _config.xml().attribute_value("verbose", false);
|
||||
|
||||
Nitpicker::Session::View_handle view = nitpicker.create_view();
|
||||
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), cursor_size);
|
||||
nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(view, geometry);
|
||||
nitpicker.enqueue<Nitpicker::Session::Command::To_front>(view);
|
||||
nitpicker.execute();
|
||||
Nitpicker::Connection _nitpicker { _env };
|
||||
|
||||
Nitpicker::Session::View_handle _view = _nitpicker.create_view();
|
||||
|
||||
bool _default_pointer_visible = false;
|
||||
|
||||
Nitpicker::Area _current_pointer_size;
|
||||
Genode::Dataspace_capability _pointer_ds;
|
||||
|
||||
void _resize_nitpicker_buffer_if_needed(Nitpicker::Area pointer_size);
|
||||
void _show_default_pointer();
|
||||
void _update_pointer();
|
||||
|
||||
/* custom shape support */
|
||||
|
||||
bool _shapes_enabled = _config.xml().attribute_value("shapes", false);
|
||||
|
||||
bool _xray = false;
|
||||
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _hover_ds;
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _xray_ds;
|
||||
|
||||
Genode::Signal_handler<Main> _hover_signal_handler {
|
||||
_env.ep(), *this, &Main::_handle_hover };
|
||||
Genode::Signal_handler<Main> _xray_signal_handler {
|
||||
_env.ep(), *this, &Main::_handle_xray };
|
||||
|
||||
Genode::Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
|
||||
|
||||
Rom::Registry _rom_registry { _sliced_heap, _env.ram(), _env.rm(), *this };
|
||||
|
||||
Report::Root _report_root { _env, _sliced_heap, _rom_registry, _verbose };
|
||||
|
||||
String _hovered_label;
|
||||
|
||||
Genode::Attached_ram_dataspace _texture_pixel_ds { _env.ram(), _env.rm(),
|
||||
Pointer::MAX_WIDTH *
|
||||
Pointer::MAX_HEIGHT *
|
||||
sizeof(Genode::Pixel_rgb888) };
|
||||
|
||||
Genode::Attached_ram_dataspace _texture_alpha_ds { _env.ram(), _env.rm(),
|
||||
Pointer::MAX_WIDTH *
|
||||
Pointer::MAX_HEIGHT };
|
||||
|
||||
void _show_shape_pointer(Shape_report &shape_report);
|
||||
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 &);
|
||||
};
|
||||
|
||||
|
||||
void Pointer::Main::_resize_nitpicker_buffer_if_needed(Nitpicker::Area pointer_size)
|
||||
{
|
||||
if (pointer_size == _current_pointer_size)
|
||||
return;
|
||||
|
||||
Framebuffer::Mode const mode { (int)pointer_size.w(),
|
||||
(int)pointer_size.h(),
|
||||
Framebuffer::Mode::RGB565 };
|
||||
|
||||
_nitpicker.buffer(mode, true /* use alpha */);
|
||||
|
||||
_pointer_ds = _nitpicker.framebuffer()->dataspace();
|
||||
|
||||
_current_pointer_size = pointer_size;
|
||||
}
|
||||
|
||||
|
||||
void Pointer::Main::_show_default_pointer()
|
||||
{
|
||||
/* only draw default pointer if not already drawn */
|
||||
if (_default_pointer_visible)
|
||||
return;
|
||||
|
||||
Nitpicker::Area const pointer_size { big_mouse.w, big_mouse.h };
|
||||
|
||||
try {
|
||||
_resize_nitpicker_buffer_if_needed(pointer_size);
|
||||
} catch (...) {
|
||||
Genode::error(__func__, ": could not resize the pointer buffer "
|
||||
"for ", pointer_size.w(), "x", pointer_size.h(), " pixels");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Attached_dataspace ds { _env.rm(), _pointer_ds };
|
||||
|
||||
convert_default_pointer_data_to_pixels(ds.local_addr<Genode::Pixel_rgb565>(),
|
||||
pointer_size);
|
||||
_nitpicker.framebuffer()->refresh(0, 0, pointer_size.w(), pointer_size.h());
|
||||
|
||||
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), pointer_size);
|
||||
_nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(_view, geometry);
|
||||
_nitpicker.execute();
|
||||
|
||||
_default_pointer_visible = true;
|
||||
}
|
||||
|
||||
|
||||
void 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(shape_size);
|
||||
} catch (...) {
|
||||
error(__func__, ": could not resize the pointer buffer "
|
||||
"for ", shape_size, " pixels");
|
||||
throw;
|
||||
}
|
||||
|
||||
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, shape_size.w(), shape_size.h());
|
||||
|
||||
Nitpicker::Rect geometry(shape_hot, shape_size);
|
||||
_nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(_view, geometry);
|
||||
_nitpicker.execute();
|
||||
|
||||
_default_pointer_visible = false;
|
||||
}
|
||||
|
||||
|
||||
void Pointer::Main::_update_pointer()
|
||||
{
|
||||
if (!_shapes_enabled || _xray) {
|
||||
_show_default_pointer();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Rom::Readable_module &shape_module =
|
||||
_rom_registry.lookup(*this, _hovered_label);
|
||||
|
||||
try {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Pointer::Main::_handle_hover()
|
||||
{
|
||||
using Pointer::read_string_attribute;
|
||||
|
||||
_hover_ds->update();
|
||||
if (!_hover_ds->valid())
|
||||
return;
|
||||
|
||||
/* read new hover information from nitpicker's hover report */
|
||||
try {
|
||||
Genode::Xml_node node(_hover_ds->local_addr<char>());
|
||||
|
||||
String hovered_label = read_string_attribute(node, "label", String());
|
||||
|
||||
if (_verbose)
|
||||
Genode::log("hovered_label: ", hovered_label);
|
||||
|
||||
/* update pointer if hovered label changed */
|
||||
if (hovered_label != _hovered_label) {
|
||||
_hovered_label = hovered_label;
|
||||
_update_pointer();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Genode::warning("could not parse hover report");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Pointer::Main::_handle_xray()
|
||||
{
|
||||
_xray_ds->update();
|
||||
if (!_xray_ds->valid())
|
||||
return;
|
||||
|
||||
try {
|
||||
Genode::Xml_node node(_xray_ds->local_addr<char>());
|
||||
|
||||
bool xray = node.attribute_value("enabled", false);
|
||||
|
||||
/* update pointer if xray status changed */
|
||||
if (xray != _xray) {
|
||||
_xray = xray;
|
||||
_update_pointer();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Genode::warning("could not parse xray report");
|
||||
}
|
||||
}
|
||||
|
||||
Pointer::Main::Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
/*
|
||||
* Try to allocate the Nitpicker buffer for the maximum supported
|
||||
* pointer size to let the user know right from the start if the
|
||||
* RAM quota is too low.
|
||||
*/
|
||||
Framebuffer::Mode const mode { Pointer::MAX_WIDTH, Pointer::MAX_HEIGHT,
|
||||
Framebuffer::Mode::RGB565 };
|
||||
|
||||
_nitpicker.buffer(mode, true /* use alpha */);
|
||||
|
||||
if (_shapes_enabled) {
|
||||
try {
|
||||
_hover_ds.construct(_env, "hover");
|
||||
_hover_ds->sigh(_hover_signal_handler);
|
||||
_handle_hover();
|
||||
} catch (Genode::Rom_connection::Rom_connection_failed) {
|
||||
Genode::warning("Could not open ROM session for \"hover\".",
|
||||
" This ROM is used for custom pointer shape support.");
|
||||
}
|
||||
|
||||
try {
|
||||
_xray_ds.construct(_env, "xray");
|
||||
_xray_ds->sigh(_xray_signal_handler);
|
||||
_handle_xray();
|
||||
} catch (Genode::Rom_connection::Rom_connection_failed) {
|
||||
Genode::warning("Could not open ROM session for \"xray\".",
|
||||
" This ROM is used for custom pointer shape support.");
|
||||
}
|
||||
}
|
||||
|
||||
_nitpicker.enqueue<Nitpicker::Session::Command::To_front>(_view);
|
||||
_nitpicker.execute();
|
||||
|
||||
_update_pointer();
|
||||
|
||||
if (_shapes_enabled) {
|
||||
/* announce 'Report' service */
|
||||
env.parent().announce(env.ep().manage(_report_root));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Pointer::Main main(env); }
|
||||
|
@ -11,15 +11,15 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _VBOX_POINTER_UTIL_H_
|
||||
#define _VBOX_POINTER_UTIL_H_
|
||||
#ifndef _POINTER_UTIL_H_
|
||||
#define _POINTER_UTIL_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
#include <util/string.h>
|
||||
|
||||
|
||||
namespace Vbox_pointer {
|
||||
namespace Pointer {
|
||||
typedef Genode::String<64> String;
|
||||
|
||||
inline String read_string_attribute(Genode::Xml_node const &node,
|
||||
@ -28,9 +28,9 @@ namespace Vbox_pointer {
|
||||
}
|
||||
|
||||
|
||||
Vbox_pointer::String Vbox_pointer::read_string_attribute(Genode::Xml_node const &node,
|
||||
char const *attr,
|
||||
String const &default_value)
|
||||
Pointer::String Pointer::read_string_attribute(Genode::Xml_node const &node,
|
||||
char const *attr,
|
||||
String const &default_value)
|
||||
{
|
||||
try {
|
||||
char buf[String::capacity()];
|
||||
@ -39,4 +39,4 @@ Vbox_pointer::String Vbox_pointer::read_string_attribute(Genode::Xml_node const
|
||||
} catch (...) { return default_value; }
|
||||
}
|
||||
|
||||
#endif /* _VBOX_POINTER_UTIL_H_ */
|
||||
#endif /* _POINTER_UTIL_H_ */
|
@ -15,7 +15,7 @@
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <util/string.h>
|
||||
#include <os/reporter.h>
|
||||
#include <vbox_pointer/shape_report.h>
|
||||
#include <pointer/shape_report.h>
|
||||
|
||||
struct Shape
|
||||
{
|
||||
@ -141,11 +141,11 @@ struct Main
|
||||
{
|
||||
Genode::Env &_env;
|
||||
|
||||
Vbox_pointer::Shape_report _shape_report {
|
||||
Pointer::Shape_report _shape_report {
|
||||
true, 0, 0, Shape::WIDTH, Shape::HEIGHT, { 0 } };
|
||||
|
||||
Genode::Reporter _reporter {
|
||||
_env, "shape", "shape", sizeof(Vbox_pointer::Shape_report) };
|
||||
_env, "shape", "shape", sizeof(Pointer::Shape_report) };
|
||||
|
||||
Genode::Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
@ -173,7 +173,7 @@ struct Main
|
||||
}
|
||||
}
|
||||
|
||||
_reporter.report(&_shape_report, sizeof(Vbox_pointer::Shape_report));
|
||||
_reporter.report(&_shape_report, sizeof(Pointer::Shape_report));
|
||||
}
|
||||
|
||||
Main(Genode::Env &env) : _env(env)
|
@ -1,3 +1,3 @@
|
||||
TARGET = test-vbox_pointer
|
||||
TARGET = test-pointer
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
@ -15,7 +15,6 @@ MIRROR_FROM_REP_DIR := src/virtualbox5 \
|
||||
src/virtualbox/rt.cc \
|
||||
src/virtualbox/thread.cc \
|
||||
include/vmm \
|
||||
include/vbox_pointer/shape_report.h \
|
||||
$(addprefix lib/mk/,$(LIB_MK_FILES))
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR)
|
||||
@ -73,7 +72,8 @@ $(MIRROR_FROM_QEMU_USB_PORT_DIR):
|
||||
mkdir -p $(dir $@)
|
||||
cp -r $(QEMU_USB_PORT_DIR)/$@ $(dir $@)
|
||||
|
||||
MIRROR_FROM_OS := src/drivers/input/spec/ps2/scan_code_set_1.h
|
||||
MIRROR_FROM_OS := src/drivers/input/spec/ps2/scan_code_set_1.h \
|
||||
include/pointer/shape_report.h \
|
||||
|
||||
content: $(MIRROR_FROM_OS)
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
SRC_DIR := src/app/vbox_pointer
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
||||
|
||||
content: include/vbox_pointer
|
||||
|
||||
include/vbox_pointer:
|
||||
$(mirror_from_rep_dir)
|
@ -1 +0,0 @@
|
||||
2017-11-08 a885637d5623c31559066e231cb22a050674e5ec
|
@ -1,6 +0,0 @@
|
||||
base
|
||||
os
|
||||
gems
|
||||
input_session
|
||||
nitpicker_session
|
||||
framebuffer_session
|
@ -28,7 +28,7 @@ set build_components {
|
||||
drivers/nic
|
||||
drivers/audio
|
||||
server/nitpicker
|
||||
app/vbox_pointer
|
||||
app/pointer
|
||||
server/nit_fb
|
||||
server/report_rom
|
||||
server/dynamic_rom
|
||||
@ -39,7 +39,7 @@ set boot_modules {
|
||||
nic_drv
|
||||
audio_drv
|
||||
nitpicker
|
||||
vbox_pointer
|
||||
pointer
|
||||
nit_fb
|
||||
report_rom
|
||||
dynamic_rom
|
||||
@ -111,8 +111,8 @@ append config_of_app {
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Report"/> <service name="ROM"/> </provides>
|
||||
<config>
|
||||
<policy label="vbox_pointer -> hover" report="nitpicker -> hover"/>
|
||||
<policy label="vbox_pointer -> xray" report="nitpicker -> xray"/>}
|
||||
<policy label="pointer -> hover" report="nitpicker -> hover"/>
|
||||
<policy label="pointer -> xray" report="nitpicker -> xray"/>}
|
||||
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"/>
|
||||
@ -140,13 +140,13 @@ append config_of_app {
|
||||
<domain name="cpu_load" layer="2" content="client" label="no" />
|
||||
<domain name="" layer="3" content="client" focus="click" hover="always" />
|
||||
|
||||
<policy label_prefix="vbox_pointer" domain="pointer"/>
|
||||
<policy label_prefix="pointer" domain="pointer"/>
|
||||
<policy label_prefix="cpu_load_display" domain="cpu_load"/>
|
||||
<default-policy domain=""/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="vbox_pointer" priority="-1">
|
||||
<start name="pointer" priority="-1">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Report"/> </provides>
|
||||
<config shapes="yes"/>
|
||||
@ -297,7 +297,7 @@ for { set i 1} { $i <= $use_vms } { incr i} {
|
||||
<service name=\"Framebuffer\"> <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} -> \"/>
|
||||
<child name=\"pointer\" label=\"nit_fb${i} -> \"/>
|
||||
</service>"
|
||||
append config_of_app {
|
||||
<service name="Report"><child name="report_rom" /></service>
|
||||
|
@ -43,7 +43,7 @@ lappend_if [expr $use_bridge] build_components server/nic_bridge
|
||||
lappend_if [expr $use_gui] build_components server/report_rom
|
||||
lappend_if [expr $use_gui] build_components server/nitpicker
|
||||
lappend_if [expr $use_gui] build_components server/nit_fb
|
||||
lappend_if [expr $use_gui] build_components app/vbox_pointer
|
||||
lappend_if [expr $use_gui] build_components app/pointer
|
||||
|
||||
append_platform_drv_build_components
|
||||
|
||||
@ -157,8 +157,8 @@ append_if [expr $use_gui] config {
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Report"/> <service name="ROM"/> </provides>
|
||||
<config>
|
||||
<policy label="vbox_pointer -> hover" report="nitpicker -> hover"/>
|
||||
<policy label="vbox_pointer -> xray" report="nitpicker -> xray"/>
|
||||
<policy label="pointer -> hover" report="nitpicker -> hover"/>
|
||||
<policy label="pointer -> xray" report="nitpicker -> xray"/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
@ -183,12 +183,12 @@ append_if [expr $use_gui] config {
|
||||
<domain name="pointer" layer="1" content="client" label="no" origin="pointer" />
|
||||
<domain name="" layer="2" content="client" focus="click" hover="always" />
|
||||
|
||||
<policy label_prefix="vbox_pointer" domain="pointer"/>
|
||||
<policy label_prefix="pointer" domain="pointer"/>
|
||||
<default-policy domain=""/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="vbox_pointer" priority="-1">
|
||||
<start name="pointer" priority="-1">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config shapes="yes"/>
|
||||
<route>
|
||||
@ -244,7 +244,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" label="shape"> <child name="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>
|
||||
@ -277,7 +277,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" label="shape"> <child name="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>}
|
||||
@ -307,7 +307,7 @@ lappend_if [have_spec x86] boot_modules rtc_drv
|
||||
lappend_if [expr $use_gui] boot_modules report_rom
|
||||
lappend_if [expr $use_gui] boot_modules nitpicker
|
||||
lappend_if [expr $use_gui] boot_modules nit_fb
|
||||
lappend_if [expr $use_gui] boot_modules vbox_pointer
|
||||
lappend_if [expr $use_gui] boot_modules pointer
|
||||
|
||||
append boot_modules {
|
||||
ld.lib.so libc.lib.so libm.lib.so pthread.lib.so libc_pipe.lib.so
|
||||
|
@ -1,26 +0,0 @@
|
||||
Hover-sensitive pointer for Nitpicker with VirtualBox shape support
|
||||
|
||||
Per default the standard "big mouse" pointer is rendered on screen,
|
||||
which is the behavior known from the classical app/pointer.
|
||||
Additionally, VirtualBox pointer supports to render "pointer shapes"
|
||||
when hovering configured Nitpicker sessions. The policies can be
|
||||
defined for labels or domains of the sessions.
|
||||
|
||||
! <start 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"/>
|
||||
! </config>
|
||||
! </start>
|
||||
|
||||
In the example above, which is from vbox_pointer.run, the domain
|
||||
"smiley" gets the ROM "smiley" as pointer shape. The labels
|
||||
"test-label-blade" and "test-label-arrow" will render the ROMs "arrow"
|
||||
resp. "blade" as pointer shape. Note that label matching is done from
|
||||
the start of the actual label until the defined label ends. So,
|
||||
"test-label-blade2" will also match the policy defined above.
|
||||
|
||||
The most common use case for vbox_pointer is VirtualBox, which reports
|
||||
the guest-pointer shapes if Guest Additions are installed.
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* \brief Mouse cursor pixel data
|
||||
* \author Norman Feske
|
||||
* \date 2006-08-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-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.
|
||||
*/
|
||||
|
||||
static struct {
|
||||
unsigned short w, h, pixels[16][16];
|
||||
} big_mouse = {
|
||||
16,16,
|
||||
{
|
||||
{0x738E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x94B2,0x7BCF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x630C,0xC638,0xC638,0x6B4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x738E,0x8C71,0xFFFF,0xB5B6,0x6B4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x630C,0x4A49,0x630C,0xB5B6,0xFFFF,0xB5B6,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x528A,0x528A,0x630C,0x9492,0xB5B6,0xFFFF,0xB5B6,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x528A,0x39C7,0x4208,0x630C,0x7BCF,0xB5B6,0xFFFF,0xFFFF,0xB5B6,0x630C,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x4208,0x39C7,0x4208,0x630C,0x7BCF,0xB5B6,0xDEFB,0xFFFF,0xFFFF,0xB5B6,0x630C,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x4A49,0x1082,0x39C7,0x4208,0x5ACB,0x7BCF,0x8C71,0xAD75,0x630C,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x1082,0x39C7,0x5ACB,0x630C,0xB5B6,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x1082,0x1082,0x39C7,0x4A49,0x630C,0xAD75,0x0000,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x1082,0x4A49,0x0000,0x4A49,0x630C,0x8C71,0x0000,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x39C7,0x4A49,0x0000,0x0000,0x4A49,0x630C,0x8C71,0x0000,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x0000,0x0000,0x0000,0x0000,0x4A49,0x630C,0x8C71,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A49,0x4A49,0x0000},
|
||||
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},
|
||||
}
|
||||
};
|
@ -1,378 +0,0 @@
|
||||
/*
|
||||
* \brief Nitpicker pointer with support for VirtualBox-defined shapes
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \author Christian Prochaska
|
||||
* \date 2014-07-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#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 "rom_registry.h"
|
||||
#include "big_mouse.h"
|
||||
|
||||
namespace Vbox_pointer { class Main; }
|
||||
|
||||
|
||||
template <typename PT>
|
||||
void convert_default_pointer_data_to_pixels(PT *pixel, Nitpicker::Area size)
|
||||
{
|
||||
unsigned char *alpha = (unsigned char *)(pixel + size.count());
|
||||
|
||||
for (unsigned y = 0; y < size.h(); y++) {
|
||||
for (unsigned x = 0; x < size.w(); x++) {
|
||||
|
||||
/* the source is known to be in RGB565 format */
|
||||
Genode::Pixel_rgb565 src =
|
||||
*(Genode::Pixel_rgb565 *)(&big_mouse.pixels[y][x]);
|
||||
|
||||
unsigned const i = y*size.w() + x;
|
||||
pixel[i] = PT(src.r(), src.g(), src.b());
|
||||
alpha[i] = src.r() ? 255 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Vbox_pointer::Main : public Rom::Reader
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Vbox_pointer::String String;
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
bool _verbose = _config.xml().attribute_value("verbose", false);
|
||||
|
||||
Nitpicker::Connection _nitpicker { _env };
|
||||
|
||||
Nitpicker::Session::View_handle _view = _nitpicker.create_view();
|
||||
|
||||
bool _default_pointer_visible = false;
|
||||
|
||||
Nitpicker::Area _current_pointer_size;
|
||||
Genode::Dataspace_capability _pointer_ds;
|
||||
|
||||
void _resize_nitpicker_buffer_if_needed(Nitpicker::Area pointer_size);
|
||||
void _show_default_pointer();
|
||||
void _update_pointer();
|
||||
|
||||
/* custom shape support */
|
||||
|
||||
bool _shapes_enabled = _config.xml().attribute_value("shapes", false);
|
||||
|
||||
bool _xray = false;
|
||||
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _hover_ds;
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _xray_ds;
|
||||
|
||||
Genode::Signal_handler<Main> _hover_signal_handler {
|
||||
_env.ep(), *this, &Main::_handle_hover };
|
||||
Genode::Signal_handler<Main> _xray_signal_handler {
|
||||
_env.ep(), *this, &Main::_handle_xray };
|
||||
|
||||
Genode::Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
|
||||
|
||||
Rom::Registry _rom_registry { _sliced_heap, _env.ram(), _env.rm(), *this };
|
||||
|
||||
Report::Root _report_root { _env, _sliced_heap, _rom_registry, _verbose };
|
||||
|
||||
String _hovered_label;
|
||||
|
||||
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 _show_shape_pointer(Shape_report &shape_report);
|
||||
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 &);
|
||||
};
|
||||
|
||||
|
||||
void Vbox_pointer::Main::_resize_nitpicker_buffer_if_needed(Nitpicker::Area pointer_size)
|
||||
{
|
||||
if (pointer_size == _current_pointer_size)
|
||||
return;
|
||||
|
||||
Framebuffer::Mode const mode { (int)pointer_size.w(),
|
||||
(int)pointer_size.h(),
|
||||
Framebuffer::Mode::RGB565 };
|
||||
|
||||
_nitpicker.buffer(mode, true /* use alpha */);
|
||||
|
||||
_pointer_ds = _nitpicker.framebuffer()->dataspace();
|
||||
|
||||
_current_pointer_size = pointer_size;
|
||||
}
|
||||
|
||||
|
||||
void Vbox_pointer::Main::_show_default_pointer()
|
||||
{
|
||||
/* only draw default pointer if not already drawn */
|
||||
if (_default_pointer_visible)
|
||||
return;
|
||||
|
||||
Nitpicker::Area const pointer_size { big_mouse.w, big_mouse.h };
|
||||
|
||||
try {
|
||||
_resize_nitpicker_buffer_if_needed(pointer_size);
|
||||
} catch (...) {
|
||||
Genode::error(__func__, ": could not resize the pointer buffer "
|
||||
"for ", pointer_size.w(), "x", pointer_size.h(), " pixels");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Attached_dataspace ds { _env.rm(), _pointer_ds };
|
||||
|
||||
convert_default_pointer_data_to_pixels(ds.local_addr<Genode::Pixel_rgb565>(),
|
||||
pointer_size);
|
||||
_nitpicker.framebuffer()->refresh(0, 0, pointer_size.w(), pointer_size.h());
|
||||
|
||||
Nitpicker::Rect geometry(Nitpicker::Point(0, 0), pointer_size);
|
||||
_nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(_view, geometry);
|
||||
_nitpicker.execute();
|
||||
|
||||
_default_pointer_visible = true;
|
||||
}
|
||||
|
||||
|
||||
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(shape_size);
|
||||
} catch (...) {
|
||||
error(__func__, ": could not resize the pointer buffer "
|
||||
"for ", shape_size, " pixels");
|
||||
throw;
|
||||
}
|
||||
|
||||
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, shape_size.w(), shape_size.h());
|
||||
|
||||
Nitpicker::Rect geometry(shape_hot, shape_size);
|
||||
_nitpicker.enqueue<Nitpicker::Session::Command::Geometry>(_view, geometry);
|
||||
_nitpicker.execute();
|
||||
|
||||
_default_pointer_visible = false;
|
||||
}
|
||||
|
||||
|
||||
void Vbox_pointer::Main::_update_pointer()
|
||||
{
|
||||
if (!_shapes_enabled || _xray) {
|
||||
_show_default_pointer();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Rom::Readable_module &shape_module =
|
||||
_rom_registry.lookup(*this, _hovered_label);
|
||||
|
||||
try {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Vbox_pointer::Main::_handle_hover()
|
||||
{
|
||||
using Vbox_pointer::read_string_attribute;
|
||||
|
||||
_hover_ds->update();
|
||||
if (!_hover_ds->valid())
|
||||
return;
|
||||
|
||||
/* read new hover information from nitpicker's hover report */
|
||||
try {
|
||||
Genode::Xml_node node(_hover_ds->local_addr<char>());
|
||||
|
||||
String hovered_label = read_string_attribute(node, "label", String());
|
||||
|
||||
if (_verbose)
|
||||
Genode::log("hovered_label: ", hovered_label);
|
||||
|
||||
/* update pointer if hovered label changed */
|
||||
if (hovered_label != _hovered_label) {
|
||||
_hovered_label = hovered_label;
|
||||
_update_pointer();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Genode::warning("could not parse hover report");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Vbox_pointer::Main::_handle_xray()
|
||||
{
|
||||
_xray_ds->update();
|
||||
if (!_xray_ds->valid())
|
||||
return;
|
||||
|
||||
try {
|
||||
Genode::Xml_node node(_xray_ds->local_addr<char>());
|
||||
|
||||
bool xray = node.attribute_value("enabled", false);
|
||||
|
||||
/* update pointer if xray status changed */
|
||||
if (xray != _xray) {
|
||||
_xray = xray;
|
||||
_update_pointer();
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Genode::warning("could not parse xray report");
|
||||
}
|
||||
}
|
||||
|
||||
Vbox_pointer::Main::Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
/*
|
||||
* Try to allocate the Nitpicker buffer for the maximum supported
|
||||
* pointer size to let the user know right from the start if the
|
||||
* RAM quota is too low.
|
||||
*/
|
||||
Framebuffer::Mode const mode { Vbox_pointer::MAX_WIDTH, Vbox_pointer::MAX_HEIGHT,
|
||||
Framebuffer::Mode::RGB565 };
|
||||
|
||||
_nitpicker.buffer(mode, true /* use alpha */);
|
||||
|
||||
if (_shapes_enabled) {
|
||||
try {
|
||||
_hover_ds.construct(_env, "hover");
|
||||
_hover_ds->sigh(_hover_signal_handler);
|
||||
_handle_hover();
|
||||
} catch (Genode::Rom_connection::Rom_connection_failed) {
|
||||
Genode::warning("Could not open ROM session for \"hover\".",
|
||||
" This ROM is used for custom pointer shape support.");
|
||||
}
|
||||
|
||||
try {
|
||||
_xray_ds.construct(_env, "xray");
|
||||
_xray_ds->sigh(_xray_signal_handler);
|
||||
_handle_xray();
|
||||
} catch (Genode::Rom_connection::Rom_connection_failed) {
|
||||
Genode::warning("Could not open ROM session for \"xray\".",
|
||||
" This ROM is used for custom pointer shape support.");
|
||||
}
|
||||
}
|
||||
|
||||
_nitpicker.enqueue<Nitpicker::Session::Command::To_front>(_view);
|
||||
_nitpicker.execute();
|
||||
|
||||
_update_pointer();
|
||||
|
||||
if (_shapes_enabled) {
|
||||
/* announce 'Report' service */
|
||||
env.parent().announce(env.ep().manage(_report_root));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Vbox_pointer::Main main(env); }
|
@ -1,3 +0,0 @@
|
||||
TARGET = vbox_pointer
|
||||
SRC_CC = main.cc
|
||||
LIBS += base
|
@ -27,7 +27,7 @@
|
||||
#include <scan_code_set_1.h>
|
||||
|
||||
/* repos/ports includes */
|
||||
#include <vbox_pointer/shape_report.h>
|
||||
#include <pointer/shape_report.h>
|
||||
|
||||
#include "../vmm.h"
|
||||
|
||||
@ -117,7 +117,7 @@ class GenodeConsole : public Console {
|
||||
Report::Connection _shape_report_connection;
|
||||
Genode::Attached_dataspace _shape_report_ds;
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _caps_lock;
|
||||
Vbox_pointer::Shape_report *_shape_report;
|
||||
Pointer::Shape_report *_shape_report;
|
||||
Genode::Reporter *_clipboard_reporter;
|
||||
Genode::Attached_rom_dataspace *_clipboard_rom;
|
||||
IKeyboard *_vbox_keyboard;
|
||||
@ -145,9 +145,9 @@ class GenodeConsole : public Console {
|
||||
_ax(0), _ay(0),
|
||||
_last_received_motion_event_was_absolute(false),
|
||||
_shape_report_connection(genode_env(), "shape",
|
||||
sizeof(Vbox_pointer::Shape_report)),
|
||||
sizeof(Pointer::Shape_report)),
|
||||
_shape_report_ds(genode_env().rm(), _shape_report_connection.dataspace()),
|
||||
_shape_report(_shape_report_ds.local_addr<Vbox_pointer::Shape_report>()),
|
||||
_shape_report(_shape_report_ds.local_addr<Pointer::Shape_report>()),
|
||||
_clipboard_reporter(nullptr),
|
||||
_clipboard_rom(nullptr),
|
||||
_vbox_keyboard(0),
|
||||
@ -204,7 +204,7 @@ class GenodeConsole : public Console {
|
||||
|
||||
size_t shape_size = shape_array.size() - (shape - and_mask);
|
||||
|
||||
if (shape_size > Vbox_pointer::MAX_SHAPE_SIZE) {
|
||||
if (shape_size > Pointer::MAX_SHAPE_SIZE) {
|
||||
Genode::error(__func__, ": shape data buffer is too small "
|
||||
"for ", shape_size, " bytes");
|
||||
return;
|
||||
@ -235,7 +235,7 @@ class GenodeConsole : public Console {
|
||||
}
|
||||
}
|
||||
|
||||
_shape_report_connection.submit(sizeof(Vbox_pointer::Shape_report));
|
||||
_shape_report_connection.submit(sizeof(Pointer::Shape_report));
|
||||
}
|
||||
|
||||
void update_video_mode();
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <scan_code_set_1.h>
|
||||
|
||||
/* repos/ports includes */
|
||||
#include <vbox_pointer/shape_report.h>
|
||||
#include <pointer/shape_report.h>
|
||||
|
||||
#include "../vmm.h"
|
||||
|
||||
@ -117,7 +117,7 @@ class GenodeConsole : public Console {
|
||||
Report::Connection _shape_report_connection;
|
||||
Genode::Attached_dataspace _shape_report_ds;
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _caps_lock;
|
||||
Vbox_pointer::Shape_report *_shape_report;
|
||||
Pointer::Shape_report *_shape_report;
|
||||
Genode::Reporter *_clipboard_reporter;
|
||||
Genode::Attached_rom_dataspace *_clipboard_rom;
|
||||
IKeyboard *_vbox_keyboard;
|
||||
@ -145,9 +145,9 @@ class GenodeConsole : public Console {
|
||||
_ax(0), _ay(0),
|
||||
_last_received_motion_event_was_absolute(false),
|
||||
_shape_report_connection(genode_env(), "shape",
|
||||
sizeof(Vbox_pointer::Shape_report)),
|
||||
sizeof(Pointer::Shape_report)),
|
||||
_shape_report_ds(genode_env().rm(), _shape_report_connection.dataspace()),
|
||||
_shape_report(_shape_report_ds.local_addr<Vbox_pointer::Shape_report>()),
|
||||
_shape_report(_shape_report_ds.local_addr<Pointer::Shape_report>()),
|
||||
_clipboard_reporter(nullptr),
|
||||
_clipboard_rom(nullptr),
|
||||
_vbox_keyboard(0),
|
||||
@ -204,7 +204,7 @@ class GenodeConsole : public Console {
|
||||
|
||||
size_t shape_size = cbShape - (shape - and_mask);
|
||||
|
||||
if (shape_size > Vbox_pointer::MAX_SHAPE_SIZE) {
|
||||
if (shape_size > Pointer::MAX_SHAPE_SIZE) {
|
||||
Genode::error(__func__, ": shape data buffer is too small for ",
|
||||
shape_size, " bytes");
|
||||
return;
|
||||
@ -249,7 +249,7 @@ class GenodeConsole : public Console {
|
||||
}
|
||||
}
|
||||
|
||||
_shape_report_connection.submit(sizeof(Vbox_pointer::Shape_report));
|
||||
_shape_report_connection.submit(sizeof(Pointer::Shape_report));
|
||||
}
|
||||
|
||||
void update_video_mode();
|
||||
|
Loading…
x
Reference in New Issue
Block a user