genode/repos/os/src/server/input_filter/accelerate_source.h

122 lines
3.0 KiB
C++

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