File indexing completed on 2024-05-12 05:37:59
0001 /* 0002 SPDX-FileCopyrightText: 2010 Ivan Cukic <ivan.cukic(at)kde.org> 0003 SPDX-FileCopyrightText: 2013 Martin Klapetek <mklapetek(at)kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "splashapp.h" 0009 #include "debug.h" 0010 #include "splashwindow.h" 0011 0012 #include <QCommandLineParser> 0013 #include <QCursor> 0014 #include <QDBusConnection> 0015 #include <QLoggingCategory> 0016 #include <QPixmap> 0017 #include <qscreen.h> 0018 0019 #include <KWindowSystem> 0020 0021 #include <KConfigGroup> 0022 #include <KSharedConfig> 0023 0024 #include <LayerShellQt/Shell> 0025 0026 #define TEST_STEP_INTERVAL 2000 0027 0028 /** 0029 * There are 7 stages in ksplash 0030 * - initial (from this class) 0031 * - startPlasma (from startplasma) 0032 * - kcminit 0033 * - ksmserver 0034 * - wm (for X11 from KWin, for Wayland from this class) 0035 * - ready (from plasma-session startup) 0036 * - desktop (from shellcorona) 0037 */ 0038 0039 SplashApp::SplashApp(int &argc, char **argv) 0040 : QGuiApplication(argc, argv) 0041 , m_stage(0) 0042 , m_testing(false) 0043 , m_window(false) 0044 { 0045 QCommandLineParser parser; 0046 parser.addOption(QCommandLineOption(QStringLiteral("test"), QStringLiteral("Run in test mode"))); 0047 parser.addOption(QCommandLineOption(QStringLiteral("window"), QStringLiteral("Run in windowed mode"))); 0048 parser.addOption(QCommandLineOption(QStringLiteral("nofork"), QStringLiteral("Don't fork"))); 0049 parser.addOption(QCommandLineOption(QStringLiteral("pid"), QStringLiteral("Print the pid of the child process"))); 0050 parser.addPositionalArgument(QStringLiteral("theme"), QStringLiteral("Path to the theme to test")); 0051 parser.addHelpOption(); 0052 0053 parser.process(*this); 0054 m_testing = parser.isSet(QStringLiteral("test")); 0055 m_window = parser.isSet(QStringLiteral("window")); 0056 m_theme = parser.positionalArguments().value(0); 0057 if (m_theme.isEmpty()) { 0058 KConfigGroup ksplashCfg = KSharedConfig::openConfig()->group(QStringLiteral("KSplash")); 0059 if (ksplashCfg.readEntry("Engine", QStringLiteral("KSplashQML")) == QLatin1String("KSplashQML")) { 0060 m_theme = ksplashCfg.readEntry("Theme", QStringLiteral("Breeze")); 0061 } 0062 } 0063 0064 QDBusConnection dbus = QDBusConnection::sessionBus(); 0065 dbus.registerObject(QStringLiteral("/KSplash"), this, QDBusConnection::ExportScriptableSlots); 0066 dbus.registerService(QStringLiteral("org.kde.KSplash")); 0067 0068 setupWaylandIntegration(); 0069 0070 for (const auto screenList{screens()}; QScreen * screen : screenList) { 0071 adoptScreen(screen); 0072 } 0073 0074 setStage(QStringLiteral("initial")); 0075 0076 if (KWindowSystem::isPlatformWayland()) { 0077 setStage(QStringLiteral("wm")); 0078 } 0079 0080 if (m_testing) { 0081 m_timer.start(TEST_STEP_INTERVAL, this); 0082 } 0083 0084 connect(this, &QGuiApplication::screenAdded, this, &SplashApp::adoptScreen); 0085 } 0086 0087 SplashApp::~SplashApp() 0088 { 0089 qDeleteAll(m_windows); 0090 } 0091 0092 void SplashApp::timerEvent(QTimerEvent *event) 0093 { 0094 if (event->timerId() == m_timer.timerId()) { 0095 m_timer.stop(); 0096 0097 setStage(m_stage + 1); 0098 0099 m_timer.start(TEST_STEP_INTERVAL, this); 0100 } 0101 } 0102 0103 void SplashApp::setStage(const QString &stage) 0104 { 0105 qCDebug(KSPLASHQML_DEBUG) << "Loading stage " << stage << ", current count " << m_stages.count(); 0106 0107 if (m_stages.contains(stage)) { 0108 return; 0109 } 0110 m_stages.append(stage); 0111 setStage(m_stages.count()); 0112 } 0113 0114 void SplashApp::setStage(int stage) 0115 { 0116 m_stage = stage; 0117 if (m_stage == 7) { 0118 QGuiApplication::exit(EXIT_SUCCESS); 0119 } 0120 for (SplashWindow *w : std::as_const(m_windows)) { 0121 w->setStage(stage); 0122 } 0123 } 0124 0125 void SplashApp::adoptScreen(QScreen *screen) 0126 { 0127 if (screen->geometry().isNull()) { 0128 return; 0129 } 0130 SplashWindow *w = new SplashWindow(m_testing, m_window, m_theme, screen); 0131 w->setGeometry(screen->geometry()); 0132 w->setStage(m_stage); 0133 w->setVisible(true); 0134 m_windows << w; 0135 0136 connect(screen, &QScreen::geometryChanged, w, &SplashWindow::setGeometry); 0137 connect(screen, &QObject::destroyed, w, [this, w]() { 0138 m_windows.removeAll(w); 0139 w->deleteLater(); 0140 }); 0141 } 0142 0143 void SplashApp::setupWaylandIntegration() 0144 { 0145 if (!KWindowSystem::isPlatformWayland()) { 0146 return; 0147 } 0148 LayerShellQt::Shell::useLayerShell(); 0149 }