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