File indexing completed on 2024-04-28 05:30:39

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
0006     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
0007     SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
0008     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0009     SPDX-FileCopyrightText: 2022 Natalie Clarius <natalie_clarius@yahoo.de>
0010 
0011     SPDX-License-Identifier: GPL-2.0-or-later
0012 */
0013 
0014 #pragma once
0015 
0016 // kwin
0017 #include "options.h"
0018 #include "sm.h"
0019 #include "utils/common.h"
0020 // Qt
0021 #include <QList>
0022 #include <QStringList>
0023 #include <QTimer>
0024 // std
0025 #include <functional>
0026 #include <memory>
0027 
0028 class KConfig;
0029 class KConfigGroup;
0030 class KStartupInfo;
0031 class KStartupInfoData;
0032 class KStartupInfoId;
0033 
0034 namespace KWin
0035 {
0036 
0037 namespace Decoration
0038 {
0039 class DecorationBridge;
0040 }
0041 
0042 namespace Xcb
0043 {
0044 class Tree;
0045 class Window;
0046 }
0047 
0048 namespace TabBox
0049 {
0050 class TabBox;
0051 }
0052 
0053 class Window;
0054 class Output;
0055 class Compositor;
0056 class Group;
0057 class InternalWindow;
0058 class KillWindow;
0059 class ShortcutDialog;
0060 class UserActionsMenu;
0061 class VirtualDesktop;
0062 class X11Window;
0063 class X11EventFilter;
0064 class FocusChain;
0065 class ApplicationMenu;
0066 class PlacementTracker;
0067 enum class Predicate;
0068 class Outline;
0069 class RuleBook;
0070 class ScreenEdges;
0071 #if KWIN_BUILD_ACTIVITIES
0072 class Activities;
0073 #endif
0074 class PlaceholderInputEventFilter;
0075 class PlaceholderOutput;
0076 class Placement;
0077 class OutputConfiguration;
0078 class TileManager;
0079 class OutputConfigurationStore;
0080 class LidSwitchTracker;
0081 class DpmsInputEventFilter;
0082 class OrientationSensor;
0083 
0084 class KWIN_EXPORT Workspace : public QObject
0085 {
0086     Q_OBJECT
0087 public:
0088     explicit Workspace();
0089     ~Workspace() override;
0090 
0091     static Workspace *self()
0092     {
0093         return _self;
0094     }
0095 
0096     bool workspaceEvent(xcb_generic_event_t *);
0097 
0098     bool hasWindow(const Window *);
0099 
0100     /**
0101      * @brief Finds the first Client matching the condition expressed by passed in @p func.
0102      *
0103      * Internally findClient uses the std::find_if algorithm and that determines how the function
0104      * needs to be implemented. An example usage for finding a Client with a matching windowId
0105      * @code
0106      * xcb_window_t w; // our test window
0107      * X11Window *client = findClient([w](const X11Window *c) -> bool {
0108      *     return c->window() == w;
0109      * });
0110      * @endcode
0111      *
0112      * For the standard cases of matching the window id with one of the Client's windows use
0113      * the simplified overload method findClient(Predicate, xcb_window_t). Above example
0114      * can be simplified to:
0115      * @code
0116      * xcb_window_t w; // our test window
0117      * X11Window *client = findClient(Predicate::WindowMatch, w);
0118      * @endcode
0119      *
0120      * @param func Unary function that accepts a X11Window *as argument and
0121      * returns a value convertible to bool. The value returned indicates whether the
0122      * X11Window *is considered a match in the context of this function.
0123      * The function shall not modify its argument.
0124      * This can either be a function pointer or a function object.
0125      * @return KWin::X11Window *The found Client or @c null
0126      * @see findClient(Predicate, xcb_window_t)
0127      */
0128     X11Window *findClient(std::function<bool(const X11Window *)> func) const;
0129     /**
0130      * @brief Finds the Client matching the given match @p predicate for the given window.
0131      *
0132      * @param predicate Which window should be compared
0133      * @param w The window id to test against
0134      * @return KWin::X11Window *The found Client or @c null
0135      * @see findClient(std::function<bool (const X11Window *)>)
0136      */
0137     X11Window *findClient(Predicate predicate, xcb_window_t w) const;
0138     void forEachClient(std::function<void(X11Window *)> func);
0139     X11Window *findUnmanaged(std::function<bool(const X11Window *)> func) const;
0140     /**
0141      * @brief Finds the Unmanaged with the given window id.
0142      *
0143      * @param w The window id to search for
0144      * @return KWin::Unmanaged* Found Unmanaged or @c null if there is no Unmanaged with given Id.
0145      */
0146     X11Window *findUnmanaged(xcb_window_t w) const;
0147 
0148     Window *findWindow(const QUuid &internalId) const;
0149     Window *findWindow(std::function<bool(const Window *)> func) const;
0150     void forEachWindow(std::function<void(Window *)> func);
0151 
0152     /**
0153      * @brief Finds a Window for the internal window @p w.
0154      *
0155      * Internal window means a window created by KWin itself. On X11 this is an Unmanaged
0156      * and mapped by the window id, on Wayland a XdgShellClient mapped on the internal window id.
0157      *
0158      * @returns Window
0159      */
0160     Window *findInternal(QWindow *w) const;
0161 
0162     QRectF clientArea(clientAreaOption, const Output *output, const VirtualDesktop *desktop) const;
0163     QRectF clientArea(clientAreaOption, const Window *window) const;
0164     QRectF clientArea(clientAreaOption, const Window *window, const Output *output) const;
0165     QRectF clientArea(clientAreaOption, const Window *window, const QPointF &pos) const;
0166 
0167     /**
0168      * Returns the geometry of this Workspace, i.e. the bounding rectangle of all outputs.
0169      */
0170     QRect geometry() const;
0171     StrutRects restrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas = StrutAreaAll) const;
0172 
0173     bool initializing() const;
0174 
0175     Output *xineramaIndexToOutput(int index) const;
0176 
0177     void setOutputOrder(const QList<Output *> &order);
0178     QList<Output *> outputOrder() const;
0179 
0180     Output *activeOutput() const;
0181     void setActiveOutput(Output *output);
0182     void setActiveOutput(const QPointF &pos);
0183     void setActiveCursorOutput(Output *output);
0184     void setActiveCursorOutput(const QPointF &pos);
0185 
0186     /**
0187      * Returns the active window, i.e. the window that has the focus (or None
0188      * if no window has the focus)
0189      */
0190     Window *activeWindow() const;
0191     /**
0192      * Window that was activated, but it's not yet really activeWindow(), because
0193      * we didn't process yet the matching FocusIn event. Used mostly in focus
0194      * stealing prevention code.
0195      */
0196     Window *mostRecentlyActivatedWindow() const;
0197 
0198     Window *windowUnderMouse(Output *output) const;
0199 
0200     void activateWindow(Window *window, bool force = false);
0201     bool requestFocus(Window *window, bool force = false);
0202     enum ActivityFlag {
0203         ActivityFocus = 1 << 0, // focus the window
0204         ActivityFocusForce = 1 << 1 | ActivityFocus, // focus even if Dock etc.
0205         ActivityRaise = 1 << 2 // raise the window
0206     };
0207     Q_DECLARE_FLAGS(ActivityFlags, ActivityFlag)
0208     bool takeActivity(Window *window, ActivityFlags flags);
0209     bool restoreFocus();
0210     void gotFocusIn(const Window *window);
0211     void setShouldGetFocus(Window *window);
0212     bool activateNextWindow(Window *window);
0213     bool focusChangeEnabled()
0214     {
0215         return block_focus == 0;
0216     }
0217 
0218     /**
0219      * Indicates that the given @a window is being moved or resized by the user.
0220      */
0221     void setMoveResizeWindow(Window *window);
0222 
0223     QRectF adjustClientArea(Window *window, const QRectF &area) const;
0224     QPointF adjustWindowPosition(Window *window, QPointF pos, bool unrestricted, double snapAdjust = 1.0);
0225     QRectF adjustWindowSize(Window *window, QRectF moveResizeGeom, Gravity gravity);
0226     void raiseWindow(Window *window, bool nogroup = false);
0227     void lowerWindow(Window *window, bool nogroup = false);
0228     void raiseWindowRequest(Window *window, NET::RequestSource src = NET::FromApplication, xcb_timestamp_t timestamp = 0);
0229     void lowerWindowRequest(X11Window *window, NET::RequestSource src, xcb_timestamp_t timestamp);
0230     void lowerWindowRequest(Window *window);
0231     void restackWindowUnderActive(Window *window);
0232     void restack(Window *window, Window *under, bool force = false);
0233     void raiseOrLowerWindow(Window *window);
0234     void resetUpdateToolWindowsTimer();
0235     void restoreSessionStackingOrder(X11Window *window);
0236     void updateStackingOrder(bool propagate_new_windows = false);
0237     void forceRestacking();
0238 
0239     void constrain(Window *below, Window *above);
0240     void unconstrain(Window *below, Window *above);
0241 
0242     void windowHidden(Window *);
0243     void windowAttentionChanged(Window *, bool set);
0244 
0245     /**
0246      * @returns List of all windows (either X11 or Wayland) currently managed by Workspace
0247      */
0248     const QList<Window *> windows() const
0249     {
0250         return m_windows;
0251     }
0252 
0253     void stackScreenEdgesUnderOverrideRedirect();
0254 
0255     SessionManager *sessionManager() const;
0256 
0257     /**
0258      * @returns the TileManager associated to a given output
0259      */
0260     TileManager *tileManager(Output *output);
0261 
0262 public:
0263     QPoint cascadeOffset(const Window *c) const;
0264 
0265 private:
0266     QTimer *m_quickTileCombineTimer;
0267     QuickTileMode m_lastTilingMode;
0268 
0269     //-------------------------------------------------
0270     // Unsorted
0271 
0272 public:
0273     // True when performing Workspace::updateClientArea().
0274     // The calls below are valid only in that case.
0275     bool inUpdateClientArea() const;
0276     StrutRects previousRestrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas = StrutAreaAll) const;
0277     QHash<const Output *, QRect> previousScreenSizes() const;
0278 
0279     /**
0280      * Returns the list of windows sorted in stacking order, with topmost window
0281      * at the last position
0282      */
0283     const QList<Window *> &stackingOrder() const;
0284     QList<Window *> unconstrainedStackingOrder() const;
0285     QList<X11Window *> ensureStackingOrder(const QList<X11Window *> &windows) const;
0286     QList<Window *> ensureStackingOrder(const QList<Window *> &windows) const;
0287 
0288     Window *topWindowOnDesktop(VirtualDesktop *desktop, Output *output = nullptr, bool unconstrained = false,
0289                                bool only_normal = true) const;
0290     Window *findDesktop(bool topmost, VirtualDesktop *desktop) const;
0291     void sendWindowToDesktops(Window *window, const QList<VirtualDesktop *> &desktops, bool dont_activate);
0292     void windowToPreviousDesktop(Window *window);
0293     void windowToNextDesktop(Window *window);
0294     void sendWindowToOutput(Window *window, Output *output);
0295 
0296     void addManualOverlay(xcb_window_t id)
0297     {
0298         manual_overlays << id;
0299     }
0300     void removeManualOverlay(xcb_window_t id)
0301     {
0302         manual_overlays.removeOne(id);
0303     }
0304 
0305     /**
0306      * Shows the menu operations menu for the window and makes it active if
0307      * it's not already.
0308      */
0309     void showWindowMenu(const QRect &pos, Window *cl);
0310     UserActionsMenu *userActionsMenu() const
0311     {
0312         return m_userActionsMenu;
0313     }
0314 
0315     void showApplicationMenu(const QRect &pos, Window *window, int actionId);
0316 
0317     void updateMinimizedOfTransients(Window *);
0318     void updateOnAllDesktopsOfTransients(Window *);
0319     void checkTransients(xcb_window_t w);
0320 
0321     SessionInfo *takeSessionInfo(X11Window *);
0322 
0323     // D-Bus interface
0324     QString supportInformation() const;
0325 
0326     enum Direction {
0327         DirectionNorth,
0328         DirectionEast,
0329         DirectionSouth,
0330         DirectionWest,
0331         DirectionPrev,
0332         DirectionNext
0333     };
0334     Output *findOutput(Output *reference, Direction direction, bool wrapAround = false) const;
0335     void switchToOutput(Output *output);
0336 
0337     QList<Output *> outputs() const;
0338     Output *outputAt(const QPointF &pos) const;
0339 
0340     /**
0341      * Set "Show Desktop" status
0342      *
0343      * @param showing @c true to show the desktop, @c false to restore the window positions
0344      * @param animated @c true if the "Show Desktop Animation" should be played, otherwise @c false
0345      */
0346     void setShowingDesktop(bool showing, bool animated = true);
0347     bool showingDesktop() const;
0348 
0349     void removeX11Window(X11Window *); // Only called from X11Window::destroyWindow() or X11Window::releaseWindow()
0350     void setActiveWindow(Window *window);
0351     Group *findGroup(xcb_window_t leader) const;
0352     void addGroup(Group *group);
0353     void removeGroup(Group *group);
0354     Group *findClientLeaderGroup(const X11Window *c) const;
0355     int unconstainedStackingOrderIndex(const X11Window *c) const;
0356 
0357     void removeUnmanaged(X11Window *);
0358     void removeDeleted(Window *);
0359     void addDeleted(Window *);
0360 
0361     bool checkStartupNotification(xcb_window_t w, KStartupInfoId &id, KStartupInfoData &data);
0362 
0363     void focusToNull(); // SELI TODO: Public?
0364 
0365     void windowShortcutUpdated(Window *window);
0366     bool shortcutAvailable(const QKeySequence &cut, Window *ignore = nullptr) const;
0367     bool globalShortcutsDisabled() const;
0368     void disableGlobalShortcutsForClient(bool disable);
0369 
0370     void setWasUserInteraction();
0371     bool wasUserInteraction() const;
0372 
0373     qreal packPositionLeft(const Window *window, qreal oldX, bool leftEdge) const;
0374     qreal packPositionRight(const Window *window, qreal oldX, bool rightEdge) const;
0375     qreal packPositionUp(const Window *window, qreal oldY, bool topEdge) const;
0376     qreal packPositionDown(const Window *window, qreal oldY, bool bottomEdge) const;
0377 
0378     void cancelDelayFocus();
0379     void requestDelayFocus(Window *);
0380 
0381     /**
0382      * updates the mouse position to track whether a focus follow mouse focus change was caused by
0383      * an actual mouse move
0384      * is esp. called on enter/motion events of inactive windows
0385      * since an active window doesn't receive mouse events, it must also be invoked if a (potentially)
0386      * active window might be moved/resize away from the cursor (causing a leave event)
0387      */
0388     void updateFocusMousePosition(const QPointF &pos);
0389     QPointF focusMousePosition() const;
0390 
0391     /**
0392      * Returns a window that is currently being moved or resized by the user.
0393      *
0394      * If none of windows is being moved or resized, @c null will be returned.
0395      */
0396     Window *moveResizeWindow()
0397     {
0398         return m_moveResizeWindow;
0399     }
0400 
0401     void quickTileWindow(QuickTileMode mode);
0402     void switchWindow(Direction direction);
0403 
0404     ShortcutDialog *shortcutDialog() const
0405     {
0406         return m_windowKeysDialog;
0407     }
0408 
0409     void addInternalWindow(InternalWindow *window);
0410     void removeInternalWindow(InternalWindow *window);
0411 
0412     /**
0413      * @internal
0414      * Used by session management
0415      */
0416     void setInitialDesktop(int desktop);
0417 
0418     bool inShouldGetFocus(Window *w) const
0419     {
0420         return should_get_focus.contains(w);
0421     }
0422     Window *lastActiveWindow() const
0423     {
0424         return m_lastActiveWindow;
0425     }
0426     FocusChain *focusChain() const;
0427     ApplicationMenu *applicationMenu() const;
0428     Decoration::DecorationBridge *decorationBridge() const;
0429     Outline *outline() const;
0430     Placement *placement() const;
0431     RuleBook *rulebook() const;
0432     ScreenEdges *screenEdges() const;
0433 #if KWIN_BUILD_TABBOX
0434     TabBox::TabBox *tabbox() const;
0435 #endif
0436 #if KWIN_BUILD_ACTIVITIES
0437     Activities *activities() const;
0438 #endif
0439 
0440     /**
0441      * Apply the requested output configuration. Note that you must use this function
0442      * instead of Platform::applyOutputChanges().
0443      */
0444     bool applyOutputConfiguration(const OutputConfiguration &config, const QList<Output *> &outputOrder = {});
0445 
0446 public Q_SLOTS:
0447     void performWindowOperation(KWin::Window *window, Options::WindowOperation op);
0448     // Keybindings
0449     // void slotSwitchToWindow( int );
0450     void slotWindowToDesktop(VirtualDesktop *desktop);
0451 
0452     // void slotWindowToListPosition( int );
0453     void slotSwitchToScreen(Output *output);
0454     void slotWindowToScreen(Output *output);
0455     void slotSwitchToLeftScreen();
0456     void slotSwitchToRightScreen();
0457     void slotSwitchToAboveScreen();
0458     void slotSwitchToBelowScreen();
0459     void slotSwitchToPrevScreen();
0460     void slotSwitchToNextScreen();
0461     void slotWindowToLeftScreen();
0462     void slotWindowToRightScreen();
0463     void slotWindowToAboveScreen();
0464     void slotWindowToBelowScreen();
0465     void slotWindowToNextScreen();
0466     void slotWindowToPrevScreen();
0467 
0468     void slotToggleShowDesktop();
0469 
0470     void slotWindowMaximize();
0471     void slotWindowMaximizeVertical();
0472     void slotWindowMaximizeHorizontal();
0473     void slotWindowMinimize();
0474     void slotWindowShade();
0475     void slotWindowRaise();
0476     void slotWindowLower();
0477     void slotWindowRaiseOrLower();
0478     void slotActivateAttentionWindow();
0479 
0480     void slotWindowCenter();
0481 
0482     void slotWindowMoveLeft();
0483     void slotWindowMoveRight();
0484     void slotWindowMoveUp();
0485     void slotWindowMoveDown();
0486     void slotWindowExpandHorizontal();
0487     void slotWindowExpandVertical();
0488     void slotWindowShrinkHorizontal();
0489     void slotWindowShrinkVertical();
0490 
0491     void slotIncreaseWindowOpacity();
0492     void slotLowerWindowOpacity();
0493 
0494     void slotWindowOperations();
0495     void slotWindowClose();
0496     void slotWindowMove();
0497     void slotWindowResize();
0498     void slotWindowAbove();
0499     void slotWindowBelow();
0500     void slotWindowOnAllDesktops();
0501     void slotWindowFullScreen();
0502     void slotWindowNoBorder();
0503 
0504     void slotWindowToNextDesktop();
0505     void slotWindowToPreviousDesktop();
0506     void slotWindowToDesktopRight();
0507     void slotWindowToDesktopLeft();
0508     void slotWindowToDesktopUp();
0509     void slotWindowToDesktopDown();
0510 
0511     void reconfigure();
0512     void slotReconfigure();
0513 
0514     void slotKillWindow();
0515 
0516     void slotSetupWindowShortcut();
0517     void setupWindowShortcutDone(bool);
0518 
0519     void updateClientArea();
0520 
0521 private Q_SLOTS:
0522     void desktopResized();
0523     void selectWmInputEventMask();
0524     void slotUpdateToolWindows();
0525     void delayFocus();
0526     void slotReloadConfig();
0527     void updateCurrentActivity(const QString &new_activity);
0528     // virtual desktop handling
0529     void slotCurrentDesktopChanged(VirtualDesktop *previousDesktop, VirtualDesktop *newDesktop);
0530     void slotCurrentDesktopChanging(VirtualDesktop *currentDesktop, QPointF delta);
0531     void slotCurrentDesktopChangingCancelled();
0532     void slotDesktopAdded(VirtualDesktop *desktop);
0533     void slotDesktopRemoved(VirtualDesktop *desktop);
0534     void slotOutputBackendOutputsQueried();
0535 
0536 Q_SIGNALS:
0537     /**
0538      * Emitted after the Workspace has setup the complete initialization process.
0539      * This can be used to connect to for performing post-workspace initialization.
0540      */
0541     void workspaceInitialized();
0542     void geometryChanged();
0543 
0544     // Signals required for the scripting interface
0545     void currentActivityChanged();
0546     void currentDesktopChanged(KWin::VirtualDesktop *previousDesktop, KWin::Window *);
0547     void currentDesktopChanging(KWin::VirtualDesktop *currentDesktop, QPointF delta, KWin::Window *); // for realtime animations
0548     void currentDesktopChangingCancelled();
0549     void windowAdded(KWin::Window *);
0550     void windowRemoved(KWin::Window *);
0551     void windowActivated(KWin::Window *);
0552     void windowMinimizedChanged(KWin::Window *);
0553     void groupAdded(KWin::Group *);
0554     void deletedRemoved(KWin::Window *);
0555     void configChanged();
0556     void showingDesktopChanged(bool showing, bool animated);
0557     void outputOrderChanged();
0558     void outputAdded(KWin::Output *);
0559     void outputRemoved(KWin::Output *);
0560     void outputsChanged();
0561     /**
0562      * This signal is emitted when the stacking order changed, i.e. a window is risen
0563      * or lowered
0564      */
0565     void stackingOrderChanged();
0566 
0567 private:
0568     void init();
0569     void initializeX11();
0570     void cleanupX11();
0571     void initShortcuts();
0572     template<typename Slot>
0573     void initShortcut(const QString &actionName, const QString &description, const QKeySequence &shortcut, Slot slot);
0574     template<typename T, typename Slot>
0575     void initShortcut(const QString &actionName, const QString &description, const QKeySequence &shortcut, T *receiver, Slot slot);
0576     void setupWindowShortcut(Window *window);
0577     bool switchWindow(Window *window, Direction direction, QPoint curPos, VirtualDesktop *desktop);
0578 
0579     void propagateWindows(bool propagate_new_windows); // Called only from updateStackingOrder
0580     QList<Window *> constrainedStackingOrder();
0581     void raiseWindowWithinApplication(Window *window);
0582     void lowerWindowWithinApplication(Window *window);
0583     bool allowFullClientRaising(const Window *window, xcb_timestamp_t timestamp);
0584     void blockStackingUpdates(bool block);
0585     void updateToolWindows(bool also_hide);
0586     void fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_reply_t *geom);
0587     void saveOldScreenSizes();
0588     void addToStack(Window *window);
0589     void removeFromStack(Window *window);
0590 
0591     /// This is the right way to create a new X11 window
0592     X11Window *createX11Window(xcb_window_t windowId, bool is_mapped);
0593     void addX11Window(X11Window *c);
0594     void setupWindowConnections(Window *window);
0595     X11Window *createUnmanaged(xcb_window_t windowId);
0596     void addUnmanaged(X11Window *c);
0597 
0598     void addWaylandWindow(Window *window);
0599     void removeWaylandWindow(Window *window);
0600 
0601     //---------------------------------------------------------------------
0602 
0603     void closeActivePopup();
0604     void updateWindowVisibilityOnDesktopChange(VirtualDesktop *newDesktop);
0605     void activateWindowOnNewDesktop(VirtualDesktop *desktop);
0606     Window *findWindowToActivateOnDesktop(VirtualDesktop *desktop);
0607     void removeWindow(Window *window);
0608     QString getPlacementTrackerHash();
0609 
0610     void updateOutputConfiguration();
0611     void updateOutputs(const QList<Output *> &outputOrder = {});
0612     void createDpmsFilter();
0613     void maybeDestroyDpmsFilter();
0614 
0615     bool breaksShowingDesktop(Window *window) const;
0616 
0617     struct Constraint
0618     {
0619         Window *below;
0620         Window *above;
0621         // All constraints above our "below" window
0622         QList<Constraint *> parents;
0623         // All constraints below our "above" window
0624         QList<Constraint *> children;
0625         // Used to prevent cycles.
0626         bool enqueued = false;
0627     };
0628 
0629     QList<Constraint *> m_constraints;
0630     QWidget *active_popup;
0631     Window *m_activePopupWindow;
0632 
0633     int m_initialDesktop;
0634     void updateXStackingOrder();
0635     void updateTabbox();
0636 
0637     QList<Output *> m_outputs;
0638     Output *m_activeOutput = nullptr;
0639     Output *m_activeCursorOutput = nullptr;
0640     QList<Output *> m_outputOrder;
0641 
0642     Window *m_activeWindow;
0643     Window *m_lastActiveWindow;
0644     Window *m_moveResizeWindow;
0645 
0646     // Delay(ed) window focus timer and window
0647     QTimer *delayFocusTimer;
0648     Window *m_delayFocusWindow;
0649     QPointF focusMousePos;
0650 
0651     QList<Window *> m_windows;
0652     QList<Window *> deleted;
0653 
0654     QList<Window *> unconstrained_stacking_order; // Topmost last
0655     QList<Window *> stacking_order; // Topmost last
0656     QList<xcb_window_t> manual_overlays; // Topmost last
0657     bool force_restacking;
0658     QList<Window *> should_get_focus; // Last is most recent
0659     QList<Window *> attention_chain;
0660 
0661     bool showing_desktop;
0662 
0663     QList<Group *> groups;
0664 
0665     bool was_user_interaction;
0666     std::unique_ptr<X11EventFilter> m_wasUserInteractionFilter;
0667 
0668     int block_focus;
0669 
0670     /**
0671      * Holds the menu containing the user actions which is shown
0672      * on e.g. right click the window decoration.
0673      */
0674     UserActionsMenu *m_userActionsMenu;
0675 
0676     void modalActionsSwitch(bool enabled);
0677 
0678     ShortcutDialog *m_windowKeysDialog = nullptr;
0679     Window *m_windowKeysWindow = nullptr;
0680     bool m_globalShortcutsDisabledForWindow = false;
0681 
0682     // Timer to collect requests for 'reconfigure'
0683     QTimer reconfigureTimer;
0684 
0685     QTimer updateToolWindowsTimer;
0686 
0687     static Workspace *_self;
0688 
0689     std::unique_ptr<KStartupInfo> m_startup;
0690 
0691     QHash<const VirtualDesktop *, QRectF> m_workAreas;
0692     QHash<const VirtualDesktop *, StrutRects> m_restrictedAreas;
0693     QHash<const VirtualDesktop *, QHash<const Output *, QRectF>> m_screenAreas;
0694     QRect m_geometry;
0695 
0696     QHash<const Output *, QRect> m_oldScreenGeometries;
0697     QHash<const VirtualDesktop *, StrutRects> m_oldRestrictedAreas;
0698     bool m_inUpdateClientArea = false;
0699 
0700     int m_setActiveWindowRecursion = 0;
0701     int m_blockStackingUpdates = 0; // When > 0, stacking updates are temporarily disabled
0702     bool m_blockedPropagatingNewWindows; // Propagate also new windows after enabling stacking updates?
0703     std::unique_ptr<Xcb::Window> m_nullFocus;
0704     friend class StackingUpdatesBlocker;
0705 
0706     std::unique_ptr<KillWindow> m_windowKiller;
0707     std::unique_ptr<X11EventFilter> m_movingClientFilter;
0708     std::unique_ptr<X11EventFilter> m_syncAlarmFilter;
0709 
0710     SessionManager *m_sessionManager;
0711     std::unique_ptr<FocusChain> m_focusChain;
0712     std::unique_ptr<ApplicationMenu> m_applicationMenu;
0713     std::unique_ptr<Decoration::DecorationBridge> m_decorationBridge;
0714     std::unique_ptr<Outline> m_outline;
0715     std::unique_ptr<Placement> m_placement;
0716     std::unique_ptr<RuleBook> m_rulebook;
0717     std::unique_ptr<ScreenEdges> m_screenEdges;
0718 #if KWIN_BUILD_TABBOX
0719     std::unique_ptr<TabBox::TabBox> m_tabbox;
0720 #endif
0721 #if KWIN_BUILD_ACTIVITIES
0722     std::unique_ptr<Activities> m_activities;
0723 #endif
0724     std::unique_ptr<PlacementTracker> m_placementTracker;
0725 
0726     PlaceholderOutput *m_placeholderOutput = nullptr;
0727     std::unique_ptr<PlaceholderInputEventFilter> m_placeholderFilter;
0728     std::map<Output *, std::unique_ptr<TileManager>> m_tileManagers;
0729     std::unique_ptr<OutputConfigurationStore> m_outputConfigStore;
0730     std::unique_ptr<LidSwitchTracker> m_lidSwitchTracker;
0731     std::unique_ptr<OrientationSensor> m_orientationSensor;
0732     std::unique_ptr<DpmsInputEventFilter> m_dpmsFilter;
0733 
0734 private:
0735     friend bool performTransiencyCheck();
0736     friend Workspace *workspace();
0737 };
0738 
0739 /**
0740  * Helper for Workspace::blockStackingUpdates() being called in pairs (True/false)
0741  */
0742 class StackingUpdatesBlocker
0743 {
0744 public:
0745     explicit StackingUpdatesBlocker(Workspace *w)
0746         : ws(w)
0747     {
0748         ws->blockStackingUpdates(true);
0749     }
0750     ~StackingUpdatesBlocker()
0751     {
0752         ws->blockStackingUpdates(false);
0753     }
0754 
0755 private:
0756     Workspace *ws;
0757 };
0758 
0759 //---------------------------------------------------------
0760 // Unsorted
0761 
0762 inline QList<Output *> Workspace::outputs() const
0763 {
0764     return m_outputs;
0765 }
0766 
0767 inline Window *Workspace::activeWindow() const
0768 {
0769     return m_activeWindow;
0770 }
0771 
0772 inline Window *Workspace::mostRecentlyActivatedWindow() const
0773 {
0774     return should_get_focus.count() > 0 ? should_get_focus.last() : m_activeWindow;
0775 }
0776 
0777 inline void Workspace::addGroup(Group *group)
0778 {
0779     Q_EMIT groupAdded(group);
0780     groups.append(group);
0781 }
0782 
0783 inline void Workspace::removeGroup(Group *group)
0784 {
0785     groups.removeAll(group);
0786 }
0787 
0788 inline const QList<Window *> &Workspace::stackingOrder() const
0789 {
0790     // TODO: Q_ASSERT( block_stacking_updates == 0 );
0791     return stacking_order;
0792 }
0793 
0794 inline bool Workspace::wasUserInteraction() const
0795 {
0796     return was_user_interaction;
0797 }
0798 
0799 inline SessionManager *Workspace::sessionManager() const
0800 {
0801     return m_sessionManager;
0802 }
0803 
0804 inline bool Workspace::showingDesktop() const
0805 {
0806     return showing_desktop;
0807 }
0808 
0809 inline bool Workspace::globalShortcutsDisabled() const
0810 {
0811     return m_globalShortcutsDisabledForWindow;
0812 }
0813 
0814 inline void Workspace::forceRestacking()
0815 {
0816     force_restacking = true;
0817     StackingUpdatesBlocker blocker(this); // Do restacking if not blocked
0818 }
0819 
0820 inline void Workspace::updateFocusMousePosition(const QPointF &pos)
0821 {
0822     focusMousePos = pos;
0823 }
0824 
0825 inline QPointF Workspace::focusMousePosition() const
0826 {
0827     return focusMousePos;
0828 }
0829 
0830 inline Workspace *workspace()
0831 {
0832     return Workspace::_self;
0833 }
0834 
0835 } // namespace
0836 Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::Workspace::ActivityFlags)