From 6a0c6c6f7f4e22328d79c185fb13637aa5bb8de2 Mon Sep 17 00:00:00 2001 From: David Redondo Date: Thu, 5 Feb 2026 15:13:39 +0100 Subject: [PATCH] try to not use private API --- src/interfaces/window.cpp | 21 +++++---- src/qwaylandlayershellintegration.cpp | 3 -- src/qwaylandlayersurface.cpp | 64 +++++++++++++++++---------- src/qwaylandlayersurface_p.h | 4 +- src/qwaylandxdgactivationv1.cpp | 12 ++--- src/qwaylandxdgactivationv1_p.h | 2 +- 6 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/interfaces/window.cpp b/src/interfaces/window.cpp index a9718c8..446dc23 100644 --- a/src/interfaces/window.cpp +++ b/src/interfaces/window.cpp @@ -7,6 +7,7 @@ #include "window.h" #include "../qwaylandlayershellintegration_p.h" +#include #include #include @@ -14,8 +15,6 @@ #include #include -#include - using namespace LayerShellQt; class LayerShellQt::WindowPrivate @@ -274,23 +273,27 @@ bool Window::eventFilter(QObject *watched, QEvent *event) void Window::initializeShell() { - auto waylandWindow = dynamic_cast(d->parentWindow->handle()); - if (!waylandWindow) { - qCWarning(LAYERSHELLQT) << d->parentWindow << "is not a wayland window. Not creating zwlr_layer_surface"; - return; - } + // FIXME + // auto waylandWindow = dynamic_cast(d->parentWindow->handle()); + // if (!waylandWindow) { + // qCWarning(LAYERSHELLQT) << d->parentWindow << "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())) { + // Why does it take a display that is unused + if (!shellIntegration->initialize(nullptr)) { 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); + // FIXME this is relevant when the plugin is not the default shell integration + // Something like QWaylandShellIntegration::assignToWindow(QPlatformWindow *)? + // waylandWindow->setShellIntegration(shellIntegration); } Window *Window::get(QWindow *window) diff --git a/src/qwaylandlayershellintegration.cpp b/src/qwaylandlayershellintegration.cpp index 2ae367e..0392216 100644 --- a/src/qwaylandlayershellintegration.cpp +++ b/src/qwaylandlayershellintegration.cpp @@ -9,9 +9,6 @@ #include "qwaylandlayersurface_p.h" #include "qwaylandxdgactivationv1_p.h" -#include -#include - namespace LayerShellQt { QWaylandLayerShellIntegration::QWaylandLayerShellIntegration() diff --git a/src/qwaylandlayersurface.cpp b/src/qwaylandlayersurface.cpp index 4c86abb..4a13655 100644 --- a/src/qwaylandlayersurface.cpp +++ b/src/qwaylandlayersurface.cpp @@ -10,12 +10,10 @@ #include "qwaylandlayersurface_p.h" #include "qwaylandxdgactivationv1_p.h" -#include -#include -#include -#include - #include +#include +#include +#include // private native interface namespace LayerShellQt { @@ -23,17 +21,19 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, : QtWaylandClient::QWaylandShellSurface(window) , QtWayland::zwlr_layer_surface_v1() , m_shell(shell) - , m_interface(Window::get(window->window())) + // FIXME reverse lookup would a QWindow getter make sense, also below a bunch + // QWindow * QWaylandShellSurface::window + , m_interface(Window::get(platformWindow()->window())) , m_window(window) { wl_output *output = nullptr; if (!m_interface->wantsToBeOnActiveScreen()) { QScreen *desiredScreen = m_interface->screen(); if (!desiredScreen) { - desiredScreen = window->window()->screen(); + desiredScreen = platformWindow()->window()->screen(); } - auto waylandScreen = dynamic_cast(desiredScreen->handle()); + auto waylandScreen = platformWindow()->window()->screen()->nativeInterface(); // Qt will always assign a screen to a window, but if the compositor has no screens available a dummy QScreen object is created // this will not cast to a QWaylandScreen if (!waylandScreen) { @@ -42,7 +42,7 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, output = waylandScreen->output(); } } - init(shell->get_layer_surface(window->waylandSurface()->object(), output, m_interface->layer(), m_interface->scope())); + init(shell->get_layer_surface(wlSurface(), output, m_interface->layer(), m_interface->scope())); connect(m_interface, &Window::layerChanged, this, [this]() { setLayer(m_interface->layer()); }); @@ -51,7 +51,7 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, connect(m_interface, &Window::anchorsChanged, this, [this]() { setAnchor(m_interface->anchors()); if (m_interface->desiredSize().isNull()) { - setDesiredSize(m_window->windowContentGeometry().size()); + setDesiredSize(m_lastContentGeometry.size()); } else { setDesiredSize(m_interface->desiredSize()); } @@ -83,12 +83,22 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, }); if (m_interface->desiredSize().isNull()) { - setDesiredSize(window->windowContentGeometry().size()); + // FIXME QWaylandWindow should call setWindowContentGeometry when creating the shell surface + // / Does a setWindowContentGeometry call arrive early enough? + // setDesiredSize(window->windowContentGeometry().size()); } else { setDesiredSize(m_interface->desiredSize()); } } +void QWaylandLayerSurface::setContentGeometry(const QRect &rect) +{ + m_lastContentGeometry = rect; + if (m_interface->desiredSize().isNull()) { + setDesiredSize(rect.size()); + } +} + QWaylandLayerSurface::~QWaylandLayerSurface() { destroy(); @@ -97,7 +107,7 @@ QWaylandLayerSurface::~QWaylandLayerSurface() void QWaylandLayerSurface::zwlr_layer_surface_v1_closed() { if (m_interface->closeOnDismissed()) { - window()->window()->close(); + platformWindow()->close(); } } @@ -113,7 +123,7 @@ void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint } else { // Later configures are resizes, so we have to queue them up for a time when we // are not painting to the window. - window()->applyConfigureWhenPossible(); + applyConfigureWhenPossible(); } } @@ -130,7 +140,7 @@ void QWaylandLayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface *po void QWaylandLayerSurface::applyConfigure() { - window()->resizeFromApplyConfigure(m_pendingSize); + resizeFromApplyConfigure(m_pendingSize); } void QWaylandLayerSurface::setDesiredSize(const QSize &size) @@ -195,20 +205,21 @@ bool QWaylandLayerSurface::requestActivate() return false; } if (!m_activationToken.isEmpty()) { - activation->activate(m_activationToken, window()->wlSurface()); + activation->activate(m_activationToken, wlSurface()); m_activationToken = {}; return true; } else if (const auto token = qEnvironmentVariable("XDG_ACTIVATION_TOKEN"); !token.isEmpty()) { - activation->activate(token, window()->wlSurface()); + activation->activate(token, wlSurface()); qunsetenv("XDG_ACTIVATION_TOKEN"); return true; } else { const auto focusWindow = QGuiApplication::focusWindow(); - const auto wlWindow = focusWindow ? static_cast(focusWindow->handle()) : window(); - if (const auto seat = wlWindow->display()->lastInputDevice()) { - const auto tokenProvider = activation->requestXdgActivationToken(wlWindow->display(), wlWindow->wlSurface(), seat->serial(), QString()); + const auto waylandApp = qGuiApp->nativeInterface(); + const auto surface = focusWindow ? focusWindow->nativeInterface()->surface() : wlSurface(); + if (const auto seat = waylandApp->lastInputSeat()) { + const auto tokenProvider = activation->requestXdgActivationToken(seat, surface, waylandApp->lastInputSerial(), QString()); connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this, [this](const QString &token) { - m_shell->activation()->activate(token, window()->wlSurface()); + m_shell->activation()->activate(token, wlSurface()); }); connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, tokenProvider, &QObject::deleteLater); return true; @@ -227,7 +238,7 @@ bool QWaylandLayerSurface::requestActivateOnShow() return false; } - if (m_window->window()->property("_q_showWithoutActivating").toBool()) { + if (platformWindow()->window()->property("_q_showWithoutActivating").toBool()) { return false; } @@ -245,16 +256,21 @@ void QWaylandLayerSurface::requestXdgActivationToken(quint32 serial) if (!activation->isActive()) { return; } - auto tokenProvider = activation->requestXdgActivationToken(window()->display(), window()->wlSurface(), serial, QString()); + const auto waylandApp = qGuiApp->nativeInterface(); + auto tokenProvider = activation->requestXdgActivationToken(waylandApp->lastInputSeat(), wlSurface(), serial, QString()); connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this, [this](const QString &token) { - Q_EMIT window()->xdgActivationTokenCreated(token); + // FIXME No way to do this without knowing QWaylandWindow because QPlatofrmWindow is not QObject + // But we wanted to make a better API as well or alternatively the signal needs to be on QWaylandShellSurface as well + // Q_EMIT window()->xdgActivationTokenCreated(token); + // QMetaObject::invokeMethod(window(), "xdgActivationTokenCreated", token); }); connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, tokenProvider, &QObject::deleteLater); } void QWaylandLayerSurface::sendExpose() { - window()->updateExposure(); + // FIXME No way to call this, needs wrapper in QWaylandShellSurface + // window()->updateExposure(); } } diff --git a/src/qwaylandlayersurface_p.h b/src/qwaylandlayersurface_p.h index a48e522..5972ec4 100644 --- a/src/qwaylandlayersurface_p.h +++ b/src/qwaylandlayersurface_p.h @@ -8,6 +8,7 @@ #ifndef _LAYERSURFACE_H #define _LAYERSURFACE_H +#include #include #include "qwaylandlayershellintegration_p.h" @@ -41,7 +42,7 @@ public: void setMargins(const QMargins &margins); void setKeyboardInteractivity(uint32_t interactivity); void setLayer(uint32_t layer); - + void setContentGeometry(const QRect &rect) override; void applyConfigure() override; void setWindowSize(const QSize &size) override; @@ -60,6 +61,7 @@ private: QtWaylandClient::QWaylandWindow *m_window; QSize m_pendingSize; QString m_activationToken; + QRect m_lastContentGeometry; bool m_configured = false; }; diff --git a/src/qwaylandxdgactivationv1.cpp b/src/qwaylandxdgactivationv1.cpp index cab4fcc..1473069 100644 --- a/src/qwaylandxdgactivationv1.cpp +++ b/src/qwaylandxdgactivationv1.cpp @@ -3,8 +3,6 @@ */ #include "qwaylandxdgactivationv1_p.h" -#include -#include QWaylandXdgActivationV1::QWaylandXdgActivationV1() : QWaylandClientExtensionTemplate(1) @@ -19,10 +17,8 @@ QWaylandXdgActivationV1::~QWaylandXdgActivationV1() } } -QWaylandXdgActivationTokenV1 *QWaylandXdgActivationV1::requestXdgActivationToken(QtWaylandClient::QWaylandDisplay *display, - struct ::wl_surface *surface, - std::optional serial, - const QString &app_id) +QWaylandXdgActivationTokenV1 * +QWaylandXdgActivationV1::requestXdgActivationToken(::wl_seat *seat, struct ::wl_surface *surface, std::optional serial, const QString &app_id) { auto wl = get_activation_token(); auto provider = new QWaylandXdgActivationTokenV1; @@ -34,8 +30,8 @@ QWaylandXdgActivationTokenV1 *QWaylandXdgActivationV1::requestXdgActivationToken if (!app_id.isEmpty()) { provider->set_app_id(app_id); } - if (serial && display->lastInputDevice()) { - provider->set_serial(*serial, display->lastInputDevice()->wl_seat()); + if (serial && seat) { + provider->set_serial(*serial, seat); } provider->commit(); return provider; diff --git a/src/qwaylandxdgactivationv1_p.h b/src/qwaylandxdgactivationv1_p.h index ecdaabe..40fc15d 100644 --- a/src/qwaylandxdgactivationv1_p.h +++ b/src/qwaylandxdgactivationv1_p.h @@ -42,7 +42,7 @@ public: ~QWaylandXdgActivationV1() override; QWaylandXdgActivationTokenV1 * - requestXdgActivationToken(QtWaylandClient::QWaylandDisplay *display, struct ::wl_surface *surface, std::optional serial, const QString &app_id); + requestXdgActivationToken(::wl_seat *seat, struct ::wl_surface *surface, std::optional serial, const QString &app_id); }; #endif // QWAYLANDXDGACTIVATIONV1_P_H