From 65389700878640fa0e90419b9cf34f48e4186fca Mon Sep 17 00:00:00 2001 From: alaricljs Date: Sat, 12 Apr 2025 10:43:13 -0400 Subject: binds: add drag_threshold for click/drag isolation (#9839) --------- Co-authored-by: Leeman --- src/layout/IHyprLayout.cpp | 92 +++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 37 deletions(-) (limited to 'src/layout/IHyprLayout.cpp') diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index a0f15f5c..0c1c3788 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -228,7 +228,8 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { } void IHyprLayout::onBeginDragWindow() { - const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); + const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); + static auto PDRAGTHRESHOLD = CConfigValue("binds:drag_threshold"); m_iMouseMoveEventCount = 1; m_vBeginDragSizeXY = Vector2D(); @@ -240,42 +241,11 @@ void IHyprLayout::onBeginDragWindow() { return; } - const bool WAS_FULLSCREEN = DRAGGINGWINDOW->isFullscreen(); - if (WAS_FULLSCREEN) { - Debug::log(LOG, "Dragging a fullscreen window"); - g_pCompositor->setWindowFullscreenInternal(DRAGGINGWINDOW, FSMODE_NONE); - } - - const auto PWORKSPACE = DRAGGINGWINDOW->m_pWorkspace; - - if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) { - Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)"); - g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); + // Try to pick up dragged window now if drag_threshold is disabled + // or at least update dragging related variables for the cursors + g_pInputManager->m_bDragThresholdReached = *PDRAGTHRESHOLD <= 0; + if (updateDragWindow()) return; - } - - DRAGGINGWINDOW->m_bDraggingTiled = false; - - m_vDraggingWindowOriginalFloatSize = DRAGGINGWINDOW->m_vLastFloatingSize; - - if (WAS_FULLSCREEN && DRAGGINGWINDOW->m_bIsFloating) { - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - *DRAGGINGWINDOW->m_vRealPosition = MOUSECOORDS - DRAGGINGWINDOW->m_vRealSize->goal() / 2.f; - } else if (!DRAGGINGWINDOW->m_bIsFloating) { - if (g_pInputManager->dragMode == MBIND_MOVE) { - DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize->goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); - changeWindowFloatingMode(DRAGGINGWINDOW); - DRAGGINGWINDOW->m_bIsFloating = true; - DRAGGINGWINDOW->m_bDraggingTiled = true; - - *DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize->goal() / 2.f; - } - } - - m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); - m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition->goal(); - m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize->goal(); - m_vLastDragXY = m_vBeginDragXY; // get the grab corner static auto RESIZECORNER = CConfigValue("general:resize_corner"); @@ -552,7 +522,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->currentlyDraggedWindow.expired()) return; - const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); + const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); + static auto PDRAGTHRESHOLD = CConfigValue("binds:drag_threshold"); // Window invalid or drag begin size 0,0 meaning we rejected it. if ((!validMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D())) { @@ -560,6 +531,15 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { return; } + // Yoink dragged window here instead if using drag_threshold and it has been reached + if (*PDRAGTHRESHOLD > 0 && !g_pInputManager->m_bDragThresholdReached) { + if ((m_vBeginDragXY.distanceSq(mousePos) <= std::pow(*PDRAGTHRESHOLD, 2) && m_vBeginDragXY == m_vLastDragXY)) + return; + g_pInputManager->m_bDragThresholdReached = true; + if (updateDragWindow()) + return; + } + static auto TIMER = std::chrono::high_resolution_clock::now(), MSTIMER = TIMER; const auto SPECIAL = DRAGGINGWINDOW->onSpecialWorkspace(); @@ -962,3 +942,41 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) { return sizePredicted; } + +bool IHyprLayout::updateDragWindow() { + const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); + + if (g_pInputManager->m_bDragThresholdReached) { + if (DRAGGINGWINDOW->isFullscreen()) { + Debug::log(LOG, "Dragging a fullscreen window"); + g_pCompositor->setWindowFullscreenInternal(DRAGGINGWINDOW, FSMODE_NONE); + } + + const auto PWORKSPACE = DRAGGINGWINDOW->m_pWorkspace; + + if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) { + Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)"); + g_pKeybindManager->changeMouseBindMode(MBIND_INVALID); + return true; + } + } + + DRAGGINGWINDOW->m_bDraggingTiled = false; + m_vDraggingWindowOriginalFloatSize = DRAGGINGWINDOW->m_vLastFloatingSize; + if (!DRAGGINGWINDOW->m_bIsFloating && g_pInputManager->dragMode == MBIND_MOVE) { + DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize->goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); + *DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize->goal() / 2.f; + if (g_pInputManager->m_bDragThresholdReached) { + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_bIsFloating = true; + DRAGGINGWINDOW->m_bDraggingTiled = true; + } + } + + m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); + m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition->goal(); + m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize->goal(); + m_vLastDragXY = m_vBeginDragXY; + + return false; +} -- cgit v1.2.3