Port pointer-constraints-v1 to the new design

This commit is contained in:
Vlad Zahorodnii 2020-11-03 20:44:32 +02:00
parent d0c93b5bc5
commit 0ed0066d74
14 changed files with 566 additions and 784 deletions

View file

@ -37,8 +37,7 @@ set(SERVER_LIB_SRCS
plasmavirtualdesktop_interface.cpp
plasmawindowmanagement_interface.cpp
pointer_interface.cpp
pointerconstraints_interface.cpp
pointerconstraints_interface_v1.cpp
pointerconstraints_v1_interface.cpp
pointergestures_v1_interface.cpp
primaryselectiondevice_v1_interface.cpp
primaryselectiondevicemanager_v1_interface.cpp
@ -175,7 +174,7 @@ ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
BASENAME pointer-gestures-unstable-v1
)
ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
PROTOCOL ${WaylandProtocols_DATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
BASENAME pointer-constraints-unstable-v1
)
@ -409,7 +408,7 @@ set(SERVER_LIB_HEADERS
plasmavirtualdesktop_interface.h
plasmawindowmanagement_interface.h
pointer_interface.h
pointerconstraints_interface.h
pointerconstraints_v1_interface.h
pointergestures_v1_interface.h
primaryselectiondevicemanager_v1_interface.h
region_interface.h

View file

@ -17,7 +17,7 @@
// server
#include "../../src/server/display.h"
#include "../../src/server/compositor_interface.h"
#include "../../src/server/pointerconstraints_interface.h"
#include "../../src/server/pointerconstraints_v1_interface.h"
#include "../../src/server/seat_interface.h"
#include "../../src/server/surface_interface.h"
@ -25,8 +25,8 @@ using namespace KWayland::Client;
using namespace KWaylandServer;
Q_DECLARE_METATYPE(KWayland::Client::PointerConstraints::LifeTime)
Q_DECLARE_METATYPE(KWaylandServer::ConfinedPointerInterface::LifeTime)
Q_DECLARE_METATYPE(KWaylandServer::LockedPointerInterface::LifeTime)
Q_DECLARE_METATYPE(KWaylandServer::ConfinedPointerV1Interface::LifeTime)
Q_DECLARE_METATYPE(KWaylandServer::LockedPointerV1Interface::LifeTime)
class TestPointerConstraints : public QObject
{
@ -47,7 +47,7 @@ private:
Display *m_display = nullptr;
CompositorInterface *m_compositorInterface = nullptr;
SeatInterface *m_seatInterface = nullptr;
PointerConstraintsInterface *m_pointerConstraintsInterface = nullptr;
PointerConstraintsV1Interface *m_pointerConstraintsInterface = nullptr;
ConnectionThread *m_connection = nullptr;
QThread *m_thread = nullptr;
EventQueue *m_queue = nullptr;
@ -71,8 +71,7 @@ void TestPointerConstraints::init()
m_seatInterface->setHasPointer(true);
m_seatInterface->create();
m_compositorInterface = m_display->createCompositor(m_display);
m_pointerConstraintsInterface = m_display->createPointerConstraints(PointerConstraintsInterfaceVersion::UnstableV1, m_display);
m_pointerConstraintsInterface->create();
m_pointerConstraintsInterface = m_display->createPointerConstraintsV1(m_display);
// setup connection
m_connection = new KWayland::Client::ConnectionThread;
@ -153,12 +152,12 @@ void TestPointerConstraints::cleanup()
void TestPointerConstraints::testLockPointer_data()
{
QTest::addColumn<PointerConstraints::LifeTime>("clientLifeTime");
QTest::addColumn<LockedPointerInterface::LifeTime>("serverLifeTime");
QTest::addColumn<LockedPointerV1Interface::LifeTime>("serverLifeTime");
QTest::addColumn<bool>("hasConstraintAfterUnlock");
QTest::addColumn<int>("pointerChangedCount");
QTest::newRow("persistent") << PointerConstraints::LifeTime::Persistent << LockedPointerInterface::LifeTime::Persistent << true << 1;
QTest::newRow("oneshot") << PointerConstraints::LifeTime::OneShot << LockedPointerInterface::LifeTime::OneShot << false << 2;
QTest::newRow("persistent") << PointerConstraints::LifeTime::Persistent << LockedPointerV1Interface::LifeTime::Persistent << true << 1;
QTest::newRow("oneshot") << PointerConstraints::LifeTime::OneShot << LockedPointerV1Interface::LifeTime::OneShot << false << 2;
}
void TestPointerConstraints::testLockPointer()
@ -173,8 +172,8 @@ void TestPointerConstraints::testLockPointer()
auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
QVERIFY(serverSurface);
QVERIFY(serverSurface->lockedPointer().isNull());
QVERIFY(serverSurface->confinedPointer().isNull());
QVERIFY(!serverSurface->lockedPointer());
QVERIFY(!serverSurface->confinedPointer());
// now create the locked pointer
QSignalSpy pointerConstraintsChangedSpy(serverSurface, &SurfaceInterface::pointerConstraintsChanged);
@ -190,20 +189,20 @@ void TestPointerConstraints::testLockPointer()
auto serverLockedPointer = serverSurface->lockedPointer();
QVERIFY(serverLockedPointer);
QVERIFY(serverSurface->confinedPointer().isNull());
QVERIFY(!serverSurface->confinedPointer());
QCOMPARE(serverLockedPointer->isLocked(), false);
QCOMPARE(serverLockedPointer->region(), QRegion());
QFETCH(LockedPointerInterface::LifeTime, serverLifeTime);
QFETCH(LockedPointerV1Interface::LifeTime, serverLifeTime);
QCOMPARE(serverLockedPointer->lifeTime(), serverLifeTime);
// setting to unlocked now should not trigger an unlocked spy
serverLockedPointer->setLocked(false);
QVERIFY(!unlockedSpy.wait(500));
// try setting a region
QSignalSpy destroyedSpy(serverLockedPointer.data(), &QObject::destroyed);
QSignalSpy destroyedSpy(serverLockedPointer, &QObject::destroyed);
QVERIFY(destroyedSpy.isValid());
QSignalSpy regionChangedSpy(serverLockedPointer.data(), &LockedPointerInterface::regionChanged);
QSignalSpy regionChangedSpy(serverLockedPointer, &LockedPointerV1Interface::regionChanged);
QVERIFY(regionChangedSpy.isValid());
lockedPointer->setRegion(m_compositor->createRegion(QRegion(0, 5, 10, 20), m_compositor));
// it's double buffered
@ -218,7 +217,7 @@ void TestPointerConstraints::testLockPointer()
QCOMPARE(serverLockedPointer->region(), QRegion());
// let's lock the surface
QSignalSpy lockedChangedSpy(serverLockedPointer.data(), &LockedPointerInterface::lockedChanged);
QSignalSpy lockedChangedSpy(serverLockedPointer, &LockedPointerV1Interface::lockedChanged);
QVERIFY(lockedChangedSpy.isValid());
m_seatInterface->setFocusedPointerSurface(serverSurface);
QSignalSpy pointerMotionSpy(m_pointer, &Pointer::motion);
@ -236,7 +235,7 @@ void TestPointerConstraints::testLockPointer()
QVERIFY(unlockedSpy.isEmpty());
const QPointF hint = QPointF(1.5, 0.5);
QSignalSpy hintChangedSpy(serverLockedPointer.data(), &LockedPointerInterface::cursorPositionHintChanged);
QSignalSpy hintChangedSpy(serverLockedPointer, &LockedPointerV1Interface::cursorPositionHintChanged);
lockedPointer->setCursorPositionHint(hint);
QCOMPARE(serverLockedPointer->cursorPositionHint(), QPointF(-1., -1.));
surface->commit(Surface::CommitFlag::None);
@ -248,7 +247,7 @@ void TestPointerConstraints::testLockPointer()
QCOMPARE(serverLockedPointer->isLocked(), false);
QCOMPARE(serverLockedPointer->cursorPositionHint(), QPointF(-1., -1.));
QCOMPARE(lockedChangedSpy.count(), 2);
QTEST(!serverSurface->lockedPointer().isNull(), "hasConstraintAfterUnlock");
QTEST(bool(serverSurface->lockedPointer()), "hasConstraintAfterUnlock");
QTEST(pointerConstraintsChangedSpy.count(), "pointerChangedCount");
QVERIFY(unlockedSpy.wait());
QCOMPARE(unlockedSpy.count(), 1);
@ -267,12 +266,12 @@ void TestPointerConstraints::testLockPointer()
void TestPointerConstraints::testConfinePointer_data()
{
QTest::addColumn<PointerConstraints::LifeTime>("clientLifeTime");
QTest::addColumn<ConfinedPointerInterface::LifeTime>("serverLifeTime");
QTest::addColumn<ConfinedPointerV1Interface::LifeTime>("serverLifeTime");
QTest::addColumn<bool>("hasConstraintAfterUnlock");
QTest::addColumn<int>("pointerChangedCount");
QTest::newRow("persistent") << PointerConstraints::LifeTime::Persistent << ConfinedPointerInterface::LifeTime::Persistent << true << 1;
QTest::newRow("oneshot") << PointerConstraints::LifeTime::OneShot << ConfinedPointerInterface::LifeTime::OneShot << false << 2;
QTest::newRow("persistent") << PointerConstraints::LifeTime::Persistent << ConfinedPointerV1Interface::LifeTime::Persistent << true << 1;
QTest::newRow("oneshot") << PointerConstraints::LifeTime::OneShot << ConfinedPointerV1Interface::LifeTime::OneShot << false << 2;
}
void TestPointerConstraints::testConfinePointer()
@ -287,8 +286,8 @@ void TestPointerConstraints::testConfinePointer()
auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
QVERIFY(serverSurface);
QVERIFY(serverSurface->lockedPointer().isNull());
QVERIFY(serverSurface->confinedPointer().isNull());
QVERIFY(!serverSurface->lockedPointer());
QVERIFY(!serverSurface->confinedPointer());
// now create the confined pointer
QSignalSpy pointerConstraintsChangedSpy(serverSurface, &SurfaceInterface::pointerConstraintsChanged);
@ -304,20 +303,20 @@ void TestPointerConstraints::testConfinePointer()
auto serverConfinedPointer = serverSurface->confinedPointer();
QVERIFY(serverConfinedPointer);
QVERIFY(serverSurface->lockedPointer().isNull());
QVERIFY(!serverSurface->lockedPointer());
QCOMPARE(serverConfinedPointer->isConfined(), false);
QCOMPARE(serverConfinedPointer->region(), QRegion());
QFETCH(ConfinedPointerInterface::LifeTime, serverLifeTime);
QFETCH(ConfinedPointerV1Interface::LifeTime, serverLifeTime);
QCOMPARE(serverConfinedPointer->lifeTime(), serverLifeTime);
// setting to unconfined now should not trigger an unconfined spy
serverConfinedPointer->setConfined(false);
QVERIFY(!unconfinedSpy.wait(500));
// try setting a region
QSignalSpy destroyedSpy(serverConfinedPointer.data(), &QObject::destroyed);
QSignalSpy destroyedSpy(serverConfinedPointer, &QObject::destroyed);
QVERIFY(destroyedSpy.isValid());
QSignalSpy regionChangedSpy(serverConfinedPointer.data(), &ConfinedPointerInterface::regionChanged);
QSignalSpy regionChangedSpy(serverConfinedPointer, &ConfinedPointerV1Interface::regionChanged);
QVERIFY(regionChangedSpy.isValid());
confinedPointer->setRegion(m_compositor->createRegion(QRegion(0, 5, 10, 20), m_compositor));
// it's double buffered
@ -332,7 +331,7 @@ void TestPointerConstraints::testConfinePointer()
QCOMPARE(serverConfinedPointer->region(), QRegion());
// let's confine the surface
QSignalSpy confinedChangedSpy(serverConfinedPointer.data(), &ConfinedPointerInterface::confinedChanged);
QSignalSpy confinedChangedSpy(serverConfinedPointer, &ConfinedPointerV1Interface::confinedChanged);
QVERIFY(confinedChangedSpy.isValid());
m_seatInterface->setFocusedPointerSurface(serverSurface);
serverConfinedPointer->setConfined(true);
@ -346,7 +345,7 @@ void TestPointerConstraints::testConfinePointer()
serverConfinedPointer->setConfined(false);
QCOMPARE(serverConfinedPointer->isConfined(), false);
QCOMPARE(confinedChangedSpy.count(), 2);
QTEST(!serverSurface->confinedPointer().isNull(), "hasConstraintAfterUnlock");
QTEST(bool(serverSurface->confinedPointer()), "hasConstraintAfterUnlock");
QTEST(pointerConstraintsChangedSpy.count(), "pointerChangedCount");
QVERIFY(unconfinedSpy.wait());
QCOMPARE(unconfinedSpy.count(), 1);

View file

@ -28,7 +28,7 @@
#include "plasmashell_interface.h"
#include "plasmavirtualdesktop_interface.h"
#include "plasmawindowmanagement_interface.h"
#include "pointerconstraints_interface_p.h"
#include "pointerconstraints_v1_interface_p.h"
#include "pointergestures_v1_interface.h"
#include "primaryselectiondevicemanager_v1_interface.h"
#include "relativepointer_v1_interface.h"
@ -380,14 +380,9 @@ PointerGesturesV1Interface *Display::createPointerGesturesV1(QObject *parent)
return p;
}
PointerConstraintsInterface *Display::createPointerConstraints(const PointerConstraintsInterfaceVersion &version, QObject *parent)
PointerConstraintsV1Interface *Display::createPointerConstraintsV1(QObject *parent)
{
PointerConstraintsInterface *p = nullptr;
switch (version) {
case PointerConstraintsInterfaceVersion::UnstableV1:
p = new PointerConstraintsUnstableV1Interface(this, parent);
break;
}
PointerConstraintsV1Interface *p = new PointerConstraintsV1Interface(this, parent);
connect(this, &Display::aboutToTerminate, p, [p] { delete p; });
return p;
}

View file

@ -59,8 +59,7 @@ class TextInputManagerV3Interface;
class XdgShellInterface;
class RelativePointerManagerV1Interface;
class PointerGesturesV1Interface;
enum class PointerConstraintsInterfaceVersion;
class PointerConstraintsInterface;
class PointerConstraintsV1Interface;
class XdgForeignV2Interface;
class AppMenuManagerInterface;
class ServerSideDecorationPaletteManagerInterface;
@ -228,12 +227,12 @@ public:
PointerGesturesV1Interface *createPointerGesturesV1(QObject *parent = nullptr);
/**
* Creates the PointerConstraintsInterface in interface @p version
* Creates the PointerConstraintsV1Interface
*
* @returns The created manager object
* @since 5.29
**/
PointerConstraintsInterface *createPointerConstraints(const PointerConstraintsInterfaceVersion &version, QObject *parent = nullptr);
PointerConstraintsV1Interface *createPointerConstraintsV1(QObject *parent = nullptr);
/**
* Creates the XdgForeignV2Interface in interface @p version

View file

@ -5,7 +5,7 @@
*/
#include "pointer_interface.h"
#include "pointer_interface_p.h"
#include "pointerconstraints_interface.h"
#include "pointerconstraints_v1_interface.h"
#include "pointergestures_v1_interface_p.h"
#include "resource_p.h"
#include "relativepointer_v1_interface_p.h"
@ -220,7 +220,7 @@ PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentRes
return;
}
}
if (!d->focusedSurface->lockedPointer().isNull() && d->focusedSurface->lockedPointer()->isLocked()) {
if (d->focusedSurface->lockedPointer() && d->focusedSurface->lockedPointer()->isLocked()) {
return;
}
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());

