From 26d4753a3c08c7e0f527c23848633f80c7ee4035 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 3 Nov 2017 15:29:29 +0100 Subject: [PATCH] input_filter: accelerate relative motion events --- repos/os/run/input_filter.run | 45 +++++++ repos/os/src/server/input_filter/README | 10 ++ .../server/input_filter/accelerate_source.h | 121 ++++++++++++++++++ repos/os/src/server/input_filter/main.cc | 4 + repos/os/src/server/input_filter/source.h | 3 +- 5 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 repos/os/src/server/input_filter/accelerate_source.h diff --git a/repos/os/run/input_filter.run b/repos/os/run/input_filter.run index f9b6b8e40..8d25aa7f4 100644 --- a/repos/os/run/input_filter.run +++ b/repos/os/run/input_filter.run @@ -306,6 +306,51 @@ append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repos/os/src/server/input_filter/README b/repos/os/src/server/input_filter/README index f8d9814fe..f29780cec 100644 --- a/repos/os/src/server/input_filter/README +++ b/repos/os/src/server/input_filter/README @@ -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. +:: + + 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 ------------------------- diff --git a/repos/os/src/server/input_filter/accelerate_source.h b/repos/os/src/server/input_filter/accelerate_source.h new file mode 100644 index 000000000..4f16566f2 --- /dev/null +++ b/repos/os/src/server/input_filter/accelerate_source.h @@ -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 +#include + +/* local includes */ +#include +#include + +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_ */ diff --git a/repos/os/src/server/input_filter/main.cc b/repos/os/src/server/input_filter/main.cc index 073443225..e291ecf10 100644 --- a/repos/os/src/server/input_filter/main.cc +++ b/repos/os/src/server/input_filter/main.cc @@ -25,6 +25,7 @@ #include #include #include +#include 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(); } diff --git a/repos/os/src/server/input_filter/source.h b/repos/os/src/server/input_filter/source.h index 3f8bc009c..c0ef40ea7 100644 --- a/repos/os/src/server/input_filter/source.h +++ b/repos/os/src/server/input_filter/source.h @@ -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; }