diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2024-03-02 21:04:55 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-02 21:04:55 +0000 |
| commit | d72ea5f2a7fdb0d0a7bf914412327195b05199b0 (patch) | |
| tree | 0ebc3bb4c8320e88cfa9010d314122c9533dcc0e /src/desktop/Constraint.cpp | |
| parent | 328ab431655f207a5ee59737291f8e8d85fab992 (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.cpp | 121 |
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; +} |
