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"/>
<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"/>
<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
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
-------------------------

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 <chargen_source.h>
#include <button_scroll_source.h>
#include <accelerate_source.h>
namespace Input_filter { struct Main; }
@ -254,6 +255,9 @@ struct Input_filter::Main : Input_connection::Avail_handler,
if (node.type() == Button_scroll_source::name())
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");
throw Source::Invalid_config();
}

View File

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