diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fcbf2dd80..00151a19f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,6 +427,7 @@ if(Wayland_Client_FOUND AND XKB_FOUND) ${kwin_KDEINIT_SRCS} wayland_backend.cpp wayland_client/buffer.cpp + wayland_client/compositor.cpp wayland_client/connection_thread.cpp wayland_client/registry.cpp wayland_client/fullscreen_shell.cpp diff --git a/autotests/wayland_client/CMakeLists.txt b/autotests/wayland_client/CMakeLists.txt index 98938f3cff..e14fc85ab9 100644 --- a/autotests/wayland_client/CMakeLists.txt +++ b/autotests/wayland_client/CMakeLists.txt @@ -62,6 +62,7 @@ ecm_mark_as_test(testWaylandOutput) ######################################################## set( testWaylandShell_SRCS test_wayland_shell.cpp + ${KWIN_SOURCE_DIR}/wayland_client/compositor.cpp ${KWIN_SOURCE_DIR}/wayland_client/connection_thread.cpp ${KWIN_SOURCE_DIR}/wayland_client/registry.cpp ${KWIN_SOURCE_DIR}/wayland_client/fullscreen_shell.cpp diff --git a/autotests/wayland_client/test_wayland_shell.cpp b/autotests/wayland_client/test_wayland_shell.cpp index 09ff052403..7dcb95b198 100644 --- a/autotests/wayland_client/test_wayland_shell.cpp +++ b/autotests/wayland_client/test_wayland_shell.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . // Qt #include // KWin +#include "../../wayland_client/compositor.h" #include "../../wayland_client/connection_thread.h" #include "../../wayland_client/shell.h" #include "../../wayland_client/surface.h" @@ -147,14 +148,16 @@ void TestWaylandShell::testShell() if (compositorSpy.isEmpty()) { QVERIFY(compositorSpy.wait()); } - wl_compositor *compositor = registry.bindCompositor(compositorSpy.first().first().value(), compositorSpy.first().last().value()); + KWin::Wayland::Compositor compositor; + compositor.setup(registry.bindCompositor(compositorSpy.first().first().value(), compositorSpy.first().last().value())); KWin::Wayland::Shell shell; shell.setup(registry.bindShell(announced.first().first().value(), announced.first().last().value())); wl_display_flush(connection.display()); - KWin::Wayland::Surface s; - s.setup(wl_compositor_create_surface(compositor)); - KWin::Wayland::ShellSurface *surface = shell.createSurface(&s, &shell); + QScopedPointer s(compositor.createSurface()); + QVERIFY(!s.isNull()); + QVERIFY(s->isValid()); + KWin::Wayland::ShellSurface *surface = shell.createSurface(s.data(), &shell); QSignalSpy sizeSpy(surface, SIGNAL(sizeChanged(QSize))); QVERIFY(sizeSpy.isValid()); QCOMPARE(surface->size(), QSize()); @@ -170,8 +173,7 @@ void TestWaylandShell::testShell() shell.release(); QVERIFY(!surface->isValid()); - s.release(); - wl_compositor_destroy(compositor); + compositor.release(); } QTEST_MAIN(TestWaylandShell) diff --git a/wayland_backend.cpp b/wayland_backend.cpp index 0588ffc1fe..147d97a4d6 100644 --- a/wayland_backend.cpp +++ b/wayland_backend.cpp @@ -23,6 +23,7 @@ along with this program. If not, see . #include "cursor.h" #include "input.h" #include "wayland_client/buffer.h" +#include "wayland_client/compositor.h" #include "wayland_client/connection_thread.h" #include "wayland_client/fullscreen_shell.h" #include "wayland_client/output.h" @@ -284,9 +285,6 @@ WaylandSeat::~WaylandSeat() if (m_seat) { wl_seat_destroy(m_seat); } - if (m_cursor) { - wl_surface_destroy(m_cursor); - } destroyTheme(); } @@ -342,12 +340,15 @@ void WaylandSeat::installCursorImage(wl_buffer *image, const QSize &size, const return; } if (!m_cursor) { - m_cursor = wl_compositor_create_surface(m_backend->compositor()); + m_cursor = m_backend->compositor()->createSurface(this); } - wl_pointer_set_cursor(m_pointer, m_enteredSerial, m_cursor, hotSpot.x(), hotSpot.y()); - wl_surface_attach(m_cursor, image, 0, 0); - wl_surface_damage(m_cursor, 0, 0, size.width(), size.height()); - wl_surface_commit(m_cursor); + if (!m_cursor || !m_cursor->isValid()) { + return; + } + wl_pointer_set_cursor(m_pointer, m_enteredSerial, *m_cursor, hotSpot.x(), hotSpot.y()); + m_cursor->attachBuffer(image); + m_cursor->damage(QRect(QPoint(0,0), size)); + m_cursor->commit(Surface::CommitFlag::None); } void WaylandSeat::installCursorImage(Qt::CursorShape shape) @@ -403,9 +404,9 @@ WaylandBackend::WaylandBackend(QObject *parent) , m_display(nullptr) , m_eventQueue(nullptr) , m_registry(new Registry(this)) - , m_compositor(NULL) + , m_compositor(new Compositor(this)) , m_shell(new Shell(this)) - , m_surface(new Surface(this)) + , m_surface(nullptr) , m_shellSurface(NULL) , m_seat() , m_shm(new ShmPool(this)) @@ -425,7 +426,7 @@ WaylandBackend::WaylandBackend(QObject *parent) connect(this, &WaylandBackend::shellSurfaceSizeChanged, this, &WaylandBackend::checkBackendReady); connect(m_registry, &Registry::compositorAnnounced, this, [this](quint32 name) { - setCompositor(m_registry->bindCompositor(name, 1)); + m_compositor->setup(m_registry->bindCompositor(name, 1)); } ); connect(m_registry, &Registry::shellAnnounced, this, @@ -461,11 +462,11 @@ WaylandBackend::~WaylandBackend() m_shellSurface->release(); } m_fullscreenShell->release(); - m_surface->release(); - m_shell->release(); - if (m_compositor) { - wl_compositor_destroy(m_compositor); + if (m_surface) { + m_surface->release(); } + m_shell->release(); + m_compositor->release(); m_registry->release(); m_seat.reset(); m_shm->release(); @@ -519,14 +520,15 @@ void WaylandBackend::initConnection() m_shellSurface = nullptr; } m_fullscreenShell->destroy(); - m_surface->destroy(); + if (m_surface) { + m_surface->destroy(); + delete m_surface; + m_surface = nullptr; + } if (m_shell) { m_shell->destroy(); } - if (m_compositor) { - free(m_compositor); - m_compositor = nullptr; - } + m_compositor->destroy(); m_registry->destroy(); if (m_display) { m_display = nullptr; @@ -557,8 +559,8 @@ void WaylandBackend::installCursorImage(Qt::CursorShape shape) void WaylandBackend::createSurface() { - m_surface->setup(wl_compositor_create_surface(m_compositor)); - if (!m_surface->isValid()) { + m_surface = m_compositor->createSurface(this); + if (!m_surface || !m_surface->isValid()) { qCritical() << "Creating Wayland Surface failed"; return; } diff --git a/wayland_backend.h b/wayland_backend.h index f9b9a3fdb1..34a92fc2b5 100644 --- a/wayland_backend.h +++ b/wayland_backend.h @@ -45,6 +45,7 @@ namespace Wayland class ShmPool; class WaylandBackend; class WaylandSeat; +class Compositor; class ConnectionThread; class FullscreenShell; class Output; @@ -108,7 +109,7 @@ private: wl_seat *m_seat; wl_pointer *m_pointer; wl_keyboard *m_keyboard; - wl_surface *m_cursor; + Surface *m_cursor; wl_cursor_theme *m_theme; uint32_t m_enteredSerial; QScopedPointer m_cursorTracker; @@ -128,8 +129,7 @@ public: virtual ~WaylandBackend(); wl_display *display(); wl_registry *registry(); - void setCompositor(wl_compositor *c); - wl_compositor *compositor(); + Compositor *compositor(); void addOutput(wl_output *o); const QList &outputs() const; ShmPool *shmPool(); @@ -152,7 +152,7 @@ private: wl_display *m_display; wl_event_queue *m_eventQueue; Registry *m_registry; - wl_compositor *m_compositor; + Compositor *m_compositor; Shell *m_shell; Surface *m_surface; ShellSurface *m_shellSurface; @@ -197,13 +197,7 @@ wl_display *WaylandBackend::display() } inline -void WaylandBackend::setCompositor(wl_compositor *c) -{ - m_compositor = c; -} - -inline -wl_compositor *WaylandBackend::compositor() +Compositor *WaylandBackend::compositor() { return m_compositor; } diff --git a/wayland_client/compositor.cpp b/wayland_client/compositor.cpp new file mode 100644 index 0000000000..8c6373a600 --- /dev/null +++ b/wayland_client/compositor.cpp @@ -0,0 +1,75 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "compositor.h" +#include "surface.h" + +#include + +namespace KWin +{ +namespace Wayland +{ + +Compositor::Compositor(QObject *parent) + : QObject(parent) + , m_compositor(nullptr) +{ +} + +Compositor::~Compositor() +{ + release(); +} + +void Compositor::setup(wl_compositor *compositor) +{ + Q_ASSERT(compositor); + Q_ASSERT(!m_compositor); + m_compositor = compositor; +} + +void Compositor::release() +{ + if (!m_compositor) { + return; + } + wl_compositor_destroy(m_compositor); + m_compositor = nullptr; +} + +void Compositor::destroy() +{ + if (!m_compositor) { + return; + } + free(m_compositor); + m_compositor = nullptr; +} + +Surface *Compositor::createSurface(QObject *parent) +{ + Q_ASSERT(isValid()); + Surface *s = new Surface(parent); + s->setup(wl_compositor_create_surface(m_compositor)); + return s; +} + +} +} diff --git a/wayland_client/compositor.h b/wayland_client/compositor.h new file mode 100644 index 0000000000..9938fd893a --- /dev/null +++ b/wayland_client/compositor.h @@ -0,0 +1,64 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_WAYLAND_COMPOSITOR_H +#define KWIN_WAYLAND_COMPOSITOR_H + +#include + +struct wl_compositor; + +namespace KWin +{ +namespace Wayland +{ + +class Surface; + +class Compositor : public QObject +{ + Q_OBJECT +public: + explicit Compositor(QObject *parent = nullptr); + virtual ~Compositor(); + + bool isValid() const { + return m_compositor != nullptr; + } + void setup(wl_compositor *compositor); + void release(); + void destroy(); + + Surface *createSurface(QObject *parent = nullptr); + + operator wl_compositor*() { + return m_compositor; + } + operator wl_compositor*() const { + return m_compositor; + } + +private: + wl_compositor *m_compositor; +}; + +} +} + +#endif