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.
This commit is contained in:
Vlad Zahorodnii 2022-12-08 12:04:35 +02:00
parent 07e63cab8c
commit 2985398375
10 changed files with 45 additions and 102 deletions

View file

@ -9,7 +9,7 @@ set(PROJECT_VERSION_MAJOR 5)
set(CMAKE_C_STANDARD 99) 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(KF6_MIN_VERSION "5.240.0")
set(KDE_COMPILERSETTINGS_LEVEL "5.82") set(KDE_COMPILERSETTINGS_LEVEL "5.82")

View file

@ -23,7 +23,7 @@ ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES
layershellqt 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) target_link_libraries(LayerShellQtInterface PRIVATE Qt::Gui Qt::WaylandClientPrivate Wayland::Client PkgConfig::XKBCOMMON)
if (TARGET Qt::XkbCommonSupportPrivate) if (TARGET Qt::XkbCommonSupportPrivate)
target_link_libraries(LayerShellQtInterface PRIVATE Qt::XkbCommonSupportPrivate) target_link_libraries(LayerShellQtInterface PRIVATE Qt::XkbCommonSupportPrivate)

View file

@ -5,11 +5,15 @@
*/ */
#include "window.h" #include "window.h"
#include "../qwaylandlayershellintegration_p.h"
#include <layershellqt_logging.h> #include <layershellqt_logging.h>
#include <QPointer> #include <QPointer>
#include <optional> #include <optional>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
using namespace LayerShellQt; using namespace LayerShellQt;
class LayerShellQt::WindowPrivate class LayerShellQt::WindowPrivate
@ -122,6 +126,27 @@ Window::Window(QWindow *window)
, d(new WindowPrivate(window)) , d(new WindowPrivate(window))
{ {
s_map.insert(d->parentWindow, this); s_map.insert(d->parentWindow, this);
window->create();
auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(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) Window *Window::get(QWindow *window)

View file

@ -1,29 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
* SPDX-FileCopyrightText: 2018 Drew DeVault <sir@cmpwn.com>
*
* 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);
}
}

View file

@ -1,32 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
* SPDX-FileCopyrightText: 2018 Drew DeVault <sir@cmpwn.com>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef _LAYERSHELL_H
#define _LAYERSHELL_H
#include <wayland-client.h>
#include <QtWaylandClient/private/qwaylandshellintegration_p.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h>
#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

View file

@ -5,45 +5,30 @@
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
#include "qwaylandlayershell_p.h"
#include "qwaylandlayershellintegration_p.h" #include "qwaylandlayershellintegration_p.h"
#include "qwaylandlayersurface_p.h"
#include <QtWaylandClient/private/qwaylanddisplay_p.h> #include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h> #include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h>
namespace LayerShellQt namespace LayerShellQt
{ {
QWaylandLayerShellIntegration::QWaylandLayerShellIntegration() QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
: QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>(4)
{ {
} }
QWaylandLayerShellIntegration::~QWaylandLayerShellIntegration() QWaylandLayerShellIntegration::~QWaylandLayerShellIntegration()
{ {
} if (object() && zwlr_layer_shell_v1_get_version(object()) >= ZWLR_LAYER_SHELL_V1_DESTROY_SINCE_VERSION) {
zwlr_layer_shell_v1_destroy(object());
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;
} }
QtWaylandClient::QWaylandShellSurface *QWaylandLayerShellIntegration::createShellSurface(QtWaylandClient::QWaylandWindow *window) 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<QWaylandLayerShellIntegration *>(data);
if (interface == zwlr_layer_shell_v1_interface.name)
shell->m_layerShell.reset(new QWaylandLayerShell(registry, id, std::min(version, 4u)));
}
} }
//#include "qwaylandlayershellintegration.moc"

View file

