File indexing completed on 2024-05-19 05:32:26

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 TabBoxConfig;
0036 class TabBox;
0037 class TabBoxHandlerImpl : public TabBoxHandler
0038 {
0039 public:
0040     explicit TabBoxHandlerImpl(TabBox *tabBox);
0041     ~TabBoxHandlerImpl() override;
0042 
0043     int activeScreen() const override;
0044     Window *activeClient() const override;
0045     QString desktopName(Window *client) const override;
0046     bool isKWinCompositing() const override;
0047     Window *nextClientFocusChain(Window *client) const override;
0048     Window *firstClientFocusChain() const override;
0049     bool isInFocusChain(Window *client) const override;
0050     QList<Window *> stackingOrder() const override;
0051     void elevateClient(Window *c, QWindow *tabbox, bool elevate) const override;
0052     void raiseClient(Window *client) const override;
0053     void restack(Window *c, Window *under) override;
0054     void shadeClient(Window *c, bool b) const override;
0055     Window *clientToAddToList(Window *client) const override;
0056     Window *desktopClient() const override;
0057     void activateAndClose() override;
0058     void highlightWindows(Window *window = nullptr, QWindow *controller = nullptr) override;
0059     bool noModifierGrab() const override;
0060 
0061 private:
0062     bool checkDesktop(Window *client) const;
0063     bool checkActivity(Window *client) const;
0064     bool checkApplications(Window *client) const;
0065     bool checkMinimized(Window *client) const;
0066     bool checkMultiScreen(Window *client) const;
0067 
0068     TabBox *m_tabBox;
0069 };
0070 
0071 class KWIN_EXPORT TabBox : public QObject
0072 {
0073     Q_OBJECT
0074 public:
0075     explicit TabBox();
0076     ~TabBox();
0077 
0078     /**
0079      * Returns the currently displayed client ( only works in TabBoxWindowsMode ).
0080      * Returns 0 if no client is displayed.
0081      */
0082     Window *currentClient();
0083 
0084     /**
0085      * Returns the list of clients potentially displayed ( only works in
0086      * TabBoxWindowsMode ).
0087      * Returns an empty list if no clients are available.
0088      */
0089     QList<Window *> currentClientList();
0090 
0091     /**
0092      * Change the currently selected client, and notify the effects.
0093      */
0094     void setCurrentClient(Window *newClient);
0095 
0096     void setMode(TabBoxMode mode);
0097     TabBoxMode mode() const
0098     {
0099         return m_tabBoxMode;
0100     }
0101 
0102     /**
0103      * Resets the tab box to display the active client in TabBoxWindowsMode
0104      */
0105     void reset(bool partial_reset = false);
0106 
0107     /**
0108      * Shows the next or previous item, depending on \a next
0109      */
0110     void nextPrev(bool next = true);
0111 
0112     /**
0113      * Shows the tab box after some delay.
0114      *
0115      * If the 'DelayTime' setting is 0, show() is simply called.
0116      *
0117      * Otherwise, we start a timer for the delay given in the settings and only
0118      * do a show() when it times out.
0119      *
0120      * This means that you can alt-tab between windows and you don't see the
0121      * tab box immediately. Not only does this make alt-tabbing faster, it gives
0122      * less 'flicker' to the eyes. You don't need to see the tab box if you're
0123      * just quickly switching between 2 or 3 windows. It seems to work quite
0124      * nicely.
0125      */
0126     void delayedShow();
0127 
0128     /**
0129      * Notify effects that the tab box is being hidden.
0130      */
0131     void hide(bool abort = false);
0132 
0133     /**
0134      * Increases the reference count, preventing the default tabbox from showing.
0135      *
0136      * @see unreference
0137      * @see isDisplayed
0138      */
0139     void reference()
0140     {
0141         ++m_displayRefcount;
0142     }
0143 
0144     /**
0145      * Decreases the reference count. Only when the reference count is 0 will
0146      * the default tab box be shown.
0147      */
0148     void unreference()
0149     {
0150         --m_displayRefcount;
0151     }
0152 
0153     /**
0154      * Returns whether the tab box is being displayed, either natively or by an
0155      * effect.
0156      *
0157      * @see reference
0158      * @see unreference
0159      */
0160     bool isDisplayed() const
0161     {
0162         return m_displayRefcount > 0;
0163     }
0164 
0165     /**
0166      * @returns @c true if TabBox is shown, @c false if replaced by Effect
0167      */
0168     bool isShown() const
0169     {
0170         return m_isShown;
0171     }
0172 
0173     bool handleMouseEvent(QMouseEvent *event);
0174     bool handleWheelEvent(QWheelEvent *event);
0175     void grabbedKeyEvent(QKeyEvent *event);
0176 
0177     bool isGrabbed() const
0178     {
0179         return m_tabGrab;
0180     }
0181 
0182     void initShortcuts();
0183 
0184     Window *nextClientStatic(Window *) const;
0185     Window *previousClientStatic(Window *) const;
0186     void keyPress(int key);
0187     void modifiersReleased();
0188 
0189     bool forcedGlobalMouseGrab() const
0190     {
0191         return m_forcedGlobalMouseGrab;
0192     }
0193 
0194     bool noModifierGrab() const
0195     {
0196         return m_noModifierGrab;
0197     }
0198     void setCurrentIndex(QModelIndex index, bool notifyEffects = true);
0199 
0200 public Q_SLOTS:
0201     /**
0202      * Notify effects that the tab box is being shown, and only display the
0203      * default tab box QFrame if no effect has referenced the tab box.
0204      */
0205     void show();
0206     void close(bool abort = false);
0207     void accept(bool closeTabBox = true);
0208     void slotWalkThroughWindows();
0209     void slotWalkBackThroughWindows();
0210     void slotWalkThroughWindowsAlternative();
0211     void slotWalkBackThroughWindowsAlternative();
0212     void slotWalkThroughCurrentAppWindows();
0213     void slotWalkBackThroughCurrentAppWindows();
0214     void slotWalkThroughCurrentAppWindowsAlternative();
0215     void slotWalkBackThroughCurrentAppWindowsAlternative();
0216 
0217     void handlerReady();
0218 
0219     bool toggle(ElectricBorder eb);
0220 
0221 Q_SIGNALS:
0222     void tabBoxAdded(int);
0223     void tabBoxClosed();
0224     void tabBoxUpdated();
0225     void tabBoxKeyEvent(QKeyEvent *);
0226 
0227 private:
0228     explicit TabBox(QObject *parent);
0229     void loadConfig(const KConfigGroup &config, TabBoxConfig &tabBoxConfig);
0230 
0231     bool startKDEWalkThroughWindows(TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
0232     void navigatingThroughWindows(bool forward, const QKeySequence &shortcut, TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
0233     void KDEWalkThroughWindows(bool forward);
0234     void CDEWalkThroughWindows(bool forward);
0235     void KDEOneStepThroughWindows(bool forward, TabBoxMode mode); // TabBoxWindowsMode | TabBoxWindowsAlternativeMode
0236     bool establishTabBoxGrab();
0237     void removeTabBoxGrab();
0238     template<typename Slot>
0239     void key(const KLazyLocalizedString &actionName, Slot slot, const QKeySequence &shortcut = QKeySequence());
0240 
0241     void shadeActivate(Window *c);
0242 
0243     bool toggleMode(TabBoxMode mode);
0244 
0245 private Q_SLOTS:
0246     void reconfigure();
0247     void globalShortcutChanged(QAction *action, const QKeySequence &seq);
0248 
0249 private:
0250     TabBoxMode m_tabBoxMode;
0251     TabBoxHandlerImpl *m_tabBox;
0252     int m_delayShowTime;
0253 
0254     QTimer m_delayedShowTimer;
0255     int m_displayRefcount;
0256 
0257     TabBoxConfig m_defaultConfig;
0258     TabBoxConfig m_alternativeConfig;
0259     TabBoxConfig m_defaultCurrentApplicationConfig;
0260     TabBoxConfig m_alternativeCurrentApplicationConfig;
0261     // false if an effect has referenced the tabbox
0262     // true if tabbox is active (independent on showTabbox setting)
0263     bool m_isShown;
0264     bool m_tabGrab;
0265     // true if tabbox is in modal mode which does not require holding a modifier
0266     bool m_noModifierGrab;
0267     QKeySequence m_cutWalkThroughWindows, m_cutWalkThroughWindowsReverse;
0268     QKeySequence m_cutWalkThroughWindowsAlternative, m_cutWalkThroughWindowsAlternativeReverse;
0269     QKeySequence m_cutWalkThroughCurrentAppWindows, m_cutWalkThroughCurrentAppWindowsReverse;
0270     QKeySequence m_cutWalkThroughCurrentAppWindowsAlternative, m_cutWalkThroughCurrentAppWindowsAlternativeReverse;
0271     bool m_forcedGlobalMouseGrab;
0272     bool m_ready; // indicates whether the config is completely loaded
0273     QList<ElectricBorder> m_borderActivate, m_borderAlternativeActivate;
0274     QHash<ElectricBorder, QAction *> m_touchActivate;
0275     QHash<ElectricBorder, QAction *> m_touchAlternativeActivate;
0276     std::unique_ptr<X11EventFilter> m_x11EventFilter;
0277 };
0278 
0279 } // namespace TabBox
0280 } // namespace