View file

@ -0,0 +1,331 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "pointerconstraints_v1_interface.h"
#include "display.h"
#include "pointer_interface.h"
#include "pointerconstraints_v1_interface_p.h"
#include "region_interface.h"
#include "surface_interface_p.h"
namespace KWaylandServer
{
static const int s_version = 1;
PointerConstraintsV1InterfacePrivate::PointerConstraintsV1InterfacePrivate(Display *display)
: QtWaylandServer::zwp_pointer_constraints_v1(*display, s_version)
{
}
static QRegion regionFromResource(::wl_resource *resource)
{
const RegionInterface *region = RegionInterface::get(resource);
return region ? region->region() : QRegion();
}
void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_lock_pointer(Resource *resource,
uint32_t id,
::wl_resource *surface_resource,
::wl_resource *pointer_resource,
::wl_resource *region_resource,
uint32_t lifetime)
{
PointerInterface *pointer = PointerInterface::get(pointer_resource);
if (!pointer) {
wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
"invalid pointer");
return;
}
SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
if (!surface) {
wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
"invalid surface");
return;
}
if (surface->lockedPointer() || surface->confinedPointer()) {
wl_resource_post_error(resource->handle, error_already_constrained,
"the surface is already constrained");
return;
}
if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) {
wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
"unknown lifetime %d", lifetime);
return;
}
wl_resource *lockedPointerResource = wl_resource_create(resource->client(),
&zwp_locked_pointer_v1_interface,
resource->version(), id);
if (!lockedPointerResource) {
wl_resource_post_no_memory(resource->handle);
return;
}
auto lockedPointer = new LockedPointerV1Interface(LockedPointerV1Interface::LifeTime(lifetime),
regionFromResource(region_resource),
lockedPointerResource);
SurfaceInterfacePrivate::get(surface)->installPointerConstraint(lockedPointer);
}
void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_confine_pointer(Resource *resource,
uint32_t id,
::wl_resource *surface_resource,
::wl_resource *pointer_resource,
::wl_resource *region_resource,
uint32_t lifetime)
{
PointerInterface *pointer = PointerInterface::get(pointer_resource);
if (!pointer) {
wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
"invalid pointer");
return;
}
SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
if (!surface) {
wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
"invalid surface");
return;
}
if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) {
wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
"unknown lifetime %d", lifetime);
return;
}
if (surface->lockedPointer() || surface->confinedPointer()) {
wl_resource_post_error(resource->handle, error_already_constrained,
"the surface is already constrained");
return;
}
wl_resource *confinedPointerResource = wl_resource_create(resource->client(),
&zwp_confined_pointer_v1_interface,
resource->version(), id);
if (!confinedPointerResource) {
wl_resource_post_no_memory(resource->handle);
return;
}
auto confinedPointer = new ConfinedPointerV1Interface(ConfinedPointerV1Interface::LifeTime(lifetime),
regionFromResource(region_resource),
confinedPointerResource);
SurfaceInterfacePrivate::get(surface)->installPointerConstraint(confinedPointer);
}
void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
PointerConstraintsV1Interface::PointerConstraintsV1Interface(Display *display, QObject *parent)
: QObject(parent)
, d(new PointerConstraintsV1InterfacePrivate(display))
{
}
PointerConstraintsV1Interface::~PointerConstraintsV1Interface()
{
}
LockedPointerV1InterfacePrivate *LockedPointerV1InterfacePrivate::get(LockedPointerV1Interface *q)
{
return q->d.data();
}
LockedPointerV1InterfacePrivate::LockedPointerV1InterfacePrivate(LockedPointerV1Interface *q,
LockedPointerV1Interface::LifeTime lifeTime,
const QRegion &region,
::wl_resource *resource)
: QtWaylandServer::zwp_locked_pointer_v1(resource)
, q(q)
, lifeTime(lifeTime)
, region(region)
{
}
void LockedPointerV1InterfacePrivate::commit()
{
if (hasPendingRegion) {
region = pendingRegion;
hasPendingRegion = false;
emit q->regionChanged();
}
if (hasPendingHint) {
hint = pendingHint;
hasPendingHint = false;
emit q->cursorPositionHintChanged();
}
}
void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy_resource(Resource *resource)
{
Q_UNUSED(resource)
emit q->aboutToBeDestroyed();
delete q;
}
void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource,
wl_fixed_t surface_x,
wl_fixed_t surface_y)
{
Q_UNUSED(resource)
pendingHint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
hasPendingHint = true;
}
void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_region(Resource *resource,
::wl_resource *region_resource)
{
Q_UNUSED(resource)
pendingRegion = regionFromResource(region_resource);
hasPendingRegion = true;
}
LockedPointerV1Interface::LockedPointerV1Interface(LifeTime lifeTime, const QRegion &region,
::wl_resource *resource)
: d(new LockedPointerV1InterfacePrivate(this, lifeTime, region, resource))
{
}
LockedPointerV1Interface::~LockedPointerV1Interface()
{
}
LockedPointerV1Interface::LifeTime LockedPointerV1Interface::lifeTime() const
{
return d->lifeTime;
}
QRegion LockedPointerV1Interface::region() const
{
return d->region;
}
QPointF LockedPointerV1Interface::cursorPositionHint() const
{
return d->hint;
}
bool LockedPointerV1Interface::isLocked() const
{
return d->isLocked;
}
void LockedPointerV1Interface::setLocked(bool locked)
{
if (d->isLocked == locked) {
return;
}
if (!locked) {
d->hint = QPointF(-1, -1);
}
d->isLocked = locked;
if (d->isLocked) {
d->send_locked();
} else {
d->send_unlocked();
}
emit lockedChanged();
}
ConfinedPointerV1InterfacePrivate *ConfinedPointerV1InterfacePrivate::get(ConfinedPointerV1Interface *q)
{
return q->d.data();
}
ConfinedPointerV1InterfacePrivate::ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q,
ConfinedPointerV1Interface::LifeTime lifeTime,
const QRegion &region,
::wl_resource *resource)
: QtWaylandServer::zwp_confined_pointer_v1(resource)
, q(q)
, lifeTime(lifeTime)
, region(region)
{
}
void ConfinedPointerV1InterfacePrivate::commit()
{
if (hasPendingRegion) {
region = pendingRegion;
hasPendingRegion = false;
emit q->regionChanged();
}
}
void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy_resource(Resource *resource)
{
Q_UNUSED(resource)
delete q;
}
void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_set_region(Resource *resource,
::wl_resource *region_resource)
{
Q_UNUSED(resource)
pendingRegion = regionFromResource(region_resource);
hasPendingRegion = true;
}
ConfinedPointerV1Interface::ConfinedPointerV1Interface(LifeTime lifeTime, const QRegion &region,
::wl_resource *resource)
: d(new ConfinedPointerV1InterfacePrivate(this, lifeTime, region, resource))
{
}
ConfinedPointerV1Interface::~ConfinedPointerV1Interface()
{
}
ConfinedPointerV1Interface::LifeTime ConfinedPointerV1Interface::lifeTime() const
{
return d->lifeTime;
}
QRegion ConfinedPointerV1Interface::region() const
{
return d->region;
}
bool ConfinedPointerV1Interface::isConfined() const
{
return d->isConfined;
}
void ConfinedPointerV1Interface::setConfined(bool confined)
{
if (d->isConfined == confined) {
return;
}
d->isConfined = confined;
if (d->isConfined) {
d->send_confined();
} else {
d->send_unconfined();
}
emit confinedChanged();
}
} // namespace KWaylandServer

