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