From 0928b39e034d73667026fae75ce5b6428f646195 Mon Sep 17 00:00:00 2001 From: pixl Date: Wed, 15 Jul 2020 17:43:24 -0400 Subject: [PATCH] Add ChangeHostAction support --- src/logid/CMakeLists.txt | 1 + src/logid/actions/Action.cpp | 3 + src/logid/actions/ChangeHostAction.cpp | 119 +++++++++++++++++++++++++ src/logid/actions/ChangeHostAction.h | 54 +++++++++++ 4 files changed, 177 insertions(+) create mode 100644 src/logid/actions/ChangeHostAction.cpp create mode 100644 src/logid/actions/ChangeHostAction.h diff --git a/src/logid/CMakeLists.txt b/src/logid/CMakeLists.txt index 8fb86a93..e6102332 100644 --- a/src/logid/CMakeLists.txt +++ b/src/logid/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(logid actions/CycleDPI.cpp actions/ChangeDPI.cpp actions/GestureAction.cpp + actions/ChangeHostAction.cpp actions/gesture/Gesture.cpp actions/gesture/ReleaseGesture.cpp actions/gesture/IntervalGesture.cpp diff --git a/src/logid/actions/Action.cpp b/src/logid/actions/Action.cpp index 307f5df8..ecac552b 100644 --- a/src/logid/actions/Action.cpp +++ b/src/logid/actions/Action.cpp @@ -26,6 +26,7 @@ #include "NullAction.h" #include "CycleDPI.h" #include "ChangeDPI.h" +#include "ChangeHostAction.h" using namespace logid; using namespace logid::actions; @@ -65,6 +66,8 @@ std::shared_ptr Action::makeAction(Device *device, libconfig::Setting return std::make_shared(device, setting); else if(type == "none") return std::make_shared(device); + else if(type == "changehost") + return std::make_shared(device, setting); else throw InvalidAction(type); diff --git a/src/logid/actions/ChangeHostAction.cpp b/src/logid/actions/ChangeHostAction.cpp new file mode 100644 index 00000000..411b8ace --- /dev/null +++ b/src/logid/actions/ChangeHostAction.cpp @@ -0,0 +1,119 @@ +/* + * 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 "ChangeHostAction.h" +#include "../Device.h" +#include "../backend/hidpp20/features/ReprogControls.h" +#include "../util/task.h" + +using namespace logid::actions; +using namespace logid::backend; + +ChangeHostAction::ChangeHostAction(Device *device, libconfig::Setting& +config) : Action(device), _config (device, config) +{ + try { + _change_host = std::make_shared(&device->hidpp20()); + } catch (hidpp20::UnsupportedFeature& e) { + logPrintf(WARN, "%s:%d: ChangeHost feature not supported, " + "ChangeHostAction will not work.", device->hidpp20() + .devicePath().c_str(), device->hidpp20().deviceIndex()); + } +} + +void ChangeHostAction::press() +{ + // Do nothing, wait until release +} + +void ChangeHostAction::release() +{ + if(_change_host) { + task::spawn([this] { + auto host_info = _change_host->getHostInfo(); + auto next_host = _config.nextHost(host_info); + if(next_host != host_info.currentHost) + _change_host->setHost(next_host); + }); + } +} + +uint8_t ChangeHostAction::reprogFlags() const +{ + return hidpp20::ReprogControls::TemporaryDiverted; +} + +ChangeHostAction::Config::Config(Device *device, libconfig::Setting& config) + : Action::Config(device) +{ + try { + auto& host = config.lookup("host"); + if(host.getType() == libconfig::Setting::TypeInt) { + _offset = false; + _host = host; + _host--; // hosts are one-indexed in config + + if(_host < 0) { + logPrintf(WARN, "Line %d: host must be positive.", + host.getSourceLine()); + _offset = true; + _host = 0; + } + + } else if(host.getType() == libconfig::Setting::TypeString) { + _offset = true; + std::string hostmode = host; + std::transform(hostmode.begin(), hostmode.end(), + hostmode.begin(), ::tolower); + + if(hostmode == "next") + _host = 1; + else if(hostmode == "prev" || hostmode == "previous") + _host = -1; + else { + logPrintf(WARN, "Line %d: host must equal an integer, 'next'," + "or 'prev'.", host.getSourceLine()); + _host = 0; + } + } else { + logPrintf(WARN, "Line %d: host must equal an integer, 'next'," + "or 'prev'.", host.getSourceLine()); + _offset = true; + _host = 0; + } + } catch (libconfig::SettingNotFoundException& e) { + logPrintf(WARN, "Line %d: host is a required field, skipping.", + config.getSourceLine()); + _offset = true; + _host = 0; + } +} + +uint8_t ChangeHostAction::Config::nextHost(hidpp20::ChangeHost::HostInfo info) +{ + if(_offset) { + return (info.currentHost + _host) % info.hostCount; + } else { + if(_host >= info.hostCount || _host < 0) { + logPrintf(WARN, "No such host %d, defaulting to current.", + _host+1); + return info.currentHost; + } else + return _host; + } +} \ No newline at end of file diff --git a/src/logid/actions/ChangeHostAction.h b/src/logid/actions/ChangeHostAction.h new file mode 100644 index 00000000..4466a625 --- /dev/null +++ b/src/logid/actions/ChangeHostAction.h @@ -0,0 +1,54 @@ +/* + * 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_CHANGEHOSTACTION_H +#define LOGID_ACTION_CHANGEHOSTACTION_H + +#include +#include "Action.h" +#include "../backend/hidpp20/features/ChangeHost.h" + +namespace logid { +namespace actions +{ + class ChangeHostAction : public Action + { + public: + ChangeHostAction(Device* device, libconfig::Setting& config); + + virtual void press(); + virtual void release(); + + virtual uint8_t reprogFlags() const; + + class Config : public Action::Config + { + public: + Config(Device* device, libconfig::Setting& setting); + uint8_t nextHost(backend::hidpp20::ChangeHost::HostInfo info); + private: + bool _offset; + int _host; + }; + + protected: + std::shared_ptr _change_host; + Config _config; + }; +}} + +#endif //LOGID_ACTION_CHANGEHOSTACTION_H