@ -8,28 +8,21 @@
#ifndef _LAYERSHELLINTEGRATION_P_H #ifndef _LAYERSHELLINTEGRATION_P_H
#define _LAYERSHELLINTEGRATION_P_H #define _LAYERSHELLINTEGRATION_P_H
#include <wayland-client.h>
#include "layershellqt_export.h" #include "layershellqt_export.h"
#include <QtWaylandClient/private/qwaylandshellintegration_p.h> #include <QtWaylandClient/private/qwaylandshellintegration_p.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h>
namespace LayerShellQt namespace LayerShellQt
{ {
class QWaylandLayerShell;
class LAYERSHELLQT_EXPORT QWaylandLayerShellIntegration : public QtWaylandClient::QWaylandShellIntegration class LAYERSHELLQT_EXPORT QWaylandLayerShellIntegration : public QtWaylandClient::QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>, public QtWayland::zwlr_layer_shell_v1
{ {
public: public:
QWaylandLayerShellIntegration(); QWaylandLayerShellIntegration();
~QWaylandLayerShellIntegration() override; ~QWaylandLayerShellIntegration() override;
bool initialize(QtWaylandClient::QWaylandDisplay *display) override;
QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) 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<QWaylandLayerShell> m_layerShell;
}; };
} }

View file

@ -5,9 +5,8 @@
* SPDX-License-Identifier: LGPL-3.0-or-later * SPDX-License-Identifier: LGPL-3.0-or-later
*/ */
#include "interfaces/shell.h" #include "interfaces/window.h"
#include "layershellqt_logging.h" #include "layershellqt_logging.h"
#include "qwaylandlayershell_p.h"
#include "qwaylandlayersurface_p.h" #include "qwaylandlayersurface_p.h"
#include <QtWaylandClient/private/qwaylandscreen_p.h> #include <QtWaylandClient/private/qwaylandscreen_p.h>
@ -16,7 +15,7 @@
namespace LayerShellQt namespace LayerShellQt
{ {
QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window) QWaylandLayerSurface::QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window)
: QtWaylandClient::QWaylandShellSurface(window) : QtWaylandClient::QWaylandShellSurface(window)
, QtWayland::zwlr_layer_surface_v1() , QtWayland::zwlr_layer_surface_v1()
{ {

View file

@ -16,13 +16,12 @@
namespace LayerShellQt namespace LayerShellQt
{ {
class QWaylandLayerShell;
class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::zwlr_layer_surface_v1 class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::zwlr_layer_surface_v1
{ {
Q_OBJECT Q_OBJECT
public: public:
QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window); QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window);
~QWaylandLayerSurface() override; ~QWaylandLayerSurface() override;
bool isExposed() const override bool isExposed() const override

View file

@ -14,7 +14,6 @@
#include <QMetaEnum> #include <QMetaEnum>
#include <interfaces/shell.h>
#include <interfaces/window.h> #include <interfaces/window.h>
using namespace LayerShellQt; using namespace LayerShellQt;
@ -51,8 +50,6 @@ class BasicWindow : public QRasterWindow
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Shell::useLayerShell();
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
const auto layerMetaEnum = QMetaEnum::fromType<Window::Layer>(); const auto layerMetaEnum = QMetaEnum::fromType<Window::Layer>();
@ -79,6 +76,8 @@ int main(int argc, char **argv)
BasicWindow window; BasicWindow window;
LayerShellQt::Window *layerShell = LayerShellQt::Window::get(&window); LayerShellQt::Window *layerShell = LayerShellQt::Window::get(&window);
layerShell->setLayer(Window::LayerBottom);
if (parser.isSet(marginsOption)) { if (parser.isSet(marginsOption)) {
int margins = parser.value(marginsOption).toInt(); int margins = parser.value(marginsOption).toInt();
layerShell->setMargins({margins, margins, margins, margins}); layerShell->setMargins({margins, margins, margins, margins});
@ -102,6 +101,10 @@ int main(int argc, char **argv)
window.show(); window.show();
BasicWindow window2;
window2.resize(400, 400);
window2.show();
// just so you don't block yourself out whilst testing // just so you don't block yourself out whilst testing
QTimer::singleShot(5000, &app, &QGuiApplication::quit); QTimer::singleShot(5000, &app, &QGuiApplication::quit);
return app.exec(); return app.exec();