From 72316718dfbb408034e53dac6507418c0e1ce977 Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Fri, 30 Oct 2015 12:26:12 +0100 Subject: [PATCH] task geometries to wayland for minimize effect this exposes the geometry of taskbar entries in plasma-windowmanagement, in order to make the minimize effects possible. unlike on X11, it takes relative positions and it has one geometry per panel, making possible to have multiple taskbars working. REVIEW:125871 --- src/wayland/autotests/client/CMakeLists.txt | 11 + .../client/test_wayland_windowmanagement.cpp | 221 ++++++++++++++++++ .../plasmawindowmanagement_interface.cpp | 45 ++++ .../plasmawindowmanagement_interface.h | 9 + 4 files changed, 286 insertions(+) create mode 100644 src/wayland/autotests/client/test_wayland_windowmanagement.cpp diff --git a/src/wayland/autotests/client/CMakeLists.txt b/src/wayland/autotests/client/CMakeLists.txt index 1556c4765a..9914434bb0 100644 --- a/src/wayland/autotests/client/CMakeLists.txt +++ b/src/wayland/autotests/client/CMakeLists.txt @@ -168,6 +168,17 @@ target_link_libraries( testSlide Qt5::Test Qt5::Gui KF5::WaylandClient KF5::Wayl add_test(kwayland-testSlide testSlide) ecm_mark_as_test(testSlide) +######################################################## +# Test Window Management +######################################################## +set( testWindowmanagement_SRCS + test_wayland_windowmanagement.cpp + ) +add_executable(testWindowmanagement ${testWindowmanagement_SRCS}) +target_link_libraries( testWindowmanagement Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client) +add_test(kwayland-testWindowmanagement testWindowmanagement) +ecm_mark_as_test(testWindowmanagement) + ######################################################## # Test DataSource ######################################################## diff --git a/src/wayland/autotests/client/test_wayland_windowmanagement.cpp b/src/wayland/autotests/client/test_wayland_windowmanagement.cpp new file mode 100644 index 0000000000..85316298ed --- /dev/null +++ b/src/wayland/autotests/client/test_wayland_windowmanagement.cpp @@ -0,0 +1,221 @@ +/******************************************************************** +Copyright 2015 Marco Martin + +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 . +*********************************************************************/ +// Qt +#include +// KWin +#include "../../src/client/compositor.h" +#include "../../src/client/connection_thread.h" +#include "../../src/client/event_queue.h" +#include "../../src/client/region.h" +#include "../../src/client/registry.h" +#include "../../src/client/surface.h" +#include "../../src/client/plasmawindowmanagement.h" +#include "../../src/client/surface.h" +#include "../../src/server/display.h" +#include "../../src/server/compositor_interface.h" +#include "../../src/server/region_interface.h" +#include "../../src/server/plasmawindowmanagement_interface.h" +#include "../../src/server/surface_interface.h" + +class TestWindowManagement : public QObject +{ + Q_OBJECT +public: + explicit TestWindowManagement(QObject *parent = nullptr); +private Q_SLOTS: + void init(); + + void testWindowTitle(); + void testMinimizedGeometry(); + + void cleanup(); + +private: + KWayland::Server::Display *m_display; + KWayland::Server::CompositorInterface *m_compositorInterface; + KWayland::Server::PlasmaWindowManagementInterface *m_windowManagementInterface; + KWayland::Server::PlasmaWindowInterface *m_windowInterface; + KWayland::Server::SurfaceInterface *m_surfaceInterface = nullptr; + + KWayland::Client::Surface *m_surface = nullptr; + KWayland::Client::ConnectionThread *m_connection; + KWayland::Client::Compositor *m_compositor; + KWayland::Client::EventQueue *m_queue; + KWayland::Client::PlasmaWindowManagement *m_windowManagement; + KWayland::Client::PlasmaWindow *m_window; + QThread *m_thread; + KWayland::Client::Registry *m_registry; +}; + +static const QString s_socketName = QStringLiteral("kwayland-test-wayland-windowmanagement-0"); + +TestWindowManagement::TestWindowManagement(QObject *parent) + : QObject(parent) + , m_display(nullptr) + , m_compositorInterface(nullptr) + , m_connection(nullptr) + , m_compositor(nullptr) + , m_queue(nullptr) + , m_thread(nullptr) +{ +} + +void TestWindowManagement::init() +{ + using namespace KWayland::Server; + delete m_display; + m_display = new Display(this); + m_display->setSocketName(s_socketName); + m_display->start(); + QVERIFY(m_display->isRunning()); + + // setup connection + m_connection = new KWayland::Client::ConnectionThread; + QSignalSpy connectedSpy(m_connection, SIGNAL(connected())); + m_connection->setSocketName(s_socketName); + + m_thread = new QThread(this); + m_connection->moveToThread(m_thread); + m_thread->start(); + + m_connection->initConnection(); + QVERIFY(connectedSpy.wait()); + + m_queue = new KWayland::Client::EventQueue(this); + QVERIFY(!m_queue->isValid()); + m_queue->setup(m_connection); + QVERIFY(m_queue->isValid()); + + m_registry = new KWayland::Client::Registry(this); + QSignalSpy compositorSpy(m_registry, SIGNAL(compositorAnnounced(quint32,quint32))); + QVERIFY(compositorSpy.isValid()); + + QSignalSpy windowManagementSpy(m_registry, SIGNAL(plasmaWindowManagementAnnounced(quint32,quint32))); + QVERIFY(windowManagementSpy.isValid()); + + + QVERIFY(!m_registry->eventQueue()); + m_registry->setEventQueue(m_queue); + QCOMPARE(m_registry->eventQueue(), m_queue); + m_registry->create(m_connection->display()); + QVERIFY(m_registry->isValid()); + m_registry->setup(); + + m_compositorInterface = m_display->createCompositor(m_display); + m_compositorInterface->create(); + QVERIFY(m_compositorInterface->isValid()); + + QVERIFY(compositorSpy.wait()); + m_compositor = m_registry->createCompositor(compositorSpy.first().first().value(), compositorSpy.first().last().value(), this); + + + m_windowManagementInterface = m_display->createPlasmaWindowManagement(m_display); + m_windowManagementInterface->create(); + QVERIFY(m_windowManagementInterface->isValid()); + + QVERIFY(windowManagementSpy.wait()); + m_windowManagement = m_registry->createPlasmaWindowManagement(windowManagementSpy.first().first().value(), windowManagementSpy.first().last().value(), this); + + QSignalSpy windowSpy(m_windowManagement, SIGNAL(windowCreated(KWayland::Client::PlasmaWindow *))); + QVERIFY(windowSpy.isValid()); + m_windowInterface = m_windowManagementInterface->createWindow(this); + + QVERIFY(windowSpy.wait()); + m_window = windowSpy.first().first().value(); + + QSignalSpy serverSurfaceCreated(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*))); + QVERIFY(serverSurfaceCreated.isValid()); + + m_surface = m_compositor->createSurface(this); + QVERIFY(m_surface); + + QVERIFY(serverSurfaceCreated.wait()); + m_surfaceInterface = serverSurfaceCreated.first().first().value(); + QVERIFY(m_surfaceInterface); + + m_surface = m_compositor->createSurface(this); + QVERIFY(m_surface); +} + +void TestWindowManagement::testWindowTitle() +{ + m_windowInterface->setTitle("Test Title"); + + QSignalSpy titleSpy(m_window, SIGNAL(titleChanged())); + QVERIFY(titleSpy.isValid()); + + QVERIFY(titleSpy.wait()); + + QCOMPARE(m_window->title(), QString::fromUtf8("Test Title")); +} + +void TestWindowManagement::testMinimizedGeometry() +{ + m_window->setMinimizedGeometry(m_surface, QRect(5, 10, 100, 200)); + + QSignalSpy geometrySpy(m_windowInterface, SIGNAL(minimizedGeometriesChanged())); + QVERIFY(geometrySpy.isValid()); + + QVERIFY(geometrySpy.wait()); + QCOMPARE(m_windowInterface->minimizedGeometries().values().first(), QRect(5, 10, 100, 200)); + + m_window->unsetMinimizedGeometry(m_surface); + QVERIFY(geometrySpy.wait()); + QVERIFY(m_windowInterface->minimizedGeometries().isEmpty()); +} + +void TestWindowManagement::cleanup() +{ + delete m_windowManagementInterface; + m_windowManagementInterface = nullptr; + + delete m_windowInterface; + m_windowInterface = nullptr; + + delete m_surfaceInterface; + m_surfaceInterface = nullptr; + + if (m_compositor) { + delete m_compositor; + m_compositor = nullptr; + } + if (m_queue) { + delete m_queue; + m_queue = nullptr; + } + if (m_registry) { + delete m_registry; + m_registry = nullptr; + } + if (m_thread) { + m_thread->quit(); + m_thread->wait(); + delete m_thread; + m_thread = nullptr; + } + delete m_connection; + m_connection = nullptr; + + delete m_display; + m_display = nullptr; +} + +QTEST_MAIN(TestWindowManagement) +#include "test_wayland_windowmanagement.moc" diff --git a/src/wayland/plasmawindowmanagement_interface.cpp b/src/wayland/plasmawindowmanagement_interface.cpp index ad714a52d0..7042ab095b 100644 --- a/src/wayland/plasmawindowmanagement_interface.cpp +++ b/src/wayland/plasmawindowmanagement_interface.cpp @@ -21,9 +21,12 @@ License along with this library. If not, see . #include "global_p.h" #include "resource_p.h" #include "display.h" +#include "surface_interface.h" #include #include +#include +#include #include #include @@ -77,6 +80,7 @@ public: }; QList resources; quint32 windowId = 0; + QHash minimizedGeometries; private: static void unbind(wl_resource *resource); @@ -84,6 +88,8 @@ private: static void setStateCallback(wl_client *client, wl_resource *resource, uint32_t flags, uint32_t state); static void setVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t number); static void closeCallback(wl_client *client, wl_resource *resource); + static void setTaskGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + static void unsetMinimizedGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel); static Private *cast(wl_resource *resource) { return reinterpret_cast(wl_resource_get_user_data(resource)); } @@ -241,6 +247,8 @@ PlasmaWindowInterface *PlasmaWindowManagementInterface::createWindow(QObject *pa const struct org_kde_plasma_window_interface PlasmaWindowInterface::Private::s_interface = { setStateCallback, setVirtualDesktopCallback, + setTaskGeometryCallback, + unsetMinimizedGeometryCallback, closeCallback }; #endif @@ -439,6 +447,38 @@ void PlasmaWindowInterface::Private::setStateCallback(wl_client *client, wl_reso } } +void PlasmaWindowInterface::Private::setTaskGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + Q_UNUSED(client) + Private *p = cast(resource); + SurfaceInterface *panelSurface = SurfaceInterface::get(panel); + + if (!panelSurface) { + return; + } + + p->minimizedGeometries[panelSurface] = QRect(x, y, width, height); + emit p->q->minimizedGeometriesChanged(); + connect(panelSurface, &QObject::destroyed, p->q, [p, panelSurface] () { + if (p->minimizedGeometries.remove(panelSurface)) {; + emit p->q->minimizedGeometriesChanged(); + } + }); +} + +void PlasmaWindowInterface::Private::unsetMinimizedGeometryCallback(wl_client *client, wl_resource *resource, wl_resource *panel) +{ + Q_UNUSED(client) + Private *p = cast(resource); + SurfaceInterface *panelSurface = SurfaceInterface::get(panel); + + if (!panelSurface) { + return; + } + p->minimizedGeometries.remove(panelSurface); + emit p->q->minimizedGeometriesChanged(); +} + PlasmaWindowInterface::PlasmaWindowInterface(PlasmaWindowManagementInterface *wm, QObject *parent) : QObject(parent) , d(new Private(wm, this)) @@ -467,6 +507,11 @@ void PlasmaWindowInterface::unmap() d->unmap(); } +QHash PlasmaWindowInterface::minimizedGeometries() const +{ + return d->minimizedGeometries; +} + void PlasmaWindowInterface::setActive(bool set) { d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE, set); diff --git a/src/wayland/plasmawindowmanagement_interface.h b/src/wayland/plasmawindowmanagement_interface.h index 6ccc22e272..b37efa4fb3 100644 --- a/src/wayland/plasmawindowmanagement_interface.h +++ b/src/wayland/plasmawindowmanagement_interface.h @@ -36,6 +36,7 @@ namespace Server class Display; class PlasmaWindowInterface; +class SurfaceInterface; class KWAYLANDSERVER_EXPORT PlasmaWindowManagementInterface : public Global { @@ -87,6 +88,13 @@ public: void unmap(); + /** + * @returns Geometries of the taskbar entries, indicized by the + * surface of the panels + * @since 5.5 + */ + QHash minimizedGeometries() const; + Q_SIGNALS: void closeRequested(); void virtualDesktopRequested(quint32 desktop); @@ -102,6 +110,7 @@ Q_SIGNALS: void maximizeableRequested(bool set); void fullscreenableRequested(bool set); void skipTaskbarRequested(bool set); + QRect minimizedGeometriesChanged(); private: friend class PlasmaWindowManagementInterface;