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
This commit is contained in:
Norman Feske 2021-11-22 14:01:36 +01:00 committed by Christian Helmuth
parent 09d020508c
commit 133d21ad38
4 changed files with 109 additions and 1 deletions

View File

@ -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
-------------------------

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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_*/