diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index 38a3760bb..644bd5d45 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -104,3 +104,34 @@ bool CRegion::containsPoint(const Vector2D& vec) { bool CRegion::empty() { return !pixman_region32_not_empty(&m_rRegion); } + +Vector2D CRegion::closestPoint(const Vector2D& vec) { + double bestDist = __FLT_MAX__; + Vector2D leader = vec; + + for (auto& box : getRects()) { + double x = 0, y = 0; + + if (vec.x >= box.x2) + x = box.x2 - 1; + else if (vec.x < box.x1) + x = box.x1; + else + x = vec.x; + + if (vec.y >= box.y2) + y = box.y2 - 1; + else if (vec.y < box.y1) + y = box.y1; + else + y = vec.y; + + double distance = sqrt(pow(x, 2) + pow(y, 2)); + if (distance < bestDist) { + bestDist = distance; + leader = {x, y}; + } + } + + return leader; +} \ No newline at end of file diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 42458234f..e5a99da2b 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -45,6 +45,7 @@ class CRegion { wlr_box getExtents(); bool containsPoint(const Vector2D& vec); bool empty(); + Vector2D closestPoint(const Vector2D& vec); std::vector getRects() const; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index dca7f1e08..84f6d8989 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -168,8 +168,8 @@ struct SConstraint { bool active = false; - bool hintSet = false; - Vector2D positionHint; // the position hint, but will be set to the current cursor pos if not set. + bool hintSet = false; + Vector2D positionHint = {-1, -1}; // the position hint, but will be set to the current cursor pos if not set. DYNLISTENER(setConstraintRegion); DYNLISTENER(destroyConstraint); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 210eaecce..c16c549bd 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -146,7 +146,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // we restrict the cursor to the confined region if (!pixman_region32_contains_point(&PCONSTRAINT->constraint->region, mouseCoords.x - CONSTRAINTPOS.x, mouseCoords.y - CONSTRAINTPOS.y, nullptr)) { if (g_pCompositor->m_sSeat.mouse->constraintActive) { - wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, NULL, mouseCoords.x, mouseCoords.y); + const auto CLOSEST = CRegion(&PCONSTRAINT->constraint->region).closestPoint(mouseCoords - CONSTRAINTPOS) + CONSTRAINTPOS; + wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, NULL, CLOSEST.x, CLOSEST.y); mouseCoords = getMouseCoordsInternal(); } } else { @@ -1230,9 +1231,6 @@ void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) { if (!pConstraint) return; - pConstraint->positionHint = Vector2D(pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); - pConstraint->hintSet = true; - const auto PWINDOW = g_pCompositor->getWindowFromSurface(pConstraint->constraint->surface); if (PWINDOW) { @@ -1242,8 +1240,18 @@ void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) { PWINDOW->m_vRealPosition.goalv(); const auto HINTSCALE = PWINDOW->m_fX11SurfaceScaledBy; - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + pConstraint->positionHint.x / HINTSCALE, RELATIVETO.y + pConstraint->positionHint.y / HINTSCALE); - wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); + if (pConstraint->hintSet) { + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + pConstraint->positionHint.x / HINTSCALE, RELATIVETO.y + pConstraint->positionHint.y / HINTSCALE); + wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); + } else { + const auto RELATIVESIZE = PWINDOW->m_bIsX11 ? + (PWINDOW->m_bIsMapped ? PWINDOW->m_vRealSize.goalv() : + g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height})) : + PWINDOW->m_vRealSize.goalv(); + + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + RELATIVESIZE.x / 2.f, RELATIVETO.y + RELATIVESIZE.y / 2.f); + wlr_seat_pointer_warp(pConstraint->constraint->seat, RELATIVESIZE.x / 2.f, RELATIVESIZE.y / 2.f); + } } } @@ -1259,8 +1267,7 @@ void CInputManager::unconstrainMouse() { wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint); const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint); - warpMouseToConstraintMiddle(PCONSTRAINT); - PCONSTRAINT->active = false; + PCONSTRAINT->active = false; g_pCompositor->m_sSeat.mouse->constraintActive = false; @@ -1569,7 +1576,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE;