From 665c0535feab9ab62df8e60c52a691d5646c03f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Fri, 20 Oct 2017 18:28:25 +0200 Subject: [PATCH] Add support for zwp_idle_inhibit_manager_v1 Summary: This protocol allows to indicate that a wl_surface should inhibit idle actions such as DPMS, screen locking if the surface is visible. The protocol is quite simple: it just creates an IdleInhibitor for a Surface. If such an IdleInhibitor exists the Surface is considered to inhibit idle. On the server side it is also exposed like that through the API. The IdleInhibitorInterface is private to the library and only SurfaceInterface is extended to expose whether it currently inhibits idle. CCBUG: 385956 Test Plan: New test case added Reviewers: #frameworks, #kwin, #plasma_on_wayland Subscribers: plasma-devel Tags: #plasma_on_wayland, #frameworks Differential Revision: https://phabricator.kde.org/D8396 --- src/wayland/CMakeLists.txt | 8 + .../client/test_wayland_registry.cpp | 31 ++++ .../autotests/client/test_wayland_surface.cpp | 63 ++++++++ src/wayland/display.cpp | 13 ++ src/wayland/display.h | 11 ++ src/wayland/server/idleinhibit_interface.cpp | 53 +++++++ src/wayland/server/idleinhibit_interface.h | 77 ++++++++++ src/wayland/server/idleinhibit_interface_p.h | 96 ++++++++++++ .../server/idleinhibit_interface_v1.cpp | 139 ++++++++++++++++++ src/wayland/surface_interface.cpp | 23 +++ src/wayland/surface_interface.h | 16 ++ src/wayland/surface_interface_p.h | 4 + src/wayland/tools/mapping.txt | 2 + 13 files changed, 536 insertions(+) create mode 100644 src/wayland/server/idleinhibit_interface.cpp create mode 100644 src/wayland/server/idleinhibit_interface.h create mode 100644 src/wayland/server/idleinhibit_interface_p.h create mode 100644 src/wayland/server/idleinhibit_interface_v1.cpp diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index 6fd35937d5..0d9d2488e6 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -10,6 +10,8 @@ set(SERVER_LIB_SRCS dpms_interface.cpp global.cpp idle_interface.cpp + idleinhibit_interface.cpp + idleinhibit_interface_v1.cpp fakeinput_interface.cpp keyboard_interface.cpp outputconfiguration_interface.cpp @@ -154,6 +156,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS BASENAME xdg-foreign-unstable-v2 ) +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/idle-inhibit-unstable-v1.xml + BASENAME idle-inhibit-unstable-v1 +) + add_library(KF5WaylandServer ${SERVER_LIB_SRCS}) generate_export_header(KF5WaylandServer BASE_NAME @@ -198,6 +205,7 @@ set(SERVER_LIB_HEADERS fakeinput_interface.h global.h idle_interface.h + idleinhibit_interface.h keyboard_interface.h outputdevice_interface.h outputchangeset.h diff --git a/src/wayland/autotests/client/test_wayland_registry.cpp b/src/wayland/autotests/client/test_wayland_registry.cpp index d7804b551b..d73baf6c8a 100644 --- a/src/wayland/autotests/client/test_wayland_registry.cpp +++ b/src/wayland/autotests/client/test_wayland_registry.cpp @@ -30,6 +30,7 @@ License along with this library. If not, see . #include "../../src/client/output.h" #include "../../src/client/pointerconstraints.h" #include "../../src/client/pointergestures.h" +#include "../../src/client/idleinhibit.h" #include "../../src/client/seat.h" #include "../../src/client/relativepointer.h" #include "../../src/client/server_decoration.h" @@ -41,6 +42,7 @@ License along with this library. If not, see . #include "../../src/server/datadevicemanager_interface.h" #include "../../src/server/display.h" #include "../../src/server/dpms_interface.h" +#include "../../src/server/idleinhibit_interface.h" #include "../../src/server/output_interface.h" #include "../../src/server/seat_interface.h" #include "../../src/server/shell_interface.h" @@ -59,6 +61,7 @@ License along with this library. If not, see . // Wayland #include #include +#include #include #include #include @@ -95,6 +98,7 @@ private Q_SLOTS: void testBindRelativePointerManagerUnstableV1(); void testBindPointerGesturesUnstableV1(); void testBindPointerConstraintsUnstableV1(); + void testBindIdleIhibitManagerUnstableV1(); void testGlobalSync(); void testGlobalSyncThreaded(); void testRemoval(); @@ -122,6 +126,7 @@ private: KWayland::Server::PointerConstraintsInterface *m_pointerConstraintsV1; KWayland::Server::BlurManagerInterface *m_blur; KWayland::Server::ContrastManagerInterface *m_contrast; + KWayland::Server::IdleInhibitManagerInterface *m_idleInhibit; }; @@ -147,6 +152,7 @@ TestWaylandRegistry::TestWaylandRegistry(QObject *parent) , m_pointerConstraintsV1(nullptr) , m_blur(nullptr) , m_contrast(nullptr) + , m_idleInhibit(nullptr) { } @@ -199,6 +205,9 @@ void TestWaylandRegistry::init() m_pointerConstraintsV1 = m_display->createPointerConstraints(KWayland::Server::PointerConstraintsInterfaceVersion::UnstableV1); m_pointerConstraintsV1->create(); QCOMPARE(m_pointerConstraintsV1->interfaceVersion(), KWayland::Server::PointerConstraintsInterfaceVersion::UnstableV1); + m_idleInhibit = m_display->createIdleInhibitManager(KWayland::Server::IdleInhibitManagerInterfaceVersion::UnstableV1); + m_idleInhibit->create(); + QCOMPARE(m_idleInhibit->interfaceVersion(), KWayland::Server::IdleInhibitManagerInterfaceVersion::UnstableV1); } void TestWaylandRegistry::cleanup() @@ -356,6 +365,11 @@ void TestWaylandRegistry::testBindPointerConstraintsUnstableV1() TEST_BIND(KWayland::Client::Registry::Interface::PointerConstraintsUnstableV1, SIGNAL(pointerConstraintsUnstableV1Announced(quint32,quint32)), bindPointerConstraintsUnstableV1, zwp_pointer_constraints_v1_destroy) } +void TestWaylandRegistry::testBindIdleIhibitManagerUnstableV1() +{ + TEST_BIND(KWayland::Client::Registry::Interface::IdleInhibitManagerUnstableV1, SIGNAL(idleInhibitManagerUnstableV1Announced(quint32,quint32)), bindIdleInhibitManagerUnstableV1, zwp_idle_inhibit_manager_v1_destroy) +} + #undef TEST_BIND void TestWaylandRegistry::testRemoval() @@ -393,6 +407,8 @@ void TestWaylandRegistry::testRemoval() QVERIFY(serverSideDecorationManagerAnnouncedSpy.isValid()); QSignalSpy blurAnnouncedSpy(®istry, &Registry::blurAnnounced); QVERIFY(blurAnnouncedSpy.isValid()); + QSignalSpy idleInhibitManagerUnstableV1AnnouncedSpy(®istry, &Registry::idleInhibitManagerUnstableV1Announced); + QVERIFY(idleInhibitManagerUnstableV1AnnouncedSpy.isValid()); QVERIFY(!registry.isValid()); registry.create(connection.display()); @@ -408,6 +424,7 @@ void TestWaylandRegistry::testRemoval() QVERIFY(!outputManagementAnnouncedSpy.isEmpty()); QVERIFY(!serverSideDecorationManagerAnnouncedSpy.isEmpty()); QVERIFY(!blurAnnouncedSpy.isEmpty()); + QVERIFY(!idleInhibitManagerUnstableV1AnnouncedSpy.isEmpty()); QVERIFY(registry.hasInterface(KWayland::Client::Registry::Interface::Compositor)); @@ -421,6 +438,7 @@ void TestWaylandRegistry::testRemoval() QVERIFY(registry.hasInterface(KWayland::Client::Registry::Interface::OutputManagement)); QVERIFY(registry.hasInterface(KWayland::Client::Registry::Interface::ServerSideDecorationManager)); QVERIFY(registry.hasInterface(KWayland::Client::Registry::Interface::Blur)); + QVERIFY(registry.hasInterface(KWayland::Client::Registry::Interface::IdleInhibitManagerUnstableV1)); QVERIFY(!registry.interfaces(KWayland::Client::Registry::Interface::Compositor).isEmpty()); QVERIFY(!registry.interfaces(KWayland::Client::Registry::Interface::Output).isEmpty()); @@ -433,6 +451,7 @@ void TestWaylandRegistry::testRemoval() QVERIFY(!registry.interfaces(KWayland::Client::Registry::Interface::OutputManagement).isEmpty()); QVERIFY(!registry.interfaces(KWayland::Client::Registry::Interface::ServerSideDecorationManager).isEmpty()); QVERIFY(!registry.interfaces(KWayland::Client::Registry::Interface::Blur).isEmpty()); + QVERIFY(!registry.interfaces(KWayland::Client::Registry::Interface::IdleInhibitManagerUnstableV1).isEmpty()); QSignalSpy seatRemovedSpy(®istry, SIGNAL(seatRemoved(quint32))); QVERIFY(seatRemovedSpy.isValid()); @@ -444,6 +463,7 @@ void TestWaylandRegistry::testRemoval() SubCompositor *subcompositor = registry.createSubCompositor(registry.interface(Registry::Interface::SubCompositor).name, registry.interface(Registry::Interface::SubCompositor).version, ®istry); ServerSideDecorationManager *serverSideDeco = registry.createServerSideDecorationManager(registry.interface(Registry::Interface::ServerSideDecorationManager).name, registry.interface(Registry::Interface::ServerSideDecorationManager).version, ®istry); BlurManager *blurManager = registry.createBlurManager(registry.interface(Registry::Interface::Blur).name, registry.interface(Registry::Interface::Blur).version, ®istry); + auto idleInhibitManager = registry.createIdleInhibitManager(registry.interface(Registry::Interface::IdleInhibitManagerUnstableV1).name, registry.interface(Registry::Interface::IdleInhibitManagerUnstableV1).version, ®istry); connection.flush(); m_display->dispatchEvents(); @@ -457,6 +477,8 @@ void TestWaylandRegistry::testRemoval() QVERIFY(compositorObjectRemovedSpy.isValid()); QSignalSpy subcompositorObjectRemovedSpy(subcompositor, &SubCompositor::removed); QVERIFY(subcompositorObjectRemovedSpy.isValid()); + QSignalSpy idleInhibitManagerObjectRemovedSpy(idleInhibitManager, &IdleInhibitManager::removed); + QVERIFY(idleInhibitManagerObjectRemovedSpy.isValid()); delete m_seat; QVERIFY(seatRemovedSpy.wait()); @@ -547,6 +569,14 @@ void TestWaylandRegistry::testRemoval() QVERIFY(registry.interfaces(KWayland::Client::Registry::Interface::Blur).isEmpty()); QCOMPARE(blurObjectRemovedSpy.count(), 1); + QSignalSpy idleInhibitManagerUnstableV1RemovedSpy(®istry, &Registry::idleInhibitManagerUnstableV1Removed); + QVERIFY(idleInhibitManagerUnstableV1RemovedSpy.isValid()); + delete m_idleInhibit; + QVERIFY(idleInhibitManagerUnstableV1RemovedSpy.wait()); + QCOMPARE(idleInhibitManagerUnstableV1RemovedSpy.first().first(), idleInhibitManagerUnstableV1AnnouncedSpy.first().first()); + QVERIFY(registry.interfaces(KWayland::Client::Registry::Interface::IdleInhibitManagerUnstableV1).isEmpty()); + QCOMPARE(idleInhibitManagerObjectRemovedSpy.count(), 1); + // cannot test shmRemoved as there is no functionality for it // verify everything has been removed only once @@ -557,6 +587,7 @@ void TestWaylandRegistry::testRemoval() QCOMPARE(subcompositorObjectRemovedSpy.count(), 1); QCOMPARE(serverSideDecoManagerObjectRemovedSpy.count(), 1); QCOMPARE(blurObjectRemovedSpy.count(), 1); + QCOMPARE(idleInhibitManagerObjectRemovedSpy.count(), 1); } void TestWaylandRegistry::testOutOfSyncRemoval() diff --git a/src/wayland/autotests/client/test_wayland_surface.cpp b/src/wayland/autotests/client/test_wayland_surface.cpp index db24b64f69..9cd99bd68b 100644 --- a/src/wayland/autotests/client/test_wayland_surface.cpp +++ b/src/wayland/autotests/client/test_wayland_surface.cpp @@ -25,6 +25,7 @@ License along with this library. If not, see . #include "../../src/client/compositor.h" #include "../../src/client/connection_thread.h" #include "../../src/client/event_queue.h" +#include "../../src/client/idleinhibit.h" #include "../../src/client/output.h" #include "../../src/client/surface.h" #include "../../src/client/region.h" @@ -33,10 +34,13 @@ License along with this library. If not, see . #include "../../src/server/buffer_interface.h" #include "../../src/server/compositor_interface.h" #include "../../src/server/display.h" +#include "../../src/server/idleinhibit_interface.h" #include "../../src/server/surface_interface.h" // Wayland #include +using KWayland::Client::Registry; + class TestWaylandSurface : public QObject { Q_OBJECT @@ -62,14 +66,17 @@ private Q_SLOTS: void testDestroyWithPendingCallback(); void testOutput(); void testDisconnect(); + void testInhibit(); private: KWayland::Server::Display *m_display; KWayland::Server::CompositorInterface *m_compositorInterface; + KWayland::Server::IdleInhibitManagerInterface *m_idleInhibitInterface = nullptr; KWayland::Client::ConnectionThread *m_connection; KWayland::Client::Compositor *m_compositor; KWayland::Client::ShmPool *m_shm; KWayland::Client::EventQueue *m_queue; + KWayland::Client::IdleInhibitManager *m_idleInhibitManager = nullptr; QThread *m_thread; }; @@ -100,6 +107,11 @@ void TestWaylandSurface::init() m_compositorInterface->create(); QVERIFY(m_compositorInterface->isValid()); + m_idleInhibitInterface = m_display->createIdleInhibitManager(IdleInhibitManagerInterfaceVersion::UnstableV1, m_display); + QVERIFY(m_idleInhibitInterface); + m_idleInhibitInterface->create(); + QVERIFY(m_idleInhibitInterface->isValid()); + // setup connection m_connection = new KWayland::Client::ConnectionThread; QSignalSpy connectedSpy(m_connection, SIGNAL(connected())); @@ -143,6 +155,9 @@ void TestWaylandSurface::init() QVERIFY(m_compositor->isValid()); m_shm = registry.createShmPool(shmSpy.first().first().value(), shmSpy.first().last().value(), this); QVERIFY(m_shm->isValid()); + + m_idleInhibitManager = registry.createIdleInhibitManager(registry.interface(Registry::Interface::IdleInhibitManagerUnstableV1).name, registry.interface(Registry::Interface::IdleInhibitManagerUnstableV1).version, this); + QVERIFY(m_idleInhibitManager->isValid()); } void TestWaylandSurface::cleanup() @@ -1091,5 +1106,53 @@ void TestWaylandSurface::testOutput() QCOMPARE(serverSurface->outputs(), QVector()); } +void TestWaylandSurface::testInhibit() +{ + using namespace KWayland::Client; + using namespace KWayland::Server; + QScopedPointer s(m_compositor->createSurface()); + // wait for the surface on the Server side + QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); + QVERIFY(surfaceCreatedSpy.isValid()); + QVERIFY(surfaceCreatedSpy.wait()); + auto serverSurface = surfaceCreatedSpy.first().first().value(); + QVERIFY(serverSurface); + QCOMPARE(serverSurface->inhibitsIdle(), false); + + QSignalSpy inhibitsChangedSpy(serverSurface, &SurfaceInterface::inhibitsIdleChanged); + QVERIFY(inhibitsChangedSpy.isValid()); + + // now create an idle inhibition + QScopedPointer inhibitor1(m_idleInhibitManager->createInhibitor(s.data())); + QVERIFY(inhibitsChangedSpy.wait()); + QCOMPARE(serverSurface->inhibitsIdle(), true); + + // creating a second idle inhibition should not trigger the signal + QScopedPointer inhibitor2(m_idleInhibitManager->createInhibitor(s.data())); + QVERIFY(!inhibitsChangedSpy.wait()); + QCOMPARE(serverSurface->inhibitsIdle(), true); + + // and also deleting the first inhibitor should not yet change the inhibition + inhibitor1.reset(); + QVERIFY(!inhibitsChangedSpy.wait()); + QCOMPARE(serverSurface->inhibitsIdle(), true); + + // but deleting also the second inhibitor should trigger + inhibitor2.reset(); + QVERIFY(inhibitsChangedSpy.wait()); + QCOMPARE(serverSurface->inhibitsIdle(), false); + QCOMPARE(inhibitsChangedSpy.count(), 2); + + // recreate inhibitor1 should inhibit again + inhibitor1.reset(m_idleInhibitManager->createInhibitor(s.data())); + QVERIFY(inhibitsChangedSpy.wait()); + QCOMPARE(serverSurface->inhibitsIdle(), true); + // and destroying should uninhibit + inhibitor1.reset(); + QVERIFY(inhibitsChangedSpy.wait()); + QCOMPARE(serverSurface->inhibitsIdle(), false); + QCOMPARE(inhibitsChangedSpy.count(), 4); +} + QTEST_GUILESS_MAIN(TestWaylandSurface) #include "test_wayland_surface.moc" diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index f3c504f845..f5e16640ed 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -25,6 +25,7 @@ License along with this library. If not, see . #include "outputmanagement_interface.h" #include "outputdevice_interface.h" #include "idle_interface.h" +#include "idleinhibit_interface_p.h" #include "fakeinput_interface.h" #include "logging_p.h" #include "output_interface.h" @@ -420,6 +421,18 @@ XdgForeignInterface *Display::createXdgForeignInterface(QObject *parent) return foreign; } +IdleInhibitManagerInterface *Display::createIdleInhibitManager(const IdleInhibitManagerInterfaceVersion &version, QObject *parent) +{ + IdleInhibitManagerInterface *i = nullptr; + switch (version) { + case IdleInhibitManagerInterfaceVersion::UnstableV1: + i = new IdleInhibitManagerUnstableV1Interface(this, parent); + break; + } + connect(this, &Display::aboutToTerminate, i, [this,i] { delete i; }); + return i; +} + void Display::createShm() { Q_ASSERT(d->display); diff --git a/src/wayland/display.h b/src/wayland/display.h index 5a9f65e689..d964a0eea0 100644 --- a/src/wayland/display.h +++ b/src/wayland/display.h @@ -53,6 +53,8 @@ class CompositorInterface; class DataDeviceManagerInterface; class DpmsManagerInterface; class IdleInterface; +enum class IdleInhibitManagerInterfaceVersion; +class IdleInhibitManagerInterface; class FakeInputInterface; class OutputInterface; class OutputDeviceInterface; @@ -227,6 +229,15 @@ public: * @since 5.40 **/ XdgForeignInterface *createXdgForeignInterface(QObject *parent = nullptr); + + /** + * Creates the IdleInhibitManagerInterface in interface @p version. + * + * @returns The created manager object + * @since 5.41 + **/ + IdleInhibitManagerInterface *createIdleInhibitManager(const IdleInhibitManagerInterfaceVersion &version, QObject *parent = nullptr); + /** * Gets the ClientConnection for the given @p client. * If there is no ClientConnection yet for the given @p client, it will be created. diff --git a/src/wayland/server/idleinhibit_interface.cpp b/src/wayland/server/idleinhibit_interface.cpp new file mode 100644 index 0000000000..97b46c26cd --- /dev/null +++ b/src/wayland/server/idleinhibit_interface.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +Copyright 2017 Martin Flöser + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "idleinhibit_interface_p.h" + +namespace KWayland +{ +namespace Server +{ + +IdleInhibitManagerInterface::Private::Private(IdleInhibitManagerInterface *q, Display *d, const wl_interface *interface, quint32 version, IdleInhibitManagerInterfaceVersion interfaceVersion) + : Global::Private(d, interface, version) + , interfaceVersion(interfaceVersion) + , q(q) +{ +} + +IdleInhibitManagerInterface::IdleInhibitManagerInterface(Private *d, QObject *parent) + : Global(d, parent) +{ +} + +IdleInhibitManagerInterface::~IdleInhibitManagerInterface() = default; + +IdleInhibitManagerInterfaceVersion IdleInhibitManagerInterface::interfaceVersion() const +{ + Q_D(); + return d->interfaceVersion; +} + +IdleInhibitManagerInterface::Private *IdleInhibitManagerInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +} +} diff --git a/src/wayland/server/idleinhibit_interface.h b/src/wayland/server/idleinhibit_interface.h new file mode 100644 index 0000000000..b634770557 --- /dev/null +++ b/src/wayland/server/idleinhibit_interface.h @@ -0,0 +1,77 @@ +/**************************************************************************** +Copyright 2017 Martin Flöser + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef KWAYLAND_SERVER_IDLEINHIBIT_H +#define KWAYLAND_SERVER_IDLEINHIBIT_H + +#include "global.h" +#include "resource.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class Display; + +/** + * Enum describing the interface versions the IdleInhibitManagerInterface can support. + * + * @since 5.41 + **/ +enum class IdleInhibitManagerInterfaceVersion { + /** + * zwp_idle_inhibit_manager_v1 + **/ + UnstableV1 +}; + +/** + * The IdleInhibitorManagerInterface is used by clients to inhibit idle on a + * SurfaceInterface. Whether a SurfaceInterface inhibits idle is exposes through + * @link{SurfaceInterface::inhibitsIdle}. + * + * @since 5.41 + **/ +class KWAYLANDSERVER_EXPORT IdleInhibitManagerInterface : public Global +{ + Q_OBJECT +public: + virtual ~IdleInhibitManagerInterface(); + + /** + * @returns The interface version used by this IdleInhibitManagerInterface + **/ + IdleInhibitManagerInterfaceVersion interfaceVersion() const; + +protected: + class Private; + explicit IdleInhibitManagerInterface(Private *d, QObject *parent = nullptr); + +private: + Private *d_func() const; +}; + + +} +} + +#endif diff --git a/src/wayland/server/idleinhibit_interface_p.h b/src/wayland/server/idleinhibit_interface_p.h new file mode 100644 index 0000000000..8ba5766cca --- /dev/null +++ b/src/wayland/server/idleinhibit_interface_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +Copyright 2017 Martin Flöser + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef KWAYLAND_SERVER_IDLEINHIBIT_P_H +#define KWAYLAND_SERVER_IDLEINHIBIT_P_H + +#include "idleinhibit_interface.h" +#include "global_p.h" +#include "resource_p.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class Q_DECL_HIDDEN IdleInhibitManagerUnstableV1Interface : public IdleInhibitManagerInterface +{ + Q_OBJECT +public: + explicit IdleInhibitManagerUnstableV1Interface(Display *display, QObject *parent = nullptr); + ~IdleInhibitManagerUnstableV1Interface() override; + +private: + class Private; +}; + +class Q_DECL_HIDDEN IdleInhibitManagerInterface::Private : public Global::Private +{ +public: + IdleInhibitManagerInterfaceVersion interfaceVersion; + +protected: + Private(IdleInhibitManagerInterface *q, Display *d, const wl_interface *interface, quint32 version, IdleInhibitManagerInterfaceVersion interfaceVersion); + IdleInhibitManagerInterface *q; +}; + +class Q_DECL_HIDDEN IdleInhibitorInterface : public Resource +{ + Q_OBJECT +public: + explicit IdleInhibitorInterface(IdleInhibitManagerInterface *c, wl_resource *parentResource); + + virtual ~IdleInhibitorInterface(); + + /** + * @returns The interface version used by this IdleInhibitorInterface + **/ + IdleInhibitManagerInterfaceVersion interfaceVersion() const; + +protected: + class Private; + +private: + Private *d_func() const; + friend class IdleInhibitManagerUnstableV1Interface; +}; + +class Q_DECL_HIDDEN IdleInhibitorInterface::Private : public Resource::Private +{ +public: + Private(IdleInhibitorInterface *q, IdleInhibitManagerInterface *m, wl_resource *parentResource); + ~Private(); + +private: + + IdleInhibitorInterface *q_func() { + return reinterpret_cast(q); + } + + static const struct zwp_idle_inhibitor_v1_interface s_interface; +}; + + +} +} + +#endif + diff --git a/src/wayland/server/idleinhibit_interface_v1.cpp b/src/wayland/server/idleinhibit_interface_v1.cpp new file mode 100644 index 0000000000..2920293476 --- /dev/null +++ b/src/wayland/server/idleinhibit_interface_v1.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +Copyright 2017 Martin Flöser + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "idleinhibit_interface_p.h" +#include "display.h" +#include "surface_interface_p.h" + +namespace KWayland +{ +namespace Server +{ + +class Q_DECL_HIDDEN IdleInhibitManagerUnstableV1Interface::Private : public IdleInhibitManagerInterface::Private +{ +public: + Private(IdleInhibitManagerUnstableV1Interface *q, Display *d); + +private: + void bind(wl_client *client, uint32_t version, uint32_t id) override; + + static void unbind(wl_resource *resource); + static Private *cast(wl_resource *r) { + return reinterpret_cast(wl_resource_get_user_data(r)); + } + + static void destroyCallback(wl_client *client, wl_resource *resource); + static void createInhibitorCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface); + + static const struct zwp_idle_inhibit_manager_v1_interface s_interface; + static const quint32 s_version; +}; + +const quint32 IdleInhibitManagerUnstableV1Interface::Private::s_version = 1; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct zwp_idle_inhibit_manager_v1_interface IdleInhibitManagerUnstableV1Interface::Private::s_interface = { + destroyCallback, + createInhibitorCallback +}; +#endif + +IdleInhibitManagerUnstableV1Interface::Private::Private(IdleInhibitManagerUnstableV1Interface *q, Display *d) + : IdleInhibitManagerInterface::Private(q, d, &zwp_idle_inhibit_manager_v1_interface, s_version, IdleInhibitManagerInterfaceVersion::UnstableV1) +{ +} + +void IdleInhibitManagerUnstableV1Interface::Private::destroyCallback(wl_client *client, wl_resource *resource) +{ + Q_UNUSED(client) + wl_resource_destroy(resource); +} + +void IdleInhibitManagerUnstableV1Interface::Private::createInhibitorCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface) +{ + auto s = SurfaceInterface::get(surface); + if (!s) { + // send error? + return; + } + auto q = cast(resource); + auto inhibitor = new IdleInhibitorInterface(q->q, resource); + inhibitor->d_func()->create(q->display->getConnection(client), version, id); + s->d_func()->installIdleInhibitor(inhibitor); +} + +void IdleInhibitManagerUnstableV1Interface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + auto c = display->getConnection(client); + wl_resource *resource = c->createResource(&zwp_idle_inhibit_manager_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 IdleInhibitManagerUnstableV1Interface::Private::unbind(wl_resource *resource) +{ + Q_UNUSED(resource) + // TODO: implement? +} + +IdleInhibitManagerUnstableV1Interface::IdleInhibitManagerUnstableV1Interface(Display *display, QObject *parent) + : IdleInhibitManagerInterface(new Private(this, display), parent) +{ +} + +IdleInhibitManagerUnstableV1Interface::~IdleInhibitManagerUnstableV1Interface() = default; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct zwp_idle_inhibitor_v1_interface IdleInhibitorInterface::Private::s_interface = { + resourceDestroyedCallback +}; +#endif + +IdleInhibitorInterface::Private::Private(IdleInhibitorInterface *q, IdleInhibitManagerInterface *c, wl_resource *parentResource) + : Resource::Private(q, c, parentResource, &zwp_idle_inhibitor_v1_interface, &s_interface) +{ +} + +IdleInhibitorInterface::Private::~Private() +{ + if (resource) { + wl_resource_destroy(resource); + resource = nullptr; + } +} + +IdleInhibitorInterface::IdleInhibitorInterface(IdleInhibitManagerInterface *m, wl_resource *parentResource) + : Resource(new Private(this, m, parentResource)) +{ +} + +IdleInhibitorInterface::~IdleInhibitorInterface() = default; + +IdleInhibitorInterface::Private *IdleInhibitorInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +} +} diff --git a/src/wayland/surface_interface.cpp b/src/wayland/surface_interface.cpp index 37179a643c..0e8936c56c 100644 --- a/src/wayland/surface_interface.cpp +++ b/src/wayland/surface_interface.cpp @@ -22,6 +22,7 @@ License along with this library. If not, see . #include "buffer_interface.h" #include "clientconnection.h" #include "compositor_interface.h" +#include "idleinhibit_interface_p.h" #include "pointerconstraints_interface_p.h" #include "region_interface.h" #include "subcompositor_interface.h" @@ -213,6 +214,22 @@ void SurfaceInterface::Private::installPointerConstraint(LockedPointerInterface emit q_func()->pointerConstraintsChanged(); } +void SurfaceInterface::Private::installIdleInhibitor(IdleInhibitorInterface *inhibitor) +{ + idleInhibitors << inhibitor; + QObject::connect(inhibitor, &IdleInhibitorInterface::aboutToBeUnbound, q, + [this, inhibitor] { + idleInhibitors.removeOne(inhibitor); + if (idleInhibitors.isEmpty()) { + emit q_func()->inhibitsIdleChanged(); + } + } + ); + if (idleInhibitors.count() == 1) { + emit q_func()->inhibitsIdleChanged(); + } +} + void SurfaceInterface::Private::installPointerConstraint(ConfinedPointerInterface *confinement) { Q_ASSERT(lockedPointer.isNull()); @@ -856,6 +873,12 @@ QPointer SurfaceInterface::confinedPointer() const return d->confinedPointer; } +bool SurfaceInterface::inhibitsIdle() const +{ + Q_D(); + return !d->idleInhibitors.isEmpty(); +} + SurfaceInterface::Private *SurfaceInterface::d_func() const { return reinterpret_cast(d.data()); diff --git a/src/wayland/surface_interface.h b/src/wayland/surface_interface.h index c7f2fc68a5..232c38c38d 100644 --- a/src/wayland/surface_interface.h +++ b/src/wayland/surface_interface.h @@ -40,6 +40,7 @@ class ConfinedPointerInterface; class ContrastInterface; class ContrastManagerInterface; class CompositorInterface; +class IdleInhibitManagerUnstableV1Interface; class LockedPointerInterface; class PointerConstraintsUnstableV1Interface; class ShadowManagerInterface; @@ -242,6 +243,13 @@ public: **/ QPointer lockedPointer() const; + /** + * @returns Whether this SurfaceInterface wants idle to be inhibited on the Output it is shown + * @see inhibitsIdleChanged + * @since 5.41 + **/ + bool inhibitsIdle() const; + /** * @returns The SurfaceInterface for the @p native resource. **/ @@ -308,6 +316,13 @@ Q_SIGNALS: **/ void pointerConstraintsChanged(); + /** + * Emitted whenever the SurfaceInterface starts/ends to inhibit idle. + * @see inhibitsIdle + * @since 5.41 + **/ + void inhibitsIdleChanged(); + private: friend class CompositorInterface; friend class SubSurfaceInterface; @@ -315,6 +330,7 @@ private: friend class BlurManagerInterface; friend class SlideManagerInterface; friend class ContrastManagerInterface; + friend class IdleInhibitManagerUnstableV1Interface; friend class PointerConstraintsUnstableV1Interface; explicit SurfaceInterface(CompositorInterface *parent, wl_resource *parentResource); diff --git a/src/wayland/surface_interface_p.h b/src/wayland/surface_interface_p.h index 30c39dbf45..974fe3b0f8 100644 --- a/src/wayland/surface_interface_p.h +++ b/src/wayland/surface_interface_p.h @@ -32,6 +32,8 @@ namespace KWayland namespace Server { +class IdleInhibitorInterface; + class SurfaceInterface::Private : public Resource::Private { public: @@ -77,6 +79,7 @@ public: void setSlide(const QPointer &slide); void installPointerConstraint(LockedPointerInterface *lock); void installPointerConstraint(ConfinedPointerInterface *confinement); + void installIdleInhibitor(IdleInhibitorInterface *inhibitor); void commitSubSurface(); void commit(); @@ -98,6 +101,7 @@ public: QPointer lockedPointer; QPointer confinedPointer; QHash outputDestroyedConnections; + QVector idleInhibitors; private: QMetaObject::Connection constrainsOneShotConnection; diff --git a/src/wayland/tools/mapping.txt b/src/wayland/tools/mapping.txt index 871599f402..77f51ab368 100644 --- a/src/wayland/tools/mapping.txt +++ b/src/wayland/tools/mapping.txt @@ -58,3 +58,5 @@ zwp_pointer_gesture_pinch_v1;PointerPinchGestureUnstableV1 zwp_pointer_constraints_v1;PointerConstraints zwp_locked_pointer_v1;LockedPointer zwp_confined_pointer_v1;ConfinedPointer +zwp_idle_inhibit_manager_v1;IdleInhibitManager +zwp_idle_inhibitor_v1;IdleInhibitor