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 Martin Gräßlin <mgraesslin@kde.org>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #ifndef KWIN_TABBOX_H
13 #define KWIN_TABBOX_H
14
15 #include <QKeySequence>
16 #include <QTimer>
17 #include <QModelIndex>
18 #include "utils.h"
19 #include "tabbox/tabboxhandler.h"
20
21 class KConfigGroup;
22 class QAction;
23 class QMouseEvent;
24 class QKeyEvent;
25 class QWheelEvent;
26
27 namespace KWin
28 {
29
30 class Workspace;
31 class AbstractClient;
32 class X11EventFilter;
33 namespace TabBox
34 {
35 class DesktopChainManager;
36 class TabBoxConfig;
37 class TabBox;
38 class TabBoxHandlerImpl : public TabBoxHandler
39 {
40 public:
41 explicit TabBoxHandlerImpl(TabBox* tabBox);
42 ~TabBoxHandlerImpl() override;
43
44 int activeScreen() const override;
45 QWeakPointer< TabBoxClient > activeClient() const override;
46 int currentDesktop() const override;
47 QString desktopName(TabBoxClient* client) const override;
48 QString desktopName(int desktop) const override;
49 bool isKWinCompositing() const override;
50 QWeakPointer< TabBoxClient > nextClientFocusChain(TabBoxClient* client) const override;
51 QWeakPointer< TabBoxClient > firstClientFocusChain() const override;
52 bool isInFocusChain (TabBoxClient* client) const override;
53 int nextDesktopFocusChain(int desktop) const override;
54 int numberOfDesktops() const override;
55 TabBoxClientList stackingOrder() const override;
56 void elevateClient(TabBoxClient* c, QWindow *tabbox, bool elevate) const override;
57 void raiseClient(TabBoxClient *client) const override;
58 void restack(TabBoxClient *c, TabBoxClient *under) override;
59 void shadeClient(TabBoxClient *c, bool b) const override;
60 QWeakPointer< TabBoxClient > clientToAddToList(KWin::TabBox::TabBoxClient* client, int desktop) const override;
61 QWeakPointer< TabBoxClient > desktopClient() const override;
62 void activateAndClose() override;
63 void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) override;
64 bool noModifierGrab() const override;
65
66 private:
67 bool checkDesktop(TabBoxClient* client, int desktop) const;
68 bool checkActivity(TabBoxClient* client) const;
69 bool checkApplications(TabBoxClient* client) const;
70 bool checkMinimized(TabBoxClient* client) const;
71 bool checkMultiScreen(TabBoxClient* client) const;
72
73 TabBox* m_tabBox;
74 DesktopChainManager* m_desktopFocusChain;
75 };
76
77 class TabBoxClientImpl : public TabBoxClient
78 {
79 public:
80 explicit TabBoxClientImpl(AbstractClient *client);
81 ~TabBoxClientImpl() override;
82
83 QString caption() const override;
84 QIcon icon() const override;
85 bool isMinimized() const override;
86 int x() const override;
87 int y() const override;
88 int width() const override;
89 int height() const override;
90 bool isCloseable() const override;
91 void close() override;
92 bool isFirstInTabBox() const override;
93 QUuid internalId() const override;
94
client()95 AbstractClient* client() const {
96 return m_client;
97 }
98
99 private:
100 AbstractClient* m_client;
101 };
102
103 class KWIN_EXPORT TabBox : public QObject
104 {
105 Q_OBJECT
106 public:
107 ~TabBox() override;
108
109 /**
110 * Returns the currently displayed client ( only works in TabBoxWindowsMode ).
111 * Returns 0 if no client is displayed.
112 */
113 AbstractClient *currentClient();
114
115 /**
116 * Returns the list of clients potentially displayed ( only works in
117 * TabBoxWindowsMode ).
118 * Returns an empty list if no clients are available.
119 */
120 QList<AbstractClient*> currentClientList();
121
122 /**
123 * Returns the currently displayed virtual desktop ( only works in
124 * TabBoxDesktopListMode )
125 * Returns -1 if no desktop is displayed.
126 */
127 int currentDesktop();
128
129 /**
130 * Returns the list of desktops potentially displayed ( only works in
131 * TabBoxDesktopListMode )
132 * Returns an empty list if no are available.
133 */
134 QList< int > currentDesktopList();
135
136 /**
137 * Change the currently selected client, and notify the effects.
138 *
139 * @see setCurrentDesktop
140 */
141 void setCurrentClient(AbstractClient *newClient);
142
143 /**
144 * Change the currently selected desktop, and notify the effects.
145 *
146 * @see setCurrentClient
147 */
148 void setCurrentDesktop(int newDesktop);
149
150 /**
151 * Sets the current mode to \a mode, either TabBoxDesktopListMode or TabBoxWindowsMode
152 *
153 * @see mode
154 */
155 void setMode(TabBoxMode mode);
mode()156 TabBoxMode mode() const {
157 return m_tabBoxMode;
158 }
159
160 /**
161 * Resets the tab box to display the active client in TabBoxWindowsMode, or the
162 * current desktop in TabBoxDesktopListMode
163 */
164 void reset(bool partial_reset = false);
165
166 /**
167 * Shows the next or previous item, depending on \a next
168 */
169 void nextPrev(bool next = true);
170
171 /**
172 * Shows the tab box after some delay.
173 *
174 * If the 'ShowDelay' setting is false, show() is simply called.
175 *
176 * Otherwise, we start a timer for the delay given in the settings and only
177 * do a show() when it times out.
178 *
179 * This means that you can alt-tab between windows and you don't see the
180 * tab box immediately. Not only does this make alt-tabbing faster, it gives
181 * less 'flicker' to the eyes. You don't need to see the tab box if you're
182 * just quickly switching between 2 or 3 windows. It seems to work quite
183 * nicely.
184 */
185 void delayedShow();
186
187 /**
188 * Notify effects that the tab box is being hidden.
189 */
190 void hide(bool abort = false);
191
192 /**
193 * Increases the reference count, preventing the default tabbox from showing.
194 *
195 * @see unreference
196 * @see isDisplayed
197 */
reference()198 void reference() {
199 ++m_displayRefcount;
200 }
201
202 /**
203 * Decreases the reference count. Only when the reference count is 0 will
204 * the default tab box be shown.
205 */
unreference()206 void unreference() {
207 --m_displayRefcount;
208 }
209
210 /**
211 * Returns whether the tab box is being displayed, either natively or by an
212 * effect.
213 *
214 * @see reference
215 * @see unreference
216 */
isDisplayed()217 bool isDisplayed() const {
218 return m_displayRefcount > 0;
219 }
220
221 /**
222 * @returns @c true if TabBox is shown, @c false if replaced by Effect
223 */
isShown()224 bool isShown() const {
225 return m_isShown;
226 }
227
228 bool handleMouseEvent(QMouseEvent *event);
229 bool handleWheelEvent(QWheelEvent *event);
230 void grabbedKeyEvent(QKeyEvent* event);
231
isGrabbed()232 bool isGrabbed() const {
233 return m_tabGrab || m_desktopGrab;
234 }
235
236 void initShortcuts();
237
238 AbstractClient* nextClientStatic(AbstractClient*) const;
239 AbstractClient* previousClientStatic(AbstractClient*) const;
240 int nextDesktopStatic(int iDesktop) const;
241 int previousDesktopStatic(int iDesktop) const;
242 void keyPress(int key);
243 void modifiersReleased();
244
forcedGlobalMouseGrab()245 bool forcedGlobalMouseGrab() const {
246 return m_forcedGlobalMouseGrab;
247 }
248
noModifierGrab()249 bool noModifierGrab() const {
250 return m_noModifierGrab;
251 }
252 void setCurrentIndex(QModelIndex index, bool notifyEffects = true);
253
254 static TabBox *self();
255 static TabBox *create(QObject *parent);
256
257 public Q_SLOTS:
258 /**
259 * Notify effects that the tab box is being shown, and only display the
260 * default tab box QFrame if no effect has referenced the tab box.
261 */
262 void show();
263 void close(bool abort = false);
264 void accept(bool closeTabBox = true);
265 void slotWalkThroughDesktops();
266 void slotWalkBackThroughDesktops();
267 void slotWalkThroughDesktopList();
268 void slotWalkBackThroughDesktopList();
269 void slotWalkThroughWindows();
270 void slotWalkBackThroughWindows();
271 void slotWalkThroughWindowsAlternative();
272 void slotWalkBackThroughWindowsAlternative();
273 void slotWalkThroughCurrentAppWindows();
274 void slotWalkBackThroughCurrentAppWindows();
275 void slotWalkThroughCurrentAppWindowsAlternative();
276 void slotWalkBackThroughCurrentAppWindowsAlternative();
277
278 void handlerReady();
279
280 bool toggle(ElectricBorder eb);
281
282 Q_SIGNALS:
283 void tabBoxAdded(int);
284 void tabBoxClosed();
285 void tabBoxUpdated();
286 void tabBoxKeyEvent(QKeyEvent*);
287
288 private:
289 explicit TabBox(QObject *parent);
290 void loadConfig(const KConfigGroup& config, TabBoxConfig& tabBoxConfig);
291
292 bool startKDEWalkThroughWindows(TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
293 bool startWalkThroughDesktops(TabBoxMode mode); // TabBoxDesktopMode | TabBoxDesktopListMode
294 bool startWalkThroughDesktops();
295 bool startWalkThroughDesktopList();
296 void navigatingThroughWindows(bool forward, const QKeySequence &shortcut, TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
297 void KDEWalkThroughWindows(bool forward);
298 void CDEWalkThroughWindows(bool forward);
299 void walkThroughDesktops(bool forward);
300 void KDEOneStepThroughWindows(bool forward, TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
301 void oneStepThroughDesktops(bool forward, TabBoxMode mode); // TabBoxDesktopMode | TabBoxDesktopListMode
302 void oneStepThroughDesktops(bool forward);
303 void oneStepThroughDesktopList(bool forward);
304 bool establishTabBoxGrab();
305 void removeTabBoxGrab();
306 template <typename Slot>
307 void key(const char *actionName, Slot slot, const QKeySequence &shortcut = QKeySequence());
308
309 void shadeActivate(AbstractClient *c);
310
311 bool toggleMode(TabBoxMode mode);
312
313 private Q_SLOTS:
314 void reconfigure();
315 void globalShortcutChanged(QAction *action, const QKeySequence &seq);
316
317 private:
318 TabBoxMode m_tabBoxMode;
319 TabBoxHandlerImpl* m_tabBox;
320 bool m_delayShow;
321 int m_delayShowTime;
322
323 QTimer m_delayedShowTimer;
324 int m_displayRefcount;
325
326 TabBoxConfig m_defaultConfig;
327 TabBoxConfig m_alternativeConfig;
328 TabBoxConfig m_defaultCurrentApplicationConfig;
329 TabBoxConfig m_alternativeCurrentApplicationConfig;
330 TabBoxConfig m_desktopConfig;
331 TabBoxConfig m_desktopListConfig;
332 // false if an effect has referenced the tabbox
333 // true if tabbox is active (independent on showTabbox setting)
334 bool m_isShown;
335 bool m_desktopGrab;
336 bool m_tabGrab;
337 // true if tabbox is in modal mode which does not require holding a modifier
338 bool m_noModifierGrab;
339 QKeySequence m_cutWalkThroughDesktops, m_cutWalkThroughDesktopsReverse;
340 QKeySequence m_cutWalkThroughDesktopList, m_cutWalkThroughDesktopListReverse;
341 QKeySequence m_cutWalkThroughWindows, m_cutWalkThroughWindowsReverse;
342 QKeySequence m_cutWalkThroughWindowsAlternative, m_cutWalkThroughWindowsAlternativeReverse;
343 QKeySequence m_cutWalkThroughCurrentAppWindows, m_cutWalkThroughCurrentAppWindowsReverse;
344 QKeySequence m_cutWalkThroughCurrentAppWindowsAlternative, m_cutWalkThroughCurrentAppWindowsAlternativeReverse;
345 bool m_forcedGlobalMouseGrab;
346 bool m_ready; // indicates whether the config is completely loaded
347 QList<ElectricBorder> m_borderActivate, m_borderAlternativeActivate;
348 QHash<ElectricBorder, QAction *> m_touchActivate;
349 QHash<ElectricBorder, QAction *> m_touchAlternativeActivate;
350 QScopedPointer<X11EventFilter> m_x11EventFilter;
351
352 static TabBox *s_self;
353 };
354
355 inline
self()356 TabBox *TabBox::self()
357 {
358 return s_self;
359 }
360
361 } // namespace TabBox
362 } // namespace
363 #endif
364