From 298539837578799a44ddd5e7d1041aa2f4edf0a1 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 8 Dec 2022 12:04:35 +0200 Subject: [PATCH] Port to QWaylandWindow::setShellIntegration() With QWaylandWindow::setShellIntegration(), it's possible to use xdg-shell and layer-shell protocols in the same process. It's important for plasmashell, where we want to use the layer shell protocol for special surfaces such as the desktop background, and the xdg shell protocol for dialogs. In order to make a QWindow use the layer shell protocol, you need to call LayerShellQt::Window::get() before the window is mapped. --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- src/interfaces/window.cpp | 25 +++++++++++++++++++++ src/qwaylandlayershell.cpp | 29 ------------------------ src/qwaylandlayershell_p.h | 32 --------------------------- src/qwaylandlayershellintegration.cpp | 27 +++++----------------- src/qwaylandlayershellintegration_p.h | 13 +++-------- src/qwaylandlayersurface.cpp | 5 ++--- src/qwaylandlayersurface_p.h | 3 +-- tests/main.cpp | 9 +++++--- 10 files changed, 45 insertions(+), 102 deletions(-) delete mode 100644 src/qwaylandlayershell.cpp delete mode 100644 src/qwaylandlayershell_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bf71d5e..33fbe0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(PROJECT_VERSION_MAJOR 5) set(CMAKE_C_STANDARD 99) -set(QT_MIN_VERSION "6.4.0") +set(QT_MIN_VERSION "6.5.0") set(KF6_MIN_VERSION "5.240.0") set(KDE_COMPILERSETTINGS_LEVEL "5.82") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 176fa52..7531ce2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,7 +23,7 @@ ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES layershellqt ) -target_sources(LayerShellQtInterface PRIVATE qwaylandlayersurface.cpp interfaces/window.cpp interfaces/shell.cpp qwaylandlayershellintegration.cpp qwaylandlayershell.cpp ${LAYER_SHELL_SOURCES}) +target_sources(LayerShellQtInterface PRIVATE qwaylandlayersurface.cpp interfaces/window.cpp interfaces/shell.cpp qwaylandlayershellintegration.cpp ${LAYER_SHELL_SOURCES}) target_link_libraries(LayerShellQtInterface PRIVATE Qt::Gui Qt::WaylandClientPrivate Wayland::Client PkgConfig::XKBCOMMON) if (TARGET Qt::XkbCommonSupportPrivate) target_link_libraries(LayerShellQtInterface PRIVATE Qt::XkbCommonSupportPrivate) diff --git a/src/interfaces/window.cpp b/src/interfaces/window.cpp index 7aa39f4..541bd59 100644 --- a/src/interfaces/window.cpp +++ b/src/interfaces/window.cpp @@ -5,11 +5,15 @@ */ #include "window.h" +#include "../qwaylandlayershellintegration_p.h" + #include #include #include +#include + using namespace LayerShellQt; class LayerShellQt::WindowPrivate @@ -122,6 +126,27 @@ Window::Window(QWindow *window) , d(new WindowPrivate(window)) { s_map.insert(d->parentWindow, this); + + window->create(); + + auto waylandWindow = dynamic_cast(window->handle()); + if (!waylandWindow) { + qCWarning(LAYERSHELLQT) << window << "is not a wayland window. Not creating zwlr_layer_surface"; + return; + } + + static QWaylandLayerShellIntegration *shellIntegration = nullptr; + if (!shellIntegration) { + shellIntegration = new QWaylandLayerShellIntegration(); + if (!shellIntegration->initialize(waylandWindow->display())) { + delete shellIntegration; + shellIntegration = nullptr; + qCWarning(LAYERSHELLQT) << "Failed to initialize layer-shell integration, possibly because compositor does not support the layer-shell protocol"; + return; + } + } + + waylandWindow->setShellIntegration(shellIntegration); } Window *Window::get(QWindow *window) diff --git a/src/qwaylandlayershell.cpp b/src/qwaylandlayershell.cpp deleted file mode 100644 index 9c54abb..0000000 --- a/src/qwaylandlayershell.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez - * SPDX-FileCopyrightText: 2018 Drew DeVault - * - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#include "qwaylandlayershell_p.h" -#include "qwaylandlayersurface_p.h" - -namespace LayerShellQt -{ -QWaylandLayerShell::QWaylandLayerShell(::wl_registry *registry, uint32_t id, uint32_t version) - : QtWayland::zwlr_layer_shell_v1(registry, id, version) -{ -} - -QWaylandLayerShell::~QWaylandLayerShell() -{ - if (zwlr_layer_shell_v1_get_version(object()) >= ZWLR_LAYER_SHELL_V1_DESTROY_SINCE_VERSION) - zwlr_layer_shell_v1_destroy(object()); -} - -QWaylandLayerSurface *QWaylandLayerShell::createLayerSurface(QtWaylandClient::QWaylandWindow *window) -{ - return new QWaylandLayerSurface(this, window); -} - -} diff --git a/src/qwaylandlayershell_p.h b/src/qwaylandlayershell_p.h deleted file mode 100644 index 135b388..0000000 --- a/src/qwaylandlayershell_p.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez - * SPDX-FileCopyrightText: 2018 Drew DeVault - * - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#ifndef _LAYERSHELL_H -#define _LAYERSHELL_H - -#include - -#include -#include - -#include "qwaylandlayersurface_p.h" - -namespace LayerShellQt -{ -class LAYERSHELLQT_EXPORT QWaylandLayerShell : public QtWayland::zwlr_layer_shell_v1 -{ -public: - QWaylandLayerShell(::wl_registry *registry, uint32_t id, uint32_t version); - ~QWaylandLayerShell() override; - - QWaylandLayerSurface *createLayerSurface(QtWaylandClient::QWaylandWindow *window); - // TODO: Popups -}; - -} - -#endif diff --git a/src/qwaylandlayershellintegration.cpp b/src/qwaylandlayershellintegration.cpp index ada426f..5d92a23 100644 --- a/src/qwaylandlayershellintegration.cpp +++ b/src/qwaylandlayershellintegration.cpp @@ -5,45 +5,30 @@ * SPDX-License-Identifier: LGPL-3.0-or-later */ -#include "qwaylandlayershell_p.h" #include "qwaylandlayershellintegration_p.h" +#include "qwaylandlayersurface_p.h" #include #include -#include namespace LayerShellQt { QWaylandLayerShellIntegration::QWaylandLayerShellIntegration() + : QWaylandShellIntegrationTemplate(4) { } QWaylandLayerShellIntegration::~QWaylandLayerShellIntegration() { -} - -bool QWaylandLayerShellIntegration::initialize(QtWaylandClient::QWaylandDisplay *display) -{ -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - QWaylandShellIntegration::initialize(display); -#endif - display->addRegistryListener(registryLayer, this); - return m_layerShell != nullptr; + if (object() && zwlr_layer_shell_v1_get_version(object()) >= ZWLR_LAYER_SHELL_V1_DESTROY_SINCE_VERSION) { + zwlr_layer_shell_v1_destroy(object()); + } } QtWaylandClient::QWaylandShellSurface *QWaylandLayerShellIntegration::createShellSurface(QtWaylandClient::QWaylandWindow *window) { - return m_layerShell->createLayerSurface(window); + return new QWaylandLayerSurface(this, window); } -void QWaylandLayerShellIntegration::registryLayer(void *data, struct wl_registry *registry, uint32_t id, const QString &interface, uint32_t version) -{ - QWaylandLayerShellIntegration *shell = static_cast(data); - - if (interface == zwlr_layer_shell_v1_interface.name) - shell->m_layerShell.reset(new QWaylandLayerShell(registry, id, std::min(version, 4u))); -} } - -//#include "qwaylandlayershellintegration.moc" diff --git a/src/qwaylandlayershellintegration_p.h b/src/qwaylandlayershellintegration_p.h index 2df4206..08c5699 100644 --- a/src/qwaylandlayershellintegration_p.h +++ b/src/qwaylandlayershellintegration_p.h @@ -8,28 +8,21 @@ #ifndef _LAYERSHELLINTEGRATION_P_H #define _LAYERSHELLINTEGRATION_P_H -#include - #include "layershellqt_export.h" + #include +#include namespace LayerShellQt { -class QWaylandLayerShell; -class LAYERSHELLQT_EXPORT QWaylandLayerShellIntegration : public QtWaylandClient::QWaylandShellIntegration +class LAYERSHELLQT_EXPORT QWaylandLayerShellIntegration : public QtWaylandClient::QWaylandShellIntegrationTemplate, public QtWayland::zwlr_layer_shell_v1 { public: QWaylandLayerShellIntegration(); ~QWaylandLayerShellIntegration() override; - bool initialize(QtWaylandClient::QWaylandDisplay *display) override; QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) override; - -private: - static void registryLayer(void *data, struct wl_registry *registry, uint32_t id, const QString &interface, uint32_t version); - - QScopedPointer m_layerShell; }; } diff --git a/src/qwaylandlayersurface.cpp b/src/qwaylandlayersurface.cpp index dd17aa0..8a9d295 100644 --- a/src/qwaylandlayersurface.cpp +++ b/src/qwaylandlayersurface.cpp @@ -5,9 +5,8 @@ * SPDX-License-Identifier: LGPL-3.0-or-later */ -#include "interfaces/shell.h" +#include "interfaces/window.h" #include "layershellqt_logging.h" -#include "qwaylandlayershell_p.h" #include "qwaylandlayersurface_p.h" #include @@ -16,7 +15,7 @@ namespace LayerShellQt { -QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window) +QWaylandLayerSurface::QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window) : QtWaylandClient::QWaylandShellSurface(window) , QtWayland::zwlr_layer_surface_v1() { diff --git a/src/qwaylandlayersurface_p.h b/src/qwaylandlayersurface_p.h index 6a59d62..2539a05 100644 --- a/src/qwaylandlayersurface_p.h +++ b/src/qwaylandlayersurface_p.h @@ -16,13 +16,12 @@ namespace LayerShellQt { -class QWaylandLayerShell; class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::zwlr_layer_surface_v1 { Q_OBJECT public: - QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window); + QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window); ~QWaylandLayerSurface() override; bool isExposed() const override diff --git a/tests/main.cpp b/tests/main.cpp index d6a0517..6d90734 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -14,7 +14,6 @@ #include -#include #include using namespace LayerShellQt; @@ -51,8 +50,6 @@ class BasicWindow : public QRasterWindow int main(int argc, char **argv) { - Shell::useLayerShell(); - QGuiApplication app(argc, argv); const auto layerMetaEnum = QMetaEnum::fromType(); @@ -79,6 +76,8 @@ int main(int argc, char **argv) BasicWindow window; LayerShellQt::Window *layerShell = LayerShellQt::Window::get(&window); + layerShell->setLayer(Window::LayerBottom); + if (parser.isSet(marginsOption)) { int margins = parser.value(marginsOption).toInt(); layerShell->setMargins({margins, margins, margins, margins}); @@ -102,6 +101,10 @@ int main(int argc, char **argv) window.show(); + BasicWindow window2; + window2.resize(400, 400); + window2.show(); + // just so you don't block yourself out whilst testing QTimer::singleShot(5000, &app, &QGuiApplication::quit); return app.exec();