diff --git a/ksplash/ksplashqml/CMakeLists.txt b/ksplash/ksplashqml/CMakeLists.txt --- a/ksplash/ksplashqml/CMakeLists.txt +++ b/ksplash/ksplashqml/CMakeLists.txt @@ -14,6 +14,8 @@ KF5::ConfigCore KF5::Package KF5::QuickAddons + KF5::WaylandClient + KF5::WindowSystem ) install(TARGETS ksplashqml ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/ksplash/ksplashqml/splashapp.h b/ksplash/ksplashqml/splashapp.h --- a/ksplash/ksplashqml/splashapp.h +++ b/ksplash/ksplashqml/splashapp.h @@ -28,6 +28,14 @@ class SplashWindow; +namespace KWayland +{ +namespace Client +{ +class PlasmaShell; +} +} + class SplashApp: public QGuiApplication { Q_OBJECT @@ -37,22 +45,30 @@ explicit SplashApp(int &argc, char ** argv); ~SplashApp() override; + + KWayland::Client::PlasmaShell *waylandPlasmaShellInterface() const { + return m_waylandPlasmaShell; + } + public Q_SLOTS: Q_SCRIPTABLE void setStage(const QString &messgae); protected: void timerEvent(QTimerEvent *event) override; void setStage(int stage); private: + void setupWaylandIntegration(); int m_stage; QList m_windows; bool m_testing; bool m_window; QStringList m_stages; QBasicTimer m_timer; QDateTime m_startTime; + KWayland::Client::PlasmaShell *m_waylandPlasmaShell = nullptr; + private Q_SLOTS: void adoptScreen(QScreen*); }; diff --git a/ksplash/ksplashqml/splashapp.cpp b/ksplash/ksplashqml/splashapp.cpp --- a/ksplash/ksplashqml/splashapp.cpp +++ b/ksplash/ksplashqml/splashapp.cpp @@ -30,6 +30,11 @@ #include #include +#include +#include +#include +#include + #define TEST_STEP_INTERVAL 2000 /** @@ -60,6 +65,8 @@ m_testing = parser.isSet(QStringLiteral("test")); m_window = parser.isSet(QStringLiteral("window")); + setupWaylandIntegration(); + foreach(QScreen* screen, screens()) adoptScreen(screen); @@ -143,3 +150,24 @@ w->deleteLater(); }); } + +void SplashApp::setupWaylandIntegration() +{ + if (!KWindowSystem::isPlatformWayland()) { + return; + } + using namespace KWayland::Client; + ConnectionThread *connection = ConnectionThread::fromApplication(this); + if (!connection) { + return; + } + Registry *registry = new Registry(this); + registry->create(connection); + connect(registry, &Registry::plasmaShellAnnounced, this, + [this, registry] (quint32 name, quint32 version) { + m_waylandPlasmaShell = registry->createPlasmaShell(name, version, this); + } + ); + registry->setup(); + connection->roundtrip(); +} diff --git a/ksplash/ksplashqml/splashwindow.h b/ksplash/ksplashqml/splashwindow.h --- a/ksplash/ksplashqml/splashwindow.h +++ b/ksplash/ksplashqml/splashwindow.h @@ -26,6 +26,14 @@ class QMouseEvent; class QKeyEvent; +namespace KWayland +{ +namespace Client +{ +class PlasmaShellSurface; +} +} + class SplashWindow: public KQuickAddons::QuickViewSharedEngine { public: @@ -35,13 +43,16 @@ virtual void setGeometry(const QRect &rect); protected: + bool event(QEvent *e) override; void keyPressEvent(QKeyEvent *event) override; void mousePressEvent(QMouseEvent *event) override; private: + void setupWaylandIntegration(); int m_stage; bool m_testing; bool m_window; + KWayland::Client::PlasmaShellSurface *m_shellSurface = nullptr; }; #endif // SPLASH_WINDOW_H_ diff --git a/ksplash/ksplashqml/splashwindow.cpp b/ksplash/ksplashqml/splashwindow.cpp --- a/ksplash/ksplashqml/splashwindow.cpp +++ b/ksplash/ksplashqml/splashwindow.cpp @@ -18,6 +18,7 @@ */ #include "splashwindow.h" +#include "splashapp.h" #include #include @@ -33,6 +34,10 @@ #include #include +#include +#include +#include + SplashWindow::SplashWindow(bool testing, bool window) : KQuickAddons::QuickViewSharedEngine(), m_stage(0), @@ -49,16 +54,17 @@ } if (!m_testing && !m_window) { - if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) { + if (KWindowSystem::isPlatformX11()) { // X11 specific hint only on X11 setFlags(Qt::BypassWindowManagerHint); - } else { + } else if (!KWindowSystem::isPlatformWayland()) { // on other platforms go fullscreen + // on Wayland we cannot go fullscreen due to QTBUG 54883 setWindowState(Qt::WindowFullScreen); } } - if (m_testing && !m_window) { + if (m_testing && !m_window && !KWindowSystem::isPlatformWayland()) { setWindowState(Qt::WindowFullScreen); } @@ -74,6 +80,24 @@ rootObject()->setProperty("stage", stage); } +bool SplashWindow::event(QEvent *e) +{ + if (e->type() == QEvent::PlatformSurface) { + if (auto pe = dynamic_cast(e)) { + switch (pe->surfaceEventType()) { + case QPlatformSurfaceEvent::SurfaceCreated: + setupWaylandIntegration(); + break; + case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: + delete m_shellSurface; + m_shellSurface = nullptr; + break; + } + } + } + return KQuickAddons::QuickViewSharedEngine::event(e); +} + void SplashWindow::keyPressEvent(QKeyEvent *event) { KQuickAddons::QuickViewSharedEngine::keyPressEvent(event); @@ -111,4 +135,32 @@ setSource(QUrl::fromLocalFile(package.filePath("splashmainscript"))); } + + if (m_shellSurface) { + m_shellSurface->setPosition(geometry().topLeft()); + } +} + +void SplashWindow::setupWaylandIntegration() +{ + if (m_shellSurface) { + // already setup + return; + } + if (SplashApp *a = qobject_cast(qApp)) { + using namespace KWayland::Client; + PlasmaShell *interface = a->waylandPlasmaShellInterface(); + if (!interface) { + return; + } + Surface *s = Surface::fromWindow(this); + if (!s) { + return; + } + m_shellSurface = interface->createSurface(s, this); + // Use OSD to make it go above all other windows + // that's the closest we have to the X11 unmanged layer we have on Wayland + m_shellSurface->setRole(PlasmaShellSurface::Role::OnScreenDisplay); + m_shellSurface->setPosition(geometry().topLeft()); + } }