View file

@ -1,96 +1,72 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef KWAYLAND_SERVER_POINTERCONSTRAINTS_INTERFACE_H
#define KWAYLAND_SERVER_POINTERCONSTRAINTS_INTERFACE_H
#include "global.h"
#include "resource.h"
#pragma once
#include <KWaylandServer/kwaylandserver_export.h>
#include <QObject>
#include <QRegion>
struct wl_resource;
namespace KWaylandServer
{
class ConfinedPointerV1InterfacePrivate;
class Display;
class LockedPointerV1InterfacePrivate;
class PointerConstraintsV1InterfacePrivate;
class SurfaceInterface;
/**
* Enum describing the interface versions the PointerConstraintsInterface can support.
*
* @since 5.29
**/
enum class PointerConstraintsInterfaceVersion {
/**
* zwp_pointer_constraints_v1
**/
UnstableV1
};
/**
* Manager object to create pointer constraints.
*
* To create this manager use {@link Display::createPointerConstraints}
* To create this manager use {@link Display::createPointerConstraintsV1}
*
* @see ConfinedPointerInterface
* @see LockedPointerInterface
* @see Display::createPointerConstraints
* @since 5.29
**/
class KWAYLANDSERVER_EXPORT PointerConstraintsInterface : public Global
* @see ConfinedPointerV1Interface
* @see LockedPointerV1Interface
*/
class KWAYLANDSERVER_EXPORT PointerConstraintsV1Interface : public QObject
{
Q_OBJECT
public:
virtual ~PointerConstraintsInterface();
/**
* @returns The interface version used by this PointerConstraintsInterface
**/
PointerConstraintsInterfaceVersion interfaceVersion() const;
protected:
class Private;
explicit PointerConstraintsInterface(Private *d, QObject *parent = nullptr);
explicit PointerConstraintsV1Interface(Display *display, QObject *parent = nullptr);
~PointerConstraintsV1Interface() override;
private:
Private *d_func() const;
QScopedPointer<PointerConstraintsV1InterfacePrivate> d;
};
/**
* The LockedPointerInterface lets the client request to disable movements of
* The LockedPointerV1Interface lets the client request to disable movements of
* the virtual pointer (i.e. the cursor), effectively locking the pointer
* to a position.
*
* It is up to the compositor whether the lock gets activated.
* To activate it needs to use {@link LockedPointerInterface::setLocked}.
* To activate it needs to use {@link LockedPointerV1Interface::setLocked}.
* The compositor needs to ensure that the SurfaceInterface has pointer focus
* and that the pointer is inside the {@link LockedPointerInterface::region} when
* and that the pointer is inside the {@link LockedPointerV1Interface::region} when
* it activates the lock.
*
* While the lock is active the PointerInterface does no longer emit pointer motion
* events, but still emits relative pointer motion events.
*
* @since 5.29
**/
class KWAYLANDSERVER_EXPORT LockedPointerInterface : public Resource
*/
class KWAYLANDSERVER_EXPORT LockedPointerV1Interface : public QObject
{
Q_OBJECT
public:
~LockedPointerV1Interface() override;
virtual ~LockedPointerInterface();
/**
* @returns The interface version used by this LockedPointerInterface
**/
PointerConstraintsInterfaceVersion interfaceVersion() const;
enum class LifeTime {
OneShot,
Persistent
enum class LifeTime : uint {
OneShot = 1,
Persistent = 2
};
LifeTime lifeTime() const;
@ -105,7 +81,7 @@ public:
*
* @see regionChanged
* @see SurfaceInterface::input
**/
*/
QRegion region() const;
/**
@ -122,22 +98,21 @@ public:
* 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
* @see lockedChanged
**/
*/
bool isLocked() const;
/**
* Activates or deactivates the lock.
*
* A pointer lock can only be activated if the SurfaceInterface
* this LockedPointerInterface was created for has pointer focus
* this LockedPointerV1Interface was created for has pointer focus
* and the pointer is inside the {@link region}.
*
* Unlocking resets the cursor position hint.
@ -145,74 +120,69 @@ public:
* @param locked Whether the lock should be active
* @see isLocked
* @see lockedChanged
**/
*/
void setLocked(bool locked);
Q_SIGNALS:
/**
* This is signal is emitted when the locked pointer is about to be destroyed.
*/
void aboutToBeDestroyed();
/**
* Emitted whenever the region changes.
* This happens when the parent SurfaceInterface gets committed
* @see region
**/
*/
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
* @see setLocked
**/
*/
void lockedChanged();
protected:
class Private;
explicit LockedPointerInterface(Private *p, QObject *parent = nullptr);
private:
Private *d_func() const;
friend class SurfaceInterfacePrivate;
LockedPointerV1Interface(LifeTime lifeTime, const QRegion &region, ::wl_resource *resource);
QScopedPointer<LockedPointerV1InterfacePrivate> d;
friend class LockedPointerV1InterfacePrivate;
friend class PointerConstraintsV1InterfacePrivate;
};
/**
*
* The ConfinedPointerInterface gets installed on a SurfaceInterface.
* The ConfinedPointerV1Interface gets installed on a SurfaceInterface.
* The confinement indicates that the SurfaceInterface wants to confine the
* pointer to a region of the SurfaceInterface.
*
* It is up to the compositor whether the confinement gets activated.
* To activate it needs to use {@link ConfinedPointerInterface::setConfined}.
* To activate it needs to use {@link ConfinedPointerV1Interface::setConfined}.
* The compositor needs to ensure that the SurfaceInterface has pointer focus
* and that the pointer is inside the {@link ConfinedPointerInterface::region} when
* and that the pointer is inside the {@link ConfinedPointerV1Interface::region} when
* it activates the confinement.
*
* From client side the confinement gets deactivated by destroying the ConfinedPointerInterface.
* From client side the confinement gets deactivated by destroying the ConfinedPointerV1Interface.
* From compositor side the confinement can be deactivated by setting
* {@link ConfinedPointerInterface::setConfined} to @c false.
*
* @since 5.29
**/
class KWAYLANDSERVER_EXPORT ConfinedPointerInterface : public Resource
* {@link ConfinedPointerV1Interface::setConfined} to @c false.
*/
class KWAYLANDSERVER_EXPORT ConfinedPointerV1Interface : public QObject
{
Q_OBJECT
public:
~ConfinedPointerV1Interface() override;
virtual ~ConfinedPointerInterface();
/**
* @returns The interface version used by this ConfinedPointerInterface
**/
PointerConstraintsInterfaceVersion interfaceVersion() const;
enum class LifeTime {
OneShot,
Persistent
enum class LifeTime : uint {
OneShot = 1,
Persistent = 2
};
LifeTime lifeTime() const;
@ -227,27 +197,27 @@ public:
*
* @see regionChanged
* @see SurfaceInterface::input
**/
*/
QRegion region() const;
/**
* Whether the Compositor set this pointer confinement to be active.
* @see setConfined
* @see confinedChanged
**/
*/
bool isConfined() const;
/**
* Activates or deactivates the confinement.
*
* A pointer confinement can only be activated if the SurfaceInterface
* this ConfinedPointerInterface was created for has pointer focus
* this ConfinedPointerV1Interface was created for has pointer focus
* and the pointer is inside the {@link region}.
*
* @param confined Whether the confinement should be active
* @see isConfined
* @see confinedChanged
**/
*/
void setConfined(bool confined);
Q_SIGNALS:
@ -255,25 +225,21 @@ Q_SIGNALS:
* Emitted whenever the region changes.
* This happens when the parent SurfaceInterface gets committed
* @see region
**/
*/
void regionChanged();
/**
* Emitted whenever the {@link isConfined} state changes.
* @see isConfined
* @see setConfined
**/
*/
void confinedChanged();
protected:
class Private;
explicit ConfinedPointerInterface(Private *p, QObject *parent = nullptr);
private:
Private *d_func() const;
friend class SurfaceInterfacePrivate;
ConfinedPointerV1Interface(LifeTime lifeTime, const QRegion &region, ::wl_resource *resource);
QScopedPointer<ConfinedPointerV1InterfacePrivate> d;
friend class ConfinedPointerV1InterfacePrivate;
friend class PointerConstraintsV1InterfacePrivate;
};
}
#endif
} // namespace KWaylandServer

View file

@ -0,0 +1,92 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include "pointerconstraints_v1_interface.h"
#include "qwayland-server-pointer-constraints-unstable-v1.h"
namespace KWaylandServer
{
class PointerConstraintsV1InterfacePrivate : public QtWaylandServer::zwp_pointer_constraints_v1
{
public:
explicit PointerConstraintsV1InterfacePrivate(Display *display);
protected:
void zwp_pointer_constraints_v1_lock_pointer(Resource *resource, uint32_t id,
struct ::wl_resource *surface_resource,
struct ::wl_resource *pointer_resource,
struct ::wl_resource *region_resource,
uint32_t lifetime) override;
void zwp_pointer_constraints_v1_confine_pointer(Resource *resource, uint32_t id,
struct ::wl_resource *surface_resource,
struct ::wl_resource *pointer_resource,
struct ::wl_resource *region_resource,
uint32_t lifetime) override;
void zwp_pointer_constraints_v1_destroy(Resource *resource) override;
};
class LockedPointerV1InterfacePrivate : public QtWaylandServer::zwp_locked_pointer_v1
{
public:
static LockedPointerV1InterfacePrivate *get(LockedPointerV1Interface *pointer);
LockedPointerV1InterfacePrivate(LockedPointerV1Interface *q,
LockedPointerV1Interface::LifeTime lifeTime,
const QRegion &region, ::wl_resource *resource);
void commit();
LockedPointerV1Interface *q;
LockedPointerV1Interface::LifeTime lifeTime;
QRegion region;
QRegion pendingRegion;
QPointF hint = QPointF(-1, -1);
QPointF pendingHint;
bool hasPendingRegion = false;
bool hasPendingHint = false;
bool isLocked = false;
protected:
void zwp_locked_pointer_v1_destroy_resource(Resource *resource) override;
void zwp_locked_pointer_v1_destroy(Resource *resource) override;
void zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource,
wl_fixed_t surface_x,
wl_fixed_t surface_y) override;
void zwp_locked_pointer_v1_set_region(Resource *resource,
struct ::wl_resource *region_resource) override;
};
class ConfinedPointerV1InterfacePrivate : public QtWaylandServer::zwp_confined_pointer_v1
{
public:
static ConfinedPointerV1InterfacePrivate *get(ConfinedPointerV1Interface *pointer);
ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q,
ConfinedPointerV1Interface::LifeTime lifeTime,
const QRegion &region, ::wl_resource *resource);
void commit();
ConfinedPointerV1Interface *q;
ConfinedPointerV1Interface::LifeTime lifeTime;
QRegion region;
QRegion pendingRegion;
bool hasPendingRegion = false;
bool isConfined = false;
protected:
void zwp_confined_pointer_v1_destroy_resource(Resource *resource) override;
void zwp_confined_pointer_v1_destroy(Resource *resource) override;
void zwp_confined_pointer_v1_set_region(Resource *resource,
struct ::wl_resource *region_resource) override;
};
} // namespace KWaylandServer

