diff --git a/startkde/plasma-session/CMakeLists.txt b/startkde/plasma-session/CMakeLists.txt --- a/startkde/plasma-session/CMakeLists.txt +++ b/startkde/plasma-session/CMakeLists.txt @@ -35,6 +35,7 @@ KF5::CoreAddons KF5::Notifications KF5::KIOCore + KF5::WindowSystem PW::KWorkspace ${PHONON_LIBRARIES} ) diff --git a/startkde/plasma-session/main.cpp b/startkde/plasma-session/main.cpp --- a/startkde/plasma-session/main.cpp +++ b/startkde/plasma-session/main.cpp @@ -19,11 +19,11 @@ #include "startup.h" #include "shutdown.h" -#include +#include int main(int argc, char **argv) { - QCoreApplication app(argc, argv); + QGuiApplication app(argc, argv); // This is needed with KJobs in a QCoreApplication as when they finish // the internal QEventLoopLocker expires and our app exits diff --git a/startkde/plasma-session/startup.h b/startkde/plasma-session/startup.h --- a/startkde/plasma-session/startup.h +++ b/startkde/plasma-session/startup.h @@ -103,3 +103,16 @@ private: }; + +class WindowManagerWaitJob: public KJob +{ + Q_OBJECT +public: + WindowManagerWaitJob(); + void start() override; +public Q_SLOTS: + void slotOnReady(bool active); +private: + bool m_enabled; +}; + diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp --- a/startkde/plasma-session/startup.cpp +++ b/startkde/plasma-session/startup.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -216,8 +217,10 @@ QStringList arguments = qApp->arguments(); arguments.removeFirst(); auto ksmserverJob = new StartServiceJob(QStringLiteral("ksmserver"), arguments, QStringLiteral("org.kde.ksmserver")); + auto wmjob = new WindowManagerWaitJob(); - connect(ksmserverJob, &KJob::finished, phase0, &KJob::start); + connect(ksmserverJob, &KJob::finished, wmjob, &KJob::start); + connect(wmjob, &KJob::finished, phase0, &KJob::start); connect(phase0, &KJob::finished, phase1, &KJob::start); @@ -429,4 +432,63 @@ } +WindowManagerWaitJob::WindowManagerWaitJob() +{ + m_enabled = true; +} + +void WindowManagerWaitJob::start() +{ + // do not wait if compositor is already up + if (KWindowSystem::compositingActive()) { + qCInfo(PLASMA_SESSION) << "WindowManagerWaitJob: skipping"; + slotOnReady(true); + return; + } + + // delay to make sure WM fully initializes + auto timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, [this]() { + qCInfo(PLASMA_SESSION) << "WindowManagerWaitJob: timeout reached"; + slotOnReady(true); + }); + + timer->start(3000); + + // cut the delay if compositor is detected + connect(KWindowSystem::self(), &KWindowSystem::compositingChanged, this, + [this](bool active) { + qCInfo(PLASMA_SESSION) << "WindowManagerWaitJob: KWindoSystem triggered"; + slotOnReady(active); + } + ); + + auto kwinWatcher = new QDBusServiceWatcher( + QStringLiteral("org.kde.KWin"), + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForRegistration, + this); + connect(kwinWatcher, &QDBusServiceWatcher::serviceRegistered, this, [this]() { + if (!m_enabled) + return; + + qCInfo(PLASMA_SESSION) << "WindowManagerWaitJob: found KWin"; + // KWin is ready, wait for its compositor + QDBusConnection::sessionBus().connect( + QStringLiteral("org.kde.KWin"), + QStringLiteral("/Compositor"), + QStringLiteral("org.kde.kwin.Compositing"), + QStringLiteral("compositingToggled"), + this, SLOT(slotOnReady(bool))); + }); +} + +void WindowManagerWaitJob::slotOnReady(bool active) +{ + if (m_enabled && active) { + m_enabled = false; + emitResult(); + } +} + #include "startup.moc"