diff --git a/.kde-ci.yml b/.kde-ci.yml index 4366ec5d8..d6e56e1d0 100644 --- a/.kde-ci.yml +++ b/.kde-ci.yml @@ -24,7 +24,6 @@ Dependencies: - 'on': ['Linux', 'FreeBSD'] 'require': - 'frameworks/kwayland': '@stable' 'frameworks/kpackage': '@stable' 'libraries/pulseaudio-qt': '@stable' 'libraries/plasma-wayland-protocols': '@stable' diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b9844d6d..0f147c1d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ else() set(Qca_LIBRARY qca-qt${QT_MAJOR_VERSION}) set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem GuiAddons) - set(KF5_OPTIONAL_COMPONENTS DocTools Wayland) + set(KF5_OPTIONAL_COMPONENTS DocTools) set_package_properties(KF5Kirigami2 PROPERTIES DESCRIPTION "QtQuick plugins to build user interfaces based on KDE UX guidelines" @@ -84,6 +84,7 @@ else() find_package(Wayland 1.9 REQUIRED Client) find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS WaylandClient) find_package(PlasmaWaylandProtocols REQUIRED) + find_package(WaylandProtocols REQUIRED) endif() find_package(KF5PeopleVCard) diff --git a/declarativeplugin/CMakeLists.txt b/declarativeplugin/CMakeLists.txt index a0754e5f1..cc8ef8d51 100644 --- a/declarativeplugin/CMakeLists.txt +++ b/declarativeplugin/CMakeLists.txt @@ -14,12 +14,22 @@ ecm_target_qml_sources(kdeconnectdeclarativeplugin qml/RemoteKeyboard.qml VERSION 1.0) -if (TARGET KF5::WaylandClient) - target_sources(kdeconnectdeclarativeplugin PRIVATE pointerlockerwayland.cpp) - target_link_libraries(kdeconnectdeclarativeplugin PRIVATE KF5::WaylandClient) +if(UNIX AND NOT APPLE) + + if (QT_MAJOR_VERSION EQUAL "5") + ecm_add_qtwayland_client_protocol(wayland_SRCS + PROTOCOL ${WaylandProtocols_DATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml + BASENAME pointer-constraints-unstable-v1 + ) + else() + qt6_generate_wayland_protocol_client_sources(kdeconnectdeclarativeplugin FILES + ${WaylandProtocols_DATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml) + endif() + + target_sources(kdeconnectdeclarativeplugin PRIVATE ${wayland_SRCS}) + target_link_libraries(kdeconnectdeclarativeplugin PRIVATE Wayland::Client Qt::WaylandClient Qt::GuiPrivate) + target_sources(kdeconnectdeclarativeplugin PUBLIC pointerlockerwayland.cpp) target_compile_definitions(kdeconnectdeclarativeplugin PRIVATE -DWITH_WAYLAND=1) -else() - target_compile_definitions(kdeconnectdeclarativeplugin PRIVATE -DWITH_WAYLAND=0) endif() target_link_libraries(kdeconnectdeclarativeplugin PRIVATE Qt::Quick kdeconnectinterfaces kdeconnectcore) diff --git a/declarativeplugin/kdeconnectdeclarativeplugin.cpp b/declarativeplugin/kdeconnectdeclarativeplugin.cpp index 1acbe4e5c..9b933681b 100644 --- a/declarativeplugin/kdeconnectdeclarativeplugin.cpp +++ b/declarativeplugin/kdeconnectdeclarativeplugin.cpp @@ -25,7 +25,7 @@ #include #include #include -#if WITH_WAYLAND == 1 +#if WITH_WAYLAND #include "pointerlockerwayland.h" #endif @@ -86,7 +86,7 @@ void KdeConnectDeclarativePlugin::registerTypes(const char *uri) }); qmlRegisterSingletonType("org.kde.kdeconnect", 1, 0, "PointerLocker", [](QQmlEngine *, QJSEngine *) -> QObject * { AbstractPointerLocker *ret; -#if WITH_WAYLAND == 1 +#if WITH_WAYLAND if (qGuiApp->platformName() == QLatin1String("wayland")) ret = new PointerLockerWayland; else diff --git a/declarativeplugin/pointerlockerwayland.cpp b/declarativeplugin/pointerlockerwayland.cpp index 4826b1c55..aa0ca982c 100644 --- a/declarativeplugin/pointerlockerwayland.cpp +++ b/declarativeplugin/pointerlockerwayland.cpp @@ -9,71 +9,73 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "qwayland-pointer-constraints-unstable-v1.h" +#include +#include -using namespace KWayland::Client; +#include + +class PointerConstraints : public QWaylandClientExtensionTemplate, public QtWayland::zwp_pointer_constraints_v1 +{ +public: + PointerConstraints() + : QWaylandClientExtensionTemplate(1) + { + } +}; + +class LockedPointer : public QObject, public QtWayland::zwp_locked_pointer_v1 +{ + Q_OBJECT +public: + LockedPointer(struct ::zwp_locked_pointer_v1 *object, QObject *parent) + : QObject(parent) + , zwp_locked_pointer_v1(object) + { + } + + Q_SIGNAL void locked(); + + Q_SIGNAL void unlocked(); + +private: + void zwp_locked_pointer_v1_locked() override + { + Q_EMIT locked(); + } + + void zwp_locked_pointer_v1_unlocked() override + { + Q_EMIT unlocked(); + } +}; PointerLockerWayland::PointerLockerWayland(QObject *parent) : AbstractPointerLocker(parent) - , m_connectionThreadObject(ConnectionThread::fromApplication(this)) { - setupRegistry(); + m_pointerConstraints = new PointerConstraints; } -void PointerLockerWayland::setupRegistry() +PointerLockerWayland::~PointerLockerWayland() { - 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(); + delete m_pointerConstraints; } bool PointerLockerWayland::isLockEffective() const { - return m_lockedPointer && m_lockedPointer->isValid(); + return m_lockedPointer; +} + +wl_pointer *PointerLockerWayland::getPointer() +{ + QPlatformNativeInterface *native = qGuiApp->platformNativeInterface(); + if (!native) { + return nullptr; + } + + window()->create(); + + return reinterpret_cast(native->nativeResourceForIntegration(QByteArrayLiteral("wl_pointer"))); } void PointerLockerWayland::enforceLock() @@ -82,23 +84,31 @@ void PointerLockerWayland::enforceLock() return; } - QScopedPointer 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); + wl_surface *wlSurface = [](QWindow *window) -> wl_surface * { + if (!window) { + return nullptr; + } - if (!lockedPointer) { + QPlatformNativeInterface *native = qGuiApp->platformNativeInterface(); + if (!native) { + return nullptr; + } + window->create(); + return reinterpret_cast(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window)); + }(m_window); + + m_lockedPointer = + new LockedPointer(m_pointerConstraints->lock_pointer(wlSurface, getPointer(), nullptr, PointerConstraints::lifetime::lifetime_persistent), this); + + if (!m_lockedPointer) { qDebug() << "ERROR when receiving locked pointer!"; return; } - m_lockedPointer = lockedPointer; - connect(lockedPointer, &LockedPointer::locked, this, [this] { + connect(m_lockedPointer, &LockedPointer::locked, this, [this] { Q_EMIT lockEffectiveChanged(true); }); - connect(lockedPointer, &LockedPointer::unlocked, this, [this] { + connect(m_lockedPointer, &LockedPointer::unlocked, this, [this] { Q_EMIT lockEffectiveChanged(false); }); } @@ -128,7 +138,7 @@ void PointerLockerWayland::cleanupLock() if (!m_lockedPointer) { return; } - m_lockedPointer->release(); + m_lockedPointer->destroy(); m_lockedPointer->deleteLater(); m_lockedPointer = nullptr; Q_EMIT lockEffectiveChanged(false); @@ -151,3 +161,5 @@ void PointerLockerWayland::setWindow(QWindow *window) enforceLock(); } } + +#include "pointerlockerwayland.moc" diff --git a/declarativeplugin/pointerlockerwayland.h b/declarativeplugin/pointerlockerwayland.h index be4bcc99e..f2658b229 100644 --- a/declarativeplugin/pointerlockerwayland.h +++ b/declarativeplugin/pointerlockerwayland.h @@ -9,30 +9,16 @@ #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 wl_pointer; class PointerLockerWayland : public AbstractPointerLocker { Q_OBJECT public: PointerLockerWayland(QObject *parent = nullptr); + ~PointerLockerWayland(); void setLocked(bool locked) override; bool isLocked() const override @@ -42,7 +28,7 @@ public: bool isLockEffective() const override; bool isSupported() const override { - return m_pointerConstraints && m_relativePointerManager; + return m_pointerConstraints; } void setWindow(QWindow *window) override; @@ -52,16 +38,12 @@ private: 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; + wl_pointer *getPointer(); - KWayland::Client::LockedPointer *m_lockedPointer = nullptr; + bool m_isLocked = false; + + PointerConstraints *m_pointerConstraints; + LockedPointer *m_lockedPointer = nullptr; }; #endif