From 133d21ad38ec2a87352aa1c0af56640e23fa8578 Mon Sep 17 00:00:00 2001 From: Norman Feske <norman.feske@genode-labs.com> Date: Mon, 22 Nov 2021 14:01:36 +0100 Subject: [PATCH] event_filter: add touch-click filter This filter bridges the gap between a touchscreen driver, which generates raw touch events and traditional GUI applications that expect a pointer (absolute motion, press/release of the left mouse button). Fixes #4332 --- repos/os/src/server/event_filter/README | 7 ++ repos/os/src/server/event_filter/main.cc | 4 + repos/os/src/server/event_filter/source.h | 3 +- .../server/event_filter/touch_click_source.h | 96 +++++++++++++++++++ 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 repos/os/src/server/event_filter/touch_click_source.h diff --git a/repos/os/src/server/event_filter/README b/repos/os/src/server/event_filter/README index 43261612d9..134c95d1af 100644 --- a/repos/os/src/server/event_filter/README +++ b/repos/os/src/server/event_filter/README @@ -79,6 +79,13 @@ one of the following filters: "0" corresponds to a linear function whereas the maximum value "255" applies a curved function. The default value is "127". +:<touch-click>: + + Augments touch events with artificial absolute motion and mouse click/clack + events as understood by regular GUI applications that are not aware of + touch input. The original touch events are preserved, enabling touch-aware + applications to interpet touch gestures. + Character generator rules ------------------------- diff --git a/repos/os/src/server/event_filter/main.cc b/repos/os/src/server/event_filter/main.cc index 56c07fa1e6..e2fbcfda79 100644 --- a/repos/os/src/server/event_filter/main.cc +++ b/repos/os/src/server/event_filter/main.cc @@ -25,6 +25,7 @@ #include <button_scroll_source.h> #include <accelerate_source.h> #include <log_source.h> +#include <touch_click_source.h> #include <event_session.h> namespace Event_filter { struct Main; } @@ -250,6 +251,9 @@ struct Event_filter::Main : Source::Factory, Source::Trigger if (node.type() == Log_source::name()) return *new (_heap) Log_source(owner, node, *this); + if (node.type() == Touch_click_source::name()) + return *new (_heap) Touch_click_source(owner, node, *this); + warning("unknown <", node.type(), "> input-source node type"); throw Source::Invalid_config(); } diff --git a/repos/os/src/server/event_filter/source.h b/repos/os/src/server/event_filter/source.h index d45176bddc..629ff0cc89 100644 --- a/repos/os/src/server/event_filter/source.h +++ b/repos/os/src/server/event_filter/source.h @@ -47,7 +47,8 @@ class Event_filter::Source || node.type() == "merge" || node.type() == "button-scroll" || node.type() == "accelerate" - || node.type() == "log"; + || node.type() == "log" + || node.type() == "touch-click"; return false; } diff --git a/repos/os/src/server/event_filter/touch_click_source.h b/repos/os/src/server/event_filter/touch_click_source.h new file mode 100644 index 0000000000..cc84a12f82 --- /dev/null +++ b/repos/os/src/server/event_filter/touch_click_source.h @@ -0,0 +1,96 @@ +/* + * \brief Input-event source that augments touch events with pointer events + * \author Norman Feske + * \date 2021-11-22 + * + * This filter supplements touch events with absolute motion events and + * artificial mouse click/release events as understood by regular GUI + * applications. The original touch events are preserved, which enables + * touch-aware applications to interpret them. + */ + +/* + * Copyright (C) 2021 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 _EVENT_FILTER__TOUCH_CLICK_SOURCE_H_ +#define _EVENT_FILTER__TOUCH_CLICK_SOURCE_H_ + +/* Genode includes */ +#include <input/keycodes.h> + +/* local includes */ +#include <source.h> + +namespace Event_filter { class Touch_click_source; } + + +class Event_filter::Touch_click_source : public Source, Source::Filter +{ + private: + + Owner _owner; + + Source &_source; + + bool _pressed = false; + + /** + * Filter interface + */ + void filter_event(Sink &destination, Input::Event const &event) override + { + Input::Event ev = event; + + /* forward original event */ + destination.submit(ev); + + /* supplement mouse click and absolute motion */ + ev.handle_touch([&] (Input::Touch_id id, float x, float y) { + + /* respond to first finger only */ + if (id.value != 0) + return; + + destination.submit(Input::Absolute_motion{ int(x), int(y) }); + + if (!_pressed) { + destination.submit(Input::Press { Input::BTN_LEFT }); + _pressed = true; + } + }); + + /* supplement mouse clack */ + ev.handle_touch_release([&] (Input::Touch_id id) { + + if (id.value != 0) + return; + + if (_pressed) { + destination.submit(Input::Release { Input::BTN_LEFT }); + _pressed = false; + } + }); + } + + public: + + static char const *name() { return "touch-click"; } + + Touch_click_source(Owner &owner, Xml_node config, Source::Factory &factory) + : + Source(owner), + _owner(factory), + _source(factory.create_source(_owner, input_sub_node(config))) + { } + + void generate(Sink &destination) override + { + Source::Filter::apply(destination, *this, _source); + } +}; + +#endif /* _EVENT_FILTER__TOUCH_CLICK_SOURCE_H_*/