File indexing completed on 2024-12-01 13:36:47
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org> 0006 SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #pragma once 0012 0013 #include <kwinanimationeffect.h> 0014 0015 #include <QJSEngine> 0016 #include <QJSValue> 0017 0018 class KConfigLoader; 0019 class KPluginMetaData; 0020 0021 namespace KWin 0022 { 0023 0024 class KWIN_EXPORT ScriptedEffect : public KWin::AnimationEffect 0025 { 0026 Q_OBJECT 0027 Q_ENUMS(DataRole) 0028 Q_ENUMS(Qt::Axis) 0029 Q_ENUMS(Anchor) 0030 Q_ENUMS(MetaType) 0031 Q_ENUMS(EasingCurve) 0032 Q_ENUMS(SessionState) 0033 Q_ENUMS(ElectricBorder) 0034 Q_ENUMS(ShaderTrait) 0035 /** 0036 * The plugin ID of the effect 0037 */ 0038 Q_PROPERTY(QString pluginId READ pluginId CONSTANT) 0039 /** 0040 * True if we are the active fullscreen effect 0041 */ 0042 Q_PROPERTY(bool isActiveFullScreenEffect READ isActiveFullScreenEffect NOTIFY isActiveFullScreenEffectChanged) 0043 0044 public: 0045 // copied from kwineffects.h 0046 enum DataRole { 0047 // Grab roles are used to force all other animations to ignore the window. 0048 // The value of the data is set to the Effect's `this` value. 0049 WindowAddedGrabRole = 1, 0050 WindowClosedGrabRole, 0051 WindowMinimizedGrabRole, 0052 WindowUnminimizedGrabRole, 0053 WindowForceBlurRole, ///< For fullscreen effects to enforce blurring of windows, 0054 WindowBlurBehindRole, ///< For single windows to blur behind 0055 WindowForceBackgroundContrastRole, ///< For fullscreen effects to enforce the background contrast, 0056 WindowBackgroundContrastRole, ///< For single windows to enable Background contrast 0057 }; 0058 enum EasingCurve { 0059 GaussianCurve = 128 0060 }; 0061 // copied from kwinglutils.h 0062 enum class ShaderTrait { 0063 MapTexture = (1 << 0), 0064 UniformColor = (1 << 1), 0065 Modulate = (1 << 2), 0066 AdjustSaturation = (1 << 3), 0067 }; 0068 0069 const QString &scriptFile() const 0070 { 0071 return m_scriptFile; 0072 } 0073 void reconfigure(ReconfigureFlags flags) override; 0074 int requestedEffectChainPosition() const override 0075 { 0076 return m_chainPosition; 0077 } 0078 QString activeConfig() const; 0079 void setActiveConfig(const QString &name); 0080 static ScriptedEffect *create(const QString &effectName, const QString &pathToScript, int chainPosition, const QString &exclusiveCategory); 0081 static ScriptedEffect *create(const KPluginMetaData &effect); 0082 static bool supported(); 0083 ~ScriptedEffect() override; 0084 /** 0085 * Whether another effect has grabbed the @p w with the given @p grabRole. 0086 * @param w The window to check 0087 * @param grabRole The grab role to check 0088 * @returns @c true if another window has grabbed the effect, @c false otherwise 0089 */ 0090 Q_SCRIPTABLE bool isGrabbed(KWin::EffectWindow *w, DataRole grabRole); 0091 0092 /** 0093 * Grabs the window with the specified role. 0094 * 0095 * @param w The window. 0096 * @param grabRole The grab role. 0097 * @param force By default, if the window is already grabbed by another effect, 0098 * then that window won't be grabbed by effect that called this method. If you 0099 * would like to grab a window even if it's grabbed by another effect, then 0100 * pass @c true. 0101 * @returns @c true if the window was grabbed successfully, otherwise @c false. 0102 */ 0103 Q_SCRIPTABLE bool grab(KWin::EffectWindow *w, DataRole grabRole, bool force = false); 0104 0105 /** 0106 * Ungrabs the window with the specified role. 0107 * 0108 * @param w The window. 0109 * @param grabRole The grab role. 0110 * @returns @c true if the window was ungrabbed successfully, otherwise @c false. 0111 */ 0112 Q_SCRIPTABLE bool ungrab(KWin::EffectWindow *w, DataRole grabRole); 0113 0114 /** 0115 * Reads the value from the configuration data for the given key. 0116 * @param key The key to search for 0117 * @param defaultValue The value to return if the key is not found 0118 * @returns The config value if present 0119 */ 0120 Q_SCRIPTABLE QJSValue readConfig(const QString &key, const QJSValue &defaultValue = QJSValue()); 0121 0122 Q_SCRIPTABLE int displayWidth() const; 0123 Q_SCRIPTABLE int displayHeight() const; 0124 Q_SCRIPTABLE int animationTime(int defaultTime) const; 0125 0126 Q_SCRIPTABLE void registerShortcut(const QString &objectName, const QString &text, 0127 const QString &keySequence, const QJSValue &callback); 0128 Q_SCRIPTABLE bool registerScreenEdge(int edge, const QJSValue &callback); 0129 Q_SCRIPTABLE bool registerRealtimeScreenEdge(int edge, const QJSValue &callback); 0130 Q_SCRIPTABLE bool unregisterScreenEdge(int edge); 0131 Q_SCRIPTABLE bool registerTouchScreenEdge(int edge, const QJSValue &callback); 0132 Q_SCRIPTABLE bool unregisterTouchScreenEdge(int edge); 0133 0134 Q_SCRIPTABLE quint64 animate(KWin::EffectWindow *window, Attribute attribute, int ms, 0135 const QJSValue &to, const QJSValue &from = QJSValue(), 0136 uint metaData = 0, int curve = QEasingCurve::Linear, int delay = 0, 0137 bool fullScreen = false, bool keepAlive = true, uint shaderId = 0); 0138 Q_SCRIPTABLE QJSValue animate(const QJSValue &object); 0139 0140 Q_SCRIPTABLE quint64 set(KWin::EffectWindow *window, Attribute attribute, int ms, 0141 const QJSValue &to, const QJSValue &from = QJSValue(), 0142 uint metaData = 0, int curve = QEasingCurve::Linear, int delay = 0, 0143 bool fullScreen = false, bool keepAlive = true, uint shaderId = 0); 0144 Q_SCRIPTABLE QJSValue set(const QJSValue &object); 0145 0146 Q_SCRIPTABLE bool retarget(quint64 animationId, const QJSValue &newTarget, 0147 int newRemainingTime = -1); 0148 Q_SCRIPTABLE bool retarget(const QList<quint64> &animationIds, const QJSValue &newTarget, 0149 int newRemainingTime = -1); 0150 Q_SCRIPTABLE bool freezeInTime(quint64 animationId, qint64 frozenTime); 0151 Q_SCRIPTABLE bool freezeInTime(const QList<quint64> &animationIds, qint64 frozenTime); 0152 0153 Q_SCRIPTABLE bool redirect(quint64 animationId, Direction direction, 0154 TerminationFlags terminationFlags = TerminateAtSource); 0155 Q_SCRIPTABLE bool redirect(const QList<quint64> &animationIds, Direction direction, 0156 TerminationFlags terminationFlags = TerminateAtSource); 0157 0158 Q_SCRIPTABLE bool complete(quint64 animationId); 0159 Q_SCRIPTABLE bool complete(const QList<quint64> &animationIds); 0160 0161 Q_SCRIPTABLE bool cancel(quint64 animationId); 0162 Q_SCRIPTABLE bool cancel(const QList<quint64> &animationIds); 0163 0164 Q_SCRIPTABLE QList<int> touchEdgesForAction(const QString &action) const; 0165 0166 Q_SCRIPTABLE uint addFragmentShader(ShaderTrait traits, const QString &fragmentShaderFile = {}); 0167 0168 Q_SCRIPTABLE void setUniform(uint shaderId, const QString &name, const QJSValue &value); 0169 0170 QHash<int, QJSValueList> &screenEdgeCallbacks() 0171 { 0172 return m_screenEdgeCallbacks; 0173 } 0174 0175 QHash<int, QJSValueList> &realtimeScreenEdgeCallbacks() 0176 { 0177 return m_realtimeScreenEdgeCallbacks; 0178 } 0179 0180 QString pluginId() const; 0181 bool isActiveFullScreenEffect() const; 0182 0183 public Q_SLOTS: 0184 bool borderActivated(ElectricBorder border) override; 0185 0186 Q_SIGNALS: 0187 /** 0188 * Signal emitted whenever the effect's config changed. 0189 */ 0190 void configChanged(); 0191 void animationEnded(KWin::EffectWindow *w, quint64 animationId); 0192 void isActiveFullScreenEffectChanged(); 0193 0194 protected: 0195 ScriptedEffect(); 0196 QJSEngine *engine() const; 0197 bool init(const QString &effectName, const QString &pathToScript); 0198 void animationEnded(KWin::EffectWindow *w, Attribute a, uint meta) override; 0199 0200 private: 0201 enum class AnimationType { 0202 Animate, 0203 Set 0204 }; 0205 0206 QJSValue animate_helper(const QJSValue &object, AnimationType animationType); 0207 0208 GLShader *findShader(uint shaderId) const; 0209 0210 QJSEngine *m_engine; 0211 QString m_effectName; 0212 QString m_scriptFile; 0213 QString m_exclusiveCategory; 0214 QHash<int, QJSValueList> m_screenEdgeCallbacks; 0215 QHash<int, QJSValueList> m_realtimeScreenEdgeCallbacks; 0216 KConfigLoader *m_config; 0217 int m_chainPosition; 0218 QHash<int, QAction *> m_touchScreenEdgeCallbacks; 0219 Effect *m_activeFullScreenEffect = nullptr; 0220 std::map<uint, std::unique_ptr<GLShader>> m_shaders; 0221 uint m_nextShaderId{1u}; 0222 }; 0223 }