View file

@ -1,197 +0,0 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "pointerconstraints_interface_p.h"
#include <functional>
namespace KWaylandServer
{
PointerConstraintsInterface::Private::Private(PointerConstraintsInterfaceVersion interfaceVersion, PointerConstraintsInterface *q, Display *d, const wl_interface *interface, quint32 version)
: Global::Private(d, interface, version)
, interfaceVersion(interfaceVersion)
, q(q)
{
}
PointerConstraintsInterface::PointerConstraintsInterface(Private *d, QObject *parent)
: Global(d, parent)
{
}
PointerConstraintsInterface::~PointerConstraintsInterface() = default;
PointerConstraintsInterfaceVersion PointerConstraintsInterface::interfaceVersion() const
{
Q_D();
return d->interfaceVersion;
}
PointerConstraintsInterface::Private *PointerConstraintsInterface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
}
LockedPointerInterface::Private::Private(PointerConstraintsInterfaceVersion interfaceVersion, LockedPointerInterface *q, Global *c, wl_resource *parentResource, const wl_interface *interface, const void *implementation)
: Resource::Private(q, c, parentResource, interface, implementation)
, interfaceVersion(interfaceVersion)
{
}
LockedPointerInterface::Private::~Private()
{
if (resource) {
wl_resource_destroy(resource);
resource = nullptr;
}
}
void LockedPointerInterface::Private::commit()
{
if (regionIsSet) {
region = pendingRegion;
pendingRegion = QRegion();
regionIsSet = false;
emit q_func()->regionChanged();
}
if (hintIsSet) {
hint = pendingHint;
hintIsSet = false;
emit q_func()->cursorPositionHintChanged();
}
}
LockedPointerInterface::LockedPointerInterface(Private *p, QObject *parent)
: Resource(p, parent)
{
connect(this, &LockedPointerInterface::unbound, this, [this]() { setLocked(false); });
}
LockedPointerInterface::~LockedPointerInterface() = default;
PointerConstraintsInterfaceVersion LockedPointerInterface::interfaceVersion() const
{
Q_D();
return d->interfaceVersion;
}
LockedPointerInterface::LifeTime LockedPointerInterface::lifeTime() const
{
Q_D();
return d->lifeTime;
}
QRegion LockedPointerInterface::region() const
{
Q_D();
return d->region;
}
QPointF LockedPointerInterface::cursorPositionHint() const
{
Q_D();
return d->hint;
}
bool LockedPointerInterface::isLocked() const
{
Q_D();
return d->locked;
}
void LockedPointerInterface::setLocked(bool locked)
{
Q_D();
if (locked == d->locked) {
return;
}
if (!locked) {
d->hint = QPointF(-1., -1.);
}
d->locked = locked;
d->updateLocked();
emit lockedChanged();
}
LockedPointerInterface::Private *LockedPointerInterface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
}
ConfinedPointerInterface::Private::Private(PointerConstraintsInterfaceVersion interfaceVersion, ConfinedPointerInterface *q, Global *c, wl_resource *parentResource, const wl_interface *interface, const void *implementation)
: Resource::Private(q, c, parentResource, interface, implementation)
, interfaceVersion(interfaceVersion)
{
}
ConfinedPointerInterface::Private::~Private()
{
if (resource) {
wl_resource_destroy(resource);
resource = nullptr;
}
}
void ConfinedPointerInterface::Private::commit()
{
if (!regionIsSet) {
return;
}
region = pendingRegion;
pendingRegion = QRegion();
regionIsSet = false;
emit q_func()->regionChanged();
}
ConfinedPointerInterface::ConfinedPointerInterface(Private *p, QObject *parent)
: Resource(p, parent)
{
connect(this, &ConfinedPointerInterface::unbound, this, [this]() { setConfined(false); });
}
ConfinedPointerInterface::~ConfinedPointerInterface() = default;
PointerConstraintsInterfaceVersion ConfinedPointerInterface::interfaceVersion() const
{
Q_D();
return d->interfaceVersion;
}
ConfinedPointerInterface::LifeTime ConfinedPointerInterface::lifeTime() const
{
Q_D();
return d->lifeTime;
}
QRegion ConfinedPointerInterface::region() const
{
Q_D();
return d->region;
}
bool ConfinedPointerInterface::isConfined() const
{
Q_D();
return d->confined;
}
void ConfinedPointerInterface::setConfined(bool confined)
{
Q_D();
if (confined == d->confined) {
return;
}
d->confined = confined;
d->updateConfined();
emit confinedChanged();
}
ConfinedPointerInterface::Private *ConfinedPointerInterface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
}
}

