From 27b6a2fd8f6b0eba915a24a7d61a6a065b2d0c74 Mon Sep 17 00:00:00 2001 From: pixl Date: Tue, 2 May 2023 18:06:25 -0400 Subject: [PATCH] Add full profile support --- src/logid/Device.cpp | 108 ++++++++++++++++++++++++---- src/logid/Device.h | 23 ++++-- src/logid/actions/Action.h | 6 +- src/logid/features/DPI.cpp | 32 +++++---- src/logid/features/DPI.h | 4 +- src/logid/features/DeviceFeature.h | 6 ++ src/logid/features/DeviceStatus.cpp | 5 +- src/logid/features/DeviceStatus.h | 2 + src/logid/features/HiresScroll.cpp | 68 +++++++++++------- src/logid/features/HiresScroll.h | 6 +- src/logid/features/RemapButton.cpp | 64 +++++++++++------ src/logid/features/RemapButton.h | 12 +++- src/logid/features/SmartShift.cpp | 53 +++++++++----- src/logid/features/SmartShift.h | 6 +- src/logid/features/ThumbWheel.cpp | 60 ++++++++++------ src/logid/features/ThumbWheel.h | 7 +- 16 files changed, 334 insertions(+), 128 deletions(-) diff --git a/src/logid/Device.cpp b/src/logid/Device.cpp index 53c59fe..739016f 100644 --- a/src/logid/Device.cpp +++ b/src/logid/Device.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -94,9 +95,11 @@ std::shared_ptr Device::make( Device::Device(std::string path, backend::hidpp::DeviceIndex index, const std::shared_ptr& manager) : _hidpp20(hidpp20::Device::make(path, index, manager, - manager->config()->io_timeout.value_or(defaults::io_timeout))), + manager->config()->io_timeout.value_or( + defaults::io_timeout))), _path(std::move(path)), _index(index), _config(_getConfig(manager, _hidpp20->name())), + _profile_name(ipcgull::property_readable, ""), _receiver(nullptr), _manager(manager), _nickname(manager), @@ -112,6 +115,7 @@ Device::Device(std::shared_ptr raw_device, manager->config()->io_timeout.value_or(defaults::io_timeout))), _path(raw_device->rawPath()), _index(index), _config(_getConfig(manager, _hidpp20->name())), + _profile_name(ipcgull::property_readable, ""), _receiver(nullptr), _manager(manager), _nickname(manager), @@ -127,6 +131,7 @@ Device::Device(Receiver* receiver, hidpp::DeviceIndex index, manager->config()->io_timeout.value_or(defaults::io_timeout))), _path(receiver->path()), _index(index), _config(_getConfig(manager, _hidpp20->name())), + _profile_name(ipcgull::property_readable, ""), _receiver(receiver), _manager(manager), _nickname(manager), @@ -139,9 +144,13 @@ void Device::_init() { logPrintf(INFO, "Device found: %s on %s:%d", name().c_str(), hidpp20().devicePath().c_str(), _index); - _profile = _config.profiles.find(_config.default_profile); - if (_profile == _config.profiles.end()) - _profile = _config.profiles.insert({_config.default_profile, {}}).first; + { + std::unique_lock lock(_profile_mutex); + _profile = _config.profiles.find(_config.default_profile); + if (_profile == _config.profiles.end()) + _profile = _config.profiles.insert({_config.default_profile, {}}).first; + _profile_name = _config.default_profile; + } _addFeature("dpi"); _addFeature("smartshift"); @@ -180,10 +189,7 @@ void Device::wakeup() { std::lock_guard lock(_state_lock); logPrintf(INFO, "%s:%d woke up.", _path.c_str(), _index); - reset(); - - for (auto& feature: _features) - feature.second->configure(); + reconfigure(); if (!_awake) { _awake = true; @@ -191,6 +197,13 @@ void Device::wakeup() { } } +void Device::reconfigure() { + reset(); + + for (auto& feature: _features) + feature.second->configure(); +} + void Device::reset() { if (_reset_mechanism) (*_reset_mechanism)(); @@ -215,11 +228,71 @@ std::shared_ptr Device::ipcNode() const { return _ipc_node; } -config::Profile& Device::activeProfile() { - return _profile->second; +std::vector Device::getProfiles() const { + std::shared_lock lock(_profile_mutex); + + std::vector ret; + for (auto& profile : _config.profiles) { + ret.push_back(profile.first); + } + + return ret; } -const config::Profile& Device::activeProfile() const { +void Device::setProfile(const std::string& profile) { + std::unique_lock lock(_profile_mutex); + + _profile = _config.profiles.find(profile); + if (_profile == _config.profiles.end()) + _profile = _config.profiles.insert({profile, {}}).first; + _profile_name = profile; + + for (auto& feature : _features) + feature.second->setProfile(_profile->second); + + reconfigure(); +} + +void Device::setProfileDelayed(const std::string& profile) { + run_task([self_weak = _self, profile](){ + if (auto self = self_weak.lock()) + self->setProfile(profile); + }); +} + +void Device::removeProfile(const std::string& profile) { + std::unique_lock lock(_profile_mutex); + + if (profile == (std::string)_profile_name) + throw std::invalid_argument("cannot remove active profile"); + else if (profile == (std::string)_config.default_profile) + throw std::invalid_argument("cannot remove default profile"); + + _config.profiles.erase(profile); +} + +void Device::clearProfile(const std::string& profile) { + std::unique_lock lock(_profile_mutex); + + if (profile == (std::string)_profile_name) { + _profile->second = config::Profile(); + + for (auto& feature : _features) + feature.second->setProfile(_profile->second); + + reconfigure(); + } else { + auto it = _config.profiles.find(profile); + if (it != _config.profiles.end()) { + it->second = config::Profile(); + } else { + throw std::invalid_argument("unknown profile"); + } + } +} + +config::Profile& Device::activeProfile() { + std::shared_lock lock(_profile_mutex); return _profile->second; } @@ -243,17 +316,22 @@ void Device::_makeResetMechanism() { Device::IPC::IPC(Device* device) : ipcgull::interface( SERVICE_ROOT_NAME ".Device", - {}, + { + {"GetProfiles", {device, &Device::getProfiles, {"profiles"}}}, + {"SetProfile", {device, &Device::setProfile, {"profile"}}}, + {"RemoveProfile", {device, &Device::removeProfile, {"profile"}}}, + {"ClearProfile", {device, &Device::clearProfile, {"profile"}}} + }, { {"Name", ipcgull::property( ipcgull::property_readable, device->name())}, {"ProductID", ipcgull::property( ipcgull::property_readable, device->pid())}, {"Active", device->_awake}, - {"DefaultProfile", device->_config.default_profile} + {"DefaultProfile", device->_config.default_profile}, + {"ActiveProfile", device->_profile_name} }, { - {"StatusChanged", - ipcgull::signal::make_signal({"active"})} + {"StatusChanged", ipcgull::signal::make_signal({"active"})} }), _device(*device) { } diff --git a/src/logid/Device.h b/src/logid/Device.h index 8af5156..e3cf4c4 100644 --- a/src/logid/Device.h +++ b/src/logid/Device.h @@ -62,10 +62,17 @@ namespace logid { uint16_t pid(); - //config::Device& config(); - config::Profile& activeProfile(); + [[nodiscard]] config::Profile& activeProfile(); - [[nodiscard]] const config::Profile& activeProfile() const; + [[nodiscard]] std::vector getProfiles() const; + + void setProfile(const std::string& profile); + + void setProfileDelayed(const std::string& profile); + + void removeProfile(const std::string& profile); + + void clearProfile(const std::string& profile); backend::hidpp20::Device& hidpp20(); @@ -88,6 +95,8 @@ namespace logid { void sleep(); + void reconfigure(); + void reset(); [[nodiscard]] std::shared_ptr virtualInput() const; @@ -107,7 +116,9 @@ namespace logid { } Device(const Device&) = delete; + Device(Device&&) = delete; + private: friend class DeviceWrapper; @@ -139,9 +150,11 @@ namespace logid { std::shared_ptr _hidpp20; std::string _path; backend::hidpp::DeviceIndex _index; - std::map> - _features; + std::map> _features; + config::Device& _config; + mutable std::shared_mutex _profile_mutex; + ipcgull::property _profile_name; std::map::iterator _profile; Receiver* _receiver; diff --git a/src/logid/actions/Action.h b/src/logid/actions/Action.h index a3c0c79..f00979b 100644 --- a/src/logid/actions/Action.h +++ b/src/logid/actions/Action.h @@ -69,11 +69,7 @@ namespace logid::actions { virtual void release() = 0; - virtual void move(int16_t x, int16_t y) { - // Suppress unused warning - (void) x; - (void) y; - } + virtual void move([[maybe_unused]] int16_t x, [[maybe_unused]] int16_t y) { } virtual bool pressed() { return _pressed; diff --git a/src/logid/features/DPI.cpp b/src/logid/features/DPI.cpp index fd6c970..fdbac5c 100644 --- a/src/logid/features/DPI.cpp +++ b/src/logid/features/DPI.cpp @@ -69,8 +69,8 @@ DPI::DPI(Device* device) : DeviceFeature(device), _config(device->activeProfile( void DPI::configure() { std::shared_lock lock(_config_mutex); - if (_config.has_value()) { - const auto& config = _config.value(); + if (_config.get().has_value()) { + const auto& config = _config.get().value(); if (std::holds_alternative(config)) { const auto& dpi = std::get(config); _fillDPILists(0); @@ -96,6 +96,11 @@ void DPI::configure() { void DPI::listen() { } +void DPI::setProfile(config::Profile& profile) { + std::unique_lock lock(_config_mutex); + _config = profile.dpi; +} + uint16_t DPI::getDPI(uint8_t sensor) { return _adjustable_dpi->getSensorDPI(sensor); } @@ -145,17 +150,19 @@ std::tuple, uint16_t, bool> DPI::IPC::getDPIs(uint8_t sens uint16_t DPI::IPC::getDPI(uint8_t sensor) const { std::shared_lock lock(_parent._config_mutex); - if (!_parent._config.has_value()) + auto& config = _parent._config.get(); + + if (!config.has_value()) return _parent.getDPI(sensor); - if (std::holds_alternative(_parent._config.value())) { + if (std::holds_alternative(config.value())) { if (sensor == 0) - return std::get(_parent._config.value()); + return std::get(config.value()); else return _parent.getDPI(sensor); } - const auto& list = std::get>(_parent._config.value()); + const auto& list = std::get>(config.value()); if (list.size() > sensor) { auto it = list.begin(); @@ -168,21 +175,22 @@ uint16_t DPI::IPC::getDPI(uint8_t sensor) const { void DPI::IPC::setDPI(uint16_t dpi, uint8_t sensor) { std::unique_lock lock(_parent._config_mutex); + auto& config = _parent._config.get(); - if (!_parent._config.has_value()) - _parent._config.emplace(std::list()); + if (!config.has_value()) + config.emplace(std::list()); - if (std::holds_alternative(_parent._config.value())) { + if (std::holds_alternative(config.value())) { if (sensor == 0) { - _parent._config.value() = dpi; + config.value() = dpi; } else { auto list = std::list(sensor + 1, 0); *list.rbegin() = dpi; *list.begin() = dpi; - _parent._config.value() = list; + config.value() = list; } } else { - auto& list = std::get>(_parent._config.value()); + auto& list = std::get>(config.value()); while (list.size() <= sensor) { list.emplace_back(0); diff --git a/src/logid/features/DPI.h b/src/logid/features/DPI.h index 35e40d5..6fff8d8 100644 --- a/src/logid/features/DPI.h +++ b/src/logid/features/DPI.h @@ -31,6 +31,8 @@ namespace logid::features { void listen() final; + void setProfile(config::Profile& profile) final; + uint16_t getDPI(uint8_t sensor = 0); void setDPI(uint16_t dpi, uint8_t sensor = 0); @@ -59,7 +61,7 @@ namespace logid::features { }; mutable std::shared_mutex _config_mutex; - std::optional& _config; + std::reference_wrapper> _config; std::shared_ptr _adjustable_dpi; mutable std::shared_mutex _dpi_list_mutex; std::vector _dpi_lists; diff --git a/src/logid/features/DeviceFeature.h b/src/logid/features/DeviceFeature.h index fc92277..08621e2 100644 --- a/src/logid/features/DeviceFeature.h +++ b/src/logid/features/DeviceFeature.h @@ -26,6 +26,10 @@ namespace logid { class Device; } +namespace logid::config { + struct Profile; +} + namespace logid::features { class UnsupportedFeature : public std::exception { public: @@ -59,6 +63,8 @@ namespace logid::features { virtual void listen() = 0; + virtual void setProfile(config::Profile& profile) = 0; + virtual ~DeviceFeature() = default; DeviceFeature(const DeviceFeature&) = delete; diff --git a/src/logid/features/DeviceStatus.cpp b/src/logid/features/DeviceStatus.cpp index 273fe51..c9a0544 100644 --- a/src/logid/features/DeviceStatus.cpp +++ b/src/logid/features/DeviceStatus.cpp @@ -61,4 +61,7 @@ void DeviceStatus::listen() { } }); } -} \ No newline at end of file +} + +void DeviceStatus::setProfile(config::Profile&) { +} diff --git a/src/logid/features/DeviceStatus.h b/src/logid/features/DeviceStatus.h index ca07e2a..acd98fa 100644 --- a/src/logid/features/DeviceStatus.h +++ b/src/logid/features/DeviceStatus.h @@ -30,6 +30,8 @@ namespace logid::features { void listen() final; + void setProfile(config::Profile& profile) final; + protected: explicit DeviceStatus(Device* dev); diff --git a/src/logid/features/HiresScroll.cpp b/src/logid/features/HiresScroll.cpp index cda67fc..c1c4587 100644 --- a/src/logid/features/HiresScroll.cpp +++ b/src/logid/features/HiresScroll.cpp @@ -39,16 +39,28 @@ HiresScroll::HiresScroll(Device* dev) : throw UnsupportedFeature(); } - if (_config.has_value()) { - if (std::holds_alternative(_config.value())) { + _makeConfig(); + + _last_scroll = std::chrono::system_clock::now(); + + _ipc_interface = dev->ipcNode()->make_interface(this); +} + +void HiresScroll::_makeConfig() { + auto& config = _config.get(); + _mode = 0; + _mask = 0; + + if (config.has_value()) { + if (std::holds_alternative(config.value())) { config::HiresScroll conf{}; - conf.hires = std::get(_config.value()); + conf.hires = std::get(config.value()); conf.invert = false; conf.target = false; _mask |= hidpp20::HiresScroll::Mode::HiRes; - _config.value() = conf; + config.value() = conf; } - auto& conf = std::get(_config.value()); + auto& conf = std::get(config.value()); if (conf.hires.has_value()) { _mask |= hidpp20::HiresScroll::Mode::HiRes; if (conf.hires.value()) @@ -68,10 +80,6 @@ HiresScroll::HiresScroll(Device* dev) : _makeGesture(_up_gesture, conf.up, "up"); _makeGesture(_down_gesture, conf.down, "down"); } - - _last_scroll = std::chrono::system_clock::now(); - - _ipc_interface = dev->ipcNode()->make_interface(this); } void HiresScroll::configure() { @@ -103,6 +111,15 @@ void HiresScroll::listen() { } } +void HiresScroll::setProfile(config::Profile& profile) { + std::unique_lock lock(_config_mutex); + + _up_gesture.reset(); + _down_gesture.reset(); + _config = profile.hiresscroll; + _makeConfig(); +} + uint8_t HiresScroll::getMode() { return _hires_scroll->getMode(); } @@ -189,15 +206,17 @@ HiresScroll::IPC::IPC(HiresScroll* parent) : ipcgull::interface( std::tuple HiresScroll::IPC::getConfig() const { std::shared_lock lock(_parent._config_mutex); - if (_parent._config.has_value()) { - if (std::holds_alternative(_parent._config.value())) { - return {std::get(_parent._config.value()), false, false}; + auto& config = _parent._config.get(); + + if (config.has_value()) { + if (std::holds_alternative(config.value())) { + return {std::get(config.value()), false, false}; } else { - const auto& config = std::get(_parent._config.value()); + const auto& config_obj = std::get(config.value()); return { - config.hires.value_or(true), - config.invert.value_or(false), - config.target.value_or(false) + config_obj.hires.value_or(true), + config_obj.invert.value_or(false), + config_obj.target.value_or(false) }; } } else { @@ -206,16 +225,17 @@ std::tuple HiresScroll::IPC::getConfig() const { } config::HiresScroll& HiresScroll::IPC::_parentConfig() { - if (!_parent._config.has_value()) { - _parent._config = config::HiresScroll(); - } else if (std::holds_alternative(_parent._config.value())) { - bool hires = std::get(_parent._config.value()); - auto config = config::HiresScroll(); - config.hires = hires; - _parent._config = hires; + auto& config = _parent._config.get(); + if (!config.has_value()) { + config = config::HiresScroll(); + } else if (std::holds_alternative(config.value())) { + bool hires = std::get(config.value()); + auto new_config = config::HiresScroll(); + new_config.hires = hires; + config = new_config; } - return std::get(_parent._config.value()); + return std::get(config.value()); } void HiresScroll::IPC::setHires(bool hires) { diff --git a/src/logid/features/HiresScroll.h b/src/logid/features/HiresScroll.h index 2625939..29b8caa 100644 --- a/src/logid/features/HiresScroll.h +++ b/src/logid/features/HiresScroll.h @@ -34,6 +34,8 @@ namespace logid::features { void listen() final; + void setProfile(config::Profile& profile) final; + [[nodiscard]] uint8_t getMode(); void setMode(uint8_t mode); @@ -42,6 +44,8 @@ namespace logid::features { explicit HiresScroll(Device* dev); private: + void _makeConfig(); + EventHandlerLock _ev_handler; void _makeGesture(std::shared_ptr& gesture, @@ -81,7 +85,7 @@ namespace logid::features { int16_t _last_direction = 0; mutable std::shared_mutex _config_mutex; - std::optional>& _config; + std::reference_wrapper>> _config; uint8_t _mode; uint8_t _mask; diff --git a/src/logid/features/RemapButton.cpp b/src/logid/features/RemapButton.cpp index 2933a33..199cbc6 100644 --- a/src/logid/features/RemapButton.cpp +++ b/src/logid/features/RemapButton.cpp @@ -46,8 +46,10 @@ RemapButton::RemapButton(Device* dev) : DeviceFeature(dev), _reprog_controls->initCidMap(); - if (!_config.has_value()) - _config = config::RemapButton(); + auto& config = _config.get(); + + if (!config.has_value()) + config = config::RemapButton(); for (const auto& control: _reprog_controls->getControls()) { const auto i = _buttons.size(); @@ -58,8 +60,7 @@ RemapButton::RemapButton(Device* dev) : DeviceFeature(dev), report.flags = hidpp20_reprog_rebind; if (action) { - if ((action->reprogFlags() & - hidpp20::ReprogControls::RawXYDiverted) && + if ((action->reprogFlags() & hidpp20::ReprogControls::RawXYDiverted) && (!_reprog_controls->supportsRawXY() || !(info.additionalFlags & hidpp20::ReprogControls::RawXY))) logPrintf(WARN, "%s: Cannot divert raw XY movements for CID 0x%02x", @@ -72,7 +73,7 @@ RemapButton::RemapButton(Device* dev) : DeviceFeature(dev), _buttons.emplace(control.second.controlID, Button::make(control.second, (int) i, _device, func, _ipc_node, - _config.value()[control.first])); + config.value()[control.first])); } _ipc_interface = _device->ipcNode()->make_interface(this); @@ -137,6 +138,18 @@ void RemapButton::listen() { } } +void RemapButton::setProfile(config::Profile& profile) { + std::lock_guard lock(_button_lock); + + _config = profile.buttons; + if (!_config.get().has_value()) + _config.get().emplace(); + auto& config = _config.get().value(); + + for(auto& button : _buttons) + button.second->setProfile(config[button.first]); +} + void RemapButton::_buttonEvent(const std::set& new_state) { // Ensure I/O doesn't occur while updating button state std::lock_guard lock(_button_lock); @@ -191,48 +204,59 @@ Button::Button(Info info, int index, _device(device), _conf_func(std::move(conf_func)), _config(config), _info(info) { - if (_config.action.has_value()) { - try { - _action = Action::makeAction(_device, _config.action.value(), _node); - } catch (std::exception& e) { - logPrintf(WARN, "Error creating button action: %s", - e.what()); - } - } + _makeConfig(); _ipc_interface = _node->make_interface(this, _info); } +void Button::_makeConfig() { + auto& config = _config.get(); + if (config.action.has_value()) { + try { + _action = Action::makeAction(_device, config.action.value(), _node); + } catch (std::exception& e) { + logPrintf(WARN, "Error creating button action: %s", e.what()); + } + } +} + void Button::press() const { - std::lock_guard lock(_action_lock); + std::shared_lock lock(_action_lock); if (_action) _action->press(); } void Button::release() const { - std::lock_guard lock(_action_lock); + std::shared_lock lock(_action_lock); if (_action) _action->release(); } void Button::move(int16_t x, int16_t y) const { - std::lock_guard lock(_action_lock); + std::shared_lock lock(_action_lock); if (_action) _action->move(x, y); } bool Button::pressed() const { - std::lock_guard lock(_action_lock); + std::shared_lock lock(_action_lock); if (_action) return _action->pressed(); return false; } void Button::configure() const { - std::lock_guard lock(_action_lock); + std::shared_lock lock(_action_lock); _conf_func(_action); } +void Button::setProfile(config::Button& config) { + std::unique_lock lock(_action_lock); + _config = config; + _action.reset(); + _makeConfig(); +} + std::shared_ptr Button::node() const { return _node; } @@ -265,11 +289,11 @@ void Button::IPC::setAction(const std::string& type) { throw std::invalid_argument("No gesture support"); { - std::lock_guard lock(_button._action_lock); + std::unique_lock lock(_button._action_lock); _button._action.reset(); _button._action = Action::makeAction( _button._device, type, - _button._config.action, _button._node); + _button._config.get().action, _button._node); } _button.configure(); } diff --git a/src/logid/features/RemapButton.h b/src/logid/features/RemapButton.h index 7f49298..231e244 100644 --- a/src/logid/features/RemapButton.h +++ b/src/logid/features/RemapButton.h @@ -42,6 +42,8 @@ namespace logid::features { void move(int16_t x, int16_t y) const; + void setProfile(config::Button& config); + [[nodiscard]] std::shared_ptr node() const; void configure() const; @@ -51,6 +53,8 @@ namespace logid::features { private: friend class ButtonWrapper; + void _makeConfig(); + Button(Info info, int index, Device* device, ConfigFunction conf_func, const std::shared_ptr& root, @@ -72,9 +76,9 @@ namespace logid::features { Device* _device; const ConfigFunction _conf_func; - config::Button& _config; + std::reference_wrapper _config; - mutable std::mutex _action_lock; + mutable std::shared_mutex _action_lock; std::shared_ptr _action; const Info _info; @@ -89,6 +93,8 @@ namespace logid::features { void listen() final; + void setProfile(config::Profile& profile) final; + protected: explicit RemapButton(Device* dev); @@ -99,7 +105,7 @@ namespace logid::features { std::set _pressed_buttons; std::mutex _button_lock; - std::optional& _config; + std::reference_wrapper> _config; std::map> _buttons; std::shared_ptr _ipc_node; diff --git a/src/logid/features/SmartShift.cpp b/src/logid/features/SmartShift.cpp index ed9d0f2..9d960ba 100644 --- a/src/logid/features/SmartShift.cpp +++ b/src/logid/features/SmartShift.cpp @@ -34,8 +34,10 @@ SmartShift::SmartShift(Device* device) : DeviceFeature(device), } void SmartShift::configure() { - if (_config.has_value()) { - const auto& conf = _config.value(); + std::shared_lock lock(_config_mutex); + auto& config = _config.get(); + if (config.has_value()) { + const auto& conf = config.value(); Status settings{}; settings.setActive = conf.on.has_value(); if (settings.setActive) @@ -51,6 +53,11 @@ void SmartShift::configure() { void SmartShift::listen() { } +void SmartShift::setProfile(config::Profile& profile) { + std::unique_lock lock(_config_mutex); + _config = profile.smartshift; +} + SmartShift::Status SmartShift::getStatus() const { return _smartshift->getStatus(); } @@ -94,39 +101,51 @@ void SmartShift::IPC::setThreshold(uint8_t threshold) { } std::tuple SmartShift::IPC::getDefault() const { - if (!_parent._config.has_value()) + std::shared_lock lock(_parent._config_mutex); + + auto& config = _parent._config.get(); + + if (!config.has_value()) return {false, false, false, 0}; std::tuple ret; - std::get<0>(ret) = _parent._config.value().on.has_value(); + std::get<0>(ret) = config.value().on.has_value(); if (std::get<0>(ret)) - std::get<1>(ret) = _parent._config.value().on.value(); - std::get<2>(ret) = _parent._config.value().threshold.has_value(); + std::get<1>(ret) = config.value().on.value(); + std::get<2>(ret) = config.value().threshold.has_value(); if (std::get<2>(ret)) - std::get<3>(ret) = _parent._config.value().threshold.value(); + std::get<3>(ret) = config.value().threshold.value(); return ret; } void SmartShift::IPC::clearDefaultActive() { - if (_parent._config.has_value()) - _parent._config.value().on.reset(); + std::unique_lock lock(_parent._config_mutex); + auto& config = _parent._config.get(); + if (config.has_value()) + config.value().on.reset(); } void SmartShift::IPC::setDefaultActive(bool active) { - if (!_parent._config.has_value()) - _parent._config = config::SmartShift{}; - _parent._config.value().on = active; + std::unique_lock lock(_parent._config_mutex); + auto& config = _parent._config.get(); + if (!config.has_value()) + config = config::SmartShift{}; + config.value().on = active; } void SmartShift::IPC::clearDefaultThreshold() { - if (_parent._config.has_value()) - _parent._config.value().threshold.reset(); + std::unique_lock lock(_parent._config_mutex); + auto& config = _parent._config.get(); + if (config.has_value()) + config.value().threshold.reset(); } void SmartShift::IPC::setDefaultThreshold(uint8_t threshold) { - if (!_parent._config.has_value()) - _parent._config = config::SmartShift{}; - _parent._config.value().threshold = threshold; + std::unique_lock lock(_parent._config_mutex); + auto& config = _parent._config.get(); + if (!config.has_value()) + config = config::SmartShift{}; + config.value().threshold = threshold; } diff --git a/src/logid/features/SmartShift.h b/src/logid/features/SmartShift.h index 63020ae..58abc06 100644 --- a/src/logid/features/SmartShift.h +++ b/src/logid/features/SmartShift.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace logid::features { class SmartShift : public DeviceFeature { @@ -31,6 +32,8 @@ namespace logid::features { void listen() final; + void setProfile(config::Profile& profile) final; + typedef backend::hidpp20::SmartShift::SmartshiftStatus Status; [[nodiscard]] Status getStatus() const; @@ -41,7 +44,8 @@ namespace logid::features { explicit SmartShift(Device* dev); private: - std::optional& _config; + mutable std::shared_mutex _config_mutex; + std::reference_wrapper> _config; std::shared_ptr _smartshift; class IPC : public ipcgull::interface { diff --git a/src/logid/features/ThumbWheel.cpp b/src/logid/features/ThumbWheel.cpp index 9f190a3..d6a06f7 100644 --- a/src/logid/features/ThumbWheel.cpp +++ b/src/logid/features/ThumbWheel.cpp @@ -80,14 +80,7 @@ ThumbWheel::ThumbWheel(Device* dev) : DeviceFeature(dev), _wheel_info(), throw UnsupportedFeature(); } - if (_config.has_value()) { - auto& conf = _config.value(); - _left_gesture = _genGesture(dev, conf.left, _left_node, "left"); - _right_gesture = _genGesture(dev, conf.right, _right_node, "right"); - _touch_action = _genAction(dev, conf.touch, _touch_node); - _tap_action = _genAction(dev, conf.tap, _tap_node); - _proxy_action = _genAction(dev, conf.proxy, _proxy_node); - } + _makeConfig(); _wheel_info = _thumb_wheel->getInfo(); @@ -109,12 +102,24 @@ ThumbWheel::ThumbWheel(Device* dev) : DeviceFeature(dev), _wheel_info(), _ipc_interface = dev->ipcNode()->make_interface(this); } +void ThumbWheel::_makeConfig() { + if (_config.get().has_value()) { + auto& conf = _config.get().value(); + _left_gesture = _genGesture(_device, conf.left, _left_node, "left"); + _right_gesture = _genGesture(_device, conf.right, _right_node, "right"); + _touch_action = _genAction(_device, conf.touch, _touch_node); + _tap_action = _genAction(_device, conf.tap, _tap_node); + _proxy_action = _genAction(_device, conf.proxy, _proxy_node); + } +} + void ThumbWheel::configure() { std::shared_lock lock(_config_mutex); - if (_config.has_value()) { - const auto& config = _config.value(); - _thumb_wheel->setStatus(config.divert.value_or(false), - config.invert.value_or(false)); + auto& config = _config.get(); + if (config.has_value()) { + const auto& value = config.value(); + _thumb_wheel->setStatus(value.divert.value_or(false), + value.invert.value_or(false)); } } @@ -123,10 +128,8 @@ void ThumbWheel::listen() { _ev_handler = _device->hidpp20().addEventHandler( {[index = _thumb_wheel->featureIndex()] (const hidpp::Report& report) -> bool { - return (report.feature() == - index) && - (report.function() == - hidpp20::ThumbWheel::Event); + return (report.feature() == index) && + (report.function() == hidpp20::ThumbWheel::Event); }, [self_weak = self()](const hidpp::Report& report) -> void { if (auto self = self_weak.lock()) @@ -136,6 +139,17 @@ void ThumbWheel::listen() { } } +void ThumbWheel::setProfile(config::Profile& profile) { + std::unique_lock lock(_config_mutex); + _config = profile.thumbwheel; + _left_gesture.reset(); + _right_gesture.reset(); + _touch_action.reset(); + _tap_action.reset(); + _proxy_action.reset(); + _makeConfig(); +} + void ThumbWheel::_handleEvent(hidpp20::ThumbWheel::ThumbwheelEvent event) { std::shared_lock lock(_config_mutex); if (event.flags & hidpp20::ThumbWheel::SingleTap) { @@ -227,22 +241,24 @@ ThumbWheel::IPC::IPC(ThumbWheel* parent) : ipcgull::interface( } config::ThumbWheel& ThumbWheel::IPC::_parentConfig() { - if (!_parent._config.has_value()) { - _parent._config.emplace(); + auto& config = _parent._config.get(); + if (!config.has_value()) { + config.emplace(); } - return _parent._config.value(); + return config.value(); } std::tuple ThumbWheel::IPC::getConfig() const { std::shared_lock lock(_parent._config_mutex); - if (!_parent._config.has_value()) { + auto& config = _parent._config.get(); + if (!config.has_value()) { return {false, false}; } - return {_parent._config.value().divert.value_or(false), - _parent._config.value().invert.value_or(false)}; + return {config.value().divert.value_or(false), + config.value().invert.value_or(false)}; } void ThumbWheel::IPC::setDivert(bool divert) { diff --git a/src/logid/features/ThumbWheel.h b/src/logid/features/ThumbWheel.h index e51f5f8..1b58923 100644 --- a/src/logid/features/ThumbWheel.h +++ b/src/logid/features/ThumbWheel.h @@ -32,7 +32,11 @@ namespace logid::features { void listen() final; + void setProfile(config::Profile& profile) final; + private: + void _makeConfig(); + void _handleEvent(backend::hidpp20::ThumbWheel::ThumbwheelEvent event); void _fixGesture(const std::shared_ptr& gesture) const; @@ -59,6 +63,7 @@ namespace logid::features { private: config::ThumbWheel& _parentConfig(); + ThumbWheel& _parent; }; @@ -82,7 +87,7 @@ namespace logid::features { bool _last_touch = false; mutable std::shared_mutex _config_mutex; - std::optional& _config; + std::reference_wrapper> _config; EventHandlerLock _ev_handler;