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

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2009 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #pragma once
0011 
0012 #include "tabboxconfig.h"
0013 
0014 #include <QModelIndex>
0015 #include <QPixmap>
0016 #include <QString>
0017 
0018 /**
0019  * @file
0020  * This file contains the classes which hide KWin core from tabbox.
0021  *
0022  * @author Martin Gräßlin <mgraesslin@kde.org>
0023  * @since 4.4
0024  */
0025 
0026 class QKeyEvent;
0027 
0028 namespace KWin
0029 {
0030 
0031 class Window;
0032 
0033 /**
0034  * The TabBox is a model based view for displaying a list while switching windows.
0035  * This functionality is mostly referred to as Alt+Tab. TabBox itself does not provide support for
0036  * switching windows. This has to be done outside of TabBox inside an independent controller.
0037  *
0038  * The main entrance point to TabBox is the class TabBoxHandler, which has to be subclassed and implemented.
0039  *
0040  * The behavior of the TabBox is defined by the TabBoxConfig and has to be set in the TabBoxHandler.
0041  *
0042  * In order to use the TabBox the TabBoxConfig has to be set. The model has to be initialized by calling
0043  * TabBoxHandler::createModel(), as the
0044  * model is undefined when the TabBox is not active. The TabBox is activated by TabBoxHandler::show().
0045  * Depending on the current set TabBoxConfig it is possible that the
0046  * highlight windows effect activated and that the view is not displayed at all. As already mentioned
0047  * the TabBox does not handle any updating of the selected item. This has to be done by invoking
0048  * TabBoxHandler::setCurrentIndex(). Nevertheless the TabBoxHandler provides methods to query for the
0049  * model index or the next or previous item, for a cursor position or for a given item. By invoking
0050  * TabBoxHandler::hide() the view, the
0051  * optional highlight windows effect are removed. The model is invalidated immediately. So if it is
0052  * necessary to retrieve the last selected item this has to be done before calling the hide method.
0053  *
0054  * The layout of the TabBox View and the items is completely customizable. Therefore TabBox provides
0055  * a widget LayoutConfig which includes a live preview (in kcmkwin/kwintabbox). The layout of items
0056  * can be defined by an xml document. That way the user is able to define own custom layouts. The view
0057  * itself is made up of two widgets: one to show the complete list and one to show only the selected
0058  * item. This way it is possible to have a view which shows for example a list containing only small
0059  * icons and nevertheless show the title of the currently selected client.
0060  */
0061 namespace TabBox
0062 {
0063 class ClientModel;
0064 class TabBoxConfig;
0065 class TabBoxHandlerPrivate;
0066 
0067 /**
0068  * This class is a wrapper around KWin Workspace. It is used for accessing the
0069  * required core methods from inside TabBox and has to be implemented in KWin core.
0070  *
0071  * @author Martin Gräßlin <mgraesslin@kde.org>
0072  * @since 4.4
0073  */
0074 class TabBoxHandler : public QObject
0075 {
0076     Q_OBJECT
0077 public:
0078     TabBoxHandler(QObject *parent);
0079     ~TabBoxHandler() override;
0080 
0081     /**
0082      * @return The id of the active screen
0083      */
0084     virtual int activeScreen() const = 0;
0085     /**
0086      * @return The current active Window or NULL
0087      * if there is no active client.
0088      */
0089     virtual Window *activeClient() const = 0;
0090     /**
0091      * @param client The client which is starting point to find the next client
0092      * @return The next Window in focus chain
0093      */
0094     virtual Window *nextClientFocusChain(Window *client) const = 0;
0095     /**
0096      * This method is used by the ClientModel to find an entrance into the focus chain in case
0097      * there is no active Client.
0098      *
0099      * @return The first Client of the focus chain
0100      * @since 4.9.1
0101      */
0102     virtual Window *firstClientFocusChain() const = 0;
0103     /**
0104      * Checks whether the given @p client is part of the focus chain at all.
0105      * This is useful to figure out whether the currently active Client can be used
0106      * as a starting point to construct the recently used list.
0107      *
0108      * In case the @p client is not in the focus chain it is recommended to use the
0109      * Client returned by firstClientFocusChain.
0110      *
0111      * The method accepts a @c null Client and in that case @c false is returned.
0112      * @param client The Client to check whether it is in the Focus Chain
0113      * @return @c true in case the Client is part of the focus chain, @c false otherwise.
0114      * @since 4.9.2
0115      */
0116     virtual bool isInFocusChain(Window *client) const = 0;
0117     /**
0118      * @param client The client whose desktop name should be retrieved
0119      * @return The desktop name of the given Window. If the client is
0120      * on all desktops the name of current desktop will be returned.
0121      */
0122     virtual QString desktopName(Window *client) const = 0;
0123 
0124     /**
0125      * whether KWin is currently compositing and it's related features (elevating) can be used
0126      */
0127     virtual bool isKWinCompositing() const = 0;
0128 
0129     /**
0130      * De-/Elevate a client using the compositor (if enabled)
0131      */
0132     virtual void elevateClient(Window *c, QWindow *tabbox, bool elevate) const = 0;
0133 
0134     /**
0135      * Raise a client (w/o activating it)
0136      */
0137     virtual void raiseClient(Window *c) const = 0;
0138 
0139     /**
0140      * @param c The client to be restacked
0141      * @param under The client the other one will be placed below
0142      */
0143     virtual void restack(Window *c, Window *under) = 0;
0144 
0145     /**
0146      * Toggle between ShadeHover and ShadeNormal - not shaded windows are unaffected
0147      * @param c The client to be shaded
0148      * @param b Whether to un- or shade
0149      */
0150     virtual void shadeClient(Window *c, bool b) const = 0;
0151 
0152     virtual void highlightWindows(Window *window = nullptr, QWindow *controller = nullptr) = 0;
0153 
0154     /**
0155      * @return The current stacking order of Windows
0156      */
0157     virtual QList<Window *> stackingOrder() const = 0;
0158     /**
0159      * Determines if given client will be added to the list:
0160      * <UL>
0161      * <LI>if the client wants to have tab focus.</LI>
0162      * <LI>The client won't be added if it has modal dialogs</LI>
0163      * <LI>In that case the modal dialog will be returned if it isn't already
0164      * included</LI>
0165      * <LI>Won't be added if it isn't on active screen when using separate
0166      * screen focus</LI>
0167      * </UL>
0168      * @param client The client to be checked for inclusion
0169      * @param allDesktops Add clients from all desktops or only from current
0170      * @return The client to be included in the list or NULL if it isn't to be included
0171      */
0172     virtual Window *clientToAddToList(Window *client) const = 0;
0173     /**
0174      * @return The first desktop window in the stacking order.
0175      */
0176     virtual Window *desktopClient() const = 0;
0177     /**
0178      * Activates the currently selected client and closes the TabBox.
0179      */
0180     virtual void activateAndClose() = 0;
0181 
0182     /**
0183      * @return The currently used TabBoxConfig
0184      */
0185     const TabBoxConfig &config() const;
0186     /**
0187      * Call this method when you want to change the currently used TabBoxConfig.
0188      * It fires the signal configChanged.
0189      * @param config Updates the currently used TabBoxConfig to config
0190      */
0191     void setConfig(const TabBoxConfig &config);
0192 
0193     /**
0194      * Call this method to show the TabBoxView. Depending on current
0195      * configuration this method might not do anything.
0196      * If highlight windows effect is to be used it will be activated.
0197      * @see TabBoxConfig::isShowTabBox
0198      * @see TabBoxConfig::isHighlightWindows
0199      */
0200     void show();
0201     /**
0202      * Hides the TabBoxView if shown.
0203      * Deactivates highlight windows effect if active.
0204      * @see show
0205      */
0206     void hide(bool abort = false);
0207 
0208     /**
0209      * Sets the current model index in the view and updates
0210      * highlight windows if active.
0211      * @param index The current Model index
0212      */
0213     void setCurrentIndex(const QModelIndex &index);
0214     /**
0215      * @returns the current index
0216      */
0217     const QModelIndex &currentIndex() const;
0218 
0219     /**
0220      * Retrieves the next or previous item of the current item.
0221      * @param forward next or previous item
0222      * @return The next or previous item. If there is no matching item
0223      * the current item will be returned.
0224      */
0225     QModelIndex nextPrev(bool forward) const;
0226 
0227     /**
0228      * Initializes the model based on the current config.
0229      * This method has to be invoked before showing the TabBox.
0230      * It can also be invoked when clients are added or removed.
0231      * In that case partialReset has to be true.
0232      *
0233      * @param partialReset Keep the currently selected item or regenerate everything
0234      */
0235     void createModel(bool partialReset = false);
0236 
0237     /**
0238      * Handles additional grabbed key events by the TabBox controller.
0239      * @param event The key event which has been grabbed
0240      */
0241     virtual void grabbedKeyEvent(QKeyEvent *event) const;
0242     /**
0243      * @param pos The position to be tested in global coordinates
0244      * @return True if the view contains the point, otherwise false.
0245      */
0246     bool containsPos(const QPoint &pos) const;
0247     /**
0248      * @param client The Window whose index should be returned
0249      * @return Returns the ModelIndex of given Window or an invalid ModelIndex
0250      * if the model does not contain the given Window.
0251      * @see ClientModel::index
0252      */
0253     QModelIndex index(Window *client) const;
0254     /**
0255      * @return Returns the current list of Windows.
0256      * @see ClientModel::clientList
0257      */
0258     QList<Window *> clientList() const;
0259     /**
0260      * @param index The index of the client to be returned
0261      * @return Returns the Window at given model index. If
0262      * the index is invalid, does not point to a Client or the list
0263      * is empty, NULL will be returned.
0264      */
0265     Window *client(const QModelIndex &index) const;
0266     /**
0267      * @return The first model index. That is the model index at position 0, 0.
0268      * It is valid, as desktop has at least one desktop and if there are no
0269      * clients an empty item is created.
0270      */
0271     QModelIndex first() const;
0272 
0273     bool eventFilter(QObject *watcher, QEvent *event) override;
0274 
0275     /**
0276      * @returns whether the TabBox operates in a no modifier grab mode.
0277      * In this mode a click on an item should directly accept and close the tabbox.
0278      */
0279     virtual bool noModifierGrab() const = 0;
0280 
0281 Q_SIGNALS:
0282     /**
0283      * This signal is fired when the TabBoxConfig changes
0284      * @see setConfig
0285      */
0286     void configChanged();
0287     void selectedIndexChanged();
0288 
0289 private Q_SLOTS:
0290     void initHighlightWindows();
0291 
0292 private:
0293     friend class TabBoxHandlerPrivate;
0294     TabBoxHandlerPrivate *d;
0295 };
0296 
0297 /**
0298  * Pointer to the global TabBoxHandler object.
0299  */
0300 extern TabBoxHandler *tabBox;
0301 
0302 } // namespace TabBox
0303 } // namespace KWin