File indexing completed on 2024-05-19 16:34:56
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 * It defines the pure virtual classes TabBoxHandler and TabBoxClient. 0022 * The classes have to be implemented in KWin Core. 0023 * 0024 * @author Martin Gräßlin <mgraesslin@kde.org> 0025 * @since 4.4 0026 */ 0027 0028 class QKeyEvent; 0029 0030 namespace KWin 0031 { 0032 /** 0033 * The TabBox is a model based view for displaying a list while switching windows or desktops. 0034 * This functionality is mostly referred to as Alt+Tab. TabBox itself does not provide support for 0035 * switching windows or desktops. This has to be done outside of TabBox inside an independent controller. 0036 * 0037 * The main entrance point to TabBox is the class TabBoxHandler, which has to be subclassed and implemented. 0038 * The class TabBoxClient, which represents a window client inside TabBox, has to be implemented as well. 0039 * 0040 * The behavior of the TabBox is defined by the TabBoxConfig and has to be set in the TabBoxHandler. 0041 * If the TabBox should be used to switch desktops as well as clients it is sufficient to just provide 0042 * different TabBoxConfig objects instead of creating an own handler for each mode. 0043 * 0044 * In order to use the TabBox the TabBoxConfig has to be set. This defines if the model for desktops or for 0045 * clients will be used. The model has to be initialized by calling TabBoxHandler::createModel(), as the 0046 * model is undefined when the TabBox is not active. The TabBox is activated by TabBoxHandler::show(). 0047 * Depending on the current set TabBoxConfig it is possible that the 0048 * highlight windows effect activated and that the view is not displayed at all. As already mentioned 0049 * the TabBox does not handle any updating of the selected item. This has to be done by invoking 0050 * TabBoxHandler::setCurrentIndex(). Nevertheless the TabBoxHandler provides methods to query for the 0051 * model index or the next or previous item, for a cursor position or for a given item (that is 0052 * TabBoxClient or desktop). By invoking TabBoxHandler::hide() the view, the 0053 * optional highlight windows effect are removed. The model is invalidated immediately. So if it is 0054 * necessary to retrieve the last selected item this has to be done before calling the hide method. 0055 * 0056 * The layout of the TabBox View and the items is completely customizable. Therefore TabBox provides 0057 * a widget LayoutConfig which includes a live preview (in kcmkwin/kwintabbox). The layout of items 0058 * can be defined by an xml document. That way the user is able to define own custom layouts. The view 0059 * itself is made up of two widgets: one to show the complete list and one to show only the selected 0060 * item. This way it is possible to have a view which shows for example a list containing only small 0061 * icons and nevertheless show the title of the currently selected client. 0062 */ 0063 namespace TabBox 0064 { 0065 class DesktopModel; 0066 class ClientModel; 0067 class TabBoxConfig; 0068 class TabBoxClient; 0069 class TabBoxHandlerPrivate; 0070 typedef QList<QWeakPointer<TabBoxClient>> TabBoxClientList; 0071 0072 /** 0073 * This class is a wrapper around KWin Workspace. It is used for accessing the 0074 * required core methods from inside TabBox and has to be implemented in KWin core. 0075 * 0076 * @author Martin Gräßlin <mgraesslin@kde.org> 0077 * @since 4.4 0078 */ 0079 class TabBoxHandler : public QObject 0080 { 0081 Q_OBJECT 0082 public: 0083 TabBoxHandler(QObject *parent); 0084 ~TabBoxHandler() override; 0085 0086 /** 0087 * @return The id of the active screen 0088 */ 0089 virtual int activeScreen() const = 0; 0090 /** 0091 * @return The current active TabBoxClient or NULL 0092 * if there is no active client. 0093 */ 0094 virtual QWeakPointer<TabBoxClient> activeClient() const = 0; 0095 /** 0096 * @param client The client which is starting point to find the next client 0097 * @return The next TabBoxClient in focus chain 0098 */ 0099 virtual QWeakPointer<TabBoxClient> nextClientFocusChain(TabBoxClient *client) const = 0; 0100 /** 0101 * This method is used by the ClientModel to find an entrance into the focus chain in case 0102 * there is no active Client. 0103 * 0104 * @return The first Client of the focus chain 0105 * @since 4.9.1 0106 */ 0107 virtual QWeakPointer<TabBoxClient> firstClientFocusChain() const = 0; 0108 /** 0109 * Checks whether the given @p client is part of the focus chain at all. 0110 * This is useful to figure out whether the currently active Client can be used 0111 * as a starting point to construct the recently used list. 0112 * 0113 * In case the @p client is not in the focus chain it is recommended to use the 0114 * Client returned by firstClientFocusChain. 0115 * 0116 * The method accepts a @c null Client and in that case @c false is returned. 0117 * @param client The Client to check whether it is in the Focus Chain 0118 * @return @c true in case the Client is part of the focus chain, @c false otherwise. 0119 * @since 4.9.2 0120 */ 0121 virtual bool isInFocusChain(TabBoxClient *client) const = 0; 0122 /** 0123 * @param client The client whose desktop name should be retrieved 0124 * @return The desktop name of the given TabBoxClient. If the client is 0125 * on all desktops the name of current desktop will be returned. 0126 */ 0127 virtual QString desktopName(TabBoxClient *client) const = 0; 0128 /** 0129 * @param desktop The desktop whose name should be retrieved 0130 * @return The desktop name of given desktop 0131 */ 0132 virtual QString desktopName(int desktop) const = 0; 0133 /** 0134 * @return The number of current desktop 0135 */ 0136 virtual int currentDesktop() const = 0; 0137 /** 0138 * @return The number of virtual desktops 0139 */ 0140 virtual int numberOfDesktops() const = 0; 0141 /** 0142 * @param desktop The desktop which is the starting point to find the next desktop 0143 * @return The next desktop in the current focus chain. 0144 */ 0145 virtual int nextDesktopFocusChain(int desktop) const = 0; 0146 0147 /** 0148 * whether KWin is currently compositing and it's related features (elevating) can be used 0149 */ 0150 virtual bool isKWinCompositing() const = 0; 0151 0152 /** 0153 * De-/Elevate a client using the compositor (if enabled) 0154 */ 0155 virtual void elevateClient(TabBoxClient *c, QWindow *tabbox, bool elevate) const = 0; 0156 0157 /** 0158 * Raise a client (w/o activating it) 0159 */ 0160 virtual void raiseClient(TabBoxClient *c) const = 0; 0161 0162 /** 0163 * @param c The client to be restacked 0164 * @param under The client the other one will be placed below 0165 */ 0166 virtual void restack(TabBoxClient *c, TabBoxClient *under) = 0; 0167 0168 /** 0169 * Toggle between ShadeHover and ShadeNormal - not shaded windows are unaffected 0170 * @param c The client to be shaded 0171 * @param b Whether to un- or shade 0172 */ 0173 virtual void shadeClient(TabBoxClient *c, bool b) const = 0; 0174 0175 virtual void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) = 0; 0176 0177 /** 0178 * @return The current stacking order of TabBoxClients 0179 */ 0180 virtual TabBoxClientList stackingOrder() const = 0; 0181 /** 0182 * Determines if given client will be added to the list: 0183 * <UL> 0184 * <LI>Depends on desktop</LI> 0185 * <LI>if the client wants to have tab focus.</LI> 0186 * <LI>The client won't be added if it has modal dialogs</LI> 0187 * <LI>In that case the modal dialog will be returned if it isn't already 0188 * included</LI> 0189 * <LI>Won't be added if it isn't on active screen when using separate 0190 * screen focus</LI> 0191 * </UL> 0192 * @param client The client to be checked for inclusion 0193 * @param desktop The desktop the client should be on. This is irrelevant if allDesktops is set 0194 * @param allDesktops Add clients from all desktops or only from current 0195 * @return The client to be included in the list or NULL if it isn't to be included 0196 */ 0197 virtual QWeakPointer<TabBoxClient> clientToAddToList(TabBoxClient *client, int desktop) const = 0; 0198 /** 0199 * @return The first desktop window in the stacking order. 0200 */ 0201 virtual QWeakPointer<TabBoxClient> desktopClient() const = 0; 0202 /** 0203 * Activates the currently selected client and closes the TabBox. 0204 */ 0205 virtual void activateAndClose() = 0; 0206 0207 /** 0208 * @return The currently used TabBoxConfig 0209 */ 0210 const TabBoxConfig &config() const; 0211 /** 0212 * Call this method when you want to change the currently used TabBoxConfig. 0213 * It fires the signal configChanged. 0214 * @param config Updates the currently used TabBoxConfig to config 0215 */ 0216 void setConfig(const TabBoxConfig &config); 0217 0218 /** 0219 * Call this method to show the TabBoxView. Depending on current 0220 * configuration this method might not do anything. 0221 * If highlight windows effect is to be used it will be activated. 0222 * Highlight windows and outline are not shown if 0223 * TabBoxConfig::TabBoxMode is TabBoxConfig::DesktopTabBox. 0224 * @see TabBoxConfig::isShowTabBox 0225 * @see TabBoxConfig::isHighlightWindows 0226 */ 0227 void show(); 0228 /** 0229 * Hides the TabBoxView if shown. 0230 * Deactivates highlight windows effect if active. 0231 * @see show 0232 */ 0233 void hide(bool abort = false); 0234 0235 /** 0236 * Sets the current model index in the view and updates 0237 * highlight windows if active. 0238 * @param index The current Model index 0239 */ 0240 void setCurrentIndex(const QModelIndex &index); 0241 /** 0242 * @returns the current index 0243 */ 0244 const QModelIndex ¤tIndex() const; 0245 0246 /** 0247 * Retrieves the next or previous item of the current item. 0248 * @param forward next or previous item 0249 * @return The next or previous item. If there is no matching item 0250 * the current item will be returned. 0251 */ 0252 QModelIndex nextPrev(bool forward) const; 0253 0254 /** 0255 * Initializes the model based on the current config. 0256 * This method has to be invoked before showing the TabBox. 0257 * It can also be invoked when clients are added or removed. 0258 * In that case partialReset has to be true. 0259 * 0260 * @param partialReset Keep the currently selected item or regenerate everything 0261 */ 0262 void createModel(bool partialReset = false); 0263 0264 /** 0265 * @param desktop The desktop whose index should be retrieved 0266 * @return The model index of given desktop. If TabBoxMode is not 0267 * TabBoxConfig::DesktopTabBox an invalid model index will be returned. 0268 */ 0269 QModelIndex desktopIndex(int desktop) const; 0270 /** 0271 * @return The current list of desktops. 0272 * If TabBoxMode is not TabBoxConfig::DesktopTabBox an empty list will 0273 * be returned. 0274 * @see DesktopModel::desktopList 0275 */ 0276 QList<int> desktopList() const; 0277 /** 0278 * @return The desktop for given model index. If the index is not valid 0279 * or TabBoxMode is not TabBoxConfig::DesktopTabBox -1 will be returned. 0280 * @see DesktopModel::desktopIndex 0281 */ 0282 int desktop(const QModelIndex &index) const; 0283 0284 /** 0285 * Handles additional grabbed key events by the TabBox controller. 0286 * @param event The key event which has been grabbed 0287 */ 0288 virtual void grabbedKeyEvent(QKeyEvent *event) const; 0289 /** 0290 * @param pos The position to be tested in global coordinates 0291 * @return True if the view contains the point, otherwise false. 0292 */ 0293 bool containsPos(const QPoint &pos) const; 0294 /** 0295 * @param client The TabBoxClient whose index should be returned 0296 * @return Returns the ModelIndex of given TabBoxClient or an invalid ModelIndex 0297 * if the model does not contain the given TabBoxClient. 0298 * @see ClientModel::index 0299 */ 0300 QModelIndex index(QWeakPointer<TabBoxClient> client) const; 0301 /** 0302 * @return Returns the current list of TabBoxClients. 0303 * If TabBoxMode is not TabBoxConfig::ClientTabBox an empty list will 0304 * be returned. 0305 * @see ClientModel::clientList 0306 */ 0307 TabBoxClientList clientList() const; 0308 /** 0309 * @param index The index of the client to be returned 0310 * @return Returns the TabBoxClient at given model index. If 0311 * the index is invalid, does not point to a Client or the list 0312 * is empty, NULL will be returned. 0313 */ 0314 TabBoxClient *client(const QModelIndex &index) const; 0315 /** 0316 * @return The first model index. That is the model index at position 0, 0. 0317 * It is valid, as desktop has at least one desktop and if there are no 0318 * clients an empty item is created. 0319 */ 0320 QModelIndex first() const; 0321 0322 bool eventFilter(QObject *watcher, QEvent *event) override; 0323 0324 /** 0325 * @returns whether the TabBox operates in a no modifier grab mode. 0326 * In this mode a click on an item should directly accept and close the tabbox. 0327 */ 0328 virtual bool noModifierGrab() const = 0; 0329 0330 Q_SIGNALS: 0331 /** 0332 * This signal is fired when the TabBoxConfig changes 0333 * @see setConfig 0334 */ 0335 void configChanged(); 0336 void selectedIndexChanged(); 0337 0338 private Q_SLOTS: 0339 void initHighlightWindows(); 0340 0341 private: 0342 friend class TabBoxHandlerPrivate; 0343 TabBoxHandlerPrivate *d; 0344 }; 0345 0346 /** 0347 * This class is a wrapper around a KWin Client. It is used for accessing the 0348 * required client methods from inside TabBox and has to be implemented in KWin core. 0349 * 0350 * @author Martin Gräßlin <mgraesslin@kde.org> 0351 * @since 4.4 0352 */ 0353 class TabBoxClient 0354 { 0355 public: 0356 TabBoxClient(); 0357 virtual ~TabBoxClient(); 0358 0359 /** 0360 * @return The caption of the client 0361 */ 0362 virtual QString caption() const = 0; 0363 /** 0364 * @param size Requested size of the icon 0365 * @return The icon of the client 0366 */ 0367 virtual QIcon icon() const = 0; 0368 /** 0369 * @return Minimized state of the client 0370 */ 0371 virtual bool isMinimized() const = 0; 0372 virtual int x() const = 0; 0373 virtual int y() const = 0; 0374 virtual int width() const = 0; 0375 virtual int height() const = 0; 0376 virtual bool isCloseable() const = 0; 0377 virtual void close() = 0; 0378 virtual bool isFirstInTabBox() const = 0; 0379 virtual QUuid internalId() const = 0; 0380 }; 0381 0382 /** 0383 * Pointer to the global TabBoxHandler object. 0384 */ 0385 extern TabBoxHandler *tabBox; 0386 0387 } // namespace TabBox 0388 } // namespace KWin