summaryrefslogtreecommitdiff
path: root/src/desktop/Constraint.cpp
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/desktop/Constraint.cpp
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/desktop/Constraint.cpp')
-rw-r--r--src/desktop/Constraint.cpp121
1 files changed, 121 insertions, 0 deletions
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;
+}