Use locked cursor position hint
Summary: Listen for cursor position hint changes and set cursor position to the hint on unlock if a valid position hint was set. Test Plan: With pointer constraints test app. Reviewers: #kwin, graesslin Reviewed By: #kwin, graesslin Subscribers: graesslin, kwin Tags: #kwin Maniphest Tasks: T4693 Differential Revision: https://phabricator.kde.org/D14176
This commit is contained in:
parent
d723ce2c40
commit
054ccc3898
5 changed files with 76 additions and 0 deletions
|
@ -594,6 +594,12 @@ void PointerInputRedirection::disconnectConfinedPointerRegionConnection()
|
|||
m_confinedPointerRegionConnection = QMetaObject::Connection();
|
||||
}
|
||||
|
||||
void PointerInputRedirection::disconnectLockedPointerAboutToBeUnboundConnection()
|
||||
{
|
||||
disconnect(m_lockedPointerAboutToBeUnboundConnection);
|
||||
m_lockedPointerAboutToBeUnboundConnection = QMetaObject::Connection();
|
||||
}
|
||||
|
||||
void PointerInputRedirection::disconnectPointerConstraintsConnection()
|
||||
{
|
||||
disconnect(m_constraintsConnection);
|
||||
|
@ -689,8 +695,13 @@ void PointerInputRedirection::updatePointerConstraints()
|
|||
if (lock) {
|
||||
if (lock->isLocked()) {
|
||||
if (!canConstrain) {
|
||||
const auto hint = lock->cursorPositionHint();
|
||||
lock->setLocked(false);
|
||||
m_locked = false;
|
||||
disconnectLockedPointerAboutToBeUnboundConnection();
|
||||
if (! (hint.x() < 0 || hint.y() < 0) && m_window) {
|
||||
processMotion(m_window->pos() - m_window->clientContentPos() + hint, waylandServer()->seat()->timestamp());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -698,6 +709,24 @@ void PointerInputRedirection::updatePointerConstraints()
|
|||
if (canConstrain && r.contains(m_pos.toPoint())) {
|
||||
lock->setLocked(true);
|
||||
m_locked = true;
|
||||
|
||||
// The client might cancel pointer locking from its side by unbinding the LockedPointerInterface.
|
||||
// In this case the cached cursor position hint must be fetched before the resource goes away
|
||||
m_lockedPointerAboutToBeUnboundConnection = connect(lock.data(), &KWayland::Server::LockedPointerInterface::aboutToBeUnbound, this,
|
||||
[this, lock]() {
|
||||
const auto hint = lock->cursorPositionHint();
|
||||
if (hint.x() < 0 || hint.y() < 0 || !m_window) {
|
||||
return;
|
||||
}
|
||||
auto globalHint = m_window->pos() - m_window->clientContentPos() + hint;
|
||||
|
||||
// When the resource finally goes away, reposition the cursor according to the hint
|
||||
connect(lock.data(), &KWayland::Server::LockedPointerInterface::unbound, this,
|
||||
[this, globalHint]() {
|
||||
processMotion(globalHint, waylandServer()->seat()->timestamp());
|
||||
});
|
||||
}
|
||||
);
|
||||
OSD::show(i18nc("notification about mouse pointer locked",
|
||||
"Pointer locked to current position.\nTo end pointer lock hold Escape for 3 seconds."),
|
||||
QStringLiteral("preferences-desktop-mouse"), 5000);
|
||||
|
@ -705,6 +734,7 @@ void PointerInputRedirection::updatePointerConstraints()
|
|||
}
|
||||
} else {
|
||||
m_locked = false;
|
||||
disconnectLockedPointerAboutToBeUnboundConnection();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ private:
|
|||
void warpXcbOnSurfaceLeft(KWayland::Server::SurfaceInterface *surface);
|
||||
QPointF applyPointerConfinement(const QPointF &pos) const;
|
||||
void disconnectConfinedPointerRegionConnection();
|
||||
void disconnectLockedPointerAboutToBeUnboundConnection();
|
||||
void disconnectPointerConstraintsConnection();
|
||||
void breakPointerConstraints(KWayland::Server::SurfaceInterface *surface);
|
||||
bool areButtonsPressed() const;
|
||||
|
@ -169,6 +170,7 @@ private:
|
|||
QMetaObject::Connection m_constraintsConnection;
|
||||
QMetaObject::Connection m_constraintsActivatedConnection;
|
||||
QMetaObject::Connection m_confinedPointerRegionConnection;
|
||||
QMetaObject::Connection m_lockedPointerAboutToBeUnboundConnection;
|
||||
QMetaObject::Connection m_decorationGeometryConnection;
|
||||
bool m_confined = false;
|
||||
bool m_locked = false;
|
||||
|
|
|
@ -142,8 +142,14 @@ void WaylandBackend::lockRequest(bool persistent, QRect region)
|
|||
}
|
||||
m_lockedPointer = lockedPointer;
|
||||
m_lockedPointerPersistent = persistent;
|
||||
|
||||
connect(lockedPointer, &LockedPointer::locked, this, [this]() {
|
||||
qDebug() << "------ LOCKED! ------";
|
||||
if(lockHint()) {
|
||||
m_lockedPointer->setCursorPositionHint(QPointF(10., 10.));
|
||||
forceSurfaceCommit();
|
||||
}
|
||||
|
||||
Q_EMIT lockChanged(true);
|
||||
});
|
||||
connect(lockedPointer, &LockedPointer::unlocked, this, [this]() {
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
Backend(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_PROPERTY(int mode READ mode CONSTANT)
|
||||
Q_PROPERTY(bool lockHint MEMBER m_lockHint NOTIFY lockHintChanged)
|
||||
Q_PROPERTY(bool errorsAllowed READ errorsAllowed WRITE setErrorsAllowed NOTIFY errorsAllowedChanged)
|
||||
|
||||
virtual void init(QQuickView *view) {
|
||||
|
@ -57,6 +58,10 @@ public:
|
|||
int mode() const {
|
||||
return (int)m_mode;
|
||||
}
|
||||
|
||||
bool lockHint() const {
|
||||
return m_lockHint;
|
||||
}
|
||||
bool errorsAllowed() const {
|
||||
return m_errorsAllowed;
|
||||
}
|
||||
|
@ -87,7 +92,9 @@ public:
|
|||
Q_SIGNALS:
|
||||
void confineChanged(bool confined);
|
||||
void lockChanged(bool locked);
|
||||
void lockHintChanged();
|
||||
void errorsAllowedChanged();
|
||||
void forceSurfaceCommit();
|
||||
|
||||
protected:
|
||||
enum class Mode {
|
||||
|
@ -105,6 +112,8 @@ protected:
|
|||
private:
|
||||
QQuickView *m_view;
|
||||
Mode m_mode;
|
||||
|
||||
bool m_lockHint = true;
|
||||
bool m_errorsAllowed = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -79,6 +79,28 @@ ColumnLayout {
|
|||
return activArea.rect();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: org_kde_kwin_tests_pointerconstraints_backend
|
||||
onForceSurfaceCommit: {
|
||||
forceCommitRect.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: forceCommitRect
|
||||
width: 10
|
||||
height: 10
|
||||
color: "red"
|
||||
visible: false
|
||||
|
||||
Timer {
|
||||
interval: 500
|
||||
running: forceCommitRect.visible
|
||||
repeat: false
|
||||
onTriggered: forceCommitRect.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
rowSpacing: 10
|
||||
|
@ -120,6 +142,13 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: lockHintChck
|
||||
text: "Send position hint on lock"
|
||||
checked: root.waylandNative
|
||||
enabled: root.waylandNative
|
||||
onCheckedChanged: org_kde_kwin_tests_pointerconstraints_backend.lockHint = checked;
|
||||
}
|
||||
CheckBox {
|
||||
id: restrAreaChck
|
||||
text: "Restrict input area (not yet implemented)"
|
||||
|
|
Loading…
Reference in a new issue