diff --git a/effectloader.h b/effectloader.h index 7dfee16f4..b817adecf 100644 --- a/effectloader.h +++ b/effectloader.h @@ -1,379 +1,379 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_EFFECT_LOADER_H #define KWIN_EFFECT_LOADER_H #include // KDE #include #include // Qt #include #include #include #include #include namespace KWin { class Effect; class EffectPluginFactory; enum class BuiltInEffect; /** * @brief Flags defining how a Loader should load an Effect. * * These Flags are only used internally when querying the configuration on whether * an Effect should be loaded. * * @see AbstractEffectLoader::readConfig() */ enum class LoadEffectFlag { Load = 1 << 0, ///< Effect should be loaded CheckDefaultFunction = 1 << 2 ///< The Check Default Function needs to be invoked if the Effect provides it }; Q_DECLARE_FLAGS(LoadEffectFlags, LoadEffectFlag) /** * @brief Interface to describe how an effect loader has to function. * * The AbstractEffectLoader specifies the methods a concrete loader has to implement and how * those methods are expected to perform. Also it provides an interface to the outside world * (that is EffectsHandlerImpl). * * The abstraction is used because there are multiple types of Effects which need to be loaded: * @li Built-In Effects * @li Scripted Effects * @li Binary Plugin Effects * * Serving all of them with one Effect Loader is rather complex given that different stores need * to be queried at the same time. Thus the idea is to have one implementation per type and one * implementation which makes use of all of them and combines the loading. */ class KWIN_EXPORT AbstractEffectLoader : public QObject { Q_OBJECT public: virtual ~AbstractEffectLoader(); /** * @brief The KSharedConfig this EffectLoader should operate on. * * Important: a valid KSharedConfig must be provided before trying to load any effects! * * @param config * @internal */ virtual void setConfig(KSharedConfig::Ptr config); /** * @brief Whether this Effect Loader can load the Effect with the given @p name. * * The Effect Loader determines whether it knows or can find an Effect called @p name, * and thus whether it can attempt to load the Effect. * * @param name The name of the Effect to look for. * @return bool @c true if the Effect Loader knows this effect, false otherwise */ virtual bool hasEffect(const QString &name) const = 0; /** * @brief All the Effects this loader knows of. * * The implementation should re-query its store whenever this method is invoked. * It's possible that the store of effects changed (e.g. a new one got installed) * * @return QStringList The internal names of the known Effects */ virtual QStringList listOfKnownEffects() const = 0; /** * @brief Synchronous loading of the Effect with the given @p name. * * Loads the Effect without checking any configuration value or any enabled by default * function provided by the Effect. * * The loader is expected to apply the following checks: * If the Effect is already loaded, the Effect should not get loaded again. Thus the loader * is expected to track which Effects it has loaded, and which of those have been destroyed. * The loader should check whether the Effect is supported. If the Effect indicates it is * not supported, it should not get loaded. * * If the Effect loaded successfully the signal effectLoaded(KWin::Effect*,const QString&) * must be emitted. Otherwise the user of the loader is not able to get the loaded Effect. * It's not returning the Effect as queryAndLoadAll() is working async and thus the users * of the loader are expected to be prepared for async loading. * * @param name The internal name of the Effect which should be loaded * @return bool @c true if the effect could be loaded, @c false in error case * @see queryAndLoadAll() * @see effectLoaded(KWin::Effect*,const QString&) */ virtual bool loadEffect(const QString &name) = 0; /** * @brief The Effect Loader should query its store for all available effects and try to load them. * * The Effect Loader is supposed to perform this operation in a highly async way. If there is * IO which needs to be performed this should be done in a background thread and a queue should * be used to load the effects. The loader should make sure to not load more than one Effect * in one event cycle. Loading the Effect has to be performed in the Compositor thread and * thus blocks the Compositor. Therefore after loading one Effect all events should get * processed first, so that the Compositor can perform a painting pass if needed. To simplify * this operation one can use the EffectLoadQueue. This requires to add another loadEffect * method with the custom loader specific type to refer to an Effect and LoadEffectFlags. * * The LoadEffectFlags have to be determined by querying the configuration with readConfig(). * If the Load flag is set the loading can proceed and all the checks from * loadEffect(const QString &) have to be applied. * In addition if the CheckDefaultFunction flag is set and the Effect provides such a method, * it should be queried to determine whether the Effect is enabled by default. If such a method * returns @c false the Effect should not get loaded. If the Effect does not provide a way to * query whether it's enabled by default at runtime the flag can get ignored. * * If the Effect loaded successfully the signal effectLoaded(KWin::Effect*,const QString&) * must be emitted. * * @see loadEffect(const QString &) * @see effectLoaded(KWin::Effect*,const QString&) */ virtual void queryAndLoadAll() = 0; /** * @brief Whether the Effect with the given @p name is supported by the compositing backend. * * @param name The name of the Effect to check. * @return bool @c true if it is supported, @c false otherwise */ virtual bool isEffectSupported(const QString &name) const = 0; /** * @brief Clears the load queue, that is all scheduled Effects are discarded from loading. **/ virtual void clear() = 0; Q_SIGNALS: /** * @brief The loader emits this signal when it successfully loaded an effect. * * @param effect The created Effect * @param name The internal name of the loaded Effect * @return void */ void effectLoaded(KWin::Effect *effect, const QString &name); protected: explicit AbstractEffectLoader(QObject *parent = nullptr); /** * @brief Checks the configuration for the Effect identified by @p effectName. * * For each Effect there could be a key called "Enabled". If there is such a key * the returned flags will contain Load in case it's @c true. If the key does not exist the * @p defaultValue determines whether the Effect should be loaded. A value of @c true means * that Load | CheckDefaultFunction is returned, in case of @c false no Load flags are returned. * - * @param effecName The name of the Effect to look for in the configuration + * @param effectName The name of the Effect to look for in the configuration * @param defaultValue Whether the Effect is enabled by default or not. * @returns Flags indicating whether the Effect should be loaded and how it should be loaded */ LoadEffectFlags readConfig(const QString &effectName, bool defaultValue) const; private: KSharedConfig::Ptr m_config; }; /** * @brief Helper class to queue the loading of Effects. * * Loading an Effect has to be done in the compositor thread and thus the Compositor is blocked * while the Effect loads. To not block the compositor for several frames the loading of all * Effects need to be queued. By invoking the slot dequeue() through a QueuedConnection the queue * can ensure that events are processed between the loading of two Effects and thus the compositor * doesn't block. * * As it needs to be a slot, the queue must subclass QObject, but it also needs to be templated as * the information to load an Effect is specific to the Effect Loader. Thus there is the * AbstractEffectLoadQueue providing the slots as pure virtual functions and the templated * EffectLoadQueue inheriting from AbstractEffectLoadQueue. * * The queue operates like a normal queue providing enqueue and a scheduleDequeue instead of dequeue. * */ class AbstractEffectLoadQueue : public QObject { Q_OBJECT public: explicit AbstractEffectLoadQueue(QObject *parent = nullptr) : QObject(parent) { } protected Q_SLOTS: virtual void dequeue() = 0; }; template class EffectLoadQueue : public AbstractEffectLoadQueue { public: explicit EffectLoadQueue(Loader *parent) : AbstractEffectLoadQueue(parent) , m_effectLoader(parent) , m_dequeueScheduled(false) { } void enqueue(const QPair value) { m_queue.enqueue(value); scheduleDequeue(); } void clear() { m_queue.clear(); m_dequeueScheduled = false; } protected: void dequeue() override { if (m_queue.isEmpty()) { return; } m_dequeueScheduled = false; const auto pair = m_queue.dequeue(); m_effectLoader->loadEffect(pair.first, pair.second); scheduleDequeue(); } private: void scheduleDequeue() { if (m_queue.isEmpty() || m_dequeueScheduled) { return; } m_dequeueScheduled = true; QMetaObject::invokeMethod(this, "dequeue", Qt::QueuedConnection); } Loader *m_effectLoader; bool m_dequeueScheduled; QQueue> m_queue; }; /** * @brief Can load the Built-In-Effects * */ class BuiltInEffectLoader : public AbstractEffectLoader { Q_OBJECT public: explicit BuiltInEffectLoader(QObject *parent = nullptr); ~BuiltInEffectLoader() override; bool hasEffect(const QString &name) const override; bool isEffectSupported(const QString &name) const override; QStringList listOfKnownEffects() const override; void clear() override; void queryAndLoadAll() override; bool loadEffect(const QString& name) override; bool loadEffect(BuiltInEffect effect, LoadEffectFlags flags); private: bool loadEffect(const QString &name, BuiltInEffect effect, LoadEffectFlags flags); QString internalName(const QString &name) const; EffectLoadQueue *m_queue; QMap m_loadedEffects; }; /** * @brief Can load scripted Effects * */ class KWIN_EXPORT ScriptedEffectLoader : public AbstractEffectLoader { Q_OBJECT public: explicit ScriptedEffectLoader(QObject* parent = nullptr); ~ScriptedEffectLoader() override; bool hasEffect(const QString &name) const override; bool isEffectSupported(const QString &name) const override; QStringList listOfKnownEffects() const override; void clear() override; void queryAndLoadAll() override; bool loadEffect(const QString &name) override; bool loadEffect(const KPluginMetaData &effect, LoadEffectFlags flags); private: QList findAllEffects() const; KPluginMetaData findEffect(const QString &name) const; QStringList m_loadedEffects; EffectLoadQueue< ScriptedEffectLoader, KPluginMetaData > *m_queue; QMetaObject::Connection m_queryConnection; }; class PluginEffectLoader : public AbstractEffectLoader { Q_OBJECT public: explicit PluginEffectLoader(QObject *parent = nullptr); ~PluginEffectLoader() override; bool hasEffect(const QString &name) const override; bool isEffectSupported(const QString &name) const override; QStringList listOfKnownEffects() const override; void clear() override; void queryAndLoadAll() override; bool loadEffect(const QString &name) override; bool loadEffect(const KPluginMetaData &info, LoadEffectFlags flags); void setPluginSubDirectory(const QString &directory); private: QVector findAllEffects() const; KPluginMetaData findEffect(const QString &name) const; EffectPluginFactory *factory(const KPluginMetaData &info) const; QStringList m_loadedEffects; EffectLoadQueue< PluginEffectLoader, KPluginMetaData> *m_queue; QString m_pluginSubDirectory; QMetaObject::Connection m_queryConnection; }; class EffectLoader : public AbstractEffectLoader { Q_OBJECT public: explicit EffectLoader(QObject *parent = nullptr); ~EffectLoader() override; bool hasEffect(const QString &name) const override; bool isEffectSupported(const QString &name) const override; QStringList listOfKnownEffects() const override; bool loadEffect(const QString &name) override; void queryAndLoadAll() override; void setConfig(KSharedConfig::Ptr config) override; void clear() override; private: QList m_loaders; }; } Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::LoadEffectFlags) #endif diff --git a/globalshortcuts.h b/globalshortcuts.h index b491879ac..8efbca7a4 100644 --- a/globalshortcuts.h +++ b/globalshortcuts.h @@ -1,192 +1,192 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2013 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_GLOBALSHORTCUTS_H #define KWIN_GLOBALSHORTCUTS_H // KWin #include // Qt #include class QAction; class KGlobalAccelD; class KGlobalAccelInterface; namespace KWin { class GlobalShortcut; class SwipeGesture; class GestureRecognizer; /** * @brief Manager for the global shortcut system inside KWin. * * This class is responsible for holding all the global shortcuts and to process a key press event. * That is trigger a shortcut if there is a match. * * For internal shortcut handling (those which are delivered inside KWin) QActions are used and * triggered if the shortcut matches. For external shortcut handling a DBus interface is used. **/ class GlobalShortcutsManager : public QObject { Q_OBJECT public: explicit GlobalShortcutsManager(QObject *parent = nullptr); virtual ~GlobalShortcutsManager(); void init(); /** * @brief Registers an internal global pointer shortcut * * @param action The action to trigger if the shortcut is pressed * @param modifiers The modifiers which need to be hold to trigger the action * @param pointerButtons The pointer button which needs to be pressed */ void registerPointerShortcut(QAction *action, Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons); /** * @brief Registers an internal global axis shortcut * * @param action The action to trigger if the shortcut is triggered * @param modifiers The modifiers which need to be hold to trigger the action - * @param pointerButtons The pointer axis + * @param axis The pointer axis */ void registerAxisShortcut(QAction *action, Qt::KeyboardModifiers modifiers, PointerAxisDirection axis); void registerTouchpadSwipe(QAction *action, SwipeDirection direction); /** * @brief Processes a key event to decide whether a shortcut needs to be triggered. * * If a shortcut triggered this method returns @c true to indicate to the caller that the event * should not be further processed. If there is no shortcut which triggered for the key, then * @c false is returned. * * @param modifiers The current hold modifiers * @param keyQt The Qt::Key which got pressed * @return @c true if a shortcut triggered, @c false otherwise */ bool processKey(Qt::KeyboardModifiers modifiers, int keyQt); bool processPointerPressed(Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons); /** * @brief Processes a pointer axis event to decide whether a shortcut needs to be triggered. * * If a shortcut triggered this method returns @c true to indicate to the caller that the event * should not be further processed. If there is no shortcut which triggered for the key, then * @c false is returned. * * @param modifiers The current hold modifiers * @param axis The axis direction which has triggered this event * @return @c true if a shortcut triggered, @c false otherwise */ bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis); void processSwipeStart(uint fingerCount); void processSwipeUpdate(const QSizeF &delta); void processSwipeCancel(); void processSwipeEnd(); void setKGlobalAccelInterface(KGlobalAccelInterface *interface) { m_kglobalAccelInterface = interface; } private: void objectDeleted(QObject *object); QHash > m_pointerShortcuts; QHash > m_axisShortcuts; QHash > m_swipeShortcuts; KGlobalAccelD *m_kglobalAccel = nullptr; KGlobalAccelInterface *m_kglobalAccelInterface = nullptr; GestureRecognizer *m_gestureRecognizer; }; class GlobalShortcut { public: virtual ~GlobalShortcut(); const QKeySequence &shortcut() const; Qt::KeyboardModifiers pointerButtonModifiers() const; Qt::MouseButtons pointerButtons() const; SwipeDirection swipeDirection() const { return m_swipeDirection; } virtual void invoke() = 0; protected: GlobalShortcut(const QKeySequence &shortcut); GlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons); GlobalShortcut(Qt::KeyboardModifiers axisModifiers); GlobalShortcut(SwipeDirection direction); private: QKeySequence m_shortcut; Qt::KeyboardModifiers m_pointerModifiers; Qt::MouseButtons m_pointerButtons; SwipeDirection m_swipeDirection = SwipeDirection::Invalid;; }; class InternalGlobalShortcut : public GlobalShortcut { public: InternalGlobalShortcut(Qt::KeyboardModifiers modifiers, const QKeySequence &shortcut, QAction *action); InternalGlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons, QAction *action); InternalGlobalShortcut(Qt::KeyboardModifiers axisModifiers, PointerAxisDirection axis, QAction *action); InternalGlobalShortcut(Qt::KeyboardModifiers swipeModifier, SwipeDirection direction, QAction *action); virtual ~InternalGlobalShortcut(); void invoke() override; QAction *action() const; SwipeGesture *swipeGesture() const { return m_swipe.data(); } private: QAction *m_action; QScopedPointer m_swipe; }; inline QAction *InternalGlobalShortcut::action() const { return m_action; } inline const QKeySequence &GlobalShortcut::shortcut() const { return m_shortcut; } inline Qt::KeyboardModifiers GlobalShortcut::pointerButtonModifiers() const { return m_pointerModifiers; } inline Qt::MouseButtons GlobalShortcut::pointerButtons() const { return m_pointerButtons; } } // namespace #endif diff --git a/screenedge.h b/screenedge.h index ee10882bb..8157e1f6d 100644 --- a/screenedge.h +++ b/screenedge.h @@ -1,590 +1,590 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2011 Arthur Arlt Copyright (C) 2013 Martin Gräßlin Since the functionality provided in this class has been moved from class Workspace, it is not clear who exactly has written the code. The list below contains the copyright holders of the class Workspace. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak Copyright (C) 2009 Lucas Murray This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_SCREENEDGE_H #define KWIN_SCREENEDGE_H // KWin #include "kwinglobals.h" // KDE includes #include // Qt #include #include #include #include class QAction; class QMouseEvent; namespace KWin { class AbstractClient; class GestureRecognizer; class ScreenEdges; class SwipeGesture; class KWIN_EXPORT Edge : public QObject { Q_OBJECT public: explicit Edge(ScreenEdges *parent); virtual ~Edge(); bool isLeft() const; bool isTop() const; bool isRight() const; bool isBottom() const; bool isCorner() const; bool isScreenEdge() const; bool triggersFor(const QPoint &cursorPos) const; bool check(const QPoint &cursorPos, const QDateTime &triggerTime, bool forceNoPushBack = false); void markAsTriggered(const QPoint &cursorPos, const QDateTime &triggerTime); bool isReserved() const; const QRect &approachGeometry() const; ElectricBorder border() const; void reserve(QObject *object, const char *slot); const QHash &callBacks() const; void reserveTouchCallBack(QAction *action); void unreserveTouchCallBack(QAction *action); QVector touchCallBacks() const { return m_touchActions; } void startApproaching(); void stopApproaching(); bool isApproaching() const; void setClient(AbstractClient *client); AbstractClient *client() const; const QRect &geometry() const; void setTouchAction(ElectricBorderAction action); bool activatesForPointer() const; bool activatesForTouchGesture() const; /** * The window id of the native window representing the edge. * Default implementation returns @c 0, which means no window. **/ virtual quint32 window() const; /** * The approach window is a special window to notice when get close to the screen border but * not yet triggering the border. * * The default implementation returns @c 0, which means no window. **/ virtual quint32 approachWindow() const; public Q_SLOTS: void reserve(); void unreserve(); void unreserve(QObject *object); void setBorder(ElectricBorder border); void setAction(ElectricBorderAction action); void setGeometry(const QRect &geometry); void updateApproaching(const QPoint &point); void checkBlocking(); Q_SIGNALS: void approaching(ElectricBorder border, qreal factor, const QRect &geometry); void activatesForTouchGestureChanged(); protected: ScreenEdges *edges(); const ScreenEdges *edges() const; bool isBlocked() const; virtual void doGeometryUpdate(); virtual void doActivate(); virtual void doDeactivate(); virtual void doStartApproaching(); virtual void doStopApproaching(); virtual void doUpdateBlocking(); private: void activate(); void deactivate(); bool canActivate(const QPoint &cursorPos, const QDateTime &triggerTime); void handle(const QPoint &cursorPos); bool handleAction(ElectricBorderAction action); bool handlePointerAction() { return handleAction(m_action); } bool handleTouchAction() { return handleAction(m_touchAction); } bool handleByCallback(); void handleTouchCallback(); void switchDesktop(const QPoint &cursorPos); void pushCursorBack(const QPoint &cursorPos); ScreenEdges *m_edges; ElectricBorder m_border; ElectricBorderAction m_action; ElectricBorderAction m_touchAction = ElectricActionNone; int m_reserved; QRect m_geometry; QRect m_approachGeometry; QDateTime m_lastTrigger; QDateTime m_lastReset; QPoint m_triggeredPoint; QHash m_callBacks; bool m_approaching; int m_lastApproachingFactor; bool m_blocked; bool m_pushBackBlocked; AbstractClient *m_client; SwipeGesture *m_gesture; QVector m_touchActions; }; /** * @short Class for controlling screen edges. * * The screen edge functionality is split into three parts: * @li This manager class ScreenEdges - * @li abstract class @link Edge - * @li specific implementation of @link Edge, e.g. @link WindowBasedEdge + * @li abstract class @ref Edge + * @li specific implementation of @ref Edge, e.g. @ref WindowBasedEdge * - * The ScreenEdges creates an @link Edge for each screen edge which is also an edge in the + * The ScreenEdges creates an @ref Edge for each screen edge which is also an edge in the * combination of all screens. E.g. if there are two screens, no Edge is created between the screens, * but at all other edges even if the screens have a different dimension. * - * In addition at each corner of the overall display geometry an one-pixel large @link Edge is + * In addition at each corner of the overall display geometry an one-pixel large @ref Edge is * created. No matter how many screens there are, there will only be exactly four of these corner * edges. This is motivated by Fitts's Law which show that it's easy to trigger such a corner, but * it would be very difficult to trigger a corner between two screens (one pixel target not visually * outlined). * * The ScreenEdges are used for one of the following functionality: - * @li switch virtual desktop (see property @link desktopSwitching) - * @li switch virtual desktop when moving a window (see property @link desktopSwitchingMovingClients) - * @li trigger a pre-defined action (see properties @link actionTop and similar) - * @li trigger an externally configured action (e.g. Effect, Script, see @link reserve, @link unreserve) + * @li switch virtual desktop (see property @ref desktopSwitching) + * @li switch virtual desktop when moving a window (see property @ref desktopSwitchingMovingClients) + * @li trigger a pre-defined action (see properties @ref actionTop and similar) + * @li trigger an externally configured action (e.g. Effect, Script, see @ref reserve, @ref unreserve) * - * An @link Edge is only active if there is at least one of the possible actions "reserved" for this + * An @ref Edge is only active if there is at least one of the possible actions "reserved" for this * edge. The idea is to not block the screen edge if nothing could be triggered there, so that the * user e.g. can configure nothing on the top edge, which tends to interfere with full screen apps - * having a hidden panel there. On X11 (currently only supported backend) the @link Edge is - * represented by a @link WindowBasedEdge which creates an input only window for the geometry and + * having a hidden panel there. On X11 (currently only supported backend) the @ref Edge is + * represented by a @ref WindowBasedEdge which creates an input only window for the geometry and * reacts on enter notify events. If the edge gets reserved for the first time a window is created * and mapped, once the edge gets unreserved again, the window gets destroyed. * * When the mouse enters one of the screen edges the following values are used to determine whether * the action should be triggered or the cursor be pushed back * @li Time difference between two entering events is not larger than a certain threshold - * @li Time difference between two entering events is larger than @link timeThreshold - * @li Time difference between two activations is larger than @link reActivateThreshold + * @li Time difference between two entering events is larger than @ref timeThreshold + * @li Time difference between two activations is larger than @ref reActivateThreshold * @li Distance between two enter events is not larger than a defined pixel distance - * These checks are performed in @link Edge + * These checks are performed in @ref Edge * * @todo change way how Effects/Scripts can reserve an edge and are notified. */ class KWIN_EXPORT ScreenEdges : public QObject { Q_OBJECT Q_PROPERTY(bool desktopSwitching READ isDesktopSwitching) Q_PROPERTY(bool desktopSwitchingMovingClients READ isDesktopSwitchingMovingClients) Q_PROPERTY(QSize cursorPushBackDistance READ cursorPushBackDistance) Q_PROPERTY(int timeThreshold READ timeThreshold) Q_PROPERTY(int reActivateThreshold READ reActivationThreshold) Q_PROPERTY(int actionTopLeft READ actionTopLeft) Q_PROPERTY(int actionTop READ actionTop) Q_PROPERTY(int actionTopRight READ actionTopRight) Q_PROPERTY(int actionRight READ actionRight) Q_PROPERTY(int actionBottomRight READ actionBottomRight) Q_PROPERTY(int actionBottom READ actionBottom) Q_PROPERTY(int actionBottomLeft READ actionBottomLeft) Q_PROPERTY(int actionLeft READ actionLeft) public: virtual ~ScreenEdges(); /** * @internal **/ void setConfig(KSharedConfig::Ptr config); /** * Initialize the screen edges. * @internal */ void init(); /** * Check, if a screen edge is entered and trigger the appropriate action * if one is enabled for the current region and the timeout is satisfied * @param pos the position of the mouse pointer * @param now the time when the function is called * @param forceNoPushBack needs to be called to workaround some DnD clients, don't use unless you want to chek on a DnD event */ void check(const QPoint& pos, const QDateTime &now, bool forceNoPushBack = false); /** * The (dpi dependent) length, reserved for the active corners of each edge - 1/3" */ int cornerOffset() const; /** * Mark the specified screen edge as reserved. This method is provided for external activation * like effects and scripts. When the effect/script does no longer need the edge it is supposed - * to call @link unreserve. + * to call @ref unreserve. * @param border the screen edge to mark as reserved * @param object The object on which the @p callback needs to be invoked * @param callback The method name to be invoked - uses QMetaObject::invokeMethod * @see unreserve * @todo: add pointer to script/effect */ void reserve(ElectricBorder border, QObject *object, const char *callback); /** * Mark the specified screen edge as unreserved. This method is provided for external activation - * like effects and scripts. This method is only allowed to be called if @link reserve had been + * like effects and scripts. This method is only allowed to be called if @ref reserve had been * called before for the same @p border. An unbalanced calling of reserve/unreserve leads to the * edge never being active or never being able to deactivate again. * @param border the screen edge to mark as unreserved * @param object the object on which the callback had been invoked * @see reserve * @todo: add pointer to script/effect */ void unreserve(ElectricBorder border, QObject *object); /** * Reserves an edge for the @p client. The idea behind this is to show the @p client if the * screen edge which the @p client borders gets triggered. * * When first called it is tried to create an Edge for the client. This is only done if the * client borders with a screen edge specified by @p border. If the client doesn't border the * screen edge, no Edge gets created and the client is shown again. Otherwise there would not * be a possibility to show the client again. * * On subsequent calls for the client no new Edge is created, but the existing one gets reused * and if the client is already hidden, the Edge gets reserved. * * Once the Edge for the client triggers, the client gets shown again and the Edge unreserved. * The idea is that the Edge can only get activated if the client is currently hidden. * * To make sure that the client can always be shown again the implementation also starts to * track geometry changes and shows the Client again. The same for screen geometry changes. * * The Edge gets automatically destroyed if the client gets released. * @param client The Client for which an Edge should be reserved * @param border The border which the client wants to use, only proper borders are supported (no corners) **/ void reserve(KWin::AbstractClient *client, ElectricBorder border); /** * Mark the specified screen edge as reserved for touch gestures. This method is provided for * external activation like effects and scripts. * When the effect/script does no longer need the edge it is supposed - * to call @link unreserveTouch. + * to call @ref unreserveTouch. * @param border the screen edge to mark as reserved * @param action The action which gets triggered * @see unreserveTouch * @since 5.10 **/ void reserveTouch(ElectricBorder border, QAction *action); /** * Unreserves the specified @p border from activating the @p action for touch gestures. * @see reserveTouch * @since 5.10 **/ void unreserveTouch(ElectricBorder border, QAction *action); /** * Reserve desktop switching for screen edges, if @p isToReserve is @c true. Unreserve otherwise. - * @param reserve indicated weather desktop switching should be reserved or unreseved + * @param isToReserve indicated whether desktop switching should be reserved or unreseved */ void reserveDesktopSwitching(bool isToReserve, Qt::Orientations o); /** * Raise electric border windows to the real top of the screen. We only need * to do this if an effect input window is active. */ void ensureOnTop(); bool isEntered(QMouseEvent *event); /** * Returns a QVector of all existing screen edge windows * @return all existing screen edge windows in a QVector */ QVector< xcb_window_t > windows() const; bool isDesktopSwitching() const; bool isDesktopSwitchingMovingClients() const; const QSize &cursorPushBackDistance() const; /** * Minimum time between the push back of the cursor and the activation by re-entering the edge. **/ int timeThreshold() const; /** * Minimum time between triggers **/ int reActivationThreshold() const; ElectricBorderAction actionTopLeft() const; ElectricBorderAction actionTop() const; ElectricBorderAction actionTopRight() const; ElectricBorderAction actionRight() const; ElectricBorderAction actionBottomRight() const; ElectricBorderAction actionBottom() const; ElectricBorderAction actionBottomLeft() const; ElectricBorderAction actionLeft() const; GestureRecognizer *gestureRecognizer() const { return m_gestureRecognizer; } bool handleDndNotify(xcb_window_t window, const QPoint &point); bool handleEnterNotifiy(xcb_window_t window, const QPoint &point, const QDateTime ×tamp); public Q_SLOTS: void reconfigure(); /** * Updates the layout of virtual desktops and adjust the reserved borders in case of * virtual desktop switching on edges. **/ void updateLayout(); /** * Recreates all edges e.g. after the screen size changes. **/ void recreateEdges(); Q_SIGNALS: /** * Signal emitted during approaching of mouse towards @p border. The @p factor indicates how * far away the mouse is from the approaching area. The values are clamped into [0.0,1.0] with * @c 0.0 meaning far away from the border, @c 1.0 in trigger distance. **/ void approaching(ElectricBorder border, qreal factor, const QRect &geometry); void checkBlocking(); private: enum { ElectricDisabled = 0, ElectricMoveOnly = 1, ElectricAlways = 2 }; void setDesktopSwitching(bool enable); void setDesktopSwitchingMovingClients(bool enable); void setCursorPushBackDistance(const QSize &distance); void setTimeThreshold(int threshold); void setReActivationThreshold(int threshold); void createHorizontalEdge(ElectricBorder border, const QRect &screen, const QRect &fullArea); void createVerticalEdge(ElectricBorder border, const QRect &screen, const QRect &fullArea); Edge *createEdge(ElectricBorder border, int x, int y, int width, int height, bool createAction = true); void setActionForBorder(ElectricBorder border, ElectricBorderAction *oldValue, ElectricBorderAction newValue); void setActionForTouchBorder(ElectricBorder border, ElectricBorderAction newValue); ElectricBorderAction actionForEdge(Edge *edge) const; ElectricBorderAction actionForTouchEdge(Edge *edge) const; void createEdgeForClient(AbstractClient *client, ElectricBorder border); void deleteEdgeForClient(AbstractClient *client); bool m_desktopSwitching; bool m_desktopSwitchingMovingClients; QSize m_cursorPushBackDistance; int m_timeThreshold; int m_reactivateThreshold; Qt::Orientations m_virtualDesktopLayout; QList m_edges; KSharedConfig::Ptr m_config; ElectricBorderAction m_actionTopLeft; ElectricBorderAction m_actionTop; ElectricBorderAction m_actionTopRight; ElectricBorderAction m_actionRight; ElectricBorderAction m_actionBottomRight; ElectricBorderAction m_actionBottom; ElectricBorderAction m_actionBottomLeft; ElectricBorderAction m_actionLeft; QMap m_touchActions; int m_cornerOffset; GestureRecognizer *m_gestureRecognizer; KWIN_SINGLETON(ScreenEdges) }; /********************************************************** * Inlines Edge *********************************************************/ inline bool Edge::isBottom() const { return m_border == ElectricBottom || m_border == ElectricBottomLeft || m_border == ElectricBottomRight; } inline bool Edge::isLeft() const { return m_border == ElectricLeft || m_border == ElectricTopLeft || m_border == ElectricBottomLeft; } inline bool Edge::isRight() const { return m_border == ElectricRight || m_border == ElectricTopRight || m_border == ElectricBottomRight; } inline bool Edge::isTop() const { return m_border == ElectricTop || m_border == ElectricTopLeft || m_border == ElectricTopRight; } inline bool Edge::isCorner() const { return m_border == ElectricTopLeft || m_border == ElectricTopRight || m_border == ElectricBottomRight || m_border == ElectricBottomLeft; } inline bool Edge::isScreenEdge() const { return m_border == ElectricLeft || m_border == ElectricRight || m_border == ElectricTop || m_border == ElectricBottom; } inline bool Edge::isReserved() const { return m_reserved != 0; } inline void Edge::setAction(ElectricBorderAction action) { m_action = action; } inline ScreenEdges *Edge::edges() { return m_edges; } inline const ScreenEdges *Edge::edges() const { return m_edges; } inline const QRect &Edge::geometry() const { return m_geometry; } inline const QRect &Edge::approachGeometry() const { return m_approachGeometry; } inline ElectricBorder Edge::border() const { return m_border; } inline const QHash< QObject *, QByteArray > &Edge::callBacks() const { return m_callBacks; } inline bool Edge::isBlocked() const { return m_blocked; } inline AbstractClient *Edge::client() const { return m_client; } inline bool Edge::isApproaching() const { return m_approaching; } /********************************************************** * Inlines ScreenEdges *********************************************************/ inline void ScreenEdges::setConfig(KSharedConfig::Ptr config) { m_config = config; } inline int ScreenEdges::cornerOffset() const { return m_cornerOffset; } inline const QSize &ScreenEdges::cursorPushBackDistance() const { return m_cursorPushBackDistance; } inline bool ScreenEdges::isDesktopSwitching() const { return m_desktopSwitching; } inline bool ScreenEdges::isDesktopSwitchingMovingClients() const { return m_desktopSwitchingMovingClients; } inline int ScreenEdges::reActivationThreshold() const { return m_reactivateThreshold; } inline int ScreenEdges::timeThreshold() const { return m_timeThreshold; } inline void ScreenEdges::setCursorPushBackDistance(const QSize &distance) { m_cursorPushBackDistance = distance; } inline void ScreenEdges::setDesktopSwitching(bool enable) { if (enable == m_desktopSwitching) { return; } m_desktopSwitching = enable; reserveDesktopSwitching(enable, m_virtualDesktopLayout); } inline void ScreenEdges::setDesktopSwitchingMovingClients(bool enable) { m_desktopSwitchingMovingClients = enable; } inline void ScreenEdges::setReActivationThreshold(int threshold) { Q_ASSERT(threshold >= m_timeThreshold); m_reactivateThreshold = threshold; } inline void ScreenEdges::setTimeThreshold(int threshold) { m_timeThreshold = threshold; } #define ACTION( name ) \ inline ElectricBorderAction ScreenEdges::name() const \ { \ return m_##name; \ } ACTION(actionTopLeft) ACTION(actionTop) ACTION(actionTopRight) ACTION(actionRight) ACTION(actionBottomRight) ACTION(actionBottom) ACTION(actionBottomLeft) ACTION(actionLeft) #undef ACTION } #endif // KWIN_SCREENEDGE_H diff --git a/virtualdesktops.h b/virtualdesktops.h index 0b233ac13..e9fe5a3c9 100644 --- a/virtualdesktops.h +++ b/virtualdesktops.h @@ -1,738 +1,738 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2012 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_VIRTUAL_DESKTOPS_H #define KWIN_VIRTUAL_DESKTOPS_H // KWin #include #include // Qt includes #include #include #include #include // KDE includes #include #include class KLocalizedString; class NETRootInfo; class QAction; namespace KWayland { namespace Server { class PlasmaVirtualDesktopManagementInterface; } } namespace KWin { class KWIN_EXPORT VirtualDesktop : public QObject { Q_OBJECT Q_PROPERTY(QByteArray id READ id CONSTANT) Q_PROPERTY(uint x11DesktopNumber READ x11DesktopNumber NOTIFY x11DesktopNumberChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) public: explicit VirtualDesktop(QObject *parent = nullptr); virtual ~VirtualDesktop(); void setId(const QByteArray &id); QByteArray id() const { return m_id; } void setName(const QString &name); QString name() const { return m_name; } void setX11DesktopNumber(uint number); uint x11DesktopNumber() const { return m_x11DesktopNumber; } Q_SIGNALS: void nameChanged(); void x11DesktopNumberChanged(); /** * Emitted just before the desktop gets destroyed. **/ void aboutToBeDestroyed(); private: QByteArray m_id; QString m_name; int m_x11DesktopNumber = 0; }; /** * @brief Two dimensional grid containing the ID of the virtual desktop at a specific position * in the grid. * * The VirtualDesktopGrid represents a visual layout of the Virtual Desktops as they are in e.g. * a Pager. This grid is used for getting a desktop next to a given desktop in any direction by * making use of the layout information. This allows navigation like move to desktop on left. **/ class VirtualDesktopGrid { public: VirtualDesktopGrid(); ~VirtualDesktopGrid(); void update(const QSize &size, Qt::Orientation orientation, const QVector &desktops); /** * @returns The coords of desktop @a id in grid units. */ QPoint gridCoords(uint id) const; /** * @returns The coords of desktop @a vd in grid units. */ QPoint gridCoords(VirtualDesktop *vd) const; /** * @returns The desktop at the point @a coords or 0 if no desktop exists at that * point. @a coords is to be in grid units. */ VirtualDesktop *at(const QPoint &coords) const; int width() const; int height() const; const QSize &size() const; private: QSize m_size; QVector> m_grid; }; /** * @brief Manages the number of available virtual desktops, the layout of those and which virtual * desktop is the current one. * * This manager is responsible for Virtual Desktop handling inside KWin. It has a property for the * count of available virtual desktops and a property for the currently active virtual desktop. All * changes to the number of virtual desktops and the current virtual desktop need to go through this * manager. * * On all changes a signal is emitted and interested parties should connect to the signal. The manager * itself does not interact with other parts of the system. E.g. it does not hide/show windows of * desktop changes. This is outside the scope of this manager. * * Internally the manager organizes the virtual desktops in a grid allowing to navigate over the * virtual desktops. For this a set of convenient methods are available which allow to get the id * of an adjacent desktop or to switch to an adjacent desktop. Interested parties should make use of * these methods and not replicate the logic to switch to the next desktop. **/ class KWIN_EXPORT VirtualDesktopManager : public QObject { Q_OBJECT /** * The number of virtual desktops currently available. * The ids of the virtual desktops are in the range [1, VirtualDesktopManager::maximum()]. **/ Q_PROPERTY(uint count READ count WRITE setCount NOTIFY countChanged) /** * The id of the virtual desktop which is currently in use. **/ Q_PROPERTY(uint current READ current WRITE setCurrent NOTIFY currentChanged) /** * Whether navigation in the desktop layout wraps around at the borders. **/ Q_PROPERTY(bool navigationWrappingAround READ isNavigationWrappingAround WRITE setNavigationWrappingAround NOTIFY navigationWrappingAroundChanged) public: virtual ~VirtualDesktopManager(); /** * @internal, for X11 case **/ void setRootInfo(NETRootInfo *info); /** * @internal, for Wayland case **/ void setVirtualDesktopManagement(KWayland::Server::PlasmaVirtualDesktopManagementInterface *management); /** * @internal **/ void setConfig(KSharedConfig::Ptr config); /** * @returns Total number of desktops currently in existence. * @see setCount * @see countChanged */ uint count() const; /** * @returns the number of rows the layout has. * @see setRows * @see rowsChanged */ uint rows() const; /** * @returns The ID of the current desktop. * @see setCurrent * @see currentChanged */ uint current() const; /** * @returns The current desktop * @see setCurrent * @see currentChanged **/ VirtualDesktop *currentDesktop() const; /** * Moves to the desktop through the algorithm described by Direction. * @param wrap If @c true wraps around to the other side of the layout * @see setCurrent **/ template void moveTo(bool wrap = false); /** * @returns The name of the @p desktop **/ QString name(uint desktop) const; /** * @returns @c true if navigation at borders of layout wraps around, @c false otherwise * @see setNavigationWrappingAround * @see navigationWrappingAroundChanged **/ bool isNavigationWrappingAround() const; /** * @returns The layout aware virtual desktop grid used by this manager. **/ const VirtualDesktopGrid &grid() const; /** * @returns The ID of the desktop above desktop @a id. Wraps around to the bottom of * the layout if @a wrap is set. If @a id is not set use the current one. */ uint above(uint id = 0, bool wrap = true) const; /** * @returns The desktop above desktop @a desktop. Wraps around to the bottom of * the layout if @a wrap is set. If @a desktop is @c null use the current one. */ VirtualDesktop *above(VirtualDesktop *desktop, bool wrap = true) const; /** * @returns The ID of the desktop to the right of desktop @a id. Wraps around to the * left of the layout if @a wrap is set. If @a id is not set use the current one. */ uint toRight(uint id = 0, bool wrap = true) const; /** * @returns The desktop to the right of desktop @a desktop. Wraps around to the * left of the layout if @a wrap is set. If @a desktop is @c null use the current one. */ VirtualDesktop *toRight(VirtualDesktop *desktop, bool wrap = true) const; /** * @returns The ID of the desktop below desktop @a id. Wraps around to the top of the * layout if @a wrap is set. If @a id is not set use the current one. */ uint below(uint id = 0, bool wrap = true) const; /** * @returns The desktop below desktop @a desktop. Wraps around to the top of the * layout if @a wrap is set. If @a desktop is @c null use the current one. */ VirtualDesktop *below(VirtualDesktop *desktop, bool wrap = true) const; /** * @returns The ID of the desktop to the left of desktop @a id. Wraps around to the * right of the layout if @a wrap is set. If @a id is not set use the current one. */ uint toLeft(uint id = 0, bool wrap = true) const; /** * @returns The desktop to the left of desktop @a desktop. Wraps around to the * right of the layout if @a wrap is set. If @a desktop is @c null use the current one. */ VirtualDesktop *toLeft(VirtualDesktop *desktop, bool wrap = true) const; /** * @returns The desktop after the desktop @a desktop. Wraps around to the first * desktop if @a wrap is set. If @a desktop is @c null use the current desktop. **/ VirtualDesktop *next(VirtualDesktop *desktop = nullptr, bool wrap = true) const; /** * @returns The desktop in front of the desktop @a desktop. Wraps around to the * last desktop if @a wrap is set. If @a desktop is @c null use the current desktop. **/ VirtualDesktop *previous(VirtualDesktop *desktop = nullptr, bool wrap = true) const; void initShortcuts(); /** * @returns all currently managed VirtualDesktops **/ QVector desktops() const { return m_desktops; } /** * @returns The VirtualDesktop for the x11 @p id, if no such VirtualDesktop @c null is returned **/ VirtualDesktop *desktopForX11Id(uint id) const; /** * @returns The VirtualDesktop for the internal desktop string @p id, if no such VirtualDesktop @c null is returned **/ VirtualDesktop *desktopForId(const QByteArray &id) const; /** * Create a new virtual desktop at the requested position. * The difference with setCount is that setCount always adds new desktops at the end of the chain. The Id is automatically generated. * @param x11DesktopNumber number for the desktop. The desktop created will have an * x11DesktopNumber guaranteed to be between 1 and numberOfDesktops(). * Existing desktops will eventually have their x11DesktopNumber increased. * @param name The name for the new desktop, if empty the default name will be used. * @returns the new VirtualDesktop, nullptr if we reached the maximum number of desktops */ VirtualDesktop *createVirtualDesktop(uint x11DesktopNumber, const QString &name = QString()); /** * Remove the virtual desktop identified by id, if it exists * difference with setCount is that is possible to remove an arbitrary desktop, * not only the last one. * @param id the string id of the desktop to remove */ void removeVirtualDesktop(const QByteArray &id); /** * Updates the net root info for new number of desktops **/ void updateRootInfo(); /** * @returns The maximum number of desktops that KWin supports. */ static uint maximum(); public Q_SLOTS: /** * Set the number of available desktops to @a count. This function overrides any previous * grid layout. * There needs to be at least one virtual desktop and the new value is capped at the maximum * number of desktops. A caller of this function cannot expect that the change has been applied. * It is the callers responsibility to either check the @link numberOfDesktops or connect to the * @link countChanged signal. * * In case the @link current desktop is on a desktop higher than the new count, the current desktop * is changed to be the new desktop with highest id. In that situation the signal @link desktopRemoved * is emitted. * @param count The new number of desktops to use * @see count * @see maximum * @see countChanged * @see desktopCreated * @see desktopRemoved */ void setCount(uint count); /** * Set the current desktop to @a current. * @returns True on success, false otherwise. * @see current * @see currentChanged * @see moveTo */ bool setCurrent(uint current); /** * Set the current desktop to @a current. * @returns True on success, false otherwise. * @see current * @see currentChanged * @see moveTo **/ bool setCurrent(VirtualDesktop *current); /** * Updates the layout to a new number of rows. The number of columns will be calculated accordingly */ void setRows(uint rows); /** * Called from within setCount() to ensure the desktop layout is still valid. */ void updateLayout(); /** - * @param enable wrapping around borders for navigation in desktop layout + * @param enabled wrapping around borders for navigation in desktop layout * @see isNavigationWrappingAround * @see navigationWrappingAroundChanged **/ void setNavigationWrappingAround(bool enabled); /** * Loads number of desktops and names from configuration file **/ void load(); /** * Saves number of desktops and names to configuration file **/ void save(); Q_SIGNALS: /** * Signal emitted whenever the number of virtual desktops changes. * @param previousCount The number of desktops prior to the change * @param newCount The new current number of desktops **/ void countChanged(uint previousCount, uint newCount); /** * Signal when the number of rows in the layout changes * @param new number of rows */ void rowsChanged(uint rows); /** * A new desktop has been created * @param desktop the new just crated desktop */ void desktopCreated(KWin::VirtualDesktop *desktop); /** * A desktop has been removed and is about to be deleted * @param desktop the desktop that has been removed. * It's guaranteed to stil la valid pointer when the signal arrives, * but it's about to be deleted. */ void desktopRemoved(KWin::VirtualDesktop *desktop); /** * Signal emitted whenever the current desktop changes. * @param previousDesktop The virtual desktop changed from * @param newDesktop The virtual desktop changed to **/ void currentChanged(uint previousDesktop, uint newDesktop); /** * Signal emitted whenever the desktop layout changes. * @param columns The new number of columns in the layout * @param rows The new number of rows in the layout **/ void layoutChanged(int columns, int rows); /** * Signal emitted whenever the navigationWrappingAround property changes. **/ void navigationWrappingAroundChanged(); private Q_SLOTS: /** * Common slot for all "Switch to Desktop n" shortcuts. * This method uses the sender() method to access some data. * DO NOT CALL DIRECTLY! ONLY TO BE USED FROM AN ACTION! **/ void slotSwitchTo(); /** * Slot for switch to next desktop action. **/ void slotNext(); /** * Slot for switch to previous desktop action. **/ void slotPrevious(); /** * Slot for switch to right desktop action. **/ void slotRight(); /** * Slot for switch to left desktop action. **/ void slotLeft(); /** * Slot for switch to desktop above action. **/ void slotUp(); /** * Slot for switch to desktop below action. **/ void slotDown(); private: /** * Generate a desktop layout from EWMH _NET_DESKTOP_LAYOUT property parameters. */ void setNETDesktopLayout(Qt::Orientation orientation, uint width, uint height, int startingCorner); /** * @returns A default name for the given @p desktop **/ QString defaultName(int desktop) const; /** * Creates all the global keyboard shortcuts for "Switch To Desktop n" actions. **/ void initSwitchToShortcuts(); /** * Creates an action and connects it to the @p slot in this Manager. This method is * meant to be used for the case that an additional information needs to be stored in * the action and the label. * @param name The name of the action to be created * @param label The localized name for the action to be created * @param value An additional value added to the label and to the created action * @param key The global shortcut for the action * @param slot The slot to invoke when the action is triggered **/ QAction *addAction(const QString &name, const KLocalizedString &label, uint value, const QKeySequence &key, void (VirtualDesktopManager::*slot)()); /** * Creates an action and connects it to the @p slot in this Manager. * Overloaded method for the case that no additional value needs to be passed to the action and * no global shortcut is defined by default. * @param name The name of the action to be created * @param label The localized name for the action to be created * @param slot The slot to invoke when the action is triggered **/ QAction *addAction(const QString &name, const QString &label, void (VirtualDesktopManager::*slot)()); QVector m_desktops; QPointer m_current; bool m_navigationWrapsAround; VirtualDesktopGrid m_grid; // TODO: QPointer NETRootInfo *m_rootInfo; KWayland::Server::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr; KSharedConfig::Ptr m_config; bool m_isLoading = false; KWIN_SINGLETON_VARIABLE(VirtualDesktopManager, s_manager) }; /** * Function object to select the desktop above in the layout. * Note: does not switch to the desktop! **/ class DesktopAbove { public: DesktopAbove() {} /** * @param desktop The desktop from which the desktop above should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already topmost desktop * @returns Id of the desktop above @p desktop **/ uint operator() (uint desktop, bool wrap) { return (*this)(VirtualDesktopManager::self()->desktopForX11Id(desktop), wrap)->x11DesktopNumber(); } /** * @param desktop The desktop from which the desktop above should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already topmost desktop * @returns the desktop above @p desktop **/ VirtualDesktop *operator() (VirtualDesktop *desktop, bool wrap) { return VirtualDesktopManager::self()->above(desktop, wrap); } }; /** * Function object to select the desktop below in the layout. * Note: does not switch to the desktop! **/ class DesktopBelow { public: DesktopBelow() {} /** * @param desktop The desktop from which the desktop below should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already lowest desktop * @returns Id of the desktop below @p desktop **/ uint operator() (uint desktop, bool wrap) { return (*this)(VirtualDesktopManager::self()->desktopForX11Id(desktop), wrap)->x11DesktopNumber(); } /** * @param desktop The desktop from which the desktop below should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already lowest desktop * @returns the desktop below @p desktop **/ VirtualDesktop *operator() (VirtualDesktop *desktop, bool wrap) { return VirtualDesktopManager::self()->below(desktop, wrap); } }; /** * Function object to select the desktop to the left in the layout. * Note: does not switch to the desktop! **/ class DesktopLeft { public: DesktopLeft() {} /** * @param desktop The desktop from which the desktop on the left should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already leftmost desktop * @returns Id of the desktop left of @p desktop **/ uint operator() (uint desktop, bool wrap) { return (*this)(VirtualDesktopManager::self()->desktopForX11Id(desktop), wrap)->x11DesktopNumber(); } /** * @param desktop The desktop from which the desktop on the left should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already leftmost desktop * @returns the desktop left of @p desktop **/ VirtualDesktop *operator() (VirtualDesktop *desktop, bool wrap) { return VirtualDesktopManager::self()->toLeft(desktop, wrap); } }; /** * Function object to select the desktop to the right in the layout. * Note: does not switch to the desktop! **/ class DesktopRight { public: DesktopRight() {} /** * @param desktop The desktop from which the desktop on the right should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already rightmost desktop * @returns Id of the desktop right of @p desktop **/ uint operator() (uint desktop, bool wrap) { return (*this)(VirtualDesktopManager::self()->desktopForX11Id(desktop), wrap)->x11DesktopNumber(); } /** * @param desktop The desktop from which the desktop on the right should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already rightmost desktop * @returns the desktop right of @p desktop **/ VirtualDesktop *operator() (VirtualDesktop *desktop, bool wrap) { return VirtualDesktopManager::self()->toRight(desktop, wrap); } }; /** * Function object to select the next desktop in the layout. * Note: does not switch to the desktop! **/ class DesktopNext { public: DesktopNext() {} /** * @param desktop The desktop from which the next desktop should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already last desktop * @returns Id of the next desktop **/ uint operator() (uint desktop, bool wrap) { return (*this)(VirtualDesktopManager::self()->desktopForX11Id(desktop), wrap)->x11DesktopNumber(); } /** * @param desktop The desktop from which the next desktop should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already last desktop * @returns the next desktop **/ VirtualDesktop *operator() (VirtualDesktop *desktop, bool wrap) { return VirtualDesktopManager::self()->next(desktop, wrap); } }; /** * Function object to select the previous desktop in the layout. * Note: does not switch to the desktop! **/ class DesktopPrevious { public: DesktopPrevious() {} /** * @param desktop The desktop from which the previous desktop should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already first desktop * @returns Id of the previous desktop **/ uint operator() (uint desktop, bool wrap) { return (*this)(VirtualDesktopManager::self()->desktopForX11Id(desktop), wrap)->x11DesktopNumber(); } /** * @param desktop The desktop from which the previous desktop should be selected. If @c 0 the current desktop is used * @param wrap Whether to wrap around if already first desktop * @returns the previous desktop **/ VirtualDesktop *operator() (VirtualDesktop *desktop, bool wrap) { return VirtualDesktopManager::self()->previous(desktop, wrap); } }; /** * Helper function to get the ID of a virtual desktop in the direction from * the given @p desktop. If @c 0 the current desktop is used as a starting point. * @param desktop The desktop from which the desktop in given Direction should be selected. * @param wrap Whether desktop navigation wraps around at the borders of the layout * @returns The next desktop in specified direction **/ template uint getDesktop(int desktop = 0, bool wrap = true); template uint getDesktop(int d, bool wrap) { Direction direction; return direction(d, wrap); } inline int VirtualDesktopGrid::width() const { return m_size.width(); } inline int VirtualDesktopGrid::height() const { return m_size.height(); } inline const QSize &VirtualDesktopGrid::size() const { return m_size; } inline uint VirtualDesktopManager::maximum() { return 20; } inline uint VirtualDesktopManager::count() const { return m_desktops.count(); } inline bool VirtualDesktopManager::isNavigationWrappingAround() const { return m_navigationWrapsAround; } inline void VirtualDesktopManager::setRootInfo(NETRootInfo *info) { m_rootInfo = info; } inline void VirtualDesktopManager::setConfig(KSharedConfig::Ptr config) { m_config = config; } inline const VirtualDesktopGrid &VirtualDesktopManager::grid() const { return m_grid; } template void VirtualDesktopManager::moveTo(bool wrap) { Direction functor; setCurrent(functor(nullptr, wrap)); } } // namespace KWin #endif