Commit a2489a41 authored by Roman Gilg's avatar Roman Gilg
Browse files

Support cursor hints on locked pointer

Summary:
Implement support for locked pointer cursor hints. Cursor hints can be
retrieved by the compositor either continuously by connecting to the
cursorHintChanged signal or only when needed. In the later case the
compositor must connect to the aboutToUnbound signal of the locked pointer
interface in order to fetch the last hint before the interface is unbound.

Test Plan: Autotest added.

Reviewers: #plasma, davidedmundson

Reviewed By: #plasma, davidedmundson

Subscribers: davidedmundson, kde-frameworks-devel

Tags: #frameworks

Maniphest Tasks: T4692

Differential Revision: https://phabricator.kde.org/D14175
parent 7809e830
......@@ -250,9 +250,18 @@ void TestPointerConstraints::testLockPointer()
QVERIFY(lockedSpy.wait());
QVERIFY(unlockedSpy.isEmpty());
const QPointF hint = QPointF(1.5, 0.5);
QSignalSpy hintChangedSpy(serverLockedPointer.data(), &LockedPointerInterface::cursorPositionHintChanged);
lockedPointer->setCursorPositionHint(hint);
QCOMPARE(serverLockedPointer->cursorPositionHint(), QPointF(-1., -1.));
surface->commit(Surface::CommitFlag::None);
QVERIFY(hintChangedSpy.wait());
QCOMPARE(serverLockedPointer->cursorPositionHint(), hint);
// and unlock again
serverLockedPointer->setLocked(false);
QCOMPARE(serverLockedPointer->isLocked(), false);
QCOMPARE(serverLockedPointer->cursorPositionHint(), QPointF(-1., -1.));
QCOMPARE(lockedChangedSpy.count(), 2);
QTEST(!serverSurface->lockedPointer().isNull(), "hasConstraintAfterUnlock");
QTEST(pointerConstraintsChangedSpy.count(), "pointerChangedCount");
......
......@@ -67,13 +67,17 @@ LockedPointerInterface::Private::~Private()
void LockedPointerInterface::Private::commit()
{
if (!regionIsSet) {
return;
if (regionIsSet) {
region = pendingRegion;
pendingRegion = QRegion();
regionIsSet = false;
emit q_func()->regionChanged();
}
if (hintIsSet) {
hint = pendingHint;
hintIsSet = false;
emit q_func()->cursorPositionHintChanged();
}
region = pendingRegion;
pendingRegion = QRegion();
regionIsSet = false;
emit q_func()->regionChanged();
}
LockedPointerInterface::LockedPointerInterface(Private *p, QObject *parent)
......@@ -102,6 +106,12 @@ QRegion LockedPointerInterface::region() const
return d->region;
}
QPointF LockedPointerInterface::cursorPositionHint() const
{
Q_D();
return d->hint;
}
bool LockedPointerInterface::isLocked() const
{
Q_D();
......@@ -114,6 +124,9 @@ void LockedPointerInterface::setLocked(bool locked)
if (locked == d->locked) {
return;
}
if (!locked) {
d->hint = QPointF(-1., -1.);
}
d->locked = locked;
d->updateLocked();
emit lockedChanged();
......
......@@ -124,6 +124,24 @@ public:
**/
QRegion region() const;
/**
* Indicates where the mouse cursor should be positioned after it has been unlocked again.
* The compositor can warp the cursor at this moment to the position. For that it
* will not emit any relative motion events. The hint is relative to the top-left
* corner of the surface the lock was applied to. Only non-negative x and y values
* are allowed. Otherwise the hint is invalid and should be ignored by the compositor.
*
* In case the client never set the hint, an invalid one will be returned.
*
* This function should be called when the compositor decides to break the lock or the
* client unbinds the resource. To set the position in this case the compositor should
* call this function when the aboutToBeUnbound signal has been emitted.
*
* @see cursorPositionHintChanged
* @since 5.49
**/
QPointF cursorPositionHint() const;
/**
* Whether the Compositor set this pointer lock to be active.
* @see setLocked
......@@ -138,6 +156,8 @@ public:
* this LockedPointerInterface was created for has pointer focus
* and the pointer is inside the {@link region}.
*
* Unlocking resets the cursor position hint.
*
* @param locked Whether the lock should be active
* @see isLocked
* @see lockedChanged
......@@ -152,6 +172,14 @@ Q_SIGNALS:
**/
void regionChanged();
/**
* Emitted whenever the cursor position hint changes.
* This happens when the parent SurfaceInterface gets committed
* @see cursorPositionHint
* @since 5.49
**/
void cursorPositionHintChanged();
/**
* Emitted whenever the {@link isLocked} state changes.
* @see isLocked
......
......@@ -64,6 +64,7 @@ public:
LifeTime lifeTime;
QRegion region;
bool locked = false;
QPointF hint = QPointF(-1., -1.);
protected:
Private(PointerConstraintsInterfaceVersion interfaceVersion, LockedPointerInterface *q, Global *c, wl_resource *parentResource, const wl_interface *interface, const void *implementation);
......@@ -71,6 +72,9 @@ protected:
QRegion pendingRegion;
bool regionIsSet = false;
QPointF pendingHint;
bool hintIsSet = false;
private:
LockedPointerInterface *q_func() {
return reinterpret_cast<LockedPointerInterface *>(q);
......
......@@ -171,11 +171,9 @@ const struct zwp_locked_pointer_v1_interface LockedPointerUnstableV1Interface::P
void LockedPointerUnstableV1Interface::Private::setCursorPositionHintCallback(wl_client *client, wl_resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
Q_UNUSED(client)
Q_UNUSED(resource)
Q_UNUSED(surface_x)
Q_UNUSED(surface_y)
// double buffered
// TODO: implement
auto p = cast<Private>(resource);
p->pendingHint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
p->hintIsSet = true;
}
void LockedPointerUnstableV1Interface::Private::setRegionCallback(wl_client *client, wl_resource *resource, wl_resource * region)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment