input_filter: accelerate relative motion events

This commit is contained in:
Norman Feske 2017-11-03 15:29:29 +01:00 committed by Christian Helmuth
parent 55dc3abf00
commit 26d4753a3c
5 changed files with 182 additions and 1 deletions

View File

@ -306,6 +306,51 @@ append config {
<expect_release code="BTN_MIDDLE"/> <expect_release code="BTN_MIDDLE"/>
<message string="accleration of relative motion events"/>
<!-- linear acceleration -->
<filter_config>
<input label="usb"/>
<output>
<accelerate max="100" curve="0" sensitivity_percent="200">
<input name="usb"/>
</accelerate>
</output>
</filter_config>
<sleep ms="100"/>
<usb>
<motion rx="1"/>
<motion rx="20"/>
<motion rx="100"/>
<motion rx="-100"/>
</usb>
<expect_motion rx="1"/>
<expect_motion rx="35"/>
<expect_motion rx="178"/>
<expect_motion rx="-178"/>
<!-- non-linear acceleration -->
<filter_config>
<input label="usb"/>
<output>
<accelerate max="100" curve="127" sensitivity_percent="200">
<input name="usb"/>
</accelerate>
</output>
</filter_config>
<sleep ms="100"/>
<usb>
<motion rx="1"/>
<motion rx="20"/>
<motion rx="100"/>
<motion rx="-100"/>
</usb>
<expect_motion rx="1"/>
<expect_motion rx="23"/>
<expect_motion rx="191"/>
<expect_motion rx="-191"/>
<message string="survive deeply nested config"/> <message string="survive deeply nested config"/>
<deep_filter_config depth="50"/> <deep_filter_config depth="50"/>

View File

@ -54,6 +54,16 @@ one of the following filters:
such that pointer movements are inhibited while the wheel emulation is such that pointer movements are inhibited while the wheel emulation is
active. All other events are passed along unmodified. active. All other events are passed along unmodified.
:<accelerate>:
Applies acceleration to relative motion values. The 'max' attribute
defines the maximum value added to the incoming motion values. The
'sensitivity_percent' attribute scales incoming motion values before
applying the (potentially non-linear) acceleration function. The 'curve'
attribute defines the degree of non-linearity of the acceleration. The value
"0" corresponds to a linear function whereas the maximum value "255" applies
a curved function. The default value is "127".
Character generator rules Character generator rules
------------------------- -------------------------

View File

@ -0,0 +1,121 @@
/*
* \brief Input-event source that accelerates relative motion events
* \author Norman Feske
* \date 2017-11-03
*/
/*
* Copyright (C) 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 _INPUT_FILTER__ACCELERATE_SOURCE_H_
#define _INPUT_FILTER__ACCELERATE_SOURCE_H_
/* Genode includes */
#include <util/bezier.h>
#include <input/keycodes.h>
/* local includes */
#include <source.h>
#include <key_code_by_name.h>
namespace Input_filter { class Accelerate_source; }
class Input_filter::Accelerate_source : public Source, Source::Sink
{
private:
Owner _owner;
Source &_source;
Source::Sink &_destination;
/**
* Look-up table used for the non-linear acceleration of motion values
*/
struct Lut
{
unsigned char values[256];
Lut(long curve)
{
/* clamp parameter to valid range */
curve = min(255, max(0, curve));
auto fill_segment = [&] (long x1, long y1, long x2, long y2)
{
for (long i = x1 >> 8; i <= (x2 >> 8); i++) values[i] = y1 >> 8;
};
long const x0 = 0, y0 = 0, x1 = curve, y1 = 0,
x2 = 255 - curve, y2 = 255, x3 = 255, y3 = 255;
bezier(x0<<8, y0<<8, x1<<8, y1<<8, x2<<8, y2<<8, x3<<8, y3<<8,
fill_segment, 8);
}
};
Lut const _lut;
/**
* Scale factor applied to incoming motion values before they are
* used as index into the LUT.
*/
long const _sensitivity_percent;
/**
* Scale factor of values obtained from the LUT. It corresponds to the
* maximum increase of motion values.
*/
long const _max;
long _apply_acceleration(long v) const
{
long const sign = (v < 0) ? -1 : 1,
index = max(0, min(255, (sign*v*_sensitivity_percent)/100)),
accel = (_lut.values[index]*_max)/256;
return v + sign*accel;
}
/**
* Sink interface
*/
void submit_event(Input::Event const &event) override
{
/* forward unrelated events */
if (!event.relative_motion()) {
_destination.submit_event(event);
return;
}
_destination.submit_event(Input::Event(Input::Event::MOTION, 0, 0, 0,
_apply_acceleration(event.rx()),
_apply_acceleration(event.ry())));
}
public:
static char const *name() { return "accelerate"; }
Accelerate_source(Owner &owner, Xml_node config, Source::Sink &destination,
Source::Factory &factory)
:
Source(owner),
_owner(factory),
_source(factory.create_source(_owner, input_sub_node(config), *this)),
_destination(destination),
_lut (config.attribute_value("curve", 127L)),
_sensitivity_percent(config.attribute_value("sensitivity_percent", 100L)),
_max (config.attribute_value("max", 20L))
{ }
void generate() override { _source.generate(); }
};
#endif /* _INPUT_FILTER__ACCELERATE_SOURCE_H_ */

View File

@ -25,6 +25,7 @@
#include <merge_source.h> #include <merge_source.h>
#include <chargen_source.h> #include <chargen_source.h>
#include <button_scroll_source.h> #include <button_scroll_source.h>
#include <accelerate_source.h>
namespace Input_filter { struct Main; } namespace Input_filter { struct Main; }
@ -254,6 +255,9 @@ struct Input_filter::Main : Input_connection::Avail_handler,
if (node.type() == Button_scroll_source::name()) if (node.type() == Button_scroll_source::name())
return *new (_heap) Button_scroll_source(owner, node, sink, *this); return *new (_heap) Button_scroll_source(owner, node, sink, *this);
if (node.type() == Accelerate_source::name())
return *new (_heap) Accelerate_source(owner, node, sink, *this);
warning("unknown <", node.type(), "> input-source node type"); warning("unknown <", node.type(), "> input-source node type");
throw Source::Invalid_config(); throw Source::Invalid_config();
} }

View File

@ -42,7 +42,8 @@ class Input_filter::Source
|| node.type() == "remap" || node.type() == "remap"
|| node.type() == "chargen" || node.type() == "chargen"
|| node.type() == "merge" || node.type() == "merge"
|| node.type() == "button-scroll"; || node.type() == "button-scroll"
|| node.type() == "accelerate";
return false; return false;
} }