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