Skip to content

Commit

Permalink
Emulate discrete scrolling from v120 events
Browse files Browse the repository at this point in the history
  • Loading branch information
Agent_00Ming committed Jul 16, 2024
1 parent 293e687 commit 3fa01f0
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("input:scroll_button_lock", Hyprlang::INT{0});
m_pConfig->addConfigValue("input:scroll_factor", {1.f});
m_pConfig->addConfigValue("input:scroll_points", {STRVAL_EMPTY});
m_pConfig->addConfigValue("input:emulate_discrete_scroll", Hyprlang::INT{1});
m_pConfig->addConfigValue("input:touchpad:natural_scroll", Hyprlang::INT{0});
m_pConfig->addConfigValue("input:touchpad:disable_while_typing", Hyprlang::INT{1});
m_pConfig->addConfigValue("input:touchpad:clickfinger_behavior", Hyprlang::INT{0});
Expand Down
4 changes: 1 addition & 3 deletions src/managers/SeatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,7 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double
if (source == 0) {
p->sendAxisValue120(axis, value120);
p->sendAxisDiscrete(axis, discrete);
}

if (value == 0)
} else if (value == 0)
p->sendAxisStop(timeMs, axis);
}
}
Expand Down
42 changes: 39 additions & 3 deletions src/managers/input/InputManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) {
static auto POFFWINDOWAXIS = CConfigValue<Hyprlang::INT>("input:off_window_axis_events");
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
static auto PEMULATEDISCRETE = CConfigValue<Hyprlang::INT>("input:emulate_discrete_scroll");

auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e.source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR);

Expand Down Expand Up @@ -798,9 +799,44 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) {
}
}
}
double deltaDiscrete = (e.deltaDiscrete != 0) ? (factor * e.deltaDiscrete / std::abs(e.deltaDiscrete)) : 0;
g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, factor * e.delta, deltaDiscrete > 0 ? std::ceil(deltaDiscrete) : std::floor(deltaDiscrete),
std::round(factor * e.deltaDiscrete), e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL);

double discrete = (e.deltaDiscrete != 0) ? (factor * e.deltaDiscrete / std::abs(e.deltaDiscrete)) : 0;
double delta = e.delta * factor;

if (e.source == 0) {
// if an application supports v120, it should ignore discrete anyways
if ((*PEMULATEDISCRETE >= 1 && std::abs(e.deltaDiscrete) != 120) || *PEMULATEDISCRETE >= 2) {

const int interval = factor != 0 ? std::round(120 * (1 / factor)) : 120;

// reset the accumulator when timeout is reached or direction/axis has changed
if (std::signbit(e.deltaDiscrete) != m_ScrollWheelState.lastEventSign || e.axis != m_ScrollWheelState.lastEventAxis ||
e.timeMs - m_ScrollWheelState.lastEventTime > 500 /* 500ms taken from libinput default timeout */) {

m_ScrollWheelState.accumulatedScroll = 0;
// send 1 discrete on first event for responsiveness
discrete = std::copysign(1, e.deltaDiscrete);
} else
discrete = 0;

for (int ac = m_ScrollWheelState.accumulatedScroll; ac >= interval; ac -= interval) {
discrete += std::copysign(1, e.deltaDiscrete);
m_ScrollWheelState.accumulatedScroll -= interval;
}

m_ScrollWheelState.lastEventSign = std::signbit(e.deltaDiscrete);
m_ScrollWheelState.lastEventAxis = e.axis;
m_ScrollWheelState.lastEventTime = e.timeMs;
m_ScrollWheelState.accumulatedScroll += std::abs(e.deltaDiscrete);

delta = 15.0 * discrete * factor;
}
}

int32_t value120 = std::round(factor * e.deltaDiscrete);
int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete);

g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL);
}

Vector2D CInputManager::getMouseCoordsInternal() {
Expand Down
8 changes: 8 additions & 0 deletions src/managers/input/InputManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ class CInputManager {

void restoreCursorIconToApp(); // no-op if restored

// discrete scrolling emulation using v120 data
struct {
bool lastEventSign = 0;
bool lastEventAxis = 0;
uint32_t lastEventTime = 0;
uint32_t accumulatedScroll = 0;
} m_ScrollWheelState;

friend class CKeybindManager;
friend class CWLSurface;
};
Expand Down

0 comments on commit 3fa01f0

Please sign in to comment.