File indexing completed on 2025-03-16 05:04:52
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #pragma once 0010 // KWin 0011 #include "effect/globals.h" 0012 #include <kwin_export.h> 0013 // Qt includes 0014 #include <QAction> 0015 #include <QObject> 0016 #include <QPoint> 0017 #include <QPointer> 0018 #include <QSize> 0019 0020 // KDE includes 0021 #include <KConfig> 0022 #include <KSharedConfig> 0023 0024 class KLocalizedString; 0025 class NETRootInfo; 0026 class QAction; 0027 0028 namespace KWin 0029 { 0030 0031 class Options; 0032 class PlasmaVirtualDesktopManagementInterface; 0033 0034 class KWIN_EXPORT VirtualDesktop : public QObject 0035 { 0036 Q_OBJECT 0037 Q_PROPERTY(QString id READ id CONSTANT) 0038 Q_PROPERTY(uint x11DesktopNumber READ x11DesktopNumber NOTIFY x11DesktopNumberChanged) 0039 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) 0040 public: 0041 explicit VirtualDesktop(QObject *parent = nullptr); 0042 ~VirtualDesktop() override; 0043 0044 void setId(const QString &id); 0045 QString id() const 0046 { 0047 return m_id; 0048 } 0049 0050 void setName(const QString &name); 0051 QString name() const 0052 { 0053 return m_name; 0054 } 0055 0056 void setX11DesktopNumber(uint number); 0057 uint x11DesktopNumber() const 0058 { 0059 return m_x11DesktopNumber; 0060 } 0061 0062 Q_SIGNALS: 0063 void nameChanged(); 0064 void x11DesktopNumberChanged(); 0065 /** 0066 * Emitted just before the desktop gets destroyed. 0067 */ 0068 void aboutToBeDestroyed(); 0069 0070 private: 0071 QString m_id; 0072 QString m_name; 0073 int m_x11DesktopNumber = 0; 0074 }; 0075 0076 /** 0077 * @brief Two dimensional grid containing the ID of the virtual desktop at a specific position 0078 * in the grid. 0079 * 0080 * The VirtualDesktopGrid represents a visual layout of the Virtual Desktops as they are in e.g. 0081 * a Pager. This grid is used for getting a desktop next to a given desktop in any direction by 0082 * making use of the layout information. This allows navigation like move to desktop on left. 0083 */ 0084 class VirtualDesktopGrid 0085 { 0086 public: 0087 VirtualDesktopGrid(); 0088 ~VirtualDesktopGrid(); 0089 void update(const QSize &size, const QList<VirtualDesktop *> &desktops); 0090 /** 0091 * @returns The coords of desktop @a id in grid units. 0092 */ 0093 QPoint gridCoords(uint id) const; 0094 /** 0095 * @returns The coords of desktop @a vd in grid units. 0096 */ 0097 QPoint gridCoords(VirtualDesktop *vd) const; 0098 /** 0099 * @returns The desktop at the point @a coords or 0 if no desktop exists at that 0100 * point. @a coords is to be in grid units. 0101 */ 0102 VirtualDesktop *at(const QPoint &coords) const; 0103 int width() const; 0104 int height() const; 0105 const QSize &size() const; 0106 0107 private: 0108 QSize m_size; 0109 QList<QList<VirtualDesktop *>> m_grid; 0110 }; 0111 0112 /** 0113 * @brief Manages the number of available virtual desktops, the layout of those and which virtual 0114 * desktop is the current one. 0115 * 0116 * This manager is responsible for Virtual Desktop handling inside KWin. It has a property for the 0117 * count of available virtual desktops and a property for the currently active virtual desktop. All 0118 * changes to the number of virtual desktops and the current virtual desktop need to go through this 0119 * manager. 0120 * 0121 * On all changes a signal is emitted and interested parties should connect to the signal. The manager 0122 * itself does not interact with other parts of the system. E.g. it does not hide/show windows of 0123 * desktop changes. This is outside the scope of this manager. 0124 * 0125 * Internally the manager organizes the virtual desktops in a grid allowing to navigate over the 0126 * virtual desktops. For this a set of convenient methods are available which allow to get the id 0127 * of an adjacent desktop or to switch to an adjacent desktop. Interested parties should make use of 0128 * these methods and not replicate the logic to switch to the next desktop. 0129 */ 0130 class KWIN_EXPORT VirtualDesktopManager : public QObject 0131 { 0132 Q_OBJECT 0133 /** 0134 * The number of virtual desktops currently available. 0135 * The ids of the virtual desktops are in the range [1, VirtualDesktopManager::maximum()]. 0136 */ 0137 Q_PROPERTY(uint count READ count WRITE setCount NOTIFY countChanged) 0138 /** 0139 * The id of the virtual desktop which is currently in use. 0140 */ 0141 Q_PROPERTY(uint current READ current WRITE setCurrent NOTIFY currentChanged) 0142 /** 0143 * Whether navigation in the desktop layout wraps around at the borders. 0144 */ 0145 Q_PROPERTY(bool navigationWrappingAround READ isNavigationWrappingAround WRITE setNavigationWrappingAround NOTIFY navigationWrappingAroundChanged) 0146 public: 0147 ~VirtualDesktopManager() override; 0148 /** 0149 * @internal, for X11 case 0150 */ 0151 void setRootInfo(NETRootInfo *info); 0152 /** 0153 * @internal, for Wayland case 0154 */ 0155 void setVirtualDesktopManagement(PlasmaVirtualDesktopManagementInterface *management); 0156 /** 0157 * @internal 0158 */ 0159 void setConfig(KSharedConfig::Ptr config); 0160 /** 0161 * @returns Total number of desktops currently in existence. 0162 * @see setCount 0163 * @see countChanged 0164 */ 0165 uint count() const; 0166 /** 0167 * @returns the number of rows the layout has. 0168 * @see setRows 0169 * @see rowsChanged 0170 */ 0171 uint rows() const; 0172 /** 0173 * @returns The ID of the current desktop. 0174 * @see setCurrent 0175 * @see currentChanged 0176 */ 0177 uint current() const; 0178 /** 0179 * @returns The current desktop 0180 * @see setCurrent 0181 * @see currentChanged 0182 */ 0183 VirtualDesktop *currentDesktop() const; 0184 /** 0185 * Moves to the desktop through the algorithm described by Direction. 0186 * @param wrap If @c true wraps around to the other side of the layout 0187 * @see setCurrent 0188 */ 0189 template<typename Direction> 0190 void moveTo(bool wrap = false); 0191 0192 /** 0193 * @returns @c true if navigation at borders of layout wraps around, @c false otherwise 0194 * @see setNavigationWrappingAround 0195 * @see navigationWrappingAroundChanged 0196 */ 0197 bool isNavigationWrappingAround() const; 0198 0199 /** 0200 * @returns The layout aware virtual desktop grid used by this manager. 0201 */ 0202 const VirtualDesktopGrid &grid() const; 0203 0204 enum class Direction { 0205 Up, 0206 Down, 0207 Right, 0208 Left, 0209 Next, 0210 Previous 0211 }; 0212 VirtualDesktop *inDirection(VirtualDesktop *desktop, Direction direction, bool wrap = true); 0213 uint inDirection(uint desktop, Direction direction, bool wrap = true); 0214 void moveTo(Direction direction, bool wrap = true); 0215 0216 /** 0217 * @returns The desktop above desktop @a desktop. Wraps around to the bottom of 0218 * the layout if @a wrap is set. If @a desktop is @c null use the current one. 0219 */ 0220 VirtualDesktop *above(VirtualDesktop *desktop, bool wrap = true) const; 0221 /** 0222 * @returns The desktop to the right of desktop @a desktop. Wraps around to the 0223 * left of the layout if @a wrap is set. If @a desktop is @c null use the current one. 0224 */ 0225 VirtualDesktop *toRight(VirtualDesktop *desktop, bool wrap = true) const; 0226 /** 0227 * @returns The desktop below desktop @a desktop. Wraps around to the top of the 0228 * layout if @a wrap is set. If @a desktop is @c null use the current one. 0229 */ 0230 VirtualDesktop *below(VirtualDesktop *desktop, bool wrap = true) const; 0231 /** 0232 * @returns The desktop to the left of desktop @a desktop. Wraps around to the 0233 * right of the layout if @a wrap is set. If @a desktop is @c null use the current one. 0234 */ 0235 VirtualDesktop *toLeft(VirtualDesktop *desktop, bool wrap = true) const; 0236 /** 0237 * @returns The desktop after the desktop @a desktop. Wraps around to the first 0238 * desktop if @a wrap is set. If @a desktop is @c null use the current desktop. 0239 */ 0240 VirtualDesktop *next(VirtualDesktop *desktop = nullptr, bool wrap = true) const; 0241 /** 0242 * @returns The desktop in front of the desktop @a desktop. Wraps around to the 0243 * last desktop if @a wrap is set. If @a desktop is @c null use the current desktop. 0244 */ 0245 VirtualDesktop *previous(VirtualDesktop *desktop = nullptr, bool wrap = true) const; 0246 0247 void initShortcuts(); 0248 0249 /** 0250 * @returns all currently managed VirtualDesktops 0251 */ 0252 QList<VirtualDesktop *> desktops() const 0253 { 0254 return m_desktops; 0255 } 0256 0257 /** 0258 * @returns The VirtualDesktop for the x11 @p id, if no such VirtualDesktop @c null is returned 0259 */ 0260 VirtualDesktop *desktopForX11Id(uint id) const; 0261 0262 /** 0263 * @returns The VirtualDesktop for the internal desktop string @p id, if no such VirtualDesktop @c null is returned 0264 */ 0265 VirtualDesktop *desktopForId(const QString &id) const; 0266 0267 /** 0268 * Create a new virtual desktop at the requested position. 0269 * The difference with setCount is that setCount always adds new desktops at the end of the chain. The Id is automatically generated. 0270 * @param position The position of the desktop. It should be in range [0, count]. 0271 * @param name The name for the new desktop, if empty the default name will be used. 0272 * @returns the new VirtualDesktop, nullptr if we reached the maximum number of desktops 0273 */ 0274 VirtualDesktop *createVirtualDesktop(uint position, const QString &name = QString()); 0275 0276 /** 0277 * Remove the virtual desktop identified by id, if it exists 0278 * difference with setCount is that is possible to remove an arbitrary desktop, 0279 * not only the last one. 0280 * @param id the string id of the desktop to remove 0281 */ 0282 void removeVirtualDesktop(const QString &id); 0283 void removeVirtualDesktop(VirtualDesktop *desktop); 0284 0285 /** 0286 * Updates the net root info for new number of desktops 0287 */ 0288 void updateRootInfo(); 0289 0290 /** 0291 * @returns The maximum number of desktops that KWin supports. 0292 */ 0293 static uint maximum(); 0294 0295 public Q_SLOTS: 0296 /** 0297 * Set the number of available desktops to @a count. This function overrides any previous 0298 * grid layout. 0299 * There needs to be at least one virtual desktop and the new value is capped at the maximum 0300 * number of desktops. A caller of this function cannot expect that the change has been applied. 0301 * It is the callers responsibility to either check the numberOfDesktops or connect to the 0302 * countChanged signal. 0303 * 0304 * In case the @ref current desktop is on a desktop higher than the new count, the current desktop 0305 * is changed to be the new desktop with highest id. In that situation the signal desktopRemoved 0306 * is emitted. 0307 * @param count The new number of desktops to use 0308 * @see count 0309 * @see maximum 0310 * @see countChanged 0311 * @see desktopCreated 0312 * @see desktopRemoved 0313 */ 0314 void setCount(uint count); 0315 /** 0316 * Set the current desktop to @a current. 0317 * @returns True on success, false otherwise. 0318 * @see current 0319 * @see currentChanged 0320 * @see moveTo 0321 */ 0322 bool setCurrent(uint current); 0323 /** 0324 * Set the current desktop to @a current. 0325 * @returns True on success, false otherwise. 0326 * @see current 0327 * @see currentChanged 0328 * @see moveTo 0329 */ 0330 bool setCurrent(VirtualDesktop *current); 0331 /** 0332 * Updates the layout to a new number of rows. The number of columns will be calculated accordingly 0333 */ 0334 void setRows(uint rows); 0335 /** 0336 * Called from within setCount() to ensure the desktop layout is still valid. 0337 */ 0338 void updateLayout(); 0339 /** 0340 * @param enabled wrapping around borders for navigation in desktop layout 0341 * @see isNavigationWrappingAround 0342 * @see navigationWrappingAroundChanged 0343 */ 0344 void setNavigationWrappingAround(bool enabled); 0345 /** 0346 * Loads number of desktops and names from configuration file 0347 */ 0348 void load(); 0349 /** 0350 * Saves number of desktops and names to configuration file 0351 */ 0352 void save(); 0353 0354 Q_SIGNALS: 0355 /** 0356 * Signal emitted whenever the number of virtual desktops changes. 0357 * @param previousCount The number of desktops prior to the change 0358 * @param newCount The new current number of desktops 0359 */ 0360 void countChanged(uint previousCount, uint newCount); 0361 0362 /** 0363 * Signal when the number of rows in the layout changes 0364 * @param rows number of rows 0365 */ 0366 void rowsChanged(uint rows); 0367 0368 /** 0369 * A new desktop has been created 0370 * @param desktop the new just crated desktop 0371 */ 0372 void desktopAdded(KWin::VirtualDesktop *desktop); 0373 0374 /** 0375 * A desktop has been removed and is about to be deleted 0376 * @param desktop the desktop that has been removed. 0377 * It's guaranteed to stil la valid pointer when the signal arrives, 0378 * but it's about to be deleted. 0379 */ 0380 void desktopRemoved(KWin::VirtualDesktop *desktop); 0381 0382 /** 0383 * Signal emitted whenever the current desktop changes. 0384 * @param previousDesktop The virtual desktop changed from 0385 * @param newDesktop The virtual desktop changed to 0386 */ 0387 void currentChanged(KWin::VirtualDesktop *previousDesktop, KWin::VirtualDesktop *newDesktop); 0388 0389 /** 0390 * Signal emmitted for realtime desktop switching animations. 0391 * @param currentDesktop The current virtual desktop 0392 * @param offset The current total change in desktop coordinate 0393 * Offset x and y are negative if switching Left and Down. 0394 * Example: x = 0.6 means 60% of the way to the desktop to the right. 0395 */ 0396 void currentChanging(KWin::VirtualDesktop *currentDesktop, QPointF offset); 0397 void currentChangingCancelled(); 0398 0399 /** 0400 * Signal emitted whenever the desktop layout changes. 0401 * @param columns The new number of columns in the layout 0402 * @param rows The new number of rows in the layout 0403 */ 0404 void layoutChanged(int columns, int rows); 0405 /** 0406 * Signal emitted whenever the navigationWrappingAround property changes. 0407 */ 0408 void navigationWrappingAroundChanged(); 0409 0410 private Q_SLOTS: 0411 /** 0412 * Common slot for all "Switch to Desktop n" shortcuts. 0413 * This method uses the sender() method to access some data. 0414 * DO NOT CALL DIRECTLY! ONLY TO BE USED FROM AN ACTION! 0415 */ 0416 void slotSwitchTo(); 0417 /** 0418 * Slot for switch to next desktop action. 0419 */ 0420 void slotNext(); 0421 /** 0422 * Slot for switch to previous desktop action. 0423 */ 0424 void slotPrevious(); 0425 /** 0426 * Slot for switch to right desktop action. 0427 */ 0428 void slotRight(); 0429 /** 0430 * Slot for switch to left desktop action. 0431 */ 0432 void slotLeft(); 0433 /** 0434 * Slot for switch to desktop above action. 0435 */ 0436 void slotUp(); 0437 /** 0438 * Slot for switch to desktop below action. 0439 */ 0440 void slotDown(); 0441 0442 /* For gestured desktopSwitching 0443 * Called when gesture ended, the thing that actually switches the desktop. 0444 */ 0445 void gestureReleasedY(); 0446 void gestureReleasedX(); 0447 0448 private: 0449 /** 0450 * @returns A default name for the given @p desktop 0451 */ 0452 QString defaultName(int desktop) const; 0453 /** 0454 * Creates all the global keyboard shortcuts for "Switch To Desktop n" actions. 0455 */ 0456 void initSwitchToShortcuts(); 0457 /** 0458 * Creates an action and connects it to the @p slot in this Manager. This method is 0459 * meant to be used for the case that an additional information needs to be stored in 0460 * the action and the label. 0461 * @param name The name of the action to be created 0462 * @param label The localized name for the action to be created 0463 * @param value An additional value added to the label and to the created action 0464 * @param key The global shortcut for the action 0465 * @param slot The slot to invoke when the action is triggered 0466 */ 0467 QAction *addAction(const QString &name, const KLocalizedString &label, uint value, const QKeySequence &key, void (VirtualDesktopManager::*slot)()); 0468 /** 0469 * Creates an action and connects it to the @p slot in this Manager. 0470 * Overloaded method for the case that no additional value needs to be passed to the action. 0471 * @param name The name of the action to be created 0472 * @param label The localized name for the action to be created 0473 * @param key The global shortcut for the action. If an empty QKeySequence is passed, no global shortcut is defined by default. 0474 * @param slot The slot to invoke when the action is triggered 0475 */ 0476 QAction *addAction(const QString &name, const QString &label, const QKeySequence &key, void (VirtualDesktopManager::*slot)()); 0477 0478 QList<VirtualDesktop *> m_desktops; 0479 QPointer<VirtualDesktop> m_current; 0480 quint32 m_rows = 2; 0481 bool m_navigationWrapsAround; 0482 VirtualDesktopGrid m_grid; 0483 // TODO: QPointer 0484 NETRootInfo *m_rootInfo; 0485 PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr; 0486 KSharedConfig::Ptr m_config; 0487 0488 std::unique_ptr<QAction> m_swipeGestureReleasedY; 0489 std::unique_ptr<QAction> m_swipeGestureReleasedX; 0490 QPointF m_currentDesktopOffset = QPointF(0, 0); 0491 0492 KWIN_SINGLETON_VARIABLE(VirtualDesktopManager, s_manager) 0493 }; 0494 0495 inline int VirtualDesktopGrid::width() const 0496 { 0497 return m_size.width(); 0498 } 0499 0500 inline int VirtualDesktopGrid::height() const 0501 { 0502 return m_size.height(); 0503 } 0504 0505 inline const QSize &VirtualDesktopGrid::size() const 0506 { 0507 return m_size; 0508 } 0509 0510 inline uint VirtualDesktopManager::maximum() 0511 { 0512 return 20; 0513 } 0514 0515 inline uint VirtualDesktopManager::count() const 0516 { 0517 return m_desktops.count(); 0518 } 0519 0520 inline bool VirtualDesktopManager::isNavigationWrappingAround() const 0521 { 0522 return m_navigationWrapsAround; 0523 } 0524 0525 inline void VirtualDesktopManager::setConfig(KSharedConfig::Ptr config) 0526 { 0527 m_config = std::move(config); 0528 } 0529 0530 inline const VirtualDesktopGrid &VirtualDesktopManager::grid() const 0531 { 0532 return m_grid; 0533 } 0534 0535 } // namespace KWin