File indexing completed on 2024-04-28 16:55:02
0001 /* 0002 SPDX-FileCopyrightText: 2008 Aaron Seigo <aseigo@kde.org> 0003 SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org> 0004 SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic@kde.org> 0005 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #pragma once 0011 0012 #include "config-X11.h" 0013 #include "plasma/corona.h" 0014 0015 #include <QDBusContext> 0016 #include <QDBusVariant> 0017 #include <QPointer> 0018 #include <QSet> 0019 #include <QTimer> 0020 0021 #include <KConfigWatcher> 0022 #include <KPackage/Package> 0023 0024 class DesktopView; 0025 class PanelView; 0026 class QMenu; 0027 class QScreen; 0028 class ScreenPool; 0029 class StrutManager; 0030 class ShellContainmentConfig; 0031 0032 namespace KActivities 0033 { 0034 class Controller; 0035 } // namespace KActivities 0036 0037 namespace KDeclarative 0038 { 0039 class QmlObjectSharedEngine; 0040 } // namespace KDeclarative 0041 0042 namespace KScreen 0043 { 0044 class Output; 0045 } // namespace KScreen 0046 0047 namespace Plasma 0048 { 0049 class Applet; 0050 } // namespace Plasma 0051 0052 namespace KWayland 0053 { 0054 namespace Client 0055 { 0056 class PlasmaShell; 0057 class PlasmaShellSurface; 0058 class PlasmaWindow; 0059 class PlasmaWindowManagement; 0060 } 0061 } 0062 0063 class ShellCorona : public Plasma::Corona, QDBusContext 0064 { 0065 Q_OBJECT 0066 Q_PROPERTY(QString shell READ shell WRITE setShell) 0067 Q_PROPERTY(int numScreens READ numScreens) 0068 Q_CLASSINFO("D-Bus Interface", "org.kde.PlasmaShell") 0069 0070 public: 0071 explicit ShellCorona(QObject *parent = nullptr); 0072 ~ShellCorona() override; 0073 0074 KPackage::Package lookAndFeelPackage(); 0075 void init(); 0076 0077 /** 0078 * Where to save global configuration that doesn't have anything to do with the scene (e.g. views) 0079 */ 0080 KSharedConfig::Ptr applicationConfig(); 0081 0082 int numScreens() const override; 0083 Q_INVOKABLE QRect screenGeometry(int id) const override; 0084 Q_INVOKABLE QRegion availableScreenRegion(int id) const override; 0085 Q_INVOKABLE QRect availableScreenRect(int id) const override; 0086 0087 // plasmashellCorona's value 0088 QRegion _availableScreenRegion(int id) const; 0089 QRect _availableScreenRect(int id) const; 0090 0091 Q_INVOKABLE QStringList availableActivities() const; 0092 0093 PanelView *panelView(Plasma::Containment *containment) const; 0094 void savePreviousWindow(); 0095 void restorePreviousWindow(); 0096 void clearPreviousWindow(); 0097 0098 // This one is a bit of an hack but are just for desktop scripting 0099 void insertActivity(const QString &id, const QString &plugin); 0100 0101 Plasma::Containment *setContainmentTypeForScreen(int screen, const QString &plugin); 0102 0103 void removeDesktop(DesktopView *desktopView); 0104 0105 /** 0106 * @returns a new containment associated with the specified @p activity and @p screen. 0107 */ 0108 Plasma::Containment *createContainmentForActivity(const QString &activity, int screenNum); 0109 0110 KWayland::Client::PlasmaShell *waylandPlasmaShellInterface() const; 0111 0112 ScreenPool *screenPool() const; 0113 0114 QList<int> screenIds() const; 0115 0116 QString defaultContainmentPlugin() const; 0117 0118 static QString defaultShell(); 0119 0120 // Set all Desktop containments (for all activities) associated to a given screen to this new screen. 0121 // swapping ones that had newScreen to oldScreen if existing. Panels are ignored 0122 void swapDesktopScreens(int oldScreen, int newScreen); 0123 0124 // Set a single containment to a new screen. 0125 // If it is a Desktop contaiment, swap it with the other containment that was associated with same screen and activity if existent 0126 void setScreenForContainment(Plasma::Containment *containment, int screen); 0127 0128 // Grab a screenshot of the contaiment if it has a view in an async fashion 0129 // containmentPreviewReady will be emitted when done 0130 // If there is no view, this will have no effect 0131 void grabContainmentPreview(Plasma::Containment *containment); 0132 0133 // If a containment preview has been grabbed, for this containment, return its path 0134 QString containmentPreviewPath(Plasma::Containment *containment) const; 0135 0136 /** 0137 * Whether "accent color from wallpaper" option is enabled in global settings 0138 */ 0139 bool accentColorFromWallpaperEnabled() const; 0140 0141 Q_SIGNALS: 0142 void glInitializationFailed(); 0143 // A preview for this containment has been rendered and saved to disk 0144 void containmentPreviewReady(Plasma::Containment *containment, const QString &path); 0145 void accentColorFromWallpaperEnabledChanged(); 0146 void colorChanged(const QColor &color); 0147 // This API is used only by autotests, do we need something else? 0148 void screenOrderChanged(QList<QScreen *> screens); 0149 0150 public Q_SLOTS: 0151 /** 0152 * Request saving applicationConfig on disk, it's event compressed, not immediate 0153 */ 0154 void requestApplicationConfigSync(); 0155 0156 /** 0157 * Cycle through all panels 0158 */ 0159 void slotCyclePanelFocus(); 0160 0161 /** 0162 * Sets the shell that the corona should display 0163 */ 0164 void setShell(const QString &shell); 0165 0166 /** 0167 * Gets the currently shown shell 0168 */ 0169 QString shell() const; 0170 0171 /// DBUS methods 0172 void toggleDashboard(); 0173 void setDashboardShown(bool show); 0174 void toggleActivityManager(); 0175 void toggleWidgetExplorer(); 0176 QString evaluateScript(const QString &string); 0177 void activateLauncherMenu(); 0178 QRgb color() const; 0179 0180 QByteArray dumpCurrentLayoutJS() const; 0181 0182 /** 0183 * loads the shell layout from a look and feel package, 0184 * resetting it to the default layout exported in the 0185 * look and feel package 0186 */ 0187 void loadLookAndFeelDefaultLayout(const QString &layout); 0188 0189 Plasma::Containment *addPanel(const QString &plugin); 0190 0191 void nextActivity(); 0192 void previousActivity(); 0193 void stopCurrentActivity(); 0194 0195 void setTestModeLayout(const QString &layout) 0196 { 0197 m_testModeLayout = layout; 0198 } 0199 0200 int panelCount() const 0201 { 0202 return m_panelViews.count(); 0203 } 0204 0205 void refreshCurrentShell(); 0206 0207 protected Q_SLOTS: 0208 /** 0209 * Loads the layout and performs the needed checks 0210 */ 0211 void load(); 0212 0213 /** 0214 * Unloads everything 0215 */ 0216 void unload(); 0217 0218 /** 0219 * Loads the default (system wide) layout for this user 0220 **/ 0221 void loadDefaultLayout() override; 0222 0223 /** 0224 * Execute any update script 0225 */ 0226 void processUpdateScripts(); 0227 0228 int screenForContainment(const Plasma::Containment *containment) const override; 0229 0230 void showAlternativesForApplet(Plasma::Applet *applet); 0231 0232 private Q_SLOTS: 0233 void createWaitingPanels(); 0234 void handleContainmentAdded(Plasma::Containment *c); 0235 void syncAppConfig(); 0236 void checkActivities(); 0237 void currentActivityChanged(const QString &newActivity); 0238 void activityAdded(const QString &id); 0239 void activityRemoved(const QString &id); 0240 void checkAddPanelAction(); 0241 void addPanel(); 0242 void addPanel(QAction *action); 0243 void populateAddPanelsMenu(); 0244 0245 void addOutput(QScreen *screen); 0246 0247 void panelContainmentDestroyed(QObject *cont); 0248 void handleScreenRemoved(QScreen *screen); 0249 void handleScreenOrderChanged(QList<QScreen *> screens); 0250 0251 void activateTaskManagerEntry(int index); 0252 0253 private: 0254 void sanitizeScreenLayout(const QString &configFileName); 0255 void updateStruts(); 0256 void configurationChanged(const QString &path); 0257 DesktopView *desktopForScreen(QScreen *screen) const; 0258 void setupWaylandIntegration(); 0259 void executeSetupPlasmoidScript(Plasma::Containment *containment, Plasma::Applet *applet); 0260 void checkAllDesktopsUiReady(bool ready); 0261 void activateLauncherMenu(const QString &screenName); 0262 void handleColorRequestedFromDBus(const QDBusMessage &msg); 0263 0264 #ifndef NDEBUG 0265 void screenInvariants() const; 0266 #endif 0267 0268 KSharedConfig::Ptr m_config; 0269 QString m_configPath; 0270 0271 // Accent color setting 0272 KConfigWatcher::Ptr m_accentColorConfigWatcher; 0273 bool m_accentColorFromWallpaperEnabled = false; 0274 QMetaObject::Connection m_fakeColorRequestConn; 0275 0276 ScreenPool *m_screenPool; 0277 QString m_shell; 0278 KActivities::Controller *m_activityController; 0279 QMap<const Plasma::Containment *, PanelView *> m_panelViews; 0280 // map from QScreen to desktop view 0281 QHash<int, DesktopView *> m_desktopViewForScreen; 0282 QHash<const Plasma::Containment *, int> m_pendingScreenChanges; 0283 KConfigGroup m_desktopDefaultsConfig; 0284 KConfigGroup m_lnfDefaultsConfig; 0285 QList<Plasma::Containment *> m_waitingPanels; 0286 QHash<QString, QString> m_activityContainmentPlugins; 0287 QAction *m_addPanelAction; 0288 std::unique_ptr<QMenu> m_addPanelsMenu; 0289 KPackage::Package m_lookAndFeelPackage; 0290 0291 // Used to restore the previous activated window after the panel loses focus 0292 KWayland::Client::PlasmaShellSurface *m_shellSurface = nullptr; 0293 #if HAVE_X11 0294 WId m_previousWId = 0; 0295 #endif 0296 bool m_blockRestorePreviousWindow = false; 0297 0298 QTimer m_waitingPanelsTimer; 0299 QTimer m_appConfigSyncTimer; 0300 #ifndef NDEBUG 0301 QTimer m_invariantsTimer; 0302 #endif 0303 KWayland::Client::PlasmaShell *m_waylandPlasmaShell; 0304 // For getting the active window on Wayland 0305 KWayland::Client::PlasmaWindowManagement *m_waylandWindowManagement = nullptr; 0306 QPointer<KWayland::Client::PlasmaWindow> m_previousPlasmaWindow; 0307 bool m_closingDown : 1; 0308 bool m_screenReorderInProgress = false; 0309 QString m_testModeLayout; 0310 0311 StrutManager *m_strutManager; 0312 QPointer<ShellContainmentConfig> m_shellContainmentConfig; 0313 friend class ShellTest; 0314 };