mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-22 16:05:58 +01:00
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
This commit is contained in:
parent
328ab43165
commit
d72ea5f2a7
14 changed files with 282 additions and 386 deletions
|
@ -1040,13 +1040,6 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||||
if (pWindow->m_phForeignToplevel)
|
if (pWindow->m_phForeignToplevel)
|
||||||
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
|
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();
|
g_pInputManager->recheckIdleInhibitorStatus();
|
||||||
|
|
||||||
// move to front of the window history
|
// 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))
|
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const auto PLASTSURF = m_pLastFocus;
|
||||||
|
|
||||||
// Unfocus last surface if should
|
// Unfocus last surface if should
|
||||||
if (m_pLastFocus && !pWindowOwner)
|
if (m_pLastFocus && !pWindowOwner)
|
||||||
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
|
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
|
||||||
|
@ -1103,6 +1098,15 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||||
m_pLastFocus = pSurface;
|
m_pLastFocus = pSurface;
|
||||||
|
|
||||||
EMIT_HOOK_EVENT("keyboardFocus", 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) {
|
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;
|
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) {
|
CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
||||||
return this->getMonitorInDirection(m_pLastMonitor, dir);
|
return this->getMonitorInDirection(m_pLastMonitor, dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,6 @@ class CCompositor {
|
||||||
int getNextAvailableNamedWorkspace();
|
int getNextAvailableNamedWorkspace();
|
||||||
bool isPointOnAnyMonitor(const Vector2D&);
|
bool isPointOnAnyMonitor(const Vector2D&);
|
||||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||||
CWindow* getConstraintWindow(SMouse*);
|
|
||||||
CMonitor* getMonitorInDirection(const char&);
|
CMonitor* getMonitorInDirection(const char&);
|
||||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||||
void updateAllWindowsAnimatedDecorationValues();
|
void updateAllWindowsAnimatedDecorationValues();
|
||||||
|
|
121
src/desktop/Constraint.cpp
Normal file
121
src/desktop/Constraint.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
44
src/desktop/Constraint.hpp
Normal file
44
src/desktop/Constraint.hpp
Normal file
|
@ -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();
|
||||||
|
};
|
|
@ -103,7 +103,10 @@ void CWLSurface::destroy() {
|
||||||
if (!m_pWLRSurface)
|
if (!m_pWLRSurface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_pConstraint.reset();
|
||||||
|
|
||||||
hyprListener_destroy.removeCallback();
|
hyprListener_destroy.removeCallback();
|
||||||
|
hyprListener_commit.removeCallback();
|
||||||
m_pWLRSurface->data = nullptr;
|
m_pWLRSurface->data = nullptr;
|
||||||
m_pWindowOwner = nullptr;
|
m_pWindowOwner = nullptr;
|
||||||
m_pLayerOwner = nullptr;
|
m_pLayerOwner = nullptr;
|
||||||
|
@ -123,6 +126,11 @@ void CWLSurface::destroy() {
|
||||||
Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this);
|
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() {
|
void CWLSurface::init() {
|
||||||
if (!m_pWLRSurface)
|
if (!m_pWLRSurface)
|
||||||
return;
|
return;
|
||||||
|
@ -133,6 +141,7 @@ void CWLSurface::init() {
|
||||||
|
|
||||||
hyprListener_destroy.initCallback(
|
hyprListener_destroy.initCallback(
|
||||||
&m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface");
|
&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);
|
Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this);
|
||||||
}
|
}
|
||||||
|
@ -172,3 +181,16 @@ std::optional<CBox> CWLSurface::getSurfaceBoxGlobal() {
|
||||||
|
|
||||||
return {};
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/Region.hpp"
|
#include "../helpers/Region.hpp"
|
||||||
|
#include "Constraint.hpp"
|
||||||
|
|
||||||
class CWindow;
|
class CWindow;
|
||||||
struct SLayerSurface;
|
struct SLayerSurface;
|
||||||
|
@ -32,6 +33,7 @@ class CWLSurface {
|
||||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||||
Vector2D getViewporterCorrectedSize() const;
|
Vector2D getViewporterCorrectedSize() const;
|
||||||
CRegion logicalDamage() const;
|
CRegion logicalDamage() const;
|
||||||
|
void onCommit();
|
||||||
|
|
||||||
// getters for owners.
|
// getters for owners.
|
||||||
CWindow* getWindow();
|
CWindow* getWindow();
|
||||||
|
@ -41,6 +43,8 @@ class CWLSurface {
|
||||||
|
|
||||||
// desktop components misc utils
|
// desktop components misc utils
|
||||||
std::optional<CBox> getSurfaceBoxGlobal();
|
std::optional<CBox> getSurfaceBoxGlobal();
|
||||||
|
void appendConstraint(wlr_pointer_constraint_v1* constraint);
|
||||||
|
CConstraint* constraint();
|
||||||
|
|
||||||
// allow stretching. Useful for plugins.
|
// allow stretching. Useful for plugins.
|
||||||
bool m_bFillIgnoreSmall = false;
|
bool m_bFillIgnoreSmall = false;
|
||||||
|
@ -72,6 +76,8 @@ class CWLSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) {
|
static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) {
|
||||||
|
if (!pSurface)
|
||||||
|
return nullptr;
|
||||||
return (CWLSurface*)pSurface->data;
|
return (CWLSurface*)pSurface->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +91,15 @@ class CWLSurface {
|
||||||
CPopup* m_pPopupOwner = nullptr;
|
CPopup* m_pPopupOwner = nullptr;
|
||||||
CSubsurface* m_pSubsurfaceOwner = nullptr;
|
CSubsurface* m_pSubsurfaceOwner = nullptr;
|
||||||
|
|
||||||
void destroy();
|
//
|
||||||
void init();
|
std::unique_ptr<CConstraint> m_pConstraint;
|
||||||
bool desktopComponent();
|
|
||||||
|
void destroy();
|
||||||
|
void init();
|
||||||
|
bool desktopComponent();
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
DYNLISTENER(commit);
|
||||||
|
|
||||||
|
friend class CConstraint;
|
||||||
};
|
};
|
|
@ -97,44 +97,14 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
||||||
|
|
||||||
Debug::log(LOG, "New mouse constraint at {:x}", (uintptr_t)PCONSTRAINT);
|
Debug::log(LOG, "New mouse constraint at {:x}", (uintptr_t)PCONSTRAINT);
|
||||||
|
|
||||||
g_pInputManager->m_lConstraints.emplace_back();
|
const auto SURFACE = CWLSurface::surfaceFromWlr(PCONSTRAINT->surface);
|
||||||
const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
|
|
||||||
|
|
||||||
CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
|
if (!SURFACE) {
|
||||||
CONSTRAINT->constraint = PCONSTRAINT;
|
Debug::log(ERR, "Refusing a constraint from an unassigned wl_surface {:x}", (uintptr_t)PCONSTRAINT->surface);
|
||||||
|
return;
|
||||||
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};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
SURFACE->appendConstraint(PCONSTRAINT);
|
||||||
|
|
||||||
g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Events::listener_setConstraintRegion(void* owner, void* data) {
|
|
||||||
// no
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
|
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
|
||||||
|
|
|
@ -65,10 +65,7 @@ namespace Events {
|
||||||
DYNLISTENFUNC(keyboardMod);
|
DYNLISTENFUNC(keyboardMod);
|
||||||
DYNLISTENFUNC(keyboardDestroy);
|
DYNLISTENFUNC(keyboardDestroy);
|
||||||
|
|
||||||
DYNLISTENFUNC(commitConstraint);
|
|
||||||
LISTENER(newConstraint);
|
LISTENER(newConstraint);
|
||||||
DYNLISTENFUNC(setConstraintRegion);
|
|
||||||
DYNLISTENFUNC(destroyConstraint);
|
|
||||||
|
|
||||||
// Various
|
// Various
|
||||||
LISTENER(requestMouse);
|
LISTENER(requestMouse);
|
||||||
|
|
|
@ -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 &&
|
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||||
// don't focus if constrained
|
// 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) {
|
if (GRABSFOCUS) {
|
||||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
||||||
|
@ -340,8 +340,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||||
layersurface->realSize.setValueAndWarp(layersurface->geometry.size());
|
layersurface->realSize.setValueAndWarp(layersurface->geometry.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layersurface->layerSurface->current.keyboard_interactive &&
|
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) // don't focus if constrained
|
||||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) // don't focus if constrained
|
|
||||||
&& !layersurface->keyboardExclusive && layersurface->mapped) {
|
&& !layersurface->keyboardExclusive && layersurface->mapped) {
|
||||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
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);
|
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_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);
|
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) {
|
layersurface->keyboardExclusive) {
|
||||||
g_pInputManager->refocus();
|
g_pInputManager->refocus();
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,8 +476,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_sAdditionalConfigData.noFocus && !PWINDOW->m_bNoInitialFocus &&
|
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 &&
|
(PWINDOW->m_iX11Type != 2 ||
|
||||||
(!PFORCEFOCUS || PFORCEFOCUS == PWINDOW)) {
|
(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);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA);
|
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(**PACTIVEALPHA);
|
||||||
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sAdditionalConfigData.forceNoDim ? 0.f : **PDIMSTRENGTH);
|
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->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||||
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
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();
|
g_pInputManager->sendMotionEventsToFocused();
|
||||||
|
|
||||||
// fix some xwayland apps that don't behave nicely
|
// fix some xwayland apps that don't behave nicely
|
||||||
|
|
|
@ -167,82 +167,6 @@ bool SLayerSurface::isFadedOut() {
|
||||||
return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated();
|
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) {
|
void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||||
xkb_state_unref(xkbTranslationState);
|
xkb_state_unref(xkbTranslationState);
|
||||||
|
|
||||||
|
|
|
@ -157,20 +157,14 @@ struct SKeyboard {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMouse {
|
struct SMouse {
|
||||||
wlr_input_device* mouse = nullptr;
|
wlr_input_device* mouse = nullptr;
|
||||||
|
|
||||||
wlr_pointer_constraint_v1* currentConstraint = nullptr;
|
std::string name = "";
|
||||||
bool constraintActive = false;
|
|
||||||
|
|
||||||
CRegion confinedTo;
|
bool virt = false;
|
||||||
|
|
||||||
std::string name = "";
|
bool connected = false; // means connected to the cursor
|
||||||
|
|
||||||
bool virt = false;
|
|
||||||
|
|
||||||
bool connected = false; // means connected to the cursor
|
|
||||||
|
|
||||||
DYNLISTENER(commitConstraint);
|
|
||||||
DYNLISTENER(destroyMouse);
|
DYNLISTENER(destroyMouse);
|
||||||
|
|
||||||
bool operator==(const SMouse& b) const {
|
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;
|
class CMonitor;
|
||||||
|
|
||||||
struct SSeat {
|
struct SSeat {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
CInputManager::~CInputManager() {
|
CInputManager::~CInputManager() {
|
||||||
m_lConstraints.clear();
|
m_vConstraints.clear();
|
||||||
m_lKeyboards.clear();
|
m_lKeyboards.clear();
|
||||||
m_lMice.clear();
|
m_lMice.clear();
|
||||||
m_lTablets.clear();
|
m_lTablets.clear();
|
||||||
|
@ -56,7 +56,7 @@ void CInputManager::simulateMouseMovement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::sendMotionEventsToFocused() {
|
void CInputManager::sendMotionEventsToFocused() {
|
||||||
if (!g_pCompositor->m_pLastFocus)
|
if (!g_pCompositor->m_pLastFocus || isConstrained())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// todo: this sucks ass
|
// todo: this sucks ass
|
||||||
|
@ -139,56 +139,27 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// constraints
|
// constraints
|
||||||
// All constraints TODO: multiple mice?
|
if (g_pCompositor->m_sSeat.mouse && isConstrained()) {
|
||||||
if (g_pCompositor->m_sSeat.mouse && g_pCompositor->m_sSeat.mouse->currentConstraint && !g_pCompositor->m_sSeat.exclusiveClient && !g_pSessionLockManager->isSessionLocked()) {
|
const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus);
|
||||||
// XWayland windows sometimes issue constraints weirdly.
|
const auto CONSTRAINT = SURF->constraint();
|
||||||
// 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) {
|
if (SURF && CONSTRAINT) {
|
||||||
unconstrainMouse();
|
if (CONSTRAINT->isLocked()) {
|
||||||
} else {
|
const auto HINT = CONSTRAINT->logicPositionHint();
|
||||||
// Native Wayland apps know how 2 constrain themselves.
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, HINT.x, HINT.y);
|
||||||
// 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.
|
|
||||||
} else {
|
} else {
|
||||||
// we restrict the cursor to the confined region
|
const auto RG = CONSTRAINT->logicConstraintRegion();
|
||||||
const auto REGION = PCONSTRAINT->getLogicCoordsRegion();
|
const auto CLOSEST = RG.closestPoint(mouseCoords);
|
||||||
|
const auto BOX = SURF->getSurfaceBoxGlobal();
|
||||||
|
const auto CLOSESTLOCAL = CLOSEST - (BOX.has_value() ? BOX->pos() : Vector2D{});
|
||||||
|
|
||||||
if (!REGION.containsPoint(mouseCoords)) {
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, CLOSEST.x, CLOSEST.y);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CONSTRAINTWINDOW->m_bIsX11) {
|
return;
|
||||||
foundSurface = CONSTRAINTWINDOW->m_pWLSurface.wlr();
|
|
||||||
surfacePos = CONSTRAINTWINDOW->m_vRealPosition.value();
|
|
||||||
} else {
|
|
||||||
g_pCompositor->vectorWindowToSurface(mouseCoords, CONSTRAINTWINDOW, surfaceCoords);
|
|
||||||
}
|
|
||||||
|
|
||||||
pFoundWindow = CONSTRAINTWINDOW;
|
} else
|
||||||
}
|
Debug::log(ERR, "BUG THIS: Null SURF/CONSTRAINT in mouse refocus. Ignoring constraints. {:x} {:x}", (uintptr_t)SURF, (uintptr_t)CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update stuff
|
// update stuff
|
||||||
|
@ -641,7 +612,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||||
if (**PFOLLOWMOUSE == 3) // don't refocus on full loose
|
if (**PFOLLOWMOUSE == 3) // don't refocus on full loose
|
||||||
break;
|
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 */) {
|
&& (w && g_pCompositor->m_pLastWindow != w) /* window should change */) {
|
||||||
// a bit hacky
|
// a bit hacky
|
||||||
// if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus
|
// 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() {
|
void CInputManager::unconstrainMouse() {
|
||||||
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)
|
if (!g_pCompositor->m_sSeat.mouse)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
for (auto& c : m_vConstraints) {
|
||||||
|
if (!c->active())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (CONSTRAINTWINDOW)
|
c->deactivate();
|
||||||
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;
|
|
||||||
|
|
||||||
g_pCompositor->m_sSeat.mouse->hyprListener_commitConstraint.removeCallback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitConstraint(void* owner, void* data) {
|
bool CInputManager::isConstrained() {
|
||||||
const auto PMOUSE = (SMouse*)owner;
|
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) {
|
return true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) {
|
return false;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::updateCapabilities() {
|
void CInputManager::updateCapabilities() {
|
||||||
|
@ -1670,15 +1535,6 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) {
|
||||||
return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno)));
|
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() {
|
void CInputManager::releaseAllMouseButtons() {
|
||||||
const auto buttonsCopy = m_lCurrentlyHeldButtons;
|
const auto buttonsCopy = m_lCurrentlyHeldButtons;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "../../helpers/Timer.hpp"
|
#include "../../helpers/Timer.hpp"
|
||||||
#include "InputMethodRelay.hpp"
|
#include "InputMethodRelay.hpp"
|
||||||
|
|
||||||
|
class CConstraint;
|
||||||
|
|
||||||
enum eClickBehaviorMode {
|
enum eClickBehaviorMode {
|
||||||
CLICKMODE_DEFAULT = 0,
|
CLICKMODE_DEFAULT = 0,
|
||||||
CLICKMODE_KILL
|
CLICKMODE_KILL
|
||||||
|
@ -80,11 +82,8 @@ class CInputManager {
|
||||||
void destroyMouse(wlr_input_device*);
|
void destroyMouse(wlr_input_device*);
|
||||||
void destroySwitch(SSwitchDevice*);
|
void destroySwitch(SSwitchDevice*);
|
||||||
|
|
||||||
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
|
|
||||||
void warpMouseToConstraintMiddle(SConstraint*);
|
|
||||||
void recheckConstraint(SMouse*);
|
|
||||||
void unconstrainMouse();
|
void unconstrainMouse();
|
||||||
SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*);
|
bool isConstrained();
|
||||||
std::string getActiveLayoutForKeyboard(SKeyboard*);
|
std::string getActiveLayoutForKeyboard(SKeyboard*);
|
||||||
|
|
||||||
Vector2D getMouseCoordsInternal();
|
Vector2D getMouseCoordsInternal();
|
||||||
|
@ -120,13 +119,12 @@ class CInputManager {
|
||||||
bool m_bWasDraggingWindow = false;
|
bool m_bWasDraggingWindow = false;
|
||||||
|
|
||||||
// for refocus to be forced
|
// 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<SKeyboard> m_lKeyboards;
|
std::list<SMouse> m_lMice;
|
||||||
std::list<SMouse> m_lMice;
|
|
||||||
|
|
||||||
// tablets
|
// tablets
|
||||||
std::list<STablet> m_lTablets;
|
std::list<STablet> m_lTablets;
|
||||||
|
@ -145,25 +143,28 @@ class CInputManager {
|
||||||
// Exclusive layer surfaces
|
// Exclusive layer surfaces
|
||||||
std::deque<SLayerSurface*> m_dExclusiveLSes;
|
std::deque<SLayerSurface*> m_dExclusiveLSes;
|
||||||
|
|
||||||
void newTabletTool(wlr_input_device*);
|
// constraints
|
||||||
void newTabletPad(wlr_input_device*);
|
std::vector<CConstraint*> m_vConstraints;
|
||||||
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 newTabletTool(wlr_input_device*);
|
||||||
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
void newTabletPad(wlr_input_device*);
|
||||||
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||||
|
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
|
||||||
|
void recheckIdleInhibitorStatus();
|
||||||
|
|
||||||
SSwipeGesture m_sActiveSwipe;
|
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
|
||||||
|
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
||||||
|
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
||||||
|
|
||||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
SSwipeGesture m_sActiveSwipe;
|
||||||
|
|
||||||
CTimer m_tmrLastCursorMovement;
|
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||||
|
|
||||||
CInputMethodRelay m_sIMERelay;
|
CTimer m_tmrLastCursorMovement;
|
||||||
|
|
||||||
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
|
CInputMethodRelay m_sIMERelay;
|
||||||
|
|
||||||
|
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
|
||||||
|
|
||||||
// for shared mods
|
// for shared mods
|
||||||
uint32_t accumulateModsFromAllKBs();
|
uint32_t accumulateModsFromAllKBs();
|
||||||
|
|
Loading…
Reference in a new issue