binds: add drag_threshold for click/drag isolation (#9839)

---------

Co-authored-by: Leeman <lstrout@enlj.com>
This commit is contained in:
alaricljs 2025-04-12 10:43:13 -04:00 committed by GitHub
parent 0399e64274
commit 6538970087
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 103 additions and 41 deletions

View file

@ -460,6 +460,7 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
.modmaskAtPressTime = MODS,
.sent = true,
.submapAtPress = m_szCurrentSelectedSubmap,
.mousePosAtPress = g_pInputManager->getMouseCoordsInternal(),
};
m_vActiveKeybinds.clear();
@ -551,6 +552,7 @@ bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) {
const auto KEY = SPressedKeyWithMods{
.keyName = KEY_NAME,
.modmaskAtPressTime = MODS,
.mousePosAtPress = g_pInputManager->getMouseCoordsInternal(),
};
m_vActiveKeybinds.clear();
@ -638,7 +640,9 @@ std::string CKeybindManager::getCurrentSubmap() {
SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) {
static auto PDISABLEINHIBIT = CConfigValue<Hyprlang::INT>("binds:disable_keybind_grabbing");
bool found = false;
static auto PDRAGTHRESHOLD = CConfigValue<Hyprlang::INT>("binds:drag_threshold");
bool found = false;
SDispatchResult res;
if (pressed) {
@ -736,6 +740,14 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
found = true; // suppress the event
continue;
}
// Require mouse to stay inside drag_threshold for clicks, outside for drags
// Check if either a mouse bind has triggered or currently over the threshold (maybe there is no mouse bind on the same key)
const auto THRESHOLDREACHED = key.mousePosAtPress.distanceSq(g_pInputManager->getMouseCoordsInternal()) > std::pow(*PDRAGTHRESHOLD, 2);
if (k->click && (g_pInputManager->m_bDragThresholdReached || THRESHOLDREACHED))
continue;
else if (k->drag && !g_pInputManager->m_bDragThresholdReached && !THRESHOLDREACHED)
continue;
}
if (k->longPress) {
@ -788,6 +800,8 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
found = true;
}
g_pInputManager->m_bDragThresholdReached = false;
// if keybind wasn't found (or dispatcher said to) then pass event
res.passEvent |= !found;

View file

@ -39,6 +39,8 @@ struct SKeybind {
bool multiKey = false;
bool hasDescription = false;
bool dontInhibit = false;
bool click = false;
bool drag = false;
// DO NOT INITIALIZE
bool shadowed = false;
@ -62,6 +64,7 @@ struct SPressedKeyWithMods {
uint32_t modmaskAtPressTime = 0;
bool sent = false;
std::string submapAtPress = "";
Vector2D mousePosAtPress = {};
};
struct SParsedKey {

View file

@ -147,8 +147,9 @@ class CInputManager {
// for dragging floating windows
PHLWINDOWREF currentlyDraggedWindow;
eMouseBindMode dragMode = MBIND_INVALID;
bool m_bWasDraggingWindow = false;
eMouseBindMode dragMode = MBIND_INVALID;
bool m_bWasDraggingWindow = false;
bool m_bDragThresholdReached = false;
// for refocus to be forced
PHLWINDOWREF m_pForcedFocus;