summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-03-02 21:04:55 +0000
committerGitHub <noreply@github.com>2024-03-02 21:04:55 +0000
commitd72ea5f2a7fdb0d0a7bf914412327195b05199b0 (patch)
tree0ebc3bb4c8320e88cfa9010d314122c9533dcc0e /src
parent328ab431655f207a5ee59737291f8e8d85fab992 (diff)
input: Rewritten pointer constraints (#4889)
* rewritten constraints * send pointer enter on activate if not pointer focus * minor cleanup * simulate movement on commit * don't ignore oneshot prop * various fixes * dont send motion on confined * update pos hint on region change
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.cpp43
-rw-r--r--src/Compositor.hpp1
-rw-r--r--src/desktop/Constraint.cpp121
-rw-r--r--src/desktop/Constraint.hpp44
-rw-r--r--src/desktop/WLSurface.cpp22
-rw-r--r--src/desktop/WLSurface.hpp18
-rw-r--r--src/events/Devices.cpp40
-rw-r--r--src/events/Events.hpp3
-rw-r--r--src/events/Layers.cpp7
-rw-r--r--src/events/Windows.cpp7
-rw-r--r--src/helpers/WLClasses.cpp76
-rw-r--r--src/helpers/WLClasses.hpp37
-rw-r--r--src/managers/input/InputManager.cpp208
-rw-r--r--src/managers/input/InputManager.hpp45
14 files changed, 284 insertions, 388 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index ee38764a..37626da9 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -1040,13 +1040,6 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
- if (!pWindow->m_bIsX11) {
- const auto PCONSTRAINT = wlr_pointer_constraints_v1_constraint_for_surface(m_sWLRPointerConstraints, pWindow->m_uSurface.xdg->surface, m_sSeat.seat);
-
- if (PCONSTRAINT)
- g_pInputManager->constrainMouse(m_sSeat.mouse, PCONSTRAINT);
- }
-
g_pInputManager->recheckIdleInhibitorStatus();
// move to front of the window history
@@ -1069,6 +1062,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
return;
+ const auto PLASTSURF = m_pLastFocus;
+
// Unfocus last surface if should
if (m_pLastFocus && !pWindowOwner)
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
@@ -1103,6 +1098,15 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
m_pLastFocus = pSurface;
EMIT_HOOK_EVENT("keyboardFocus", pSurface);
+
+ const auto SURF = CWLSurface::surfaceFromWlr(pSurface);
+ const auto OLDSURF = CWLSurface::surfaceFromWlr(PLASTSURF);
+
+ if (OLDSURF && OLDSURF->constraint())
+ OLDSURF->constraint()->deactivate();
+
+ if (SURF && SURF->constraint())
+ SURF->constraint()->activate();
}
bool CCompositor::windowValidMapped(CWindow* pWindow) {
@@ -1770,31 +1774,6 @@ void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) {
pair->second = pair->second || pSurface == pair->first;
}
-CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
- if (!pMouse->currentConstraint)
- return nullptr;
-
- const auto PSURFACE = pMouse->currentConstraint->surface;
-
- for (auto& w : m_vWindows) {
- if (w->isHidden() || !w->m_bIsMapped || !w->m_pWLSurface.exists())
- continue;
-
- if (w->m_bIsX11) {
- if (PSURFACE == w->m_pWLSurface.wlr())
- return w.get();
- } else {
- std::pair<wlr_surface*, bool> check = {PSURFACE, false};
- wlr_surface_for_each_surface(w->m_uSurface.xdg->surface, checkFocusSurfaceIter, &check);
-
- if (check.second)
- return w.get();
- }
- }
-
- return nullptr;
-}
-
CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
return this->getMonitorInDirection(m_pLastMonitor, dir);
}
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index e9edae04..5d75b199 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -166,7 +166,6 @@ class CCompositor {
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
- CWindow* getConstraintWindow(SMouse*);
CMonitor* getMonitorInDirection(const char&);
CMonitor* getMonitorInDirection(CMonitor*, const char&);
void updateAllWindowsAnimatedDecorationValues();
diff --git a/src/desktop/Constraint.cpp b/src/desktop/Constraint.cpp
new file mode 100644
index 00000000..ea89037f
--- /dev/null
+++ b/src/desktop/Constraint.cpp
@@ -0,0 +1,121 @@
+#include "Constraint.hpp"
+#include "WLSurface.hpp"
+#include "../Compositor.hpp"
+
+CConstraint::CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner) : m_pOwner(owner), m_pConstraint(constraint) {
+ initSignals();
+
+ m_vCursorPosOnActivate = g_pInputManager->getMouseCoordsInternal();
+
+ g_pInputManager->m_vConstraints.push_back(this);
+
+ if (g_pCompositor->m_pLastFocus == m_pOwner->wlr())
+ activate();
+}
+
+CConstraint::~CConstraint() {
+ std::erase(g_pInputManager->m_vConstraints, this);
+}
+
+static void onConstraintDestroy(void* owner, void* data) {
+ const auto CONSTRAINT = (CConstraint*)owner;
+ CONSTRAINT->onDestroy();
+}
+
+static void onConstraintSetRegion(void* owner, void* data) {
+ const auto CONSTRAINT = (CConstraint*)owner;
+ CONSTRAINT->onSetRegion();
+}
+
+void CConstraint::initSignals() {
+ hyprListener_setConstraintRegion.initCallback(&m_pConstraint->events.set_region, ::onConstraintSetRegion, this, "CConstraint");
+ hyprListener_destroyConstraint.initCallback(&m_pConstraint->events.destroy, ::onConstraintDestroy, this, "CConstraint");
+}
+
+void CConstraint::onDestroy() {
+ if (active())
+ deactivate();
+
+ // this is us
+ m_pOwner->m_pConstraint.reset();
+}
+
+void CConstraint::onSetRegion() {
+ if (!m_bActive)
+ return;
+
+ m_rRegion.set(&m_pConstraint->region);
+ m_vPositionHint = m_rRegion.closestPoint(m_vPositionHint);
+ g_pInputManager->simulateMouseMovement(); // to warp the cursor if anything's amiss
+}
+
+void CConstraint::onCommit() {
+ if (!m_bActive)
+ return;
+
+ const auto COMMITTED = m_pConstraint->current.committed;
+
+ if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
+ m_bHintSet = true;
+ m_vPositionHint = {m_pConstraint->current.cursor_hint.x, m_pConstraint->current.cursor_hint.y};
+ g_pInputManager->simulateMouseMovement();
+ }
+
+ if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_REGION)
+ onSetRegion();
+}
+
+CRegion CConstraint::logicConstraintRegion() {
+ CRegion rg = m_rRegion;
+ const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
+ const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{};
+ rg.translate(CONSTRAINTPOS);
+ return rg;
+}
+
+CWLSurface* CConstraint::owner() {
+ return m_pOwner;
+}
+
+bool CConstraint::isLocked() {
+ return m_pConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED;
+}
+
+Vector2D CConstraint::logicPositionHint() {
+ const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
+ const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{};
+
+ return m_bHintSet ? CONSTRAINTPOS + m_vPositionHint : m_vCursorPosOnActivate;
+}
+
+void CConstraint::deactivate() {
+ if (!m_bActive)
+ return;
+
+ wlr_pointer_constraint_v1_send_deactivated(m_pConstraint);
+ m_bActive = false;
+ g_pCompositor->warpCursorTo(logicPositionHint(), true);
+
+ if (m_pConstraint->lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT)
+ m_bDead = true;
+}
+
+void CConstraint::activate() {
+ if (m_bActive || m_bDead)
+ return;
+
+ // TODO: hack, probably not a super duper great idea
+ if (g_pCompositor->m_sSeat.seat->pointer_state.focused_surface != m_pOwner->wlr()) {
+ const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
+ const auto LOCAL = SURFBOX.has_value() ? logicPositionHint() - SURFBOX->pos() : Vector2D{};
+ wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, m_pOwner->wlr(), LOCAL.x, LOCAL.y);
+ }
+
+ g_pCompositor->warpCursorTo(logicPositionHint(), true);
+ wlr_pointer_constraint_v1_send_activated(m_pConstraint);
+ m_bActive = true;
+}
+
+bool CConstraint::active() {
+ return m_bActive;
+}
diff --git a/src/desktop/Constraint.hpp b/src/desktop/Constraint.hpp
new file mode 100644
index 00000000..34690217
--- /dev/null
+++ b/src/desktop/Constraint.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "../includes.hpp"
+#include "../helpers/Region.hpp"
+#include "../helpers/WLListener.hpp"
+
+class CWLSurface;
+
+class CConstraint {
+ public:
+ CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner);
+ ~CConstraint();
+
+ void onCommit();
+ void onDestroy();
+ void onSetRegion();
+ CRegion logicConstraintRegion();
+ bool isLocked();
+ Vector2D logicPositionHint();
+
+ void deactivate();
+ void activate();
+ bool active();
+
+ CWLSurface* owner();
+
+ private:
+ bool m_bActive = false;
+ CWLSurface* m_pOwner = nullptr;
+ wlr_pointer_constraint_v1* m_pConstraint;
+
+ CRegion m_rRegion;
+ bool m_bHintSet = false;
+ Vector2D m_vPositionHint = {-1, -1};
+ Vector2D m_vCursorPosOnActivate = {-1, -1};
+
+ // for oneshot constraints that have been activated once
+ bool m_bDead = false;
+
+ DYNLISTENER(destroyConstraint);
+ DYNLISTENER(setConstraintRegion);
+
+ void initSignals();
+}; \ No newline at end of file
diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp
index 9ec121bb..b102c5ce 100644
--- a/src/desktop/WLSurface.cpp
+++ b/src/desktop/WLSurface.cpp
@@ -103,7 +103,10 @@ void CWLSurface::destroy() {
if (!m_pWLRSurface)
return;
+ m_pConstraint.reset();
+
hyprListener_destroy.removeCallback();
+ hyprListener_commit.removeCallback();
m_pWLRSurface->data = nullptr;
m_pWindowOwner = nullptr;
m_pLayerOwner = nullptr;
@@ -123,6 +126,11 @@ void CWLSurface::destroy() {
Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this);
}
+static void onCommit(void* owner, void* data) {
+ const auto SURF = (CWLSurface*)owner;
+ SURF->onCommit();
+}
+
void CWLSurface::init() {
if (!m_pWLRSurface)
return;
@@ -133,6 +141,7 @@ void CWLSurface::init() {
hyprListener_destroy.initCallback(
&m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface");
+ hyprListener_commit.initCallback(&m_pWLRSurface->events.commit, ::onCommit, this, "CWLSurface");
Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this);
}
@@ -172,3 +181,16 @@ std::optional<CBox> CWLSurface::getSurfaceBoxGlobal() {
return {};
}
+
+void CWLSurface::appendConstraint(wlr_pointer_constraint_v1* constraint) {
+ m_pConstraint = std::make_unique<CConstraint>(constraint, this);
+}
+
+void CWLSurface::onCommit() {
+ if (m_pConstraint)
+ m_pConstraint->onCommit();
+}
+
+CConstraint* CWLSurface::constraint() {
+ return m_pConstraint.get();
+}
diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp
index 3e04b4b2..b9306eea 100644
--- a/src/desktop/WLSurface.hpp
+++ b/src/desktop/WLSurface.hpp
@@ -2,6 +2,7 @@
#include "../defines.hpp"
#include "../helpers/Region.hpp"
+#include "Constraint.hpp"
class CWindow;
struct SLayerSurface;
@@ -32,6 +33,7 @@ class CWLSurface {
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
Vector2D getViewporterCorrectedSize() const;
CRegion logicalDamage() const;
+ void onCommit();
// getters for owners.
CWindow* getWindow();
@@ -41,6 +43,8 @@ class CWLSurface {
// desktop components misc utils
std::optional<CBox> getSurfaceBoxGlobal();
+ void appendConstraint(wlr_pointer_constraint_v1* constraint);
+ CConstraint* constraint();
// allow stretching. Useful for plugins.
bool m_bFillIgnoreSmall = false;
@@ -72,6 +76,8 @@ class CWLSurface {
}
static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) {
+ if (!pSurface)
+ return nullptr;
return (CWLSurface*)pSurface->data;
}
@@ -85,9 +91,15 @@ class CWLSurface {
CPopup* m_pPopupOwner = nullptr;
CSubsurface* m_pSubsurfaceOwner = nullptr;
- void destroy();
- void init();
- bool desktopComponent();
+ //
+ std::unique_ptr<CConstraint> m_pConstraint;
+
+ void destroy();
+ void init();
+ bool desktopComponent();
DYNLISTENER(destroy);
+ DYNLISTENER(commit);
+
+ friend class CConstraint;
}; \ No newline at end of file
diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp
index 1ba6cad4..64050320 100644
--- a/src/events/Devices.cpp
+++ b/src/events/Devices.cpp
@@ -97,44 +97,14 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) {
Debug::log(LOG, "New mouse constraint at {:x}", (uintptr_t)PCONSTRAINT);
- g_pInputManager->m_lConstraints.emplace_back();
- const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
+ const auto SURFACE = CWLSurface::surfaceFromWlr(PCONSTRAINT->surface);
- CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
- CONSTRAINT->constraint = PCONSTRAINT;
-
- CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint");
- CONSTRAINT->hyprListener_setConstraintRegion.initCallback(&PCONSTRAINT->events.set_region, &Events::listener_setConstraintRegion, CONSTRAINT, "Constraint");
-
- if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
- g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
-
- if (!CONSTRAINT->hintSet)
- CONSTRAINT->positionHint = Vector2D{-1, -1};
+ if (!SURFACE) {
+ Debug::log(ERR, "Refusing a constraint from an unassigned wl_surface {:x}", (uintptr_t)PCONSTRAINT->surface);
+ return;
}
-}
-
-void Events::listener_destroyConstraint(void* owner, void* data) {
- const auto PCONSTRAINT = (SConstraint*)owner;
-
- if (PCONSTRAINT->pMouse->currentConstraint == PCONSTRAINT->constraint) {
- PCONSTRAINT->pMouse->hyprListener_commitConstraint.removeCallback();
-
- const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
-
- if (PWINDOW && PCONSTRAINT->active && PCONSTRAINT->constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
- g_pInputManager->warpMouseToConstraintMiddle(PCONSTRAINT);
-
- PCONSTRAINT->pMouse->currentConstraint = nullptr;
- }
-
- Debug::log(LOG, "Unconstrained mouse from {:x}", (uintptr_t)PCONSTRAINT->constraint);
-
- g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
-}
-void Events::listener_setConstraintRegion(void* owner, void* data) {
- // no
+ SURFACE->appendConstraint(PCONSTRAINT);
}
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
diff --git a/src/events/Events.hpp b/src/events/Events.hpp
index 69faf6c1..a105846e 100644
--- a/src/events/Events.hpp
+++ b/src/events/Events.hpp
@@ -65,10 +65,7 @@ namespace Events {
DYNLISTENFUNC(keyboardMod);
DYNLISTENFUNC(keyboardDestroy);
- DYNLISTENFUNC(commitConstraint);
LISTENER(newConstraint);
- DYNLISTENFUNC(setConstraintRegion);
- DYNLISTENFUNC(destroyConstraint);
// Various
LISTENER(requestMouse);
diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp
index 2d94f1ed..ad65f8fb 100644
--- a/src/events/Layers.cpp
+++ b/src/events/Layers.cpp
@@ -144,7 +144,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
// don't focus if constrained
- (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
+ (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained());
if (GRABSFOCUS) {
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
@@ -340,8 +340,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
layersurface->realSize.setValueAndWarp(layersurface->geometry.size());
}
- if (layersurface->layerSurface->current.keyboard_interactive &&
- (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained
+ if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) // don't focus if constrained
&& !layersurface->keyboardExclusive && layersurface->mapped) {
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
@@ -349,7 +348,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
- } else if (!layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) &&
+ } else if (!layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) &&
layersurface->keyboardExclusive) {
g_pInputManager->refocus();
}
diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp
index 83a37ec3..778b857e 100644
--- a/src/events/Windows.cpp
+++ b/src/events/Windows.cpp
@@ -476,8 +476,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus &&
- (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
- (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
+ (PWINDOW->m_iX11Type != 2 ||
+ (PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->window_type_len > 0 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) &&
+ !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && !g_pInputManager->isConstrained()) {
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA);
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : **PDIMSTRENGTH);
@@ -645,7 +646,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
- if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->constraintActive)
+ if (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained())
g_pInputManager->sendMotionEventsToFocused();
// fix some xwayland apps that don't behave nicely
diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp
index 3cf170bf..8964ba59 100644
--- a/src/helpers/WLClasses.cpp
+++ b/src/helpers/WLClasses.cpp
@@ -167,82 +167,6 @@ bool SLayerSurface::isFadedOut() {
return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated();
}
-CRegion SConstraint::getLogicCoordsRegion() {
- CRegion result;
-
- if (!constraint)
- return result;
-
- const auto PWINDOWOWNER = g_pCompositor->getWindowFromSurface(constraint->surface);
-
- if (!PWINDOWOWNER)
- return result;
-
- result.add(&constraint->region); // surface-local coords
-
- if (!PWINDOWOWNER->m_bIsX11) {
- result.translate(PWINDOWOWNER->m_vRealPosition.goal());
- return result;
- }
-
- const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goal() :
- g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y});
-
- const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ? g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) : g_pCompositor->getMonitorFromVector(COORDS);
-
- if (!PMONITOR)
- return CRegion{};
-
- result.scale(PMONITOR->xwaylandScale);
-
- result.translate(COORDS);
-
- return result;
-}
-
-Vector2D SConstraint::getLogicConstraintPos() {
- if (!constraint)
- return {};
-
- const auto PWINDOWOWNER = g_pCompositor->getWindowFromSurface(constraint->surface);
-
- if (!PWINDOWOWNER)
- return {};
-
- if (!PWINDOWOWNER->m_bIsX11)
- return PWINDOWOWNER->m_vRealPosition.goal();
-
- const auto COORDS = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealPosition.goal() :
- g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y});
-
- return COORDS;
-}
-
-Vector2D SConstraint::getLogicConstraintSize() {
- if (!constraint)
- return {};
-
- const auto PWINDOWOWNER = g_pCompositor->getWindowFromSurface(constraint->surface);
-
- if (!PWINDOWOWNER)
- return {};
-
- if (!PWINDOWOWNER->m_bIsX11)
- return PWINDOWOWNER->m_vRealSize.goal();
-
- const auto PMONITOR = PWINDOWOWNER->m_bIsMapped ?
- g_pCompositor->getMonitorFromID(PWINDOWOWNER->m_iMonitorID) :
- g_pCompositor->getMonitorFromVector(g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOWOWNER->m_uSurface.xwayland->x, PWINDOWOWNER->m_uSurface.xwayland->y}));
-
- if (!PMONITOR)
- return {};
-
- const auto SIZE = PWINDOWOWNER->m_bIsMapped ? PWINDOWOWNER->m_vRealSize.goal() :
- Vector2D{PWINDOWOWNER->m_uSurface.xwayland->width, PWINDOWOWNER->m_uSurface.xwayland->height} * PMONITOR->xwaylandScale;
-
- return SIZE;
-}
-
void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
xkb_state_unref(xkbTranslationState);
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index b1c6c9d7..5fc2692a 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -157,20 +157,14 @@ struct SKeyboard {
};
struct SMouse {
- wlr_input_device* mouse = nullptr;
+ wlr_input_device* mouse = nullptr;
- wlr_pointer_constraint_v1* currentConstraint = nullptr;
- bool constraintActive = false;
-
- CRegion confinedTo;
-
- std::string name = "";
+ std::string name = "";
- bool virt = false;
+ bool virt = false;
- bool connected = false; // means connected to the cursor
+ bool connected = false; // means connected to the cursor
- DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
bool operator==(const SMouse& b) const {
@@ -178,29 +172,6 @@ struct SMouse {
}
};
-struct SConstraint {
- SMouse* pMouse = nullptr;
- wlr_pointer_constraint_v1* constraint = nullptr;
-
- bool active = false;
-
- bool hintSet = false;
- Vector2D positionHint = {-1, -1}; // the position hint, but will use cursorPosOnActivate if unset
- Vector2D cursorPosOnActivate = {-1, -1};
-
- DYNLISTENER(setConstraintRegion);
- DYNLISTENER(destroyConstraint);
-
- CRegion getLogicCoordsRegion();
- Vector2D getLogicConstraintPos();
- Vector2D getLogicConstraintSize();
-
- //
- bool operator==(const SConstraint& b) const {
- return constraint == b.constraint;
- }
-};
-
class CMonitor;
struct SSeat {
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index 989d863a..c634037c 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -4,7 +4,7 @@
#include <ranges>
CInputManager::~CInputManager() {
- m_lConstraints.clear();
+ m_vConstraints.clear();
m_lKeyboards.clear();
m_lMice.clear();
m_lTablets.clear();
@@ -56,7 +56,7 @@ void CInputManager::simulateMouseMovement() {
}
void CInputManager::sendMotionEventsToFocused() {
- if (!g_pCompositor->m_pLastFocus)
+ if (!g_pCompositor->m_pLastFocus || isConstrained())
return;
// todo: this sucks ass
@@ -139,56 +139,27 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
// constraints
- // All constraints TODO: multiple mice?
- if (g_pCompositor->m_sSeat.mouse && g_pCompositor->m_sSeat.mouse->currentConstraint && !g_pCompositor->m_sSeat.exclusiveClient && !g_pSessionLockManager->isSessionLocked()) {
- // XWayland windows sometimes issue constraints weirdly.
- // TODO: We probably should search their parent. wlr_xwayland_surface->parent
- const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
- const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint);
-
- if (!CONSTRAINTWINDOW || !PCONSTRAINT) {
- unconstrainMouse();
- } else {
- // Native Wayland apps know how 2 constrain themselves.
- // XWayland, we just have to accept them. Might cause issues, but thats XWayland for ya.
- const auto CONSTRAINTPOS = PCONSTRAINT->getLogicConstraintPos();
- const auto CONSTRAINTSIZE = PCONSTRAINT->getLogicConstraintSize();
-
- if (g_pCompositor->m_sSeat.mouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) {
- // we just snap the cursor to where it should be.
-
- if (PCONSTRAINT->hintSet)
- wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, CONSTRAINTPOS.x + PCONSTRAINT->positionHint.x,
- CONSTRAINTPOS.y + PCONSTRAINT->positionHint.y);
-
- return; // don't process anything else, the cursor is locked. The surface should not receive any further events.
- // these are usually FPS games. They will use the relative motion.
+ if (g_pCompositor->m_sSeat.mouse && isConstrained()) {
+ const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus);
+ const auto CONSTRAINT = SURF->constraint();
+
+ if (SURF && CONSTRAINT) {
+ if (CONSTRAINT->isLocked()) {
+ const auto HINT = CONSTRAINT->logicPositionHint();
+ wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, HINT.x, HINT.y);
} else {
- // we restrict the cursor to the confined region
- const auto REGION = PCONSTRAINT->getLogicCoordsRegion();
-
- if (!REGION.containsPoint(mouseCoords)) {
- if (g_pCompositor->m_sSeat.mouse->constraintActive) {
- const auto CLOSEST = REGION.closestPoint(mouseCoords);
- wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, NULL, CLOSEST.x, CLOSEST.y);
- mouseCoords = getMouseCoordsInternal();
- }
- } else {
- if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
- g_pCompositor->m_sSeat.mouse->constraintActive = true;
- }
- }
- }
+ const auto RG = CONSTRAINT->logicConstraintRegion();
+ const auto CLOSEST = RG.closestPoint(mouseCoords);
+ const auto BOX = SURF->getSurfaceBoxGlobal();
+ const auto CLOSESTLOCAL = CLOSEST - (BOX.has_value() ? BOX->pos() : Vector2D{});
- if (CONSTRAINTWINDOW->m_bIsX11) {
- foundSurface = CONSTRAINTWINDOW->m_pWLSurface.wlr();
- surfacePos = CONSTRAINTWINDOW->m_vRealPosition.value();
- } else {
- g_pCompositor->vectorWindowToSurface(mouseCoords, CONSTRAINTWINDOW, surfaceCoords);
+ wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, CLOSEST.x, CLOSEST.y);
}
- pFoundWindow = CONSTRAINTWINDOW;
- }
+ return;
+
+ } else
+ Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF, (uintptr_t)CONSTRAINT);
}
// update stuff
@@ -641,7 +612,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
if (**PFOLLOWMOUSE == 3) // don't refocus on full loose
break;
- if ((!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) /* No constraints */
+ if ((!g_pCompositor->m_sSeat.mouse || !isConstrained()) /* No constraints */
&& (w && g_pCompositor->m_pLastWindow != w) /* window should change */) {
// a bit hacky
// if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus
@@ -1278,133 +1249,27 @@ void CInputManager::updateDragIcon() {
}
}
-void CInputManager::recheckConstraint(SMouse* pMouse) {
- if (!pMouse->currentConstraint)
- return;
-
- const auto PREGION = &pMouse->currentConstraint->region;
-
- if (pMouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED)
- pMouse->confinedTo.set(PREGION);
- else
- pMouse->confinedTo.clear();
-}
-
-void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* constraint) {
-
- if (pMouse->currentConstraint == constraint)
- return;
-
- const auto MOUSECOORDS = getMouseCoordsInternal();
- const auto PCONSTRAINT = constraintFromWlr(constraint);
-
- pMouse->hyprListener_commitConstraint.removeCallback();
-
- if (pMouse->currentConstraint)
- wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint);
-
- if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(constraint->surface); PWINDOW) {
- const auto RELATIVETO = PWINDOW->m_bIsX11 ?
- (PWINDOW->m_bIsMapped ? PWINDOW->m_vRealPosition.goal() :
- g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) :
- PWINDOW->m_vRealPosition.goal();
-
- PCONSTRAINT->cursorPosOnActivate = (MOUSECOORDS - RELATIVETO) * PWINDOW->m_fX11SurfaceScaledBy;
- }
-
- if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
- PCONSTRAINT->hintSet = true;
- PCONSTRAINT->positionHint = {constraint->current.cursor_hint.x, constraint->current.cursor_hint.y};
- }
-
- if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
- warpMouseToConstraintMiddle(PCONSTRAINT);
-
- pMouse->currentConstraint = constraint;
- pMouse->constraintActive = true;
-
- if (pixman_region32_not_empty(&constraint->current.region))
- pixman_region32_intersect(&constraint->region, &constraint->surface->input_region, &constraint->current.region);
- else
- pixman_region32_copy(&constraint->region, &constraint->surface->input_region);
-
- // warp to the constraint
- recheckConstraint(pMouse);
-
- PCONSTRAINT->active = true;
-
- wlr_pointer_constraint_v1_send_activated(pMouse->currentConstraint);
-
- pMouse->hyprListener_commitConstraint.initCallback(&pMouse->currentConstraint->surface->events.commit, &Events::listener_commitConstraint, pMouse, "Mouse constraint commit");
-
- Debug::log(LOG, "Constrained mouse to {:x}", (uintptr_t)pMouse->currentConstraint);
-}
-
-void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) {
-
- if (!pConstraint)
- return;
-
- const auto PWINDOW = g_pCompositor->getWindowFromSurface(pConstraint->constraint->surface);
-
- if (PWINDOW) {
- const auto RELATIVETO = pConstraint->getLogicConstraintPos();
- const auto HINTSCALE = PWINDOW->m_fX11SurfaceScaledBy;
-
- auto HINT = pConstraint->hintSet ? pConstraint->positionHint : pConstraint->cursorPosOnActivate;
-
- if (HINT == Vector2D{-1, -1})
- HINT = pConstraint->getLogicConstraintSize() / 2.f;
-
- if (HINT != Vector2D{-1, -1}) {
- wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + HINT.x / HINTSCALE, RELATIVETO.y + HINT.y / HINTSCALE);
- wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y);
- }
- }
-}
-
void CInputManager::unconstrainMouse() {
- if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)
+ if (!g_pCompositor->m_sSeat.mouse)
return;
- const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
-
- if (CONSTRAINTWINDOW)
- g_pXWaylandManager->activateSurface(CONSTRAINTWINDOW->m_pWLSurface.wlr(), false);
-
- wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint);
-
- const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint);
- if (PCONSTRAINT)
- PCONSTRAINT->active = false;
-
- g_pCompositor->m_sSeat.mouse->constraintActive = false;
-
- // TODO: its better to somehow detect the workspace...
- g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
+ for (auto& c : m_vConstraints) {
+ if (!c->active())
+ continue;
- g_pCompositor->m_sSeat.mouse->hyprListener_commitConstraint.removeCallback();
+ c->deactivate();
+ }
}
-void Events::listener_commitConstraint(void* owner, void* data) {
- const auto PMOUSE = (SMouse*)owner;
+bool CInputManager::isConstrained() {
+ for (auto& c : m_vConstraints) {
+ if (!c->active() || c->owner()->wlr() != g_pCompositor->m_pLastFocus)
+ continue;
- if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
- const auto PCONSTRAINT = g_pInputManager->constraintFromWlr(PMOUSE->currentConstraint);
- if (PCONSTRAINT) { // should never be null but who knows
- PCONSTRAINT->positionHint = Vector2D(PMOUSE->currentConstraint->current.cursor_hint.x, PMOUSE->currentConstraint->current.cursor_hint.y);
- PCONSTRAINT->hintSet = true;
- }
+ return true;
}
- if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) {
- if (pixman_region32_not_empty(&PMOUSE->currentConstraint->current.region))
- pixman_region32_intersect(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region, &PMOUSE->currentConstraint->current.region);
- else
- pixman_region32_copy(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region);
-
- g_pInputManager->recheckConstraint(PMOUSE);
- }
+ return false;
}
void CInputManager::updateCapabilities() {
@@ -1670,15 +1535,6 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) {
return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno)));
}
-SConstraint* CInputManager::constraintFromWlr(wlr_pointer_constraint_v1* constraint) {
- for (auto& c : m_lConstraints) {
- if (c.constraint == constraint)
- return &c;
- }
-
- return nullptr;
-}
-
void CInputManager::releaseAllMouseButtons() {
const auto buttonsCopy = m_lCurrentlyHeldButtons;
diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp
index e32e27f8..cef8386f 100644
--- a/src/managers/input/InputManager.hpp
+++ b/src/managers/input/InputManager.hpp
@@ -7,6 +7,8 @@
#include "../../helpers/Timer.hpp"
#include "InputMethodRelay.hpp"
+class CConstraint;
+
enum eClickBehaviorMode {
CLICKMODE_DEFAULT = 0,
CLICKMODE_KILL
@@ -80,11 +82,8 @@ class CInputManager {
void destroyMouse(wlr_input_device*);
void destroySwitch(SSwitchDevice*);
- void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
- void warpMouseToConstraintMiddle(SConstraint*);
- void recheckConstraint(SMouse*);
void unconstrainMouse();
- SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*);
+ bool isConstrained();
std::string getActiveLayoutForKeyboard(SKeyboard*);
Vector2D getMouseCoordsInternal();
@@ -120,13 +119,12 @@ class CInputManager {
bool m_bWasDraggingWindow = false;
// for refocus to be forced
- CWindow* m_pForcedFocus = nullptr;
+ CWindow* m_pForcedFocus = nullptr;
- SDrag m_sDrag;
+ SDrag m_sDrag;
- std::list<SConstraint> m_lConstraints;
- std::list<SKeyboard> m_lKeyboards;
- std::list<SMouse> m_lMice;
+ std::list<SKeyboard> m_lKeyboards;
+ std::list<SMouse> m_lMice;
// tablets
std::list<STablet> m_lTablets;
@@ -145,25 +143,28 @@ class CInputManager {
// Exclusive layer surfaces
std::deque<SLayerSurface*> m_dExclusiveLSes;
- void newTabletTool(wlr_input_device*);
- void newTabletPad(wlr_input_device*);
- void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
- void newIdleInhibitor(wlr_idle_inhibitor_v1*);
- void recheckIdleInhibitorStatus();
+ // constraints
+ std::vector<CConstraint*> m_vConstraints;
+
+ void newTabletTool(wlr_input_device*);
+ void newTabletPad(wlr_input_device*);
+ void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
+ void newIdleInhibitor(wlr_idle_inhibitor_v1*);
+ void recheckIdleInhibitorStatus();
- void onSwipeBegin(wlr_pointer_swipe_begin_event*);
- void onSwipeEnd(wlr_pointer_swipe_end_event*);
- void onSwipeUpdate(wlr_pointer_swipe_update_event*);
+ void onSwipeBegin(wlr_pointer_swipe_begin_event*);
+ void onSwipeEnd(wlr_pointer_swipe_end_event*);
+ void onSwipeUpdate(wlr_pointer_swipe_update_event*);
- SSwipeGesture m_sActiveSwipe;
+ SSwipeGesture m_sActiveSwipe;
- SKeyboard* m_pActiveKeyboard = nullptr;
+ SKeyboard* m_pActiveKeyboard = nullptr;
- CTimer m_tmrLastCursorMovement;
+ CTimer m_tmrLastCursorMovement;
- CInputMethodRelay m_sIMERelay;
+ CInputMethodRelay m_sIMERelay;
- void updateKeyboardsLeds(wlr_input_device* pKeyboard);
+ void updateKeyboardsLeds(wlr_input_device* pKeyboard);
// for shared mods
uint32_t accumulateModsFromAllKBs();