Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GestureAction: Add scroll support #384

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/logid/actions/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ namespace logid::actions {

virtual void move([[maybe_unused]] int16_t x, [[maybe_unused]] int16_t y) { }

virtual void scroll(int16_t s) {
// Suppress unused warning
(void)s;
};

virtual bool pressed() {
return _pressed;
}
Expand Down
115 changes: 82 additions & 33 deletions src/logid/actions/GestureAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ GestureAction::Direction GestureAction::toDirection(std::string direction) {
return Left;
else if (direction == "right")
return Right;
else if(direction == "scrollup")
return ScrollUp;
else if(direction == "scrolldown")
return ScrollDown;
else if (direction == "none")
return None;
else
Expand All @@ -53,6 +57,10 @@ std::string GestureAction::fromDirection(Direction direction) {
return "left";
case Right:
return "right";
case ScrollUp:
return "scrollup";
case ScrollDown:
return "scrolldown";
case None:
return "none";
}
Expand All @@ -61,15 +69,15 @@ std::string GestureAction::fromDirection(Direction direction) {
throw InvalidGesture();
}

GestureAction::Direction GestureAction::toDirection(int32_t x, int32_t y) {
if (x >= 0 && y >= 0)
return x >= y ? Right : Down;
else if (x < 0 && y >= 0)
return -x <= y ? Down : Left;
else if (x <= 0 /* && y < 0 */)
return x <= y ? Left : Up;
GestureAction::Direction GestureAction::toDirection(int32_t x, int32_t y, int16_t s) {
if(isScroll())
return s > 0 ? ScrollUp : ScrollDown;
else if(isVertical())
return y < 0 ? Up : Down;
else if(isHorizontal())
return x < 0 ? Left : Right;
else
return x <= -y ? Up : Right;
return None;
}

GestureAction::GestureAction(Device* dev, config::GestureAction& config,
Expand Down Expand Up @@ -118,40 +126,50 @@ void GestureAction::release() {
std::shared_lock lock(_config_mutex);

_pressed = false;
bool threshold_met = false;

auto d = toDirection(_x, _y);
auto primary_gesture = _gestures.find(d);
if (primary_gesture != _gestures.end()) {
threshold_met = primary_gesture->second->metThreshold();
primary_gesture->second->release(true);
}
Direction d = toDirection(_x, _y, _s);

for (auto& gesture: _gestures) {
if (gesture.first == d || gesture.first == None)
continue;
if (!threshold_met) {
if (gesture.second->metThreshold()) {
// If the primary gesture did not meet its threshold, use the
// secondary one.
threshold_met = true;
gesture.second->release(true);
}
} else {
gesture.second->release(false);
}
gesture.second->release(gesture.first == d);
}

auto none_gesture = _gestures.find(None);
if (none_gesture != _gestures.end()) {
none_gesture->second->release(!threshold_met);
if (d == None && none_gesture != _gestures.end()) {
none_gesture->second->release(none_gesture->first == d);
}
}

void GestureAction::move(int16_t x, int16_t y) {

bool GestureAction::isScroll()
{
auto scrollUp = _gestures.find(ScrollUp);
bool isScrollUp = scrollUp == _gestures.end() ? false : scrollUp->second->metThreshold();
auto scrollDown = _gestures.find(ScrollDown);
bool isScrollDown = scrollDown == _gestures.end() ? false : scrollDown->second->metThreshold();
return isScrollUp || isScrollDown;
}

bool GestureAction::isVertical()
{
auto up = _gestures.find(Up);
bool isUp = up == _gestures.end() ? false : up->second->metThreshold();
auto down = _gestures.find(Down);
bool isDown = down == _gestures.end() ? false : down->second->metThreshold();
return isUp || isDown;
}

bool GestureAction::isHorizontal()
{
auto left = _gestures.find(Left);
bool isLeft = left == _gestures.end() ? false : left->second->metThreshold();
auto right = _gestures.find(Right);
bool isRight = right == _gestures.end() ? false : right->second->metThreshold();
return isLeft || isRight;
}

void GestureAction::move3D(int16_t x, int16_t y, int16_t s) {
std::shared_lock lock(_config_mutex);

int32_t new_x = _x + x, new_y = _y + y;
int32_t new_x = _x + x, new_y = _y + y, new_s = _s + s;

if (abs(x) > 0) {
if (_x < 0 && new_x >= 0) { // Left -> Origin/Right
Expand Down Expand Up @@ -213,8 +231,39 @@ void GestureAction::move(int16_t x, int16_t y) {
}
}

if (abs(s) > 0) {
if(_s > 0 && new_s <= 0) { // ScrollDown -> Origin/ScrollUp
auto down = _gestures.find(ScrollDown);
if(down != _gestures.end())
down->second->move(_s);
if(new_s) { // Ignore to origin
auto up = _gestures.find(ScrollUp);
if(up != _gestures.end())
up->second->move(new_s);
}
} else if(_s < 0 && new_s >= 0) { // ScrollUp -> Origin/ScrollDown
auto up = _gestures.find(ScrollUp);
if(up != _gestures.end())
up->second->move(-_s);
if(new_s) { // Ignore to origin
auto down = _gestures.find(ScrollDown);
if(down != _gestures.end())
down->second->move(-new_s);
}
} else if(new_s < 0) { // Origin/ScrollDown to ScrollDown
auto down = _gestures.find(ScrollDown);
if(down != _gestures.end())
down->second->move(-s);
} else if(new_s > 0) {// Origin/ScrollUp to ScrollUp
auto up = _gestures.find(ScrollUp);
if(up != _gestures.end())
up->second->move(s);
}
}

_x = new_x;
_y = new_y;
_s = new_s;
}

uint8_t GestureAction::reprogFlags() const {
Expand All @@ -231,7 +280,7 @@ void GestureAction::setGesture(const std::string& direction, const std::string&

if (it != _gestures.end()) {
if (pressed()) {
auto current = toDirection(_x, _y);
auto current = toDirection(_x, _y, _s);
if (it->second)
it->second->release(current == d);
}
Expand Down
25 changes: 21 additions & 4 deletions src/logid/actions/GestureAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ namespace logid::actions {
Up,
Down,
Left,
Right
Right,
ScrollUp,
ScrollDown,
};

static Direction toDirection(std::string direction);

static std::string fromDirection(Direction direction);

static Direction toDirection(int32_t x, int32_t y);
Direction toDirection(int32_t x, int32_t y, int16_t s);

GestureAction(Device* dev, config::GestureAction& config,
const std::shared_ptr<ipcgull::node>& parent);
Expand All @@ -48,18 +50,33 @@ namespace logid::actions {

void release() final;

void move(int16_t x, int16_t y) final;
void move(int16_t x, int16_t y) final {
move3D(x, y, 0);
};

void scroll(int16_t s) {
move3D(0, 0, s);
};

uint8_t reprogFlags() const final;

void setGesture(const std::string& direction,
const std::string& type);

protected:
int32_t _x{}, _y{};
int32_t _x{}, _y{}, _s{};
std::shared_ptr<ipcgull::node> _node;
std::map<Direction, std::shared_ptr<Gesture>> _gestures;
config::GestureAction& _config;

bool isScroll();

bool isVertical();

bool isHorizontal();

private:
void move3D(int16_t, int16_t, int16_t);
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/logid/features/HiresScroll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*
*/
#include <features/HiresScroll.h>
#include <features/RemapButton.h>
#include <actions/gesture/AxisGesture.h>
#include <Device.h>
#include <InputDevice.h>
Expand Down Expand Up @@ -152,6 +153,9 @@ void HiresScroll::_fixGesture(const std::shared_ptr<actions::Gesture>& gesture)
}

void HiresScroll::_handleScroll(hidpp20::HiresScroll::WheelStatus event) {
auto remapbutton = _device->getFeature<features::RemapButton>("remapbutton");
if (remapbutton && remapbutton->onHiresScroll(event.deltaV)) return;

std::shared_lock lock(_config_mutex);
auto now = std::chrono::system_clock::now();
if (std::chrono::duration_cast<std::chrono::seconds>(now - _last_scroll).count() >= 1) {
Expand Down
11 changes: 11 additions & 0 deletions src/logid/features/RemapButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,17 @@ void RemapButton::setProfile(config::Profile& profile) {
button.second->setProfile(config[button.first]);
}

bool RemapButton::onHiresScroll(int16_t deltaV)
{
bool handled = false;
for (const auto& button: _buttons)
if (button.second->pressed()) {
button.second->getAction()->scroll(deltaV);
handled = true;
}
return handled;
}

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);
Expand Down
6 changes: 6 additions & 0 deletions src/logid/features/RemapButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ namespace logid::features {

bool pressed() const;

auto getAction() const {
return _action;
};

private:
friend class ButtonWrapper;

Expand Down Expand Up @@ -97,6 +101,8 @@ namespace logid::features {

void setProfile(config::Profile& profile) final;

bool onHiresScroll(int16_t);

protected:
explicit RemapButton(Device* dev);

Expand Down