1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
6     SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
7 
8     SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 
11 #ifndef KWIN_SCRIPTEDEFFECT_H
12 #define KWIN_SCRIPTEDEFFECT_H
13 
14 #include <kwinanimationeffect.h>
15 
16 #include <QJSEngine>
17 #include <QJSValue>
18 
19 class KConfigLoader;
20 class KPluginMetaData;
21 
22 namespace KWin
23 {
24 class KWIN_EXPORT ScriptedEffect : public KWin::AnimationEffect
25 {
26     Q_OBJECT
27     Q_ENUMS(DataRole)
28     Q_ENUMS(Qt::Axis)
29     Q_ENUMS(Anchor)
30     Q_ENUMS(MetaType)
31     Q_ENUMS(EasingCurve)
32     Q_ENUMS(SessionState)
33     /**
34      * The plugin ID of the effect
35      */
36     Q_PROPERTY(QString pluginId READ pluginId CONSTANT)
37     /**
38      * True if we are the active fullscreen effect
39      */
40     Q_PROPERTY(bool isActiveFullScreenEffect READ isActiveFullScreenEffect NOTIFY isActiveFullScreenEffectChanged)
41 public:
42     // copied from kwineffects.h
43     enum DataRole {
44         // Grab roles are used to force all other animations to ignore the window.
45         // The value of the data is set to the Effect's `this` value.
46         WindowAddedGrabRole = 1,
47         WindowClosedGrabRole,
48         WindowMinimizedGrabRole,
49         WindowUnminimizedGrabRole,
50         WindowForceBlurRole, ///< For fullscreen effects to enforce blurring of windows,
51         WindowBlurBehindRole, ///< For single windows to blur behind
52         WindowForceBackgroundContrastRole, ///< For fullscreen effects to enforce the background contrast,
53         WindowBackgroundContrastRole, ///< For single windows to enable Background contrast
54         LanczosCacheRole
55     };
56     enum EasingCurve {
57         GaussianCurve = 128
58     };
scriptFile()59     const QString &scriptFile() const {
60         return m_scriptFile;
61     }
62     void reconfigure(ReconfigureFlags flags) override;
requestedEffectChainPosition()63     int requestedEffectChainPosition() const override {
64         return m_chainPosition;
65     }
66     QString activeConfig() const;
67     void setActiveConfig(const QString &name);
68     static ScriptedEffect *create(const QString &effectName, const QString &pathToScript, int chainPosition);
69     static ScriptedEffect *create(const KPluginMetaData &effect);
70     static bool supported();
71     ~ScriptedEffect() override;
72     /**
73      * Whether another effect has grabbed the @p w with the given @p grabRole.
74      * @param w The window to check
75      * @param grabRole The grab role to check
76      * @returns @c true if another window has grabbed the effect, @c false otherwise
77      */
78     Q_SCRIPTABLE bool isGrabbed(KWin::EffectWindow *w, DataRole grabRole);
79 
80     /**
81      * Grabs the window with the specified role.
82      *
83      * @param w The window.
84      * @param grabRole The grab role.
85      * @param force By default, if the window is already grabbed by another effect,
86      *   then that window won't be grabbed by effect that called this method. If you
87      *   would like to grab a window even if it's grabbed by another effect, then
88      *   pass @c true.
89      * @returns @c true if the window was grabbed successfully, otherwise @c false.
90      */
91     Q_SCRIPTABLE bool grab(KWin::EffectWindow *w, DataRole grabRole, bool force = false);
92 
93     /**
94      * Ungrabs the window with the specified role.
95      *
96      * @param w The window.
97      * @param grabRole The grab role.
98      * @returns @c true if the window was ungrabbed successfully, otherwise @c false.
99      */
100     Q_SCRIPTABLE bool ungrab(KWin::EffectWindow *w, DataRole grabRole);
101 
102     /**
103      * Reads the value from the configuration data for the given key.
104      * @param key The key to search for
105      * @param defaultValue The value to return if the key is not found
106      * @returns The config value if present
107      */
108     Q_SCRIPTABLE QJSValue readConfig(const QString &key, const QJSValue &defaultValue = QJSValue());
109 
110     Q_SCRIPTABLE int displayWidth() const;
111     Q_SCRIPTABLE int displayHeight() const;
112     Q_SCRIPTABLE int animationTime(int defaultTime) const;
113 
114     Q_SCRIPTABLE void registerShortcut(const QString &objectName, const QString &text,
115                                        const QString &keySequence, const QJSValue &callback);
116     Q_SCRIPTABLE bool registerScreenEdge(int edge, const QJSValue &callback);
117     Q_SCRIPTABLE bool unregisterScreenEdge(int edge);
118     Q_SCRIPTABLE bool registerTouchScreenEdge(int edge, const QJSValue &callback);
119     Q_SCRIPTABLE bool unregisterTouchScreenEdge(int edge);
120 
121     Q_SCRIPTABLE quint64 animate(KWin::EffectWindow *window, Attribute attribute, int ms,
122                                  const QJSValue &to, const QJSValue &from = QJSValue(),
123                                  uint metaData = 0, int curve = QEasingCurve::Linear, int delay = 0,
124                                  bool fullScreen = false, bool keepAlive = true);
125     Q_SCRIPTABLE QJSValue animate(const QJSValue &object);
126 
127     Q_SCRIPTABLE quint64 set(KWin::EffectWindow *window, Attribute attribute, int ms,
128                              const QJSValue &to, const QJSValue &from = QJSValue(),
129                              uint metaData = 0, int curve = QEasingCurve::Linear, int delay = 0,
130                              bool fullScreen = false, bool keepAlive = true);
131     Q_SCRIPTABLE QJSValue set(const QJSValue &object);
132 
133     Q_SCRIPTABLE bool retarget(quint64 animationId, const QJSValue &newTarget,
134                                int newRemainingTime = -1);
135     Q_SCRIPTABLE bool retarget(const QList<quint64> &animationIds, const QJSValue &newTarget,
136                                int newRemainingTime = -1);
137 
138     Q_SCRIPTABLE bool redirect(quint64 animationId, Direction direction,
139                                TerminationFlags terminationFlags = TerminateAtSource);
140     Q_SCRIPTABLE bool redirect(const QList<quint64> &animationIds, Direction direction,
141                                TerminationFlags terminationFlags = TerminateAtSource);
142 
143     Q_SCRIPTABLE bool complete(quint64 animationId);
144     Q_SCRIPTABLE bool complete(const QList<quint64> &animationIds);
145 
146     Q_SCRIPTABLE bool cancel(quint64 animationId);
147     Q_SCRIPTABLE bool cancel(const QList<quint64> &animationIds);
148 
screenEdgeCallbacks()149     QHash<int, QJSValueList> &screenEdgeCallbacks() {
150         return m_screenEdgeCallbacks;
151     }
152 
153     QString pluginId() const;
154     bool isActiveFullScreenEffect() const;
155 
156 public Q_SLOTS:
157     bool borderActivated(ElectricBorder border) override;
158 
159 Q_SIGNALS:
160     /**
161      * Signal emitted whenever the effect's config changed.
162      */
163     void configChanged();
164     void animationEnded(KWin::EffectWindow *w, quint64 animationId);
165     void isActiveFullScreenEffectChanged();
166 
167 protected:
168     ScriptedEffect();
169     QJSEngine *engine() const;
170     bool init(const QString &effectName, const QString &pathToScript);
171     void animationEnded(KWin::EffectWindow *w, Attribute a, uint meta) override;
172 
173 private:
174     enum class AnimationType {
175         Animate,
176         Set
177     };
178 
179     QJSValue animate_helper(const QJSValue &object, AnimationType animationType);
180 
181     QJSEngine *m_engine;
182     QString m_effectName;
183     QString m_scriptFile;
184     QHash<int, QJSValueList> m_screenEdgeCallbacks;
185     KConfigLoader *m_config;
186     int m_chainPosition;
187     QHash<int, QAction*> m_touchScreenEdgeCallbacks;
188     Effect *m_activeFullScreenEffect = nullptr;
189 };
190 
191 }
192 
193 #endif // KWIN_SCRIPTEDEFFECT_H
194