Add Gesture support
Only supports OnRelease right now. Also, some bugs were spotted while writing this: - Sometimes deadlocks on startup (cause unknown) - Sometimes valid CIDs will be unknown (bug may have been fixed?)
This commit is contained in:
parent
41049deb35
commit
0fbeb1e3c9
|
@ -24,6 +24,9 @@ add_executable(logid
|
|||
actions/KeypressAction.cpp
|
||||
actions/ToggleHiresScroll.cpp
|
||||
actions/ToggleSmartShift.cpp
|
||||
actions/GestureAction.cpp
|
||||
actions/gesture/Gesture.cpp
|
||||
actions/gesture/ReleaseGesture.cpp
|
||||
backend/Error.cpp
|
||||
backend/raw/DeviceMonitor.cpp
|
||||
backend/raw/RawDevice.cpp
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace logid
|
|||
int workerCount() const;
|
||||
private:
|
||||
std::map<std::string, std::string> _device_paths;
|
||||
std::chrono::milliseconds _io_timeout;
|
||||
std::chrono::milliseconds _io_timeout = LOGID_DEFAULT_RAWDEVICE_TIMEOUT;
|
||||
int _worker_threads;
|
||||
libconfig::Config _config;
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "KeypressAction.h"
|
||||
#include "ToggleSmartShift.h"
|
||||
#include "ToggleHiresScroll.h"
|
||||
#include "GestureAction.h"
|
||||
|
||||
using namespace logid;
|
||||
using namespace logid::actions;
|
||||
|
@ -53,6 +54,8 @@ std::shared_ptr<Action> Action::makeAction(Device *device, libconfig::Setting
|
|||
return std::make_shared<ToggleSmartShift>(device);
|
||||
else if(type == "togglehiresscroll")
|
||||
return std::make_shared<ToggleHiresScroll>(device);
|
||||
else if(type == "gestures")
|
||||
return std::make_shared<GestureAction>(device, setting);
|
||||
else
|
||||
throw InvalidAction(type);
|
||||
|
||||
|
|
|
@ -65,11 +65,10 @@ namespace actions {
|
|||
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
protected:
|
||||
explicit Config(Device* device) : _device (device)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
Device* _device;
|
||||
};
|
||||
protected:
|
||||
|
|
269
src/logid/actions/GestureAction.cpp
Normal file
269
src/logid/actions/GestureAction.cpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include "GestureAction.h"
|
||||
#include "../Device.h"
|
||||
#include "../backend/hidpp20/features/ReprogControls.h"
|
||||
|
||||
using namespace logid::actions;
|
||||
using namespace logid;
|
||||
using namespace logid::backend;
|
||||
|
||||
GestureAction::Direction GestureAction::toDirection(std::string direction)
|
||||
{
|
||||
std::transform(direction.begin(), direction.end(), direction.begin(),
|
||||
::tolower);
|
||||
if(direction == "up")
|
||||
return Up;
|
||||
else if(direction == "down")
|
||||
return Down;
|
||||
else if(direction == "left")
|
||||
return Left;
|
||||
else if(direction == "right")
|
||||
return Right;
|
||||
else if(direction == "none")
|
||||
return None;
|
||||
else
|
||||
throw std::invalid_argument("direction");
|
||||
}
|
||||
|
||||
GestureAction::Direction GestureAction::toDirection(int16_t x, int16_t y)
|
||||
{
|
||||
if(x >= 0 && y >= 0)
|
||||
return x >= y ? Right : Down;
|
||||
else if(x < 0 && y >= 0)
|
||||
return -x <= y ? Down : Left;
|
||||
else if(x <= 0 && y < 0)
|
||||
return x <= y ? Left : Up;
|
||||
else
|
||||
return x <= -y ? Up : Right;
|
||||
}
|
||||
|
||||
GestureAction::GestureAction(Device* dev, libconfig::Setting& config) :
|
||||
Action (dev), _config (dev, config)
|
||||
{
|
||||
}
|
||||
|
||||
void GestureAction::press()
|
||||
{
|
||||
_pressed = true;
|
||||
_x = 0, _y = 0;
|
||||
for(auto& gesture : _config.gestures())
|
||||
gesture.second->press();
|
||||
}
|
||||
|
||||
void GestureAction::release()
|
||||
{
|
||||
_pressed = false;
|
||||
bool threshold_met = false;
|
||||
|
||||
auto d = toDirection(_x, _y);
|
||||
auto primary_gesture = _config.gestures().find(d);
|
||||
if(primary_gesture != _config.gestures().end()) {
|
||||
threshold_met = primary_gesture->second->metThreshold();
|
||||
primary_gesture->second->release(true);
|
||||
}
|
||||
|
||||
for(auto& gesture : _config.gestures()) {
|
||||
if(gesture.first == d)
|
||||
continue;
|
||||
if(!threshold_met) {
|
||||
if(gesture.second->metThreshold()) {
|
||||
// If the primary gesture did not meet its threshold, use the
|
||||
// secondary one.
|
||||
threshold_met = true;
|
||||
gesture.second->release(true);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
gesture.second->release(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(!threshold_met) {
|
||||
if(_config.noneAction()) {
|
||||
_config.noneAction()->press();
|
||||
_config.noneAction()->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GestureAction::move(int16_t x, int16_t y)
|
||||
{
|
||||
auto new_x = _x + x, new_y = _y + y;
|
||||
|
||||
if(abs(x) > 0) {
|
||||
if(_x < 0 && new_x >= 0) { // Left -> Origin/Right
|
||||
auto left = _config.gestures().find(Left);
|
||||
if(left != _config.gestures().end())
|
||||
left->second->move(_x);
|
||||
if(new_x) { // Ignore to origin
|
||||
auto right = _config.gestures().find(Right);
|
||||
if(right != _config.gestures().end())
|
||||
right->second->move(new_x);
|
||||
}
|
||||
} else if(_x > 0 && new_x <= 0) { // Right -> Origin/Left
|
||||
auto right = _config.gestures().find(Right);
|
||||
if(right != _config.gestures().end())
|
||||
right->second->move(-_x);
|
||||
if(new_x) { // Ignore to origin
|
||||
auto left = _config.gestures().find(Left);
|
||||
if(left != _config.gestures().end())
|
||||
left->second->move(-new_x);
|
||||
}
|
||||
} else if(new_x < 0) { // Origin/Left to Left
|
||||
auto left = _config.gestures().find(Left);
|
||||
if(left != _config.gestures().end())
|
||||
left->second->move(-x);
|
||||
} else if(new_x > 0) { // Origin/Right to Right
|
||||
auto right = _config.gestures().find(Right);
|
||||
if(right != _config.gestures().end())
|
||||
right->second->move(x);
|
||||
}
|
||||
}
|
||||
|
||||
if(abs(y) > 0) {
|
||||
if(_y > 0 && new_y <= 0) { // Up -> Origin/Down
|
||||
auto up = _config.gestures().find(Up);
|
||||
if(up != _config.gestures().end())
|
||||
up->second->move(_y);
|
||||
if(new_y) { // Ignore to origin
|
||||
auto down = _config.gestures().find(Down);
|
||||
if(down != _config.gestures().end())
|
||||
down->second->move(new_y);
|
||||
}
|
||||
} else if(_y < 0 && new_y >= 0) { // Down -> Origin/Up
|
||||
auto down = _config.gestures().find(Down);
|
||||
if(down != _config.gestures().end())
|
||||
down->second->move(-_y);
|
||||
if(new_y) { // Ignore to origin
|
||||
auto up = _config.gestures().find(Up);
|
||||
if(up != _config.gestures().end())
|
||||
up->second->move(-new_y);
|
||||
}
|
||||
} else if(new_y < 0) { // Origin/Up to Up
|
||||
auto up = _config.gestures().find(Up);
|
||||
if(up != _config.gestures().end())
|
||||
up->second->move(-y);
|
||||
} else if(new_y > 0) {// Origin/Down to Down
|
||||
auto down = _config.gestures().find(Down);
|
||||
if(down != _config.gestures().end())
|
||||
down->second->move(y);
|
||||
}
|
||||
}
|
||||
|
||||
_x = new_x; _y = new_y;
|
||||
}
|
||||
|
||||
uint8_t GestureAction::reprogFlags() const
|
||||
{
|
||||
return (hidpp20::ReprogControls::TemporaryDiverted |
|
||||
hidpp20::ReprogControls::RawXYDiverted);
|
||||
}
|
||||
|
||||
GestureAction::Config::Config(Device* device, libconfig::Setting &root) :
|
||||
Action::Config(device)
|
||||
{
|
||||
try {
|
||||
auto& gestures = root.lookup("gestures");
|
||||
|
||||
if(!gestures.isList()) {
|
||||
logPrintf(WARN, "Line %d: gestures must be a list, ignoring.",
|
||||
gestures.getSourceLine());
|
||||
return;
|
||||
}
|
||||
|
||||
int gesture_count = gestures.getLength();
|
||||
|
||||
for(int i = 0; i < gesture_count; i++) {
|
||||
if(!gestures[i].isGroup()) {
|
||||
logPrintf(WARN, "Line %d: gesture must be a group, skipping.",
|
||||
gestures[i].getSourceLine());
|
||||
continue;
|
||||
}
|
||||
|
||||
Direction d;
|
||||
try {
|
||||
auto& direction = gestures[i].lookup("direction");
|
||||
if(direction.getType() != libconfig::Setting::TypeString) {
|
||||
logPrintf(WARN, "Line %d: direction must be a string, "
|
||||
"skipping.", direction.getSourceLine());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
d = toDirection(direction);
|
||||
} catch(std::invalid_argument& e) {
|
||||
logPrintf(WARN, "Line %d: Invalid direction %s",
|
||||
direction.getSourceLine(), (const char*)direction);
|
||||
continue;
|
||||
}
|
||||
} catch(libconfig::SettingNotFoundException& e) {
|
||||
logPrintf(WARN, "Line %d: direction is a required field, "
|
||||
"skipping.", gestures[i].getSourceLine());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(_gestures.find(d) != _gestures.end() || (d == None && _none_action)) {
|
||||
logPrintf(WARN, "Line %d: Gesture is already defined for "
|
||||
"this direction, duplicate ignored.",
|
||||
gestures[i].getSourceLine());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(d == None) {
|
||||
try {
|
||||
_none_action = Action::makeAction(_device,
|
||||
gestures[i].lookup("action"));
|
||||
} catch (InvalidAction& e) {
|
||||
logPrintf(WARN, "Line %d: %s is not a valid action, "
|
||||
"skipping.", gestures[i].lookup("action")
|
||||
.getSourceLine(), e.what());
|
||||
} catch (libconfig::SettingNotFoundException& e) {
|
||||
logPrintf(WARN, "Line %d: action is a required field, "
|
||||
"skipping.", gestures[i].getSourceLine(),
|
||||
e.what());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
_gestures.emplace(d, Gesture::makeGesture(_device,
|
||||
gestures[i]));
|
||||
} catch(InvalidGesture& e) {
|
||||
logPrintf(WARN, "Line %d: Invalid gesture: %s",
|
||||
gestures[i].getSourceLine(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
} catch(libconfig::SettingNotFoundException& e) {
|
||||
logPrintf(WARN, "Line %d: gestures is a required field, ignoring.",
|
||||
root.getSourceLine());
|
||||
}
|
||||
}
|
||||
|
||||
std::map<GestureAction::Direction, std::shared_ptr<Gesture>>&
|
||||
GestureAction::Config::gestures()
|
||||
{
|
||||
return _gestures;
|
||||
}
|
||||
|
||||
std::shared_ptr<Action> GestureAction::Config::noneAction()
|
||||
{
|
||||
return _none_action;
|
||||
}
|
67
src/logid/actions/GestureAction.h
Normal file
67
src/logid/actions/GestureAction.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef LOGID_ACTION_GESTUREACTION_H
|
||||
#define LOGID_ACTION_GESTUREACTION_H
|
||||
|
||||
#include <map>
|
||||
#include <libconfig.h++>
|
||||
#include "Action.h"
|
||||
#include "gesture/Gesture.h"
|
||||
|
||||
namespace logid {
|
||||
namespace actions {
|
||||
class GestureAction : public Action
|
||||
{
|
||||
public:
|
||||
enum Direction
|
||||
{
|
||||
None,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
static Direction toDirection(std::string direction);
|
||||
static Direction toDirection(int16_t x, int16_t y);
|
||||
|
||||
GestureAction(Device* dev, libconfig::Setting& config);
|
||||
|
||||
virtual void press();
|
||||
virtual void release();
|
||||
virtual void move(int16_t x, int16_t y);
|
||||
|
||||
virtual uint8_t reprogFlags() const;
|
||||
|
||||
class Config : public Action::Config
|
||||
{
|
||||
public:
|
||||
Config(Device* device, libconfig::Setting& root);
|
||||
std::map<Direction, std::shared_ptr<Gesture>>& gestures();
|
||||
std::shared_ptr<Action> noneAction();
|
||||
protected:
|
||||
std::map<Direction, std::shared_ptr<Gesture>> _gestures;
|
||||
std::shared_ptr<Action> _none_action;
|
||||
};
|
||||
|
||||
protected:
|
||||
int16_t _x, _y;
|
||||
Config _config;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif //LOGID_ACTION_GESTUREACTION_H
|
109
src/logid/actions/gesture/Gesture.cpp
Normal file
109
src/logid/actions/gesture/Gesture.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "Gesture.h"
|
||||
#include "../../util/log.h"
|
||||
#include "ReleaseGesture.h"
|
||||
#include "../../backend/hidpp20/features/ReprogControls.h"
|
||||
|
||||
using namespace logid::actions;
|
||||
|
||||
Gesture::Gesture(Device *device) : _device (device)
|
||||
{
|
||||
}
|
||||
|
||||
Gesture::Config::Config(Device* device, libconfig::Setting& root,
|
||||
bool action_required) : _device (device)
|
||||
{
|
||||
if(action_required) {
|
||||
try {
|
||||
_action = Action::makeAction(_device,
|
||||
root.lookup("action"));
|
||||
} catch (libconfig::SettingNotFoundException &e) {
|
||||
throw InvalidGesture("action is missing");
|
||||
}
|
||||
|
||||
if(_action->reprogFlags() & backend::hidpp20::ReprogControls::RawXYDiverted)
|
||||
throw InvalidGesture("gesture cannot require RawXY");
|
||||
}
|
||||
|
||||
_threshold = LOGID_GESTURE_DEFAULT_THRESHOLD;
|
||||
try {
|
||||
auto& threshold = root.lookup("threshold");
|
||||
if(threshold.getType() == libconfig::Setting::TypeInt) {
|
||||
_threshold = (int)threshold;
|
||||
if(_threshold <= 0) {
|
||||
_threshold = LOGID_GESTURE_DEFAULT_THRESHOLD;
|
||||
logPrintf(WARN, "Line %d: threshold must be positive, setting"
|
||||
"to default (%d)", threshold.getSourceLine(),
|
||||
_threshold);
|
||||
}
|
||||
} else
|
||||
logPrintf(WARN, "Line %d: threshold must be an integer, setting "
|
||||
"to default (%d).", threshold.getSourceLine());
|
||||
} catch(libconfig::SettingNotFoundException& e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Gesture> Gesture::makeGesture(Device *device,
|
||||
libconfig::Setting &setting)
|
||||
{
|
||||
if(!setting.isGroup()) {
|
||||
logPrintf(WARN, "Line %d: Gesture is not a group, ignoring.",
|
||||
setting.getSourceLine());
|
||||
throw InvalidGesture();
|
||||
}
|
||||
|
||||
try {
|
||||
auto& gesture_mode = setting.lookup("mode");
|
||||
|
||||
if(gesture_mode.getType() != libconfig::Setting::TypeString) {
|
||||
logPrintf(WARN, "Line %d: Gesture mode must be a string,"
|
||||
"defaulting to OnRelease.",
|
||||
gesture_mode.getSourceLine());
|
||||
return std::make_shared<ReleaseGesture>(device, setting);
|
||||
}
|
||||
|
||||
std::string type = gesture_mode;
|
||||
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
|
||||
|
||||
if(type == "onrelease")
|
||||
return std::make_shared<ReleaseGesture>(device, setting);
|
||||
else {
|
||||
logPrintf(WARN, "Line %d: Unknown gesture mode %s, defaulting to "
|
||||
"OnRelease.", gesture_mode.getSourceLine(),
|
||||
(const char*)gesture_mode);
|
||||
return std::make_shared<ReleaseGesture>(device, setting);
|
||||
}
|
||||
|
||||
} catch(libconfig::SettingNotFoundException& e) {
|
||||
return std::make_shared<ReleaseGesture>(device, setting);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t Gesture::Config::threshold() const
|
||||
{
|
||||
return _threshold;
|
||||
}
|
||||
|
||||
std::shared_ptr<Action> Gesture::Config::action()
|
||||
{
|
||||
return _action;
|
||||
}
|
73
src/logid/actions/gesture/Gesture.h
Normal file
73
src/logid/actions/gesture/Gesture.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef LOGID_ACTION_GESTURE_H
|
||||
#define LOGID_ACTION_GESTURE_H
|
||||
|
||||
#include "../Action.h"
|
||||
|
||||
#define LOGID_GESTURE_DEFAULT_THRESHOLD 50
|
||||
|
||||
namespace logid {
|
||||
namespace actions
|
||||
{
|
||||
class InvalidGesture : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit InvalidGesture(std::string what="") : _what (what)
|
||||
{
|
||||
}
|
||||
virtual const char* what()
|
||||
{
|
||||
return _what.c_str();
|
||||
}
|
||||
private:
|
||||
std::string _what;
|
||||
};
|
||||
|
||||
class Gesture
|
||||
{
|
||||
public:
|
||||
virtual void press() = 0;
|
||||
virtual void release(bool primary=false) = 0;
|
||||
virtual void move(int16_t axis) = 0;
|
||||
|
||||
virtual bool metThreshold() const = 0;
|
||||
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
Config(Device* device, libconfig::Setting& root,
|
||||
bool action_required=true);
|
||||
virtual int16_t threshold() const;
|
||||
virtual std::shared_ptr<Action> action();
|
||||
protected:
|
||||
Device* _device;
|
||||
std::shared_ptr<Action> _action;
|
||||
int16_t _threshold;
|
||||
};
|
||||
|
||||
static std::shared_ptr<Gesture> makeGesture(Device* device,
|
||||
libconfig::Setting& setting);
|
||||
|
||||
protected:
|
||||
explicit Gesture(Device* device);
|
||||
Device* _device;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif //LOGID_ACTION_GESTURE_H
|
49
src/logid/actions/gesture/ReleaseGesture.cpp
Normal file
49
src/logid/actions/gesture/ReleaseGesture.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "ReleaseGesture.h"
|
||||
#include "../../util/log.h"
|
||||
|
||||
using namespace logid::actions;
|
||||
|
||||
ReleaseGesture::ReleaseGesture(Device *device, libconfig::Setting &root) :
|
||||
Gesture (device), _config (device, root)
|
||||
{
|
||||
}
|
||||
|
||||
void ReleaseGesture::press()
|
||||
{
|
||||
_axis = 0;
|
||||
}
|
||||
|
||||
void ReleaseGesture::release(bool primary)
|
||||
{
|
||||
if(metThreshold() && primary) {
|
||||
_config.action()->press();
|
||||
_config.action()->release();
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseGesture::move(int16_t axis)
|
||||
{
|
||||
_axis += axis;
|
||||
}
|
||||
|
||||
bool ReleaseGesture::metThreshold() const
|
||||
{
|
||||
return _axis >= _config.threshold();
|
||||
}
|
43
src/logid/actions/gesture/ReleaseGesture.h
Normal file
43
src/logid/actions/gesture/ReleaseGesture.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef LOGID_ACTION_RELEASEGESTURE_H
|
||||
#define LOGID_ACTION_RELEASEGESTURE_H
|
||||
|
||||
#include "Gesture.h"
|
||||
|
||||
namespace logid {
|
||||
namespace actions
|
||||
{
|
||||
class ReleaseGesture : public Gesture
|
||||
{
|
||||
public:
|
||||
ReleaseGesture(Device* device, libconfig::Setting& root);
|
||||
|
||||
virtual void press();
|
||||
virtual void release(bool primary=false);
|
||||
virtual void move(int16_t axis);
|
||||
|
||||
virtual bool metThreshold() const;
|
||||
|
||||
protected:
|
||||
int16_t _axis;
|
||||
Gesture::Config _config;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif //LOGID_ACTION_RELEASEGESTURE_H
|
|
@ -36,11 +36,11 @@ try { \
|
|||
}
|
||||
|
||||
// Define all of the ReprogControls versions
|
||||
DEFINE_REPROG(ReprogControls, Feature);
|
||||
DEFINE_REPROG(ReprogControlsV2, ReprogControls);
|
||||
DEFINE_REPROG(ReprogControlsV2_2, ReprogControlsV2);
|
||||
DEFINE_REPROG(ReprogControlsV3, ReprogControlsV2_2);
|
||||
DEFINE_REPROG(ReprogControlsV4, ReprogControlsV3);
|
||||
DEFINE_REPROG(ReprogControls, Feature)
|
||||
DEFINE_REPROG(ReprogControlsV2, ReprogControls)
|
||||
DEFINE_REPROG(ReprogControlsV2_2, ReprogControlsV2)
|
||||
DEFINE_REPROG(ReprogControlsV3, ReprogControlsV2_2)
|
||||
DEFINE_REPROG(ReprogControlsV4, ReprogControlsV3)
|
||||
|
||||
std::shared_ptr<ReprogControls> ReprogControls::autoVersion(Device *dev)
|
||||
{
|
||||
|
@ -81,10 +81,16 @@ ReprogControls::ControlInfo ReprogControls::getControlInfo(uint8_t index)
|
|||
|
||||
ReprogControls::ControlInfo ReprogControls::getControlIdInfo(uint16_t cid)
|
||||
{
|
||||
if(_cids.empty()) {
|
||||
for(uint8_t i = 0; i < getControlCount(); i++) {
|
||||
auto info = getControlInfo(i);
|
||||
_cids.emplace(info.controlID, info);
|
||||
if(!_cids_initialized) {
|
||||
std::unique_lock<std::mutex> lock(_cids_populating);
|
||||
if(!_cids_initialized) {
|
||||
uint8_t controls = getControlCount();
|
||||
for(uint8_t i = 0; i < controls; i++) {
|
||||
auto info = getControlInfo(i);
|
||||
_cids.emplace(info.controlID, info);
|
||||
}
|
||||
_cids_populating.unlock();
|
||||
_cids_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,8 @@ namespace hidpp20
|
|||
protected:
|
||||
ReprogControls(Device* dev, uint16_t _id);
|
||||
std::map<uint16_t, ControlInfo> _cids;
|
||||
bool _cids_initialized = false;
|
||||
std::mutex _cids_populating;
|
||||
};
|
||||
|
||||
class ReprogControlsV2 : public ReprogControls
|
||||
|
|
|
@ -56,7 +56,7 @@ void RemapButton::configure()
|
|||
}
|
||||
|
||||
if((i.second->reprogFlags() & hidpp20::ReprogControls::RawXYDiverted) &&
|
||||
(!_reprog_controls->supportsRawXY() || (info.additionalFlags &
|
||||
(!_reprog_controls->supportsRawXY() || !(info.additionalFlags &
|
||||
hidpp20::ReprogControls::RawXY)))
|
||||
logPrintf(WARN, "%s: Cannot divert raw XY movements for CID "
|
||||
"0x%02x", _device->name().c_str(), i.first);
|
||||
|
|
Loading…
Reference in New Issue
Block a user