File indexing completed on 2024-05-19 16:34:55

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 Martin Gräßlin <mgraesslin@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #pragma once
0013 
0014 #include "tabbox/tabboxhandler.h"
0015 #include "utils/common.h"
0016 #include <QKeySequence>
0017 #include <QModelIndex>
0018 #include <QTimer>
0019 
0020 class KConfigGroup;
0021 class KLazyLocalizedString;
0022 class QAction;
0023 class QMouseEvent;
0024 class QKeyEvent;
0025 class QWheelEvent;
0026 
0027 namespace KWin
0028 {
0029 
0030 class Workspace;
0031 class Window;
0032 class X11EventFilter;
0033 namespace TabBox
0034 {
0035 class DesktopChainManager;
0036 class TabBoxConfig;
0037 class TabBox;
0038 class TabBoxHandlerImpl : public TabBoxHandler
0039 {
0040 public:
0041     explicit TabBoxHandlerImpl(TabBox *tabBox);
0042     ~TabBoxHandlerImpl() override;
0043 
0044     int activeScreen() const override;
0045     QWeakPointer<TabBoxClient> activeClient() const override;
0046     int currentDesktop() const override;
0047     QString desktopName(TabBoxClient *client) const override;
0048     QString desktopName(int desktop) const override;
0049     bool isKWinCompositing() const override;
0050     QWeakPointer<TabBoxClient> nextClientFocusChain(TabBoxClient *client) const override;
0051     QWeakPointer<TabBoxClient> firstClientFocusChain() const override;
0052     bool isInFocusChain(TabBoxClient *client) const override;
0053     int nextDesktopFocusChain(int desktop) const override;
0054     int numberOfDesktops() const override;
0055     TabBoxClientList stackingOrder() const override;
0056     void elevateClient(TabBoxClient *c, QWindow *tabbox, bool elevate) const override;
0057     void raiseClient(TabBoxClient *client) const override;
0058     void restack(TabBoxClient *c, TabBoxClient *under) override;
0059     void shadeClient(TabBoxClient *c, bool b) const override;
0060     QWeakPointer<TabBoxClient> clientToAddToList(KWin::TabBox::TabBoxClient *client, int desktop) const override;
0061     QWeakPointer<TabBoxClient> desktopClient() const override;
0062     void activateAndClose() override;
0063     void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) override;
0064     bool noModifierGrab() const override;
0065 
0066 private:
0067     bool checkDesktop(TabBoxClient *client, int desktop) const;
0068     bool checkActivity(TabBoxClient *client) const;
0069     bool checkApplications(TabBoxClient *client) const;
0070     bool checkMinimized(TabBoxClient *client) const;
0071     bool checkMultiScreen(TabBoxClient *client) const;
0072 
0073     TabBox *m_tabBox;
0074     DesktopChainManager *m_desktopFocusChain;
0075 };
0076 
0077 class TabBoxClientImpl : public TabBoxClient
0078 {
0079 public:
0080     explicit TabBoxClientImpl(Window *client);
0081     ~TabBoxClientImpl() override;
0082 
0083     QString caption() const override;
0084     QIcon icon() const override;
0085     bool isMinimized() const override;
0086     int x() const override;
0087     int y() const override;
0088     int width() const override;
0089     int height() const override;
0090     bool isCloseable() const override;
0091     void close() override;
0092     bool isFirstInTabBox() const override;
0093     QUuid internalId() const override;
0094 
0095     Window *client() const
0096     {
0097         return m_client;
0098     }
0099 
0100 private:
0101     Window *m_client;
0102 };
0103 
0104 class KWIN_EXPORT TabBox : public QObject
0105 {
0106     Q_OBJECT
0107 public:
0108     explicit TabBox();
0109     ~TabBox();
0110 
0111     /**
0112      * Returns the currently displayed client ( only works in TabBoxWindowsMode ).
0113      * Returns 0 if no client is displayed.
0114      */
0115     Window *currentClient();
0116 
0117     /**
0118      * Returns the list of clients potentially displayed ( only works in
0119      * TabBoxWindowsMode ).
0120      * Returns an empty list if no clients are available.
0121      */
0122     QList<Window *> currentClientList();
0123 
0124     /**
0125      * Returns the currently displayed virtual desktop ( only works in
0126      * TabBoxDesktopListMode )
0127      * Returns -1 if no desktop is displayed.
0128      */
0129     int currentDesktop();
0130 
0131     /**
0132      * Returns the list of desktops potentially displayed ( only works in
0133      * TabBoxDesktopListMode )
0134      * Returns an empty list if no are available.
0135      */
0136     QList<int> currentDesktopList();
0137 
0138     /**
0139      * Change the currently selected client, and notify the effects.
0140      *
0141      * @see setCurrentDesktop
0142      */
0143     void setCurrentClient(Window *newClient);
0144 
0145     /**
0146      * Change the currently selected desktop, and notify the effects.
0147      *
0148      * @see setCurrentClient
0149      */
0150     void setCurrentDesktop(int newDesktop);
0151 
0152     /**
0153      * Sets the current mode to \a mode, either TabBoxDesktopListMode or TabBoxWindowsMode
0154      *
0155      * @see mode
0156      */
0157     void setMode(TabBoxMode mode);
0158     TabBoxMode mode() const
0159     {
0160         return m_tabBoxMode;
0161     }
0162 
0163     /**
0164      * Resets the tab box to display the active client in TabBoxWindowsMode, or the
0165      * current desktop in TabBoxDesktopListMode
0166      */
0167     void reset(bool partial_reset = false);
0168 
0169     /**
0170      * Shows the next or previous item, depending on \a next
0171      */
0172     void nextPrev(bool next = true);
0173 
0174     /**
0175      * Shows the tab box after some delay.
0176      *
0177      * If the 'DelayTime' setting is 0, show() is simply called.
0178      *
0179      * Otherwise, we start a timer for the delay given in the settings and only
0180      * do a show() when it times out.
0181      *
0182      * This means that you can alt-tab between windows and you don't see the
0183      * tab box immediately. Not only does this make alt-tabbing faster, it gives
0184      * less 'flicker' to the eyes. You don't need to see the tab box if you're
0185      * just quickly switching between 2 or 3 windows. It seems to work quite
0186      * nicely.
0187      */
0188     void delayedShow();
0189 
0190     /**
0191      * Notify effects that the tab box is being hidden.
0192      */
0193     void hide(bool abort = false);
0194 
0195     /**
0196      * Increases the reference count, preventing the default tabbox from showing.
0197      *
0198      * @see unreference
0199      * @see isDisplayed
0200      */
0201     void reference()
0202     {
0203         ++m_displayRefcount;
0204     }
0205 
0206     /**
0207      * Decreases the reference count. Only when the reference count is 0 will
0208      * the default tab box be shown.
0209      */
0210     void unreference()
0211     {
0212         --m_displayRefcount;
0213     }
0214 
0215     /**
0216      * Returns whether the tab box is being displayed, either natively or by an
0217      * effect.
0218      *
0219      * @see reference
0220      * @see unreference
0221      */
0222     bool isDisplayed() const
0223     {
0224         return m_displayRefcount > 0;
0225     }
0226 
0227     /**
0228      * @returns @c true if TabBox is shown, @c false if replaced by Effect
0229      */
0230     bool isShown() const
0231     {
0232         return m_isShown;
0233     }
0234 
0235     bool handleMouseEvent(QMouseEvent *event);
0236     bool handleWheelEvent(QWheelEvent *event);
0237     void grabbedKeyEvent(QKeyEvent *event);
0238 
0239     bool isGrabbed() const
0240     {
0241         return m_tabGrab || m_desktopGrab;
0242     }
0243 
0244     void initShortcuts();
0245 
0246     Window *nextClientStatic(Window *) const;
0247     Window *previousClientStatic(Window *) const;
0248     int nextDesktopStatic(int iDesktop) const;
0249     int previousDesktopStatic(int iDesktop) const;
0250     void keyPress(int key);
0251     void modifiersReleased();
0252 
0253     bool forcedGlobalMouseGrab() const
0254     {
0255         return m_forcedGlobalMouseGrab;
0256     }
0257 
0258     bool noModifierGrab() const
0259     {
0260         return m_noModifierGrab;
0261     }
0262     void setCurrentIndex(QModelIndex index, bool notifyEffects = true);
0263 
0264 public Q_SLOTS:
0265     /**
0266      * Notify effects that the tab box is being shown, and only display the
0267      * default tab box QFrame if no effect has referenced the tab box.
0268      */
0269     void show();
0270     void close(bool abort = false);
0271     void accept(bool closeTabBox = true);
0272     void slotWalkThroughDesktops();
0273     void slotWalkBackThroughDesktops();
0274     void slotWalkThroughDesktopList();
0275     void slotWalkBackThroughDesktopList();
0276     void slotWalkThroughWindows();
0277     void slotWalkBackThroughWindows();
0278     void slotWalkThroughWindowsAlternative();
0279     void slotWalkBackThroughWindowsAlternative();
0280     void slotWalkThroughCurrentAppWindows();
0281     void slotWalkBackThroughCurrentAppWindows();
0282     void slotWalkThroughCurrentAppWindowsAlternative();
0283     void slotWalkBackThroughCurrentAppWindowsAlternative();
0284 
0285     void handlerReady();
0286 
0287     bool toggle(ElectricBorder eb);
0288 
0289 Q_SIGNALS:
0290     void tabBoxAdded(int);
0291     void tabBoxClosed();
0292     void tabBoxUpdated();
0293     void tabBoxKeyEvent(QKeyEvent *);
0294 
0295 private:
0296     explicit TabBox(QObject *parent);
0297     void loadConfig(const KConfigGroup &config, TabBoxConfig &tabBoxConfig);
0298 
0299     bool startKDEWalkThroughWindows(TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
0300     bool startWalkThroughDesktops(TabBoxMode mode); // TabBoxDesktopMode | TabBoxDesktopListMode
0301     bool startWalkThroughDesktops();
0302     bool startWalkThroughDesktopList();
0303     void navigatingThroughWindows(bool forward, const QKeySequence &shortcut, TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
0304     void KDEWalkThroughWindows(bool forward);
0305     void CDEWalkThroughWindows(bool forward);
0306     void walkThroughDesktops(bool forward);
0307     void KDEOneStepThroughWindows(bool forward, TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
0308     void oneStepThroughDesktops(bool forward, TabBoxMode mode); // TabBoxDesktopMode | TabBoxDesktopListMode
0309     void oneStepThroughDesktops(bool forward);
0310     void oneStepThroughDesktopList(bool forward);
0311     bool establishTabBoxGrab();
0312     void removeTabBoxGrab();
0313     template<typename Slot>
0314     void key(const KLazyLocalizedString &actionName, Slot slot, const QKeySequence &shortcut = QKeySequence());
0315 
0316     void shadeActivate(Window *c);
0317 
0318     bool toggleMode(TabBoxMode mode);
0319 
0320 private Q_SLOTS:
0321     void reconfigure();
0322     void globalShortcutChanged(QAction *action, const QKeySequence &seq);
0323 
0324 private:
0325     TabBoxMode m_tabBoxMode;
0326     TabBoxHandlerImpl *m_tabBox;
0327     int m_delayShowTime;
0328 
0329     QTimer m_delayedShowTimer;
0330     int m_displayRefcount;
0331 
0332     TabBoxConfig m_defaultConfig;
0333     TabBoxConfig m_alternativeConfig;
0334     TabBoxConfig m_defaultCurrentApplicationConfig;
0335     TabBoxConfig m_alternativeCurrentApplicationConfig;
0336     TabBoxConfig m_desktopConfig;
0337     TabBoxConfig m_desktopListConfig;
0338     // false if an effect has referenced the tabbox
0339     // true if tabbox is active (independent on showTabbox setting)
0340     bool m_isShown;
0341     bool m_desktopGrab;
0342     bool m_tabGrab;
0343     // true if tabbox is in modal mode which does not require holding a modifier
0344     bool m_noModifierGrab;
0345     QKeySequence m_cutWalkThroughDesktops, m_cutWalkThroughDesktopsReverse;
0346     QKeySequence m_cutWalkThroughDesktopList, m_cutWalkThroughDesktopListReverse;
0347     QKeySequence m_cutWalkThroughWindows, m_cutWalkThroughWindowsReverse;
0348     QKeySequence m_cutWalkThroughWindowsAlternative, m_cutWalkThroughWindowsAlternativeReverse;
0349     QKeySequence m_cutWalkThroughCurrentAppWindows, m_cutWalkThroughCurrentAppWindowsReverse;
0350     QKeySequence m_cutWalkThroughCurrentAppWindowsAlternative, m_cutWalkThroughCurrentAppWindowsAlternativeReverse;
0351     bool m_forcedGlobalMouseGrab;
0352     bool m_ready; // indicates whether the config is completely loaded
0353     QList<ElectricBorder> m_borderActivate, m_borderAlternativeActivate;
0354     QHash<ElectricBorder, QAction *> m_touchActivate;
0355     QHash<ElectricBorder, QAction *> m_touchAlternativeActivate;
0356     std::unique_ptr<X11EventFilter> m_x11EventFilter;
0357 };
0358 
0359 } // namespace TabBox
0360 } // namespace