View file

@ -1,123 +0,0 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef KWAYLAND_SERVER_POINTERCONSTRAINTS_INTERFACE_P_H
#define KWAYLAND_SERVER_POINTERCONSTRAINTS_INTERFACE_P_H
#include "pointerconstraints_interface.h"
#include "global_p.h"
#include "resource_p.h"
#include <QRegion>
namespace KWaylandServer
{
class PointerConstraintsInterface::Private : public Global::Private
{
public:
PointerConstraintsInterfaceVersion interfaceVersion;
protected:
Private(PointerConstraintsInterfaceVersion interfaceVersion, PointerConstraintsInterface *q, Display *d, const wl_interface *interface, quint32 version);
PointerConstraintsInterface *q;
};
class PointerConstraintsUnstableV1Interface : public PointerConstraintsInterface
{
Q_OBJECT
public:
explicit PointerConstraintsUnstableV1Interface(Display *display, QObject *parent = nullptr);
virtual ~PointerConstraintsUnstableV1Interface();
private:
class Private;
};
class LockedPointerInterface::Private : public Resource::Private
{
public:
~Private();
virtual void updateLocked() = 0;
void commit();
PointerConstraintsInterfaceVersion interfaceVersion;
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);
QRegion pendingRegion;
bool regionIsSet = false;
QPointF pendingHint;
bool hintIsSet = false;
private:
LockedPointerInterface *q_func() {
return reinterpret_cast<LockedPointerInterface *>(q);
}
};
class LockedPointerUnstableV1Interface : public LockedPointerInterface
{
Q_OBJECT
public:
explicit LockedPointerUnstableV1Interface(PointerConstraintsUnstableV1Interface *parent, wl_resource *parentResource);
virtual ~LockedPointerUnstableV1Interface();
private:
class Private;
Private *d_func() const;
friend class PointerConstraintsUnstableV1Interface;
};
class ConfinedPointerInterface::Private : public Resource::Private
{
public:
~Private();
virtual void updateConfined() = 0;
void commit();
PointerConstraintsInterfaceVersion interfaceVersion;
LifeTime lifeTime;
QRegion region;
bool confined = false;
protected:
Private(PointerConstraintsInterfaceVersion interfaceVersion, ConfinedPointerInterface *q, Global *c, wl_resource *parentResource, const wl_interface *interface, const void *implementation);
QRegion pendingRegion;
bool regionIsSet = false;
private:
ConfinedPointerInterface *q_func() {
return reinterpret_cast<ConfinedPointerInterface *>(q);
}
};
class ConfinedPointerUnstableV1Interface : public ConfinedPointerInterface
{
Q_OBJECT
public:
explicit ConfinedPointerUnstableV1Interface(PointerConstraintsUnstableV1Interface *parent, wl_resource *parentResource);
virtual ~ConfinedPointerUnstableV1Interface();
private:
class Private;
Private *d_func() const;
friend class PointerConstraintsUnstableV1Interface;
};
}
#endif

