1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
7     SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
8     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
9 
10     SPDX-License-Identifier: GPL-2.0-or-later
11 */
12 
13 #ifndef KWIN_WORKSPACE_H
14 #define KWIN_WORKSPACE_H
15 
16 // kwin
17 #include "options.h"
18 #include "sm.h"
19 #include "utils.h"
20 // Qt
21 #include <QTimer>
22 #include <QVector>
23 // std
24 #include <functional>
25 #include <memory>
26 
27 class KConfig;
28 class KConfigGroup;
29 class KStartupInfo;
30 class KStartupInfoData;
31 class KStartupInfoId;
32 class QStringList;
33 
34 namespace KWin
35 {
36 
37 namespace Xcb
38 {
39 class Tree;
40 class Window;
41 }
42 
43 class AbstractClient;
44 class AbstractOutput;
45 class ColorMapper;
46 class Compositor;
47 class Deleted;
48 class Group;
49 class InternalClient;
50 class KillWindow;
51 class ShortcutDialog;
52 class Toplevel;
53 class Unmanaged;
54 class UserActionsMenu;
55 class VirtualDesktop;
56 class X11Client;
57 class X11EventFilter;
58 enum class Predicate;
59 
60 class KWIN_EXPORT Workspace : public QObject
61 {
62     Q_OBJECT
63 public:
64     explicit Workspace();
65     ~Workspace() override;
66 
self()67     static Workspace* self() {
68         return _self;
69     }
70 
71     bool workspaceEvent(xcb_generic_event_t*);
72     bool workspaceEvent(QEvent*);
73 
74     bool hasClient(const AbstractClient*);
75 
76     /**
77      * @brief Finds the first Client matching the condition expressed by passed in @p func.
78      *
79      * Internally findClient uses the std::find_if algorithm and that determines how the function
80      * needs to be implemented. An example usage for finding a Client with a matching windowId
81      * @code
82      * xcb_window_t w; // our test window
83      * X11Client *client = findClient([w](const X11Client *c) -> bool {
84      *     return c->window() == w;
85      * });
86      * @endcode
87      *
88      * For the standard cases of matching the window id with one of the Client's windows use
89      * the simplified overload method findClient(Predicate, xcb_window_t). Above example
90      * can be simplified to:
91      * @code
92      * xcb_window_t w; // our test window
93      * X11Client *client = findClient(Predicate::WindowMatch, w);
94      * @endcode
95      *
96      * @param func Unary function that accepts a X11Client *as argument and
97      * returns a value convertible to bool. The value returned indicates whether the
98      * X11Client *is considered a match in the context of this function.
99      * The function shall not modify its argument.
100      * This can either be a function pointer or a function object.
101      * @return KWin::X11Client *The found Client or @c null
102      * @see findClient(Predicate, xcb_window_t)
103      */
104     X11Client *findClient(std::function<bool (const X11Client *)> func) const;
105     AbstractClient *findAbstractClient(std::function<bool (const AbstractClient*)> func) const;
106     AbstractClient *findAbstractClient(const QUuid &internalId) const;
107     /**
108      * @brief Finds the Client matching the given match @p predicate for the given window.
109      *
110      * @param predicate Which window should be compared
111      * @param w The window id to test against
112      * @return KWin::X11Client *The found Client or @c null
113      * @see findClient(std::function<bool (const X11Client *)>)
114      */
115     X11Client *findClient(Predicate predicate, xcb_window_t w) const;
116     void forEachClient(std::function<void (X11Client *)> func);
117     void forEachAbstractClient(std::function<void (AbstractClient*)> func);
118     Unmanaged *findUnmanaged(std::function<bool (const Unmanaged*)> func) const;
119     /**
120      * @brief Finds the Unmanaged with the given window id.
121      *
122      * @param w The window id to search for
123      * @return KWin::Unmanaged* Found Unmanaged or @c null if there is no Unmanaged with given Id.
124      */
125     Unmanaged *findUnmanaged(xcb_window_t w) const;
126     void forEachUnmanaged(std::function<void (Unmanaged*)> func);
127     Toplevel *findToplevel(std::function<bool (const Toplevel*)> func) const;
128     void forEachToplevel(std::function<void (Toplevel *)> func);
129 
130     Toplevel *findToplevel(const QUuid &internalId) const;
131 
132     /**
133      * @brief Finds a Toplevel for the internal window @p w.
134      *
135      * Internal window means a window created by KWin itself. On X11 this is an Unmanaged
136      * and mapped by the window id, on Wayland a XdgShellClient mapped on the internal window id.
137      *
138      * @returns Toplevel
139      */
140     Toplevel *findInternal(QWindow *w) const;
141 
142     QRect clientArea(clientAreaOption, const AbstractOutput *output, const VirtualDesktop *desktop) const;
143     QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const;
144     QRect clientArea(clientAreaOption, const Toplevel *window) const;
145     QRect clientArea(clientAreaOption, const Toplevel *window, const AbstractOutput *output) const;
146     QRect clientArea(clientAreaOption, const Toplevel *window, const QPoint &pos) const;
147     QRect clientArea(clientAreaOption, int screen, int desktop) const;
148 
149     /**
150      * Returns the geometry of this Workspace, i.e. the bounding rectangle of all outputs.
151      */
152     QRect geometry() const;
153     QRegion restrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas = StrutAreaAll) const;
154 
155     bool initializing() const;
156 
157     AbstractOutput *activeOutput() const;
158     void setActiveOutput(AbstractOutput *output);
159     void setActiveOutput(const QPoint &pos);
160 
161     /**
162      * Returns the active client, i.e. the client that has the focus (or None
163      * if no client has the focus)
164      */
165     AbstractClient* activeClient() const;
166     /**
167      * Client that was activated, but it's not yet really activeClient(), because
168      * we didn't process yet the matching FocusIn event. Used mostly in focus
169      * stealing prevention code.
170      */
171     AbstractClient* mostRecentlyActivatedClient() const;
172 
173     AbstractClient *clientUnderMouse(AbstractOutput *output) const;
174 
175     void activateClient(AbstractClient*, bool force = false);
176     bool requestFocus(AbstractClient* c, bool force = false);
177     enum ActivityFlag {
178         ActivityFocus = 1 << 0, // focus the window
179         ActivityFocusForce = 1 << 1 | ActivityFocus, // focus even if Dock etc.
180         ActivityRaise = 1 << 2 // raise the window
181     };
182     Q_DECLARE_FLAGS(ActivityFlags, ActivityFlag)
183     bool takeActivity(AbstractClient* c, ActivityFlags flags);
184     bool allowClientActivation(const AbstractClient* c, xcb_timestamp_t time = -1U, bool focus_in = false,
185                                bool ignore_desktop = false);
186     bool restoreFocus();
187     void gotFocusIn(const AbstractClient*);
188     void setShouldGetFocus(AbstractClient*);
189     bool activateNextClient(AbstractClient* c);
focusChangeEnabled()190     bool focusChangeEnabled() {
191         return block_focus == 0;
192     }
193 
194     /**
195      * Indicates that the client c is being moved or resized by the user.
196      */
197     void setMoveResizeClient(AbstractClient* c);
198 
199     QRect adjustClientArea(AbstractClient *client, const QRect &area) const;
200     QPoint adjustClientPosition(AbstractClient* c, QPoint pos, bool unrestricted, double snapAdjust = 1.0);
201     QRect adjustClientSize(AbstractClient* c, QRect moveResizeGeom, int mode);
202     void raiseClient(AbstractClient* c, bool nogroup = false);
203     void lowerClient(AbstractClient* c, bool nogroup = false);
204     void raiseClientRequest(AbstractClient* c, NET::RequestSource src = NET::FromApplication, xcb_timestamp_t timestamp = 0);
205     void lowerClientRequest(X11Client *c, NET::RequestSource src, xcb_timestamp_t timestamp);
206     void lowerClientRequest(AbstractClient* c);
207     void restackClientUnderActive(AbstractClient*);
208     void restack(AbstractClient *c, AbstractClient *under, bool force = false);
209     void raiseOrLowerClient(AbstractClient*);
210     void resetUpdateToolWindowsTimer();
211     void restoreSessionStackingOrder(X11Client *c);
212     void updateStackingOrder(bool propagate_new_clients = false);
213     void forceRestacking();
214 
215     void constrain(AbstractClient *below, AbstractClient *above);
216     void unconstrain(AbstractClient *below, AbstractClient *above);
217 
218     void clientHidden(AbstractClient*);
219     void clientAttentionChanged(AbstractClient* c, bool set);
220 
221     /**
222      * @return List of clients currently managed by Workspace
223      */
clientList()224     const QList<X11Client *> &clientList() const {
225         return m_x11Clients;
226     }
227     /**
228      * @return List of unmanaged "clients" currently registered in Workspace
229      */
unmanagedList()230     const QList<Unmanaged *> &unmanagedList() const {
231         return m_unmanaged;
232     }
233     /**
234      * @return List of deleted "clients" currently managed by Workspace
235      */
deletedList()236     const QList<Deleted *> &deletedList() const {
237         return deleted;
238     }
239     /**
240      * @returns List of all clients (either X11 or Wayland) currently managed by Workspace
241      */
allClientList()242     const QList<AbstractClient*> allClientList() const {
243         return m_allClients;
244     }
245 
246     /**
247      * @returns List of all internal clients currently managed by Workspace
248      */
internalClients()249     const QList<InternalClient *> &internalClients() const {
250         return m_internalClients;
251     }
252 
253     void stackScreenEdgesUnderOverrideRedirect();
254 
255     SessionManager *sessionManager() const;
256 
257 public:
258     QPoint cascadeOffset(const AbstractClient *c) const;
259 
260 private:
261     Compositor *m_compositor;
262     QTimer *m_quickTileCombineTimer;
263     QuickTileMode m_lastTilingMode;
264 
265     //-------------------------------------------------
266     // Unsorted
267 
268 public:
269     bool isOnCurrentHead();
270     // True when performing Workspace::updateClientArea().
271     // The calls below are valid only in that case.
272     bool inUpdateClientArea() const;
273     QRegion previousRestrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas = StrutAreaAll) const;
274     QVector< QRect > previousScreenSizes() const;
275     int oldDisplayWidth() const;
276     int oldDisplayHeight() const;
277 
278     /**
279      * Returns the list of clients sorted in stacking order, with topmost client
280      * at the last position
281      */
282     const QList<Toplevel *> &stackingOrder() const;
283     QList<Toplevel *> xStackingOrder() const;
284     QList<X11Client *> ensureStackingOrder(const QList<X11Client *> &clients) const;
285     QList<AbstractClient*> ensureStackingOrder(const QList<AbstractClient*> &clients) const;
286 
287     AbstractClient *topClientOnDesktop(VirtualDesktop *desktop, AbstractOutput *output = nullptr, bool unconstrained = false,
288                                        bool only_normal = true) const;
289     AbstractClient *findDesktop(bool topmost, VirtualDesktop *desktop) const;
290     void sendClientToDesktop(AbstractClient* c, int desktop, bool dont_activate);
291     void windowToPreviousDesktop(AbstractClient* c);
292     void windowToNextDesktop(AbstractClient* c);
293     void sendClientToOutput(AbstractClient *client, AbstractOutput *output);
294 
addManualOverlay(xcb_window_t id)295     void addManualOverlay(xcb_window_t id) {
296         manual_overlays << id;
297     }
removeManualOverlay(xcb_window_t id)298     void removeManualOverlay(xcb_window_t id) {
299         manual_overlays.removeOne(id);
300     }
301 
302     /**
303      * Shows the menu operations menu for the client and makes it active if
304      * it's not already.
305      */
306     void showWindowMenu(const QRect& pos, AbstractClient* cl);
userActionsMenu()307     const UserActionsMenu *userActionsMenu() const {
308         return m_userActionsMenu;
309     }
310 
311     void showApplicationMenu(const QRect &pos, AbstractClient *c, int actionId);
312 
313     void updateMinimizedOfTransients(AbstractClient*);
314     void updateOnAllDesktopsOfTransients(AbstractClient*);
315     void checkTransients(xcb_window_t w);
316 
317     void storeSession(const QString &sessionName, SMSavePhase phase);
318     void storeClient(KConfigGroup &cg, int num, X11Client *c);
319     void storeSubSession(const QString &name, QSet<QByteArray> sessionIds);
320     void loadSubSessionInfo(const QString &name);
321 
322     SessionInfo* takeSessionInfo(X11Client *);
323 
324     // D-Bus interface
325     QString supportInformation() const;
326 
327     AbstractOutput *nextOutput(AbstractOutput *reference) const;
328     AbstractOutput *previousOutput(AbstractOutput *reference) const;
329     void switchToOutput(AbstractOutput *output);
330 
331     void setShowingDesktop(bool showing);
332     bool showingDesktop() const;
333 
334     void removeX11Client(X11Client *);   // Only called from X11Client::destroyClient() or X11Client::releaseWindow()
335     void setActiveClient(AbstractClient*);
336     Group* findGroup(xcb_window_t leader) const;
337     void addGroup(Group* group);
338     void removeGroup(Group* group);
339     Group* findClientLeaderGroup(const X11Client *c) const;
340 
341     void removeUnmanaged(Unmanaged*);   // Only called from Unmanaged::release()
342     void removeDeleted(Deleted*);
343     void addDeleted(Deleted*, Toplevel*);
344 
345     bool checkStartupNotification(xcb_window_t w, KStartupInfoId& id, KStartupInfoData& data);
346 
347     void focusToNull(); // SELI TODO: Public?
348 
349     void clientShortcutUpdated(AbstractClient* c);
350     bool shortcutAvailable(const QKeySequence &cut, AbstractClient* ignore = nullptr) const;
351     bool globalShortcutsDisabled() const;
352     void disableGlobalShortcutsForClient(bool disable);
353 
354     void setWasUserInteraction();
355     bool wasUserInteraction() const;
356 
357     int packPositionLeft(const AbstractClient *client, int oldX, bool leftEdge) const;
358     int packPositionRight(const AbstractClient *client, int oldX, bool rightEdge) const;
359     int packPositionUp(const AbstractClient *client, int oldY, bool topEdge) const;
360     int packPositionDown(const AbstractClient *client, int oldY, bool bottomEdge) const;
361 
362     void cancelDelayFocus();
363     void requestDelayFocus(AbstractClient*);
364 
365     /**
366      * updates the mouse position to track whether a focus follow mouse focus change was caused by
367      * an actual mouse move
368      * is esp. called on enter/motion events of inactive windows
369      * since an active window doesn't receive mouse events, it must also be invoked if a (potentially)
370      * active window might be moved/resize away from the cursor (causing a leave event)
371      */
372     void updateFocusMousePosition(const QPoint& pos);
373     QPoint focusMousePosition() const;
374 
375     /**
376      * Returns a client that is currently being moved or resized by the user.
377      *
378      * If none of clients is being moved or resized, @c null will be returned.
379      */
moveResizeClient()380     AbstractClient* moveResizeClient() {
381         return movingClient;
382     }
383 
384     void markXStackingOrderAsDirty();
385 
386     void quickTileWindow(QuickTileMode mode);
387 
388     enum Direction {
389         DirectionNorth,
390         DirectionEast,
391         DirectionSouth,
392         DirectionWest
393     };
394     void switchWindow(Direction direction);
395 
shortcutDialog()396     ShortcutDialog *shortcutDialog() const {
397         return client_keys_dialog;
398     }
399 
400     /**
401      * Adds the internal client to Workspace.
402      *
403      * This method will be called by InternalClient when it's mapped.
404      *
405      * @see internalClientAdded
406      * @internal
407      */
408     void addInternalClient(InternalClient *client);
409 
410     /**
411      * Removes the internal client from Workspace.
412      *
413      * This method is meant to be called only by InternalClient.
414      *
415      * @see internalClientRemoved
416      * @internal
417      */
418     void removeInternalClient(InternalClient *client);
419 
420 public Q_SLOTS:
421     void performWindowOperation(KWin::AbstractClient* c, Options::WindowOperation op);
422     // Keybindings
423     //void slotSwitchToWindow( int );
424     void slotWindowToDesktop(VirtualDesktop *desktop);
425 
426     //void slotWindowToListPosition( int );
427     void slotSwitchToScreen();
428     void slotWindowToScreen();
429     void slotSwitchToNextScreen();
430     void slotWindowToNextScreen();
431     void slotSwitchToPrevScreen();
432     void slotWindowToPrevScreen();
433     void slotToggleShowDesktop();
434 
435     void slotWindowMaximize();
436     void slotWindowMaximizeVertical();
437     void slotWindowMaximizeHorizontal();
438     void slotWindowMinimize();
439     void slotWindowShade();
440     void slotWindowRaise();
441     void slotWindowLower();
442     void slotWindowRaiseOrLower();
443     void slotActivateAttentionWindow();
444     void slotWindowPackLeft();
445     void slotWindowPackRight();
446     void slotWindowPackUp();
447     void slotWindowPackDown();
448     void slotWindowGrowHorizontal();
449     void slotWindowGrowVertical();
450     void slotWindowShrinkHorizontal();
451     void slotWindowShrinkVertical();
452 
453     void slotIncreaseWindowOpacity();
454     void slotLowerWindowOpacity();
455 
456     void slotWindowOperations();
457     void slotWindowClose();
458     void slotWindowMove();
459     void slotWindowResize();
460     void slotWindowAbove();
461     void slotWindowBelow();
462     void slotWindowOnAllDesktops();
463     void slotWindowFullScreen();
464     void slotWindowNoBorder();
465 
466     void slotWindowToNextDesktop();
467     void slotWindowToPreviousDesktop();
468     void slotWindowToDesktopRight();
469     void slotWindowToDesktopLeft();
470     void slotWindowToDesktopUp();
471     void slotWindowToDesktopDown();
472 
473     void reconfigure();
474     void slotReconfigure();
475 
476     void slotKillWindow();
477 
478     void slotSetupWindowShortcut();
479     void setupWindowShortcutDone(bool);
480 
481     void updateClientArea();
482 
483 private Q_SLOTS:
484     void desktopResized();
485     void selectWmInputEventMask();
486     void slotUpdateToolWindows();
487     void delayFocus();
488     void slotReloadConfig();
489     void updateCurrentActivity(const QString &new_activity);
490     // virtual desktop handling
491     void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop);
492     void slotDesktopAdded(VirtualDesktop *desktop);
493     void slotDesktopRemoved(VirtualDesktop *desktop);
494     void slotOutputEnabled(AbstractOutput *output);
495     void slotOutputDisabled(AbstractOutput *output);
496 
497 Q_SIGNALS:
498     /**
499      * Emitted after the Workspace has setup the complete initialization process.
500      * This can be used to connect to for performing post-workspace initialization.
501      */
502     void workspaceInitialized();
503 
504     //Signals required for the scripting interface
505     void desktopPresenceChanged(KWin::AbstractClient*, int);
506     void currentDesktopChanged(int, KWin::AbstractClient*);
507     void clientAdded(KWin::AbstractClient *);
508     void clientRemoved(KWin::AbstractClient*);
509     void clientActivated(KWin::AbstractClient*);
510     void clientDemandsAttentionChanged(KWin::AbstractClient*, bool);
511     void clientMinimizedChanged(KWin::AbstractClient*);
512     void groupAdded(KWin::Group*);
513     void unmanagedAdded(KWin::Unmanaged*);
514     void unmanagedRemoved(KWin::Unmanaged*);
515     void deletedRemoved(KWin::Deleted*);
516     void configChanged();
517     void showingDesktopChanged(bool showing);
518     /**
519      * This signal is emitted when the stacking order changed, i.e. a window is risen
520      * or lowered
521      */
522     void stackingOrderChanged();
523 
524     /**
525      * This signal is emitted whenever an internal client is created.
526      */
527     void internalClientAdded(KWin::InternalClient *client);
528 
529     /**
530      * This signal is emitted whenever an internal client gets removed.
531      */
532     void internalClientRemoved(KWin::InternalClient *client);
533 
534 private:
535     void init();
536     void initializeX11();
537     void cleanupX11();
538     void initShortcuts();
539     template <typename Slot>
540     void initShortcut(const QString &actionName, const QString &description, const QKeySequence &shortcut,
541                       Slot slot, const QVariant &data = QVariant());
542     template <typename T, typename Slot>
543     void initShortcut(const QString &actionName, const QString &description, const QKeySequence &shortcut, T *receiver, Slot slot, const QVariant &data = QVariant());
544     void setupWindowShortcut(AbstractClient* c);
545     bool switchWindow(AbstractClient *c, Direction direction, QPoint curPos, VirtualDesktop *desktop);
546 
547     void propagateClients(bool propagate_new_clients);   // Called only from updateStackingOrder
548     QList<Toplevel *> constrainedStackingOrder();
549     void raiseClientWithinApplication(AbstractClient* c);
550     void lowerClientWithinApplication(AbstractClient* c);
551     bool allowFullClientRaising(const AbstractClient* c, xcb_timestamp_t timestamp);
552     void blockStackingUpdates(bool block);
553     void updateToolWindows(bool also_hide);
554     void fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_reply_t *geom);
555     void saveOldScreenSizes();
556     void addToStack(Toplevel *toplevel);
557     void replaceInStack(Toplevel *original, Deleted *deleted);
558     void removeFromStack(Toplevel *toplevel);
559 
560     /// This is the right way to create a new client
561     X11Client *createClient(xcb_window_t w, bool is_mapped);
562     void setupClientConnections(AbstractClient *client);
563     void addClient(X11Client *c);
564     Unmanaged* createUnmanaged(xcb_window_t w);
565     void addUnmanaged(Unmanaged* c);
566 
567     void addShellClient(AbstractClient *client);
568     void removeShellClient(AbstractClient *client);
569 
570     //---------------------------------------------------------------------
571 
572     void closeActivePopup();
573     void updateClientVisibilityOnDesktopChange(VirtualDesktop *newDesktop);
574     void activateClientOnNewDesktop(VirtualDesktop *desktop);
575     AbstractClient *findClientToActivateOnDesktop(VirtualDesktop *desktop);
576     void removeAbstractClient(AbstractClient *client);
577 
578     struct Constraint
579     {
580         Toplevel *below;
581         Toplevel *above;
582         // All constraints above our "below" window
583         QList<Constraint *> parents;
584         // All constraints below our "above" window
585         QList<Constraint *> children;
586         // Used to prevent cycles.
587         bool enqueued = false;
588     };
589 
590     QList<Constraint *> m_constraints;
591     QWidget* active_popup;
592     AbstractClient* active_popup_client;
593 
594     int m_initialDesktop;
595     void loadSessionInfo(const QString &sessionName);
596     void addSessionInfo(KConfigGroup &cg);
597 
598     QList<SessionInfo*> session;
599 
600     void updateXStackingOrder();
601     void updateTabbox();
602 
603     AbstractOutput *m_activeOutput = nullptr;
604     AbstractClient* active_client;
605     AbstractClient* last_active_client;
606     AbstractClient* movingClient;
607 
608     // Delay(ed) window focus timer and client
609     QTimer* delayFocusTimer;
610     AbstractClient* delayfocus_client;
611     QPoint focusMousePos;
612 
613     QList<X11Client *> m_x11Clients;
614     QList<AbstractClient*> m_allClients;
615     QList<Unmanaged *> m_unmanaged;
616     QList<Deleted *> deleted;
617     QList<InternalClient *> m_internalClients;
618 
619     QList<Toplevel *> unconstrained_stacking_order; // Topmost last
620     QList<Toplevel *> stacking_order; // Topmost last
621     QVector<xcb_window_t> manual_overlays; //Topmost last
622     bool force_restacking;
623     QList<Toplevel *> x_stacking; // From XQueryTree()
624     std::unique_ptr<Xcb::Tree> m_xStackingQueryTree;
625     bool m_xStackingDirty = false;
626     QList<AbstractClient*> should_get_focus; // Last is most recent
627     QList<AbstractClient*> attention_chain;
628 
629     bool showing_desktop;
630 
631     QList<Group *> groups;
632 
633     bool was_user_interaction;
634     QScopedPointer<X11EventFilter> m_wasUserInteractionFilter;
635 
636     int session_active_client;
637     int session_desktop;
638 
639     int block_focus;
640 
641     /**
642      * Holds the menu containing the user actions which is shown
643      * on e.g. right click the window decoration.
644      */
645     UserActionsMenu *m_userActionsMenu;
646 
647     void modalActionsSwitch(bool enabled);
648 
649     ShortcutDialog* client_keys_dialog;
650     AbstractClient* client_keys_client;
651     bool global_shortcuts_disabled_for_client;
652 
653     // Timer to collect requests for 'reconfigure'
654     QTimer reconfigureTimer;
655 
656     QTimer updateToolWindowsTimer;
657 
658     static Workspace* _self;
659 
660     bool workspaceInit;
661 
662     QScopedPointer<KStartupInfo> m_startup;
663     QScopedPointer<ColorMapper> m_colorMapper;
664 
665     QHash<const VirtualDesktop *, QRect> m_workAreas;
666     QHash<const VirtualDesktop *, StrutRects> m_restrictedAreas;
667     QHash<const VirtualDesktop *, QHash<const AbstractOutput *, QRect>> m_screenAreas;
668     QRect m_geometry;
669 
670     QVector< QRect > oldscreensizes; // array of previous sizes of xinerama screens
671     QSize olddisplaysize; // previous sizes od displayWidth()/displayHeight()
672     QHash<const VirtualDesktop *, StrutRects> m_oldRestrictedAreas;
673 
674     int set_active_client_recursion;
675     int block_stacking_updates; // When > 0, stacking updates are temporarily disabled
676     bool blocked_propagating_new_clients; // Propagate also new clients after enabling stacking updates?
677     QScopedPointer<Xcb::Window> m_nullFocus;
678     friend class StackingUpdatesBlocker;
679 
680     QScopedPointer<KillWindow> m_windowKiller;
681     QScopedPointer<X11EventFilter> m_movingClientFilter;
682     QScopedPointer<X11EventFilter> m_syncAlarmFilter;
683 
684     SessionManager *m_sessionManager;
685 private:
686     friend bool performTransiencyCheck();
687     friend Workspace *workspace();
688 };
689 
690 /**
691  * Helper for Workspace::blockStackingUpdates() being called in pairs (True/false)
692  */
693 class StackingUpdatesBlocker
694 {
695 public:
StackingUpdatesBlocker(Workspace * w)696     explicit StackingUpdatesBlocker(Workspace* w)
697         : ws(w) {
698         ws->blockStackingUpdates(true);
699     }
~StackingUpdatesBlocker()700     ~StackingUpdatesBlocker() {
701         ws->blockStackingUpdates(false);
702     }
703 
704 private:
705     Workspace* ws;
706 };
707 
708 class ColorMapper : public QObject
709 {
710     Q_OBJECT
711 public:
712     ColorMapper(QObject *parent);
713     ~ColorMapper() override;
714 public Q_SLOTS:
715     void update();
716 private:
717     xcb_colormap_t m_default;
718     xcb_colormap_t m_installed;
719 };
720 
721 //---------------------------------------------------------
722 // Unsorted
723 
initializing()724 inline bool Workspace::initializing() const
725 {
726     return workspaceInit;
727 }
728 
activeClient()729 inline AbstractClient *Workspace::activeClient() const
730 {
731     return active_client;
732 }
733 
mostRecentlyActivatedClient()734 inline AbstractClient *Workspace::mostRecentlyActivatedClient() const
735 {
736     return should_get_focus.count() > 0 ? should_get_focus.last() : active_client;
737 }
738 
addGroup(Group * group)739 inline void Workspace::addGroup(Group* group)
740 {
741     Q_EMIT groupAdded(group);
742     groups.append(group);
743 }
744 
removeGroup(Group * group)745 inline void Workspace::removeGroup(Group* group)
746 {
747     groups.removeAll(group);
748 }
749 
stackingOrder()750 inline const QList<Toplevel *> &Workspace::stackingOrder() const
751 {
752     // TODO: Q_ASSERT( block_stacking_updates == 0 );
753     return stacking_order;
754 }
755 
wasUserInteraction()756 inline bool Workspace::wasUserInteraction() const
757 {
758     return was_user_interaction;
759 }
760 
sessionManager()761 inline SessionManager *Workspace::sessionManager() const
762 {
763     return m_sessionManager;
764 }
765 
showingDesktop()766 inline bool Workspace::showingDesktop() const
767 {
768     return showing_desktop;
769 }
770 
globalShortcutsDisabled()771 inline bool Workspace::globalShortcutsDisabled() const
772 {
773     return global_shortcuts_disabled_for_client;
774 }
775 
forceRestacking()776 inline void Workspace::forceRestacking()
777 {
778     force_restacking = true;
779     StackingUpdatesBlocker blocker(this);   // Do restacking if not blocked
780 }
781 
updateFocusMousePosition(const QPoint & pos)782 inline void Workspace::updateFocusMousePosition(const QPoint& pos)
783 {
784     focusMousePos = pos;
785 }
786 
focusMousePosition()787 inline QPoint Workspace::focusMousePosition() const
788 {
789     return focusMousePos;
790 }
791 
792 inline
forEachClient(std::function<void (X11Client *)> func)793 void Workspace::forEachClient(std::function< void (X11Client *) > func)
794 {
795     std::for_each(m_x11Clients.constBegin(), m_x11Clients.constEnd(), func);
796 }
797 
798 inline
forEachUnmanaged(std::function<void (Unmanaged *)> func)799 void Workspace::forEachUnmanaged(std::function< void (Unmanaged*) > func)
800 {
801     std::for_each(m_unmanaged.constBegin(), m_unmanaged.constEnd(), func);
802 }
803 
workspace()804 inline Workspace *workspace()
805 {
806     return Workspace::_self;
807 }
808 
809 } // namespace
810 Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::Workspace::ActivityFlags)
811 
812 #endif
813