input: Emulate discrete scrolling from v120 events (#6881)

* seat: avoid sending axis_stop() when source is wheel

 * fix rounding for absolute discrete values greater than 1

Co-authored-by: Agent_00Ming <agent00ming9366@gmail.com>
This commit is contained in:
Agent00Ming 2024-07-18 15:57:08 -04:00 committed by GitHub
parent 300228b503
commit 8e15f91c24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 6 deletions

View file

@ -472,6 +472,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("input:scroll_button_lock", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:scroll_button_lock", Hyprlang::INT{0});
m_pConfig->addConfigValue("input:scroll_factor", {1.f}); m_pConfig->addConfigValue("input:scroll_factor", {1.f});
m_pConfig->addConfigValue("input:scroll_points", {STRVAL_EMPTY}); 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:natural_scroll", Hyprlang::INT{0});
m_pConfig->addConfigValue("input:touchpad:disable_while_typing", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:touchpad:disable_while_typing", Hyprlang::INT{1});
m_pConfig->addConfigValue("input:touchpad:clickfinger_behavior", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:touchpad:clickfinger_behavior", Hyprlang::INT{0});

View file

@ -333,9 +333,7 @@ void CSeatManager::sendPointerAxis(uint32_t timeMs, wl_pointer_axis axis, double
if (source == 0) { if (source == 0) {
p->sendAxisValue120(axis, value120); p->sendAxisValue120(axis, value120);
p->sendAxisDiscrete(axis, discrete); p->sendAxisDiscrete(axis, discrete);
} } else if (value == 0)
if (value == 0)
p->sendAxisStop(timeMs, axis); p->sendAxisStop(timeMs, axis);
} }
} }

View file

@ -760,6 +760,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) {
static auto POFFWINDOWAXIS = CConfigValue<Hyprlang::INT>("input:off_window_axis_events"); static auto POFFWINDOWAXIS = CConfigValue<Hyprlang::INT>("input:off_window_axis_events");
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor"); static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad: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); auto factor = (*PTOUCHPADSCROLLFACTOR <= 0.f || e.source == WL_POINTER_AXIS_SOURCE_FINGER ? *PTOUCHPADSCROLLFACTOR : *PINPUTSCROLLFACTOR);
@ -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), double discrete = (e.deltaDiscrete != 0) ? (factor * e.deltaDiscrete / std::abs(e.deltaDiscrete)) : 0;
std::round(factor * e.deltaDiscrete), e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); 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() { Vector2D CInputManager::getMouseCoordsInternal() {

View file

@ -278,6 +278,14 @@ class CInputManager {
void restoreCursorIconToApp(); // no-op if restored 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 CKeybindManager;
friend class CWLSurface; friend class CWLSurface;
}; };