View file

@ -1,269 +0,0 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "pointerconstraints_interface_p.h"
#include "display.h"
#include "pointer_interface.h"
#include "region_interface.h"
#include "surface_interface_p.h"
#include <wayland-pointer-constraints-unstable-v1-server-protocol.h>
namespace KWaylandServer
{
class PointerConstraintsUnstableV1Interface::Private : public PointerConstraintsInterface::Private
{
public:
Private(PointerConstraintsUnstableV1Interface *q, Display *d);
private:
void bind(wl_client *client, uint32_t version, uint32_t id) override;
template <class T>
void createConstraint(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface, wl_resource *pointer, wl_resource *region, uint32_t lifetime);
static void unbind(wl_resource *resource);
static Private *cast(wl_resource *r) {
return reinterpret_cast<Private*>(wl_resource_get_user_data(r));
}
static void destroyCallback(wl_client *client, wl_resource *resource);
static void lockPointerCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface, wl_resource * pointer, wl_resource * region, uint32_t lifetime);
static void confinePointerCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface, wl_resource * pointer, wl_resource * region, uint32_t lifetime);
PointerConstraintsUnstableV1Interface *q;
static const struct zwp_pointer_constraints_v1_interface s_interface;
static const quint32 s_version;
};
class LockedPointerUnstableV1Interface::Private : public LockedPointerInterface::Private
{
public:
Private(LockedPointerUnstableV1Interface *q, PointerConstraintsUnstableV1Interface *c, wl_resource *parentResource);
~Private();
void updateLocked() override;
private:
static void setCursorPositionHintCallback(wl_client *client, wl_resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y);
static void setRegionCallback(wl_client *client, wl_resource *resource, wl_resource * region);
LockedPointerUnstableV1Interface *q_func() {
return reinterpret_cast<LockedPointerUnstableV1Interface *>(q);
}
static const struct zwp_locked_pointer_v1_interface s_interface;
};
const quint32 PointerConstraintsUnstableV1Interface::Private::s_version = 1;
#ifndef K_DOXYGEN
const struct zwp_pointer_constraints_v1_interface PointerConstraintsUnstableV1Interface::Private::s_interface = {
destroyCallback,
lockPointerCallback,
confinePointerCallback
};
#endif
void PointerConstraintsUnstableV1Interface::Private::destroyCallback(wl_client *client, wl_resource *resource)
{
Q_UNUSED(client)
wl_resource_destroy(resource);
}
template <class T>
void PointerConstraintsUnstableV1Interface::Private::createConstraint(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface, wl_resource *pointer, wl_resource *region, uint32_t lifetime)
{
auto s = SurfaceInterface::get(surface);
auto p = PointerInterface::get(pointer);
if (!s || !p) {
// send error?
return;
}
if (!s->lockedPointer().isNull() || !s->confinedPointer().isNull()) {
wl_resource_post_error(surface, ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED, "Surface already constrained");
return;
}
auto constraint = new T(q, resource);
switch (lifetime) {
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
constraint->d_func()->lifeTime = T::LifeTime::Persistent;
break;
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT: // fall through
default:
constraint->d_func()->lifeTime = T::LifeTime::OneShot;
break;
}
auto r = RegionInterface::get(region);
constraint->d_func()->region = r ? r->region() : QRegion();
constraint->d_func()->create(display->getConnection(client), version, id);
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(s);
surfacePrivate->installPointerConstraint(constraint);
}
void PointerConstraintsUnstableV1Interface::Private::lockPointerCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface, wl_resource *pointer, wl_resource *region, uint32_t lifetime)
{
cast(resource)->createConstraint<LockedPointerUnstableV1Interface>(client, resource, id, surface, pointer, region, lifetime);
}
void PointerConstraintsUnstableV1Interface::Private::confinePointerCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface, wl_resource *pointer, wl_resource *region, uint32_t lifetime)
{
cast(resource)->createConstraint<ConfinedPointerUnstableV1Interface>(client, resource, id, surface, pointer, region, lifetime);
}
PointerConstraintsUnstableV1Interface::Private::Private(PointerConstraintsUnstableV1Interface *q, Display *d)
: PointerConstraintsInterface::Private(PointerConstraintsInterfaceVersion::UnstableV1, q, d, &zwp_pointer_constraints_v1_interface, s_version)
, q(q)
{
}
void PointerConstraintsUnstableV1Interface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
{
auto c = display->getConnection(client);
wl_resource *resource = c->createResource(&zwp_pointer_constraints_v1_interface, qMin(version, s_version), id);
if (!resource) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(resource, &s_interface, this, unbind);
// TODO: should we track?
}
void PointerConstraintsUnstableV1Interface::Private::unbind(wl_resource *resource)
{
Q_UNUSED(resource)
// TODO: implement?
}
PointerConstraintsUnstableV1Interface::PointerConstraintsUnstableV1Interface(Display *display, QObject *parent)
: PointerConstraintsInterface(new Private(this, display), parent)
{
}
PointerConstraintsUnstableV1Interface::~PointerConstraintsUnstableV1Interface() = default;
#ifndef K_DOXYGEN
const struct zwp_locked_pointer_v1_interface LockedPointerUnstableV1Interface::Private::s_interface = {
resourceDestroyedCallback,
setCursorPositionHintCallback,
setRegionCallback
};
#endif
void LockedPointerUnstableV1Interface::Private::setCursorPositionHintCallback(wl_client *client, wl_resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
Q_UNUSED(client)
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)
{
Q_UNUSED(client)
auto p = cast<Private>(resource);
auto r = RegionInterface::get(region);
p->pendingRegion = r ? r->region() : QRegion();
p->regionIsSet = true;
}
void LockedPointerUnstableV1Interface::Private::updateLocked()
{
if (!resource) {
return;
}
if (locked) {
zwp_locked_pointer_v1_send_locked(resource);
} else {
zwp_locked_pointer_v1_send_unlocked(resource);
}
}
LockedPointerUnstableV1Interface::Private::Private(LockedPointerUnstableV1Interface *q, PointerConstraintsUnstableV1Interface *c, wl_resource *parentResource)
: LockedPointerInterface::Private(PointerConstraintsInterfaceVersion::UnstableV1, q, c, parentResource, &zwp_locked_pointer_v1_interface, &s_interface)
{
}
LockedPointerUnstableV1Interface::LockedPointerUnstableV1Interface(PointerConstraintsUnstableV1Interface *parent, wl_resource *parentResource)
: LockedPointerInterface(new Private(this, parent, parentResource))
{
}
LockedPointerUnstableV1Interface::Private::~Private() = default;
LockedPointerUnstableV1Interface::~LockedPointerUnstableV1Interface() = default;
LockedPointerUnstableV1Interface::Private *LockedPointerUnstableV1Interface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
}
class ConfinedPointerUnstableV1Interface::Private : public ConfinedPointerInterface::Private
{
public:
Private(ConfinedPointerUnstableV1Interface *q, PointerConstraintsUnstableV1Interface *c, wl_resource *parentResource);
~Private();
void updateConfined() override;
private:
static void setRegionCallback(wl_client *client, wl_resource *resource, wl_resource * region);
ConfinedPointerUnstableV1Interface *q_func() {
return reinterpret_cast<ConfinedPointerUnstableV1Interface *>(q);
}
static const struct zwp_confined_pointer_v1_interface s_interface;
};
#ifndef K_DOXYGEN
const struct zwp_confined_pointer_v1_interface ConfinedPointerUnstableV1Interface::Private::s_interface = {
resourceDestroyedCallback,
setRegionCallback
};
#endif
void ConfinedPointerUnstableV1Interface::Private::setRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region)
{
Q_UNUSED(client)
auto p = cast<Private>(resource);
auto r = RegionInterface::get(region);
p->pendingRegion = r ? r->region() : QRegion();
p->regionIsSet = true;
}
ConfinedPointerUnstableV1Interface::Private::Private(ConfinedPointerUnstableV1Interface *q, PointerConstraintsUnstableV1Interface *c, wl_resource *parentResource)
: ConfinedPointerInterface::Private(PointerConstraintsInterfaceVersion::UnstableV1, q, c, parentResource, &zwp_confined_pointer_v1_interface, &s_interface)
{
}
ConfinedPointerUnstableV1Interface::ConfinedPointerUnstableV1Interface(PointerConstraintsUnstableV1Interface *parent, wl_resource *parentResource)
: ConfinedPointerInterface(new Private(this, parent, parentResource))
{
}
ConfinedPointerUnstableV1Interface::Private::~Private() = default;
ConfinedPointerUnstableV1Interface::~ConfinedPointerUnstableV1Interface() = default;
void ConfinedPointerUnstableV1Interface::Private::updateConfined()
{
if (!resource) {
return;
}
if (confined) {
zwp_confined_pointer_v1_send_confined(resource);
} else {
zwp_confined_pointer_v1_send_unconfined(resource);
}
}
ConfinedPointerUnstableV1Interface::Private *ConfinedPointerUnstableV1Interface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
}
}

