app: make it possible to lock the mouse when using the remote input
It makes it possible to use normal touchpads and mice
This commit is contained in:
parent
55b946f825
commit
cf8ada2b5d
8 changed files with 441 additions and 3 deletions
|
@ -61,7 +61,7 @@ else()
|
||||||
set(Qca_LIBRARY qca-qt5)
|
set(Qca_LIBRARY qca-qt5)
|
||||||
|
|
||||||
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem)
|
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem)
|
||||||
set(KF5_OPTIONAL_COMPONENTS DocTools)
|
set(KF5_OPTIONAL_COMPONENTS DocTools Wayland)
|
||||||
|
|
||||||
set_package_properties(KF5Kirigami2 PROPERTIES
|
set_package_properties(KF5Kirigami2 PROPERTIES
|
||||||
DESCRIPTION "QtQuick plugins to build user interfaces based on KDE UX guidelines"
|
DESCRIPTION "QtQuick plugins to build user interfaces based on KDE UX guidelines"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.2
|
import QtQuick.Controls 2.2
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import org.kde.kirigami 2.7 as Kirigami
|
import org.kde.kirigami 2.7 as Kirigami
|
||||||
|
@ -20,6 +20,10 @@ Kirigami.Page
|
||||||
// Otherwise swiping on the MouseArea might trigger changing the page
|
// Otherwise swiping on the MouseArea might trigger changing the page
|
||||||
Kirigami.ColumnView.preventStealing: true
|
Kirigami.ColumnView.preventStealing: true
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
PointerLocker.window = applicationWindow()
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout
|
ColumnLayout
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -34,6 +38,37 @@ Kirigami.Page
|
||||||
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: lockButton
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: i18n("Lock")
|
||||||
|
visible: !Kirigami.Settings.tabletMode && !PointerLocker.isLocked
|
||||||
|
onClicked: {
|
||||||
|
PointerLocker.isLocked = true
|
||||||
|
area.pressedPos = Qt.point(-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: PointerLocker.isLocked
|
||||||
|
text: i18n("Press the right 'x' key or the left and right mouse buttons at the same time to unlock")
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: PointerLocker
|
||||||
|
onPointerMoved: {
|
||||||
|
if (!PointerLocker.isLocked)
|
||||||
|
return;
|
||||||
|
mousepad.pluginInterface.moveCursor(Qt.point(delta.x, delta.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to see the lock button when using a touchscreen
|
||||||
|
TapHandler {
|
||||||
|
acceptedDevices: PointerDevice.TouchScreen
|
||||||
|
onTapped: lockButton.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var clickType = "";
|
var clickType = "";
|
||||||
var packet = {};
|
var packet = {};
|
||||||
|
@ -90,9 +125,21 @@ Kirigami.Page
|
||||||
lastPos = Qt.point(mouse.x, mouse.y);
|
lastPos = Qt.point(mouse.x, mouse.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: {
|
||||||
|
if (event.key == Qt.Key_X) {
|
||||||
|
PointerLocker.isLocked = false
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
onPressed: {
|
onPressed: {
|
||||||
|
if (PointerLocker.isLocked) {
|
||||||
|
if (pressedButtons === (Qt.LeftButton | Qt.RightButton)) {
|
||||||
|
PointerLocker.isLocked = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
pressedPos = Qt.point(mouse.x, mouse.y);
|
pressedPos = Qt.point(mouse.x, mouse.y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onWheel: {
|
onWheel: {
|
||||||
var packet = {};
|
var packet = {};
|
||||||
|
|
|
@ -2,6 +2,7 @@ add_library(kdeconnectdeclarativeplugin SHARED
|
||||||
kdeconnectdeclarativeplugin.cpp
|
kdeconnectdeclarativeplugin.cpp
|
||||||
responsewaiter.cpp
|
responsewaiter.cpp
|
||||||
objectfactory.cpp
|
objectfactory.cpp
|
||||||
|
pointerlocker.cpp
|
||||||
resources.qrc
|
resources.qrc
|
||||||
)
|
)
|
||||||
target_link_libraries(kdeconnectdeclarativeplugin
|
target_link_libraries(kdeconnectdeclarativeplugin
|
||||||
|
@ -10,6 +11,14 @@ target_link_libraries(kdeconnectdeclarativeplugin
|
||||||
kdeconnectcore
|
kdeconnectcore
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (TARGET KF5::WaylandClient)
|
||||||
|
target_sources(kdeconnectdeclarativeplugin PRIVATE pointerlockerwayland.cpp)
|
||||||
|
target_link_libraries(kdeconnectdeclarativeplugin KF5::WaylandClient)
|
||||||
|
target_compile_definitions(kdeconnectdeclarativeplugin PRIVATE -DWITH_WAYLAND=1)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(kdeconnectdeclarativeplugin PRIVATE -DWITH_WAYLAND=0)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS kdeconnectdeclarativeplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kdeconnect)
|
install(TARGETS kdeconnectdeclarativeplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kdeconnect)
|
||||||
install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/kdeconnect)
|
install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/kdeconnect)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QDBusPendingCall>
|
#include <QDBusPendingCall>
|
||||||
#include <QDBusPendingReply>
|
#include <QDBusPendingReply>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include "objectfactory.h"
|
#include "objectfactory.h"
|
||||||
#include "responsewaiter.h"
|
#include "responsewaiter.h"
|
||||||
|
@ -22,6 +23,10 @@
|
||||||
#include <pluginmodel.h>
|
#include <pluginmodel.h>
|
||||||
#include "core/kdeconnectpluginconfig.h"
|
#include "core/kdeconnectpluginconfig.h"
|
||||||
#include "interfaces/commandsmodel.h"
|
#include "interfaces/commandsmodel.h"
|
||||||
|
#include "pointerlocker.h"
|
||||||
|
#if WITH_WAYLAND == 1
|
||||||
|
#include "pointerlockerwayland.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
QObject* createDBusResponse()
|
QObject* createDBusResponse()
|
||||||
{
|
{
|
||||||
|
@ -63,6 +68,16 @@ void KdeConnectDeclarativePlugin::registerTypes(const char* uri)
|
||||||
return new DaemonDbusInterface;
|
return new DaemonDbusInterface;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
qmlRegisterSingletonType<AbstractPointerLocker>("org.kde.kdeconnect", 1, 0, "PointerLocker", [] (QQmlEngine *, QJSEngine *) -> QObject * {
|
||||||
|
AbstractPointerLocker *ret;
|
||||||
|
#if WITH_WAYLAND == 1
|
||||||
|
if (qGuiApp->platformName() == QLatin1String("wayland"))
|
||||||
|
ret = new PointerLockerWayland;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ret = new PointerLockerQt;
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
qmlRegisterAnonymousType<QAbstractItemModel>(uri, 1);
|
qmlRegisterAnonymousType<QAbstractItemModel>(uri, 1);
|
||||||
|
|
72
declarativeplugin/pointerlocker.cpp
Normal file
72
declarativeplugin/pointerlocker.cpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pointerlocker.h"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
#include <QCursor>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
void AbstractPointerLocker::setWindow(QWindow* window)
|
||||||
|
{
|
||||||
|
if (m_window == window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_window = window;
|
||||||
|
Q_EMIT windowChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerLockerQt::PointerLockerQt(QObject *parent)
|
||||||
|
: AbstractPointerLocker(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerLockerQt::~PointerLockerQt() = default;
|
||||||
|
|
||||||
|
void PointerLockerQt::setLocked(bool lock)
|
||||||
|
{
|
||||||
|
if (isLocked() == lock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock) {
|
||||||
|
/* Cursor needs to be hidden such that Xwayland emulates warps. */
|
||||||
|
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
|
||||||
|
m_originalPosition = QCursor::pos();
|
||||||
|
m_window->installEventFilter(this);
|
||||||
|
Q_EMIT lockedChanged(true);
|
||||||
|
Q_EMIT lockEffectiveChanged(true);
|
||||||
|
} else {
|
||||||
|
m_window->removeEventFilter(this);
|
||||||
|
QGuiApplication::restoreOverrideCursor();
|
||||||
|
Q_EMIT lockedChanged(false);
|
||||||
|
Q_EMIT lockEffectiveChanged(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PointerLockerQt::isLocked() const
|
||||||
|
{
|
||||||
|
return !m_originalPosition.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PointerLockerQt::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
if (watched != m_window || event->type() != QEvent::MouseMove || !isLocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto newPos = QCursor::pos();
|
||||||
|
const QPointF dist = newPos - m_originalPosition;
|
||||||
|
Q_EMIT pointerMoved({ dist.x(), dist.y() });
|
||||||
|
QCursor::setPos(m_originalPosition);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
64
declarativeplugin/pointerlocker.h
Normal file
64
declarativeplugin/pointerlocker.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POINTERLOCKER_H
|
||||||
|
#define POINTERLOCKER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
class AbstractPointerLocker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool isSupported READ isSupported NOTIFY supportedChanged)
|
||||||
|
Q_PROPERTY(bool isLocked READ isLocked WRITE setLocked NOTIFY lockedChanged)
|
||||||
|
Q_PROPERTY(bool isLockEffective READ isLockEffective NOTIFY lockEffectiveChanged)
|
||||||
|
Q_PROPERTY(QWindow* window READ window WRITE setWindow NOTIFY windowChanged)
|
||||||
|
public:
|
||||||
|
AbstractPointerLocker(QObject *parent = nullptr) : QObject(parent) {}
|
||||||
|
|
||||||
|
virtual void setLocked(bool locked) = 0;
|
||||||
|
virtual bool isLocked() const = 0;
|
||||||
|
virtual bool isLockEffective() const = 0;
|
||||||
|
virtual bool isSupported() const = 0;
|
||||||
|
|
||||||
|
virtual void setWindow(QWindow *window);
|
||||||
|
QWindow *window() const {
|
||||||
|
return m_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void supportedChanged(bool isSupported);
|
||||||
|
void lockedChanged(bool isLocked);
|
||||||
|
void lockEffectiveChanged(bool isLockEffective);
|
||||||
|
void windowChanged();
|
||||||
|
void pointerMoved(const QPointF &delta);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QWindow *m_window = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointerLockerQt : public AbstractPointerLocker
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PointerLockerQt(QObject *parent = nullptr);
|
||||||
|
~PointerLockerQt() override;
|
||||||
|
|
||||||
|
void setLocked(bool locked) override;
|
||||||
|
bool isLocked() const override;
|
||||||
|
bool isSupported() const override { return true; }
|
||||||
|
bool isLockEffective() const override { return isLocked(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
|
|
||||||
|
QPoint m_originalPosition;
|
||||||
|
bool m_moving = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
170
declarativeplugin/pointerlockerwayland.cpp
Normal file
170
declarativeplugin/pointerlockerwayland.cpp
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pointerlockerwayland.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <KWayland/Client/compositor.h>
|
||||||
|
#include <KWayland/Client/connection_thread.h>
|
||||||
|
#include <KWayland/Client/pointer.h>
|
||||||
|
#include <KWayland/Client/pointerconstraints.h>
|
||||||
|
#include <KWayland/Client/registry.h>
|
||||||
|
#include <KWayland/Client/region.h>
|
||||||
|
#include <KWayland/Client/relativepointer.h>
|
||||||
|
#include <KWayland/Client/seat.h>
|
||||||
|
#include <KWayland/Client/surface.h>
|
||||||
|
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
|
||||||
|
PointerLockerWayland::PointerLockerWayland(QObject *parent)
|
||||||
|
: AbstractPointerLocker(parent)
|
||||||
|
, m_connectionThreadObject(ConnectionThread::fromApplication(this))
|
||||||
|
{
|
||||||
|
setupRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerLockerWayland::setupRegistry()
|
||||||
|
{
|
||||||
|
Registry *registry = new Registry(this);
|
||||||
|
|
||||||
|
connect(registry, &Registry::compositorAnnounced, this,
|
||||||
|
[this, registry](quint32 name, quint32 version) {
|
||||||
|
m_compositor = registry->createCompositor(name, version, this);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(registry, &Registry::relativePointerManagerUnstableV1Announced, this,
|
||||||
|
[this, registry](quint32 name, quint32 version) {
|
||||||
|
Q_ASSERT(!m_relativePointerManager);
|
||||||
|
m_relativePointerManager = registry->createRelativePointerManager(name, version, this);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(registry, &Registry::seatAnnounced, this,
|
||||||
|
[this, registry](quint32 name, quint32 version) {
|
||||||
|
m_seat = registry->createSeat(name, version, this);
|
||||||
|
if (m_seat->hasPointer()) {
|
||||||
|
m_pointer = m_seat->createPointer(this);
|
||||||
|
}
|
||||||
|
connect(m_seat, &Seat::hasPointerChanged, this,
|
||||||
|
[this] (bool hasPointer) {
|
||||||
|
delete m_pointer;
|
||||||
|
|
||||||
|
if (!hasPointer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_pointer = m_seat->createPointer(this);
|
||||||
|
|
||||||
|
delete m_relativePointer;
|
||||||
|
m_relativePointer = m_relativePointerManager->createRelativePointer(m_pointer, this);
|
||||||
|
connect(m_relativePointer, &RelativePointer::relativeMotion,
|
||||||
|
this, [this] (const QSizeF &delta) {
|
||||||
|
Q_EMIT pointerMoved({delta.width(), delta.height()});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(registry, &Registry::pointerConstraintsUnstableV1Announced, this,
|
||||||
|
[this, registry](quint32 name, quint32 version) {
|
||||||
|
m_pointerConstraints = registry->createPointerConstraints(name, version, this);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
connect(registry, &Registry::interfacesAnnounced, this,
|
||||||
|
[this] {
|
||||||
|
Q_ASSERT(m_compositor);
|
||||||
|
Q_ASSERT(m_seat);
|
||||||
|
Q_ASSERT(m_pointerConstraints);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
registry->create(m_connectionThreadObject);
|
||||||
|
registry->setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PointerLockerWayland::isLockEffective() const
|
||||||
|
{
|
||||||
|
return m_lockedPointer && m_lockedPointer->isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerLockerWayland::enforceLock()
|
||||||
|
{
|
||||||
|
if (!m_isLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScopedPointer<Surface> winSurface(Surface::fromWindow(m_window));
|
||||||
|
if (!winSurface) {
|
||||||
|
qWarning() << "Locking a window that is not mapped";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto *lockedPointer = m_pointerConstraints->lockPointer(winSurface.data(),
|
||||||
|
m_pointer,
|
||||||
|
nullptr,
|
||||||
|
PointerConstraints::LifeTime::Persistent,
|
||||||
|
this);
|
||||||
|
|
||||||
|
if (!lockedPointer) {
|
||||||
|
qDebug() << "ERROR when receiving locked pointer!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_lockedPointer = lockedPointer;
|
||||||
|
|
||||||
|
connect(lockedPointer, &LockedPointer::locked, this, [this] {
|
||||||
|
Q_EMIT lockEffectiveChanged(true);
|
||||||
|
});
|
||||||
|
connect(lockedPointer, &LockedPointer::unlocked, this, [this] {
|
||||||
|
Q_EMIT lockEffectiveChanged(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerLockerWayland::setLocked(bool lock)
|
||||||
|
{
|
||||||
|
if (m_isLocked == lock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSupported()) {
|
||||||
|
qWarning() << "Locking before having our interfaces announced";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_isLocked = lock;
|
||||||
|
if (lock) {
|
||||||
|
enforceLock();
|
||||||
|
} else {
|
||||||
|
cleanupLock();
|
||||||
|
}
|
||||||
|
Q_EMIT lockedChanged(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerLockerWayland::cleanupLock()
|
||||||
|
{
|
||||||
|
if (!m_lockedPointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_lockedPointer->release();
|
||||||
|
m_lockedPointer->deleteLater();
|
||||||
|
m_lockedPointer = nullptr;
|
||||||
|
Q_EMIT lockEffectiveChanged(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerLockerWayland::setWindow(QWindow* window)
|
||||||
|
{
|
||||||
|
if (m_window == window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cleanupLock();
|
||||||
|
|
||||||
|
if (m_window) {
|
||||||
|
disconnect(m_window, &QWindow::visibleChanged, this, &PointerLockerWayland::enforceLock);
|
||||||
|
}
|
||||||
|
AbstractPointerLocker::setWindow(window);
|
||||||
|
connect(m_window, &QWindow::visibleChanged, this, &PointerLockerWayland::enforceLock);
|
||||||
|
|
||||||
|
if (m_isLocked) {
|
||||||
|
enforceLock();
|
||||||
|
}
|
||||||
|
}
|
61
declarativeplugin/pointerlockerwayland.h
Normal file
61
declarativeplugin/pointerlockerwayland.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POINTERLOCKERWAYLAND_H
|
||||||
|
#define POINTERLOCKERWAYLAND_H
|
||||||
|
|
||||||
|
#include "pointerlocker.h"
|
||||||
|
|
||||||
|
namespace KWayland {
|
||||||
|
namespace Client {
|
||||||
|
|
||||||
|
class ConnectionThread;
|
||||||
|
class Registry;
|
||||||
|
class Compositor;
|
||||||
|
class Seat;
|
||||||
|
class Pointer;
|
||||||
|
class PointerConstraints;
|
||||||
|
class LockedPointer;
|
||||||
|
class ConfinedPointer;
|
||||||
|
class RelativePointer;
|
||||||
|
class RelativePointerManager;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PointerLockerWayland : public AbstractPointerLocker
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PointerLockerWayland(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void setLocked(bool locked) override;
|
||||||
|
bool isLocked() const override { return m_isLocked; }
|
||||||
|
bool isLockEffective() const override;
|
||||||
|
bool isSupported() const override {
|
||||||
|
return m_pointerConstraints && m_relativePointerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWindow(QWindow * window) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupRegistry();
|
||||||
|
void enforceLock();
|
||||||
|
void cleanupLock();
|
||||||
|
|
||||||
|
bool m_isLocked = false;
|
||||||
|
KWayland::Client::ConnectionThread *m_connectionThreadObject;
|
||||||
|
KWayland::Client::Compositor *m_compositor = nullptr;
|
||||||
|
KWayland::Client::Seat *m_seat = nullptr;
|
||||||
|
KWayland::Client::Pointer *m_pointer = nullptr;
|
||||||
|
KWayland::Client::PointerConstraints *m_pointerConstraints = nullptr;
|
||||||
|
KWayland::Client::RelativePointer *m_relativePointer = nullptr;
|
||||||
|
KWayland::Client::RelativePointerManager *m_relativePointerManager = nullptr;
|
||||||
|
|
||||||
|
KWayland::Client::LockedPointer *m_lockedPointer = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue