mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-14 05:12:34 +08:00
Add full profile support
This commit is contained in:
parent
c0e532b1de
commit
27b6a2fd8f
@ -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) {
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -61,4 +61,7 @@ void DeviceStatus::listen() {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceStatus::setProfile(config::Profile&) {
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ namespace logid::features {
|
||||
|
||||
void listen() final;
|
||||
|
||||
void setProfile(config::Profile& profile) final;
|
||||
|
||||
protected:
|
||||
explicit DeviceStatus(Device* dev);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user