View file

@ -11,7 +11,7 @@
#include "compositor_interface.h"
#include "display.h"
#include "idleinhibit_v1_interface_p.h"
#include "pointerconstraints_interface_p.h"
#include "pointerconstraints_v1_interface_p.h"
#include "region_interface.h"
#include "subcompositor_interface.h"
#include "subsurface_interface_p.h"
@ -202,14 +202,15 @@ void SurfaceInterfacePrivate::setContrast(const QPointer<ContrastInterface> &con
pending.contrastIsSet = true;
}
void SurfaceInterfacePrivate::installPointerConstraint(LockedPointerInterface *lock)
void SurfaceInterfacePrivate::installPointerConstraint(LockedPointerV1Interface *lock)
{
Q_ASSERT(lockedPointer.isNull());
Q_ASSERT(confinedPointer.isNull());
lockedPointer = QPointer<LockedPointerInterface>(lock);
Q_ASSERT(!lockedPointer);
Q_ASSERT(!confinedPointer);
lockedPointer = lock;
auto cleanUp = [this]() {
lockedPointer.clear();
lockedPointer = nullptr;
QObject::disconnect(constrainsOneShotConnection);
constrainsOneShotConnection = QMetaObject::Connection();
QObject::disconnect(constrainsUnboundConnection);
@ -217,35 +218,29 @@ void SurfaceInterfacePrivate::installPointerConstraint(LockedPointerInterface *l
emit q->pointerConstraintsChanged();
};
if (lock->lifeTime() == LockedPointerInterface::LifeTime::OneShot) {
constrainsOneShotConnection = QObject::connect(lock, &LockedPointerInterface::lockedChanged, q,
if (lock->lifeTime() == LockedPointerV1Interface::LifeTime::OneShot) {
constrainsOneShotConnection = QObject::connect(lock, &LockedPointerV1Interface::lockedChanged, q,
[this, cleanUp] {
if (lockedPointer.isNull() || lockedPointer->isLocked()) {
if (lockedPointer->isLocked()) {
return;
}
cleanUp();
}
);
}
constrainsUnboundConnection = QObject::connect(lock, &LockedPointerInterface::unbound, q,
[this, cleanUp] {
if (lockedPointer.isNull()) {
return;
}
cleanUp();
}
);
constrainsUnboundConnection = QObject::connect(lock, &LockedPointerV1Interface::destroyed, q, cleanUp);
emit q->pointerConstraintsChanged();
}
void SurfaceInterfacePrivate::installPointerConstraint(ConfinedPointerInterface *confinement)
void SurfaceInterfacePrivate::installPointerConstraint(ConfinedPointerV1Interface *confinement)
{
Q_ASSERT(lockedPointer.isNull());
Q_ASSERT(confinedPointer.isNull());
confinedPointer = QPointer<ConfinedPointerInterface>(confinement);
Q_ASSERT(!lockedPointer);
Q_ASSERT(!confinedPointer);
confinedPointer = confinement;
auto cleanUp = [this]() {
confinedPointer.clear();
confinedPointer = nullptr;
QObject::disconnect(constrainsOneShotConnection);
constrainsOneShotConnection = QMetaObject::Connection();
QObject::disconnect(constrainsUnboundConnection);
@ -253,24 +248,17 @@ void SurfaceInterfacePrivate::installPointerConstraint(ConfinedPointerInterface
emit q->pointerConstraintsChanged();
};
if (confinement->lifeTime() == ConfinedPointerInterface::LifeTime::OneShot) {
constrainsOneShotConnection = QObject::connect(confinement, &ConfinedPointerInterface::confinedChanged, q,
if (confinement->lifeTime() == ConfinedPointerV1Interface::LifeTime::OneShot) {
constrainsOneShotConnection = QObject::connect(confinement, &ConfinedPointerV1Interface::confinedChanged, q,
[this, cleanUp] {
if (confinedPointer.isNull() || confinedPointer->isConfined()) {
if (confinedPointer->isConfined()) {
return;
}
cleanUp();
}
);
}
constrainsUnboundConnection = QObject::connect(confinement, &ConfinedPointerInterface::unbound, q,
[this, cleanUp] {
if (confinedPointer.isNull()) {
return;
}
cleanUp();
}
);
constrainsUnboundConnection = QObject::connect(confinement, &ConfinedPointerV1Interface::destroyed, q, cleanUp);
emit q->pointerConstraintsChanged();
}
@ -572,11 +560,13 @@ void SurfaceInterfacePrivate::swapStates(State *source, State *target, bool emit
target->bufferTransform = source->bufferTransform;
target->bufferTransformIsSet = true;
}
if (!lockedPointer.isNull()) {
lockedPointer->d_func()->commit();
if (lockedPointer) {
auto lockedPointerPrivate = LockedPointerV1InterfacePrivate::get(lockedPointer);
lockedPointerPrivate->commit();
}
if (!confinedPointer.isNull()) {
confinedPointer->d_func()->commit();
if (confinedPointer) {
auto confinedPointerPrivate = ConfinedPointerV1InterfacePrivate::get(confinedPointer);
confinedPointerPrivate->commit();
}
*source = State{};
@ -909,12 +899,12 @@ SurfaceInterface *SurfaceInterface::inputSurfaceAt(const QPointF &position)
return nullptr;
}
QPointer<LockedPointerInterface> SurfaceInterface::lockedPointer() const
LockedPointerV1Interface *SurfaceInterface::lockedPointer() const
{
return d->lockedPointer;
}
QPointer<ConfinedPointerInterface> SurfaceInterface::confinedPointer() const
ConfinedPointerV1Interface *SurfaceInterface::confinedPointer() const
{
return d->confinedPointer;
}

View file

@ -20,10 +20,10 @@ namespace KWaylandServer
{
class BlurInterface;
class BufferInterface;
class ConfinedPointerInterface;
class ConfinedPointerV1Interface;
class ContrastInterface;
class CompositorInterface;
class LockedPointerInterface;
class LockedPointerV1Interface;
class ShadowInterface;
class SlideInterface;
class SubSurfaceInterface;
@ -323,14 +323,14 @@ public:
* @see pointerConstraintsChanged
* @since 5.29
**/
QPointer<ConfinedPointerInterface> confinedPointer() const;
ConfinedPointerV1Interface *confinedPointer() const;
/**
* Pointer lock installed on this SurfaceInterface.
* @see pointerConstraintsChanged
* @since 5.29
**/
QPointer<LockedPointerInterface> lockedPointer() const;
LockedPointerV1Interface *lockedPointer() const;
/**
* @returns Whether this SurfaceInterface wants idle to be inhibited on the Output it is shown

View file

@ -84,8 +84,8 @@ public:
void setBlur(const QPointer<BlurInterface> &blur);
void setContrast(const QPointer<ContrastInterface> &contrast);
void setSlide(const QPointer<SlideInterface> &slide);
void installPointerConstraint(LockedPointerInterface *lock);
void installPointerConstraint(ConfinedPointerInterface *confinement);
void installPointerConstraint(LockedPointerV1Interface *lock);
void installPointerConstraint(ConfinedPointerV1Interface *confinement);
void installIdleInhibitor(IdleInhibitorV1Interface *inhibitor);
void commit();
@ -114,8 +114,8 @@ public:
QVector<OutputInterface *> outputs;
QPointer<LockedPointerInterface> lockedPointer;
QPointer<ConfinedPointerInterface> confinedPointer;
LockedPointerV1Interface *lockedPointer = nullptr;
ConfinedPointerV1Interface *confinedPointer = nullptr;
QHash<OutputInterface*, QMetaObject::Connection> outputDestroyedConnections;
QVector<IdleInhibitorV1Interface*> idleInhibitors;
ViewportInterface *viewportExtension = nullptr;