Add full profile support

This commit is contained in:
pixl 2023-05-02 18:06:25 -04:00
parent c0e532b1de
commit 27b6a2fd8f
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
16 changed files with 334 additions and 128 deletions

View File

@ -25,6 +25,7 @@
#include <features/DeviceStatus.h>
#include <features/ThumbWheel.h>
#include <backend/hidpp20/features/Reset.h>
#include <util/task.h>
#include <util/log.h>
#include <thread>
#include <utility>
@ -94,9 +95,11 @@ std::shared_ptr<Device> Device::make(
Device::Device(std::string path, backend::hidpp::DeviceIndex index,
const std::shared_ptr<DeviceManager>& 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<backend::raw::RawDevice> 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<features::DPI>("dpi");
_addFeature<features::SmartShift>("smartshift");
@ -180,10 +189,7 @@ void Device::wakeup() {
std::lock_guard<std::mutex> 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<ipcgull::node> Device::ipcNode() const {
return _ipc_node;
}
config::Profile& Device::activeProfile() {
return _profile->second;
std::vector<std::string> Device::getProfiles() const {
std::shared_lock lock(_profile_mutex);
std::vector<std::string> 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<std::string>(
ipcgull::property_readable, device->name())},
{"ProductID", ipcgull::property<uint16_t>(
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<bool>({"active"})}
{"StatusChanged", ipcgull::signal::make_signal<bool>({"active"})}
}), _device(*device) {
}

View File

@ -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<std::string> 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<InputDevice> 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<backend::hidpp20::Device> _hidpp20;
std::string _path;
backend::hidpp::DeviceIndex _index;
std::map<std::string, std::shared_ptr<features::DeviceFeature>>
_features;
std::map<std::string, std::shared_ptr<features::DeviceFeature>> _features;
config::Device& _config;
mutable std::shared_mutex _profile_mutex;
ipcgull::property<std::string> _profile_name;
std::map<std::string, config::Profile>::iterator _profile;
Receiver* _receiver;

View File

@ -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;

View File

@ -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<int>(config)) {
const auto& dpi = std::get<int>(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<std::vector<uint16_t>, 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<int>(_parent._config.value())) {
if (std::holds_alternative<int>(config.value())) {
if (sensor == 0)
return std::get<int>(_parent._config.value());
return std::get<int>(config.value());
else
return _parent.getDPI(sensor);
}
const auto& list = std::get<std::list<int>>(_parent._config.value());
const auto& list = std::get<std::list<int>>(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<int>());
if (!config.has_value())
config.emplace(std::list<int>());
if (std::holds_alternative<int>(_parent._config.value())) {
if (std::holds_alternative<int>(config.value())) {
if (sensor == 0) {
_parent._config.value() = dpi;
config.value() = dpi;
} else {
auto list = std::list<int>(sensor + 1, 0);
*list.rbegin() = dpi;
*list.begin() = dpi;
_parent._config.value() = list;
config.value() = list;
}
} else {
auto& list = std::get<std::list<int>>(_parent._config.value());
auto& list = std::get<std::list<int>>(config.value());
while (list.size() <= sensor) {
list.emplace_back(0);

View File

@ -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::DPI>& _config;
std::reference_wrapper<std::optional<config::DPI>> _config;
std::shared_ptr<backend::hidpp20::AdjustableDPI> _adjustable_dpi;
mutable std::shared_mutex _dpi_list_mutex;
std::vector<backend::hidpp20::AdjustableDPI::SensorDPIList> _dpi_lists;

View File

@ -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;

View File

@ -61,4 +61,7 @@ void DeviceStatus::listen() {
}
});
}
}
}
void DeviceStatus::setProfile(config::Profile&) {
}

View File

@ -30,6 +30,8 @@ namespace logid::features {
void listen() final;
void setProfile(config::Profile& profile) final;
protected:
explicit DeviceStatus(Device* dev);

View File

@ -39,16 +39,28 @@ HiresScroll::HiresScroll(Device* dev) :
throw UnsupportedFeature();
}
if (_config.has_value()) {
if (std::holds_alternative<bool>(_config.value())) {
_makeConfig();
_last_scroll = std::chrono::system_clock::now();
_ipc_interface = dev->ipcNode()->make_interface<IPC>(this);
}
void HiresScroll::_makeConfig() {
auto& config = _config.get();
_mode = 0;
_mask = 0;
if (config.has_value()) {
if (std::holds_alternative<bool>(config.value())) {
config::HiresScroll conf{};
conf.hires = std::get<bool>(_config.value());
conf.hires = std::get<bool>(config.value());
conf.invert = false;
conf.target = false;
_mask |= hidpp20::HiresScroll::Mode::HiRes;
_config.value() = conf;
config.value() = conf;
}
auto& conf = std::get<config::HiresScroll>(_config.value());
auto& conf = std::get<config::HiresScroll>(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<IPC>(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<bool, bool, bool> HiresScroll::IPC::getConfig() const {
std::shared_lock lock(_parent._config_mutex);
if (_parent._config.has_value()) {
if (std::holds_alternative<bool>(_parent._config.value())) {
return {std::get<bool>(_parent._config.value()), false, false};
auto& config = _parent._config.get();
if (config.has_value()) {
if (std::holds_alternative<bool>(config.value())) {
return {std::get<bool>(config.value()), false, false};
} else {
const auto& config = std::get<config::HiresScroll>(_parent._config.value());
const auto& config_obj = std::get<config::HiresScroll>(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<bool, bool, bool> HiresScroll::IPC::getConfig() const {
}
config::HiresScroll& HiresScroll::IPC::_parentConfig() {
if (!_parent._config.has_value()) {
_parent._config = config::HiresScroll();
} else if (std::holds_alternative<bool>(_parent._config.value())) {
bool hires = std::get<bool>(_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<bool>(config.value())) {
bool hires = std::get<bool>(config.value());
auto new_config = config::HiresScroll();
new_config.hires = hires;
config = new_config;
}
return std::get<config::HiresScroll>(_parent._config.value());
return std::get<config::HiresScroll>(config.value());
}
void HiresScroll::IPC::setHires(bool hires) {

View File

@ -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<backend::hidpp::Device> _ev_handler;
void _makeGesture(std::shared_ptr<actions::Gesture>& gesture,
@ -81,7 +85,7 @@ namespace logid::features {
int16_t _last_direction = 0;
mutable std::shared_mutex _config_mutex;
std::optional<std::variant<bool, config::HiresScroll>>& _config;
std::reference_wrapper<std::optional<std::variant<bool, config::HiresScroll>>> _config;
uint8_t _mode;
uint8_t _mask;

View File

@ -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<IPC>(this);
@ -137,6 +138,18 @@ void RemapButton::listen() {
}
}
void RemapButton::setProfile(config::Profile& profile) {
std::lock_guard<std::mutex> 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<uint16_t>& new_state) {
// Ensure I/O doesn't occur while updating button state
std::lock_guard<std::mutex> 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<IPC>(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<std::mutex> lock(_action_lock);
std::shared_lock lock(_action_lock);
if (_action)
_action->press();
}
void Button::release() const {
std::lock_guard<std::mutex> 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<std::mutex> lock(_action_lock);
std::shared_lock lock(_action_lock);
if (_action)
_action->move(x, y);
}
bool Button::pressed() const {
std::lock_guard<std::mutex> lock(_action_lock);
std::shared_lock lock(_action_lock);
if (_action)
return _action->pressed();
return false;
}
void Button::configure() const {
std::lock_guard<std::mutex> 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<ipcgull::node> 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<std::mutex> 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();
}

View File

@ -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<ipcgull::node> 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<ipcgull::node>& root,
@ -72,9 +76,9 @@ namespace logid::features {
Device* _device;
const ConfigFunction _conf_func;
config::Button& _config;
std::reference_wrapper<config::Button> _config;
mutable std::mutex _action_lock;
mutable std::shared_mutex _action_lock;
std::shared_ptr<actions::Action> _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<uint16_t> _pressed_buttons;
std::mutex _button_lock;
std::optional<config::RemapButton>& _config;
std::reference_wrapper<std::optional<config::RemapButton>> _config;
std::map<uint16_t, std::shared_ptr<Button>> _buttons;
std::shared_ptr<ipcgull::node> _ipc_node;

View File

@ -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<bool, bool, bool, uint8_t> 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<bool, bool, bool, uint8_t> 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;
}

View File

@ -22,6 +22,7 @@
#include <backend/hidpp20/features/SmartShift.h>
#include <ipcgull/interface.h>
#include <config/schema.h>
#include <shared_mutex>
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::SmartShift>& _config;
mutable std::shared_mutex _config_mutex;
std::reference_wrapper<std::optional<config::SmartShift>> _config;
std::shared_ptr<backend::hidpp20::SmartShift> _smartshift;
class IPC : public ipcgull::interface {

View File

@ -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<IPC>(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<ThumbWheel>()](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<bool, bool> 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) {

View File

@ -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<actions::Gesture>& 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::ThumbWheel>& _config;
std::reference_wrapper<std::optional<config::ThumbWheel>> _config;
EventHandlerLock<backend::hidpp::Device> _ev_handler;