From 10bb10e5c54919d7231a3ed79f967ad6a31c275e Mon Sep 17 00:00:00 2001 From: pixl Date: Sat, 11 Jul 2020 23:14:32 -0400 Subject: [PATCH] Add Axis gesture --- src/logid/CMakeLists.txt | 1 + src/logid/InputDevice.cpp | 2 +- src/logid/actions/gesture/AxisGesture.cpp | 126 ++++++++++++++++++++++ src/logid/actions/gesture/AxisGesture.h | 55 ++++++++++ src/logid/actions/gesture/Gesture.cpp | 7 +- 5 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 src/logid/actions/gesture/AxisGesture.cpp create mode 100644 src/logid/actions/gesture/AxisGesture.h diff --git a/src/logid/CMakeLists.txt b/src/logid/CMakeLists.txt index c50a83f..55f8f74 100644 --- a/src/logid/CMakeLists.txt +++ b/src/logid/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(logid actions/gesture/Gesture.cpp actions/gesture/ReleaseGesture.cpp actions/gesture/IntervalGesture.cpp + actions/gesture/AxisGesture.cpp backend/Error.cpp backend/raw/DeviceMonitor.cpp backend/raw/RawDevice.cpp diff --git a/src/logid/InputDevice.cpp b/src/logid/InputDevice.cpp index 972d127..041e3f4 100644 --- a/src/logid/InputDevice.cpp +++ b/src/logid/InputDevice.cpp @@ -87,7 +87,7 @@ uint InputDevice::toKeyCode(std::string name) uint InputDevice::toAxisCode(std::string name) { - return _toEventCode(EV_KEY, std::move(name)); + return _toEventCode(EV_REL, std::move(name)); } uint InputDevice::_toEventCode(uint type, const std::string& name) diff --git a/src/logid/actions/gesture/AxisGesture.cpp b/src/logid/actions/gesture/AxisGesture.cpp new file mode 100644 index 0000000..615c893 --- /dev/null +++ b/src/logid/actions/gesture/AxisGesture.cpp @@ -0,0 +1,126 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include +#include "AxisGesture.h" +#include "../../InputDevice.h" +#include "../../util/log.h" + +using namespace logid::actions; + +AxisGesture::AxisGesture(Device *device, libconfig::Setting &root) : + Gesture (device), _config (device, root) +{ +} + +void AxisGesture::press() +{ + _axis = 0; + _axis_remainder = 0; +} + +void AxisGesture::release(bool primary) +{ + // Do nothing + (void)primary; // Suppress unused warning +} + +void AxisGesture::move(int16_t axis) +{ + int16_t new_axis = _axis + axis; + if(new_axis > _config.threshold()) { + double move = axis; + if(_axis < _config.threshold()) + move = new_axis - _config.threshold(); + bool negative_multiplier = _config.multiplier() < 0; + if(negative_multiplier) + move *= -_config.multiplier(); + else + move *= _config.multiplier(); + + double move_floor = floor(move); + _axis_remainder = move - move_floor; + if(_axis_remainder >= 1) { + double int_remainder = floor(_axis_remainder); + move_floor += int_remainder; + _axis_remainder -= int_remainder; + } + + if(negative_multiplier) + move_floor = -move_floor; + + virtual_input->moveAxis(_config.axis(), move_floor); + } + _axis = new_axis; +} + +bool AxisGesture::metThreshold() const +{ + return _axis >= _config.threshold(); +} + +AxisGesture::Config::Config(Device *device, libconfig::Setting &setting) : + Gesture::Config(device, setting, false) +{ + try { + auto& axis = setting.lookup("axis"); + if(axis.isNumber()) { + _axis = axis; + } else if(axis.getType() == libconfig::Setting::TypeString) { + try { + _axis = virtual_input->toAxisCode(axis); + } catch(InputDevice::InvalidEventCode& e) { + logPrintf(WARN, "Line %d: Invalid axis %s, skipping." + , axis.getSourceLine(), axis.c_str()); + } + } else { + logPrintf(WARN, "Line %d: axis must be string or int, skipping.", + axis.getSourceLine(), axis.c_str()); + throw InvalidGesture(); + } + } catch(libconfig::SettingNotFoundException& e) { + logPrintf(WARN, "Line %d: axis is a required field, skippimg.", + setting.getSourceLine()); + throw InvalidGesture(); + } + + try { + auto& multiplier = setting.lookup("axis_multiplier"); + if(multiplier.isNumber()) { + if(multiplier.getType() == libconfig::Setting::TypeFloat) + _multiplier = multiplier; + else + _multiplier = (int)multiplier; + } else { + logPrintf(WARN, "Line %d: axis_multiplier must be a number, " + "setting to default (1).", + multiplier.getSourceLine()); + } + } catch(libconfig::SettingNotFoundException& e) { + // Ignore + } +} + +unsigned int AxisGesture::Config::axis() const +{ + return _axis; +} + +double AxisGesture::Config::multiplier() const +{ + return _multiplier; +} \ No newline at end of file diff --git a/src/logid/actions/gesture/AxisGesture.h b/src/logid/actions/gesture/AxisGesture.h new file mode 100644 index 0000000..2b69d41 --- /dev/null +++ b/src/logid/actions/gesture/AxisGesture.h @@ -0,0 +1,55 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOGID_ACTION_AXISGESTURE_H +#define LOGID_ACTION_AXISGESTURE_H + +#include "Gesture.h" + +namespace logid { + namespace actions + { + class AxisGesture : public Gesture + { + public: + AxisGesture(Device* device, libconfig::Setting& root); + + virtual void press(); + virtual void release(bool primary=false); + virtual void move(int16_t axis); + + virtual bool metThreshold() const; + + class Config : public Gesture::Config + { + public: + Config(Device* device, libconfig::Setting& setting); + unsigned int axis() const; + double multiplier() const; + private: + unsigned int _axis; + double _multiplier = 1; + }; + + protected: + int16_t _axis; + double _axis_remainder; + Config _config; + }; + }} + +#endif //LOGID_ACTION_AXISGESTURE_H diff --git a/src/logid/actions/gesture/Gesture.cpp b/src/logid/actions/gesture/Gesture.cpp index bebba9b..04b1460 100644 --- a/src/logid/actions/gesture/Gesture.cpp +++ b/src/logid/actions/gesture/Gesture.cpp @@ -22,6 +22,7 @@ #include "ReleaseGesture.h" #include "../../backend/hidpp20/features/ReprogControls.h" #include "IntervalGesture.h" +#include "AxisGesture.h" using namespace logid::actions; @@ -51,7 +52,7 @@ Gesture::Config::Config(Device* device, libconfig::Setting& root, _threshold = (int)threshold; if(_threshold <= 0) { _threshold = LOGID_GESTURE_DEFAULT_THRESHOLD; - logPrintf(WARN, "Line %d: threshold must be positive, setting" + logPrintf(WARN, "Line %d: threshold must be positive, setting " "to default (%d)", threshold.getSourceLine(), _threshold); } @@ -87,8 +88,10 @@ std::shared_ptr Gesture::makeGesture(Device *device, if(type == "onrelease") return std::make_shared(device, setting); - if(type == "oninterval" || type == "onfewpixels") + else if(type == "oninterval" || type == "onfewpixels") return std::make_shared(device, setting); + else if(type == "axis") + return std::make_shared(device, setting); else { logPrintf(WARN, "Line %d: Unknown gesture mode %s, defaulting to " "OnRelease.", gesture_mode.getSourceLine(),