/* KWin - the KDE window manager This file is part of the KDE project. SPDX-FileCopyrightText: 2012 Martin Gräßlin SPDX-FileCopyrightText: 2018 David Edmundson SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "effect/animationeffect.h" #include #include class KConfigLoader; class KPluginMetaData; class QAction; namespace KWin { class KWIN_EXPORT ScriptedEffect : public KWin::AnimationEffect { Q_OBJECT Q_ENUMS(DataRole) Q_ENUMS(Qt::Axis) Q_ENUMS(Anchor) Q_ENUMS(MetaType) Q_ENUMS(EasingCurve) Q_ENUMS(SessionState) Q_ENUMS(ElectricBorder) Q_ENUMS(ShaderTrait) /** * The plugin ID of the effect */ Q_PROPERTY(QString pluginId READ pluginId CONSTANT) /** * True if we are the active fullscreen effect */ Q_PROPERTY(bool isActiveFullScreenEffect READ isActiveFullScreenEffect NOTIFY isActiveFullScreenEffectChanged) public: // copied from effecthandler.h enum DataRole { // Grab roles are used to force all other animations to ignore the window. // The value of the data is set to the Effect's `this` value. WindowAddedGrabRole = 1, WindowClosedGrabRole, WindowMinimizedGrabRole, WindowUnminimizedGrabRole, WindowForceBlurRole, ///< For fullscreen effects to enforce blurring of windows, WindowForceBackgroundContrastRole, ///< For fullscreen effects to enforce the background contrast, }; enum EasingCurve { GaussianCurve = 128 }; // copied from kwinglutils.h enum class ShaderTrait { MapTexture = (1 << 0), UniformColor = (1 << 1), Modulate = (1 << 2), AdjustSaturation = (1 << 3), }; const QString &scriptFile() const { return m_scriptFile; } void reconfigure(ReconfigureFlags flags) override; int requestedEffectChainPosition() const override { return m_chainPosition; } QString activeConfig() const; void setActiveConfig(const QString &name); static ScriptedEffect *create(const QString &effectName, const QString &pathToScript, int chainPosition, const QString &exclusiveCategory); static ScriptedEffect *create(const KPluginMetaData &effect); static bool supported(); ~ScriptedEffect() override; /** * Whether another effect has grabbed the @p w with the given @p grabRole. * @param w The window to check * @param grabRole The grab role to check * @returns @c true if another window has grabbed the effect, @c false otherwise */ Q_SCRIPTABLE bool isGrabbed(KWin::EffectWindow *w, DataRole grabRole); /** * Grabs the window with the specified role. * * @param w The window. * @param grabRole The grab role. * @param force By default, if the window is already grabbed by another effect, * then that window won't be grabbed by effect that called this method. If you * would like to grab a window even if it's grabbed by another effect, then * pass @c true. * @returns @c true if the window was grabbed successfully, otherwise @c false. */ Q_SCRIPTABLE bool grab(KWin::EffectWindow *w, DataRole grabRole, bool force = false); /** * Ungrabs the window with the specified role. * * @param w The window. * @param grabRole The grab role. * @returns @c true if the window was ungrabbed successfully, otherwise @c false. */ Q_SCRIPTABLE bool ungrab(KWin::EffectWindow *w, DataRole grabRole); /** * Reads the value from the configuration data for the given key. * @param key The key to search for * @param defaultValue The value to return if the key is not found * @returns The config value if present */ Q_SCRIPTABLE QJSValue readConfig(const QString &key, const QJSValue &defaultValue = QJSValue()); Q_SCRIPTABLE int displayWidth() const; Q_SCRIPTABLE int displayHeight() const; Q_SCRIPTABLE int animationTime(int defaultTime) const; Q_SCRIPTABLE void registerShortcut(const QString &objectName, const QString &text, const QString &keySequence, const QJSValue &callback); Q_SCRIPTABLE bool registerScreenEdge(int edge, const QJSValue &callback); Q_SCRIPTABLE bool registerRealtimeScreenEdge(int edge, const QJSValue &callback); Q_SCRIPTABLE bool unregisterScreenEdge(int edge); Q_SCRIPTABLE bool registerTouchScreenEdge(int edge, const QJSValue &callback); Q_SCRIPTABLE bool unregisterTouchScreenEdge(int edge); Q_SCRIPTABLE quint64 animate(KWin::EffectWindow *window, Attribute attribute, int ms, const QJSValue &to, const QJSValue &from = QJSValue(), uint metaData = 0, int curve = QEasingCurve::Linear, int delay = 0, bool fullScreen = false, bool keepAlive = true, uint shaderId = 0); Q_SCRIPTABLE QJSValue animate(const QJSValue &object); Q_SCRIPTABLE quint64 set(KWin::EffectWindow *window, Attribute attribute, int ms, const QJSValue &to, const QJSValue &from = QJSValue(), uint metaData = 0, int curve = QEasingCurve::Linear, int delay = 0, bool fullScreen = false, bool keepAlive = true, uint shaderId = 0); Q_SCRIPTABLE QJSValue set(const QJSValue &object); Q_SCRIPTABLE bool retarget(quint64 animationId, const QJSValue &newTarget, int newRemainingTime = -1); Q_SCRIPTABLE bool retarget(const QList &animationIds, const QJSValue &newTarget, int newRemainingTime = -1); Q_SCRIPTABLE bool freezeInTime(quint64 animationId, qint64 frozenTime); Q_SCRIPTABLE bool freezeInTime(const QList &animationIds, qint64 frozenTime); Q_SCRIPTABLE bool redirect(quint64 animationId, Direction direction, TerminationFlags terminationFlags = TerminateAtSource); Q_SCRIPTABLE bool redirect(const QList &animationIds, Direction direction, TerminationFlags terminationFlags = TerminateAtSource); Q_SCRIPTABLE bool complete(quint64 animationId); Q_SCRIPTABLE bool complete(const QList &animationIds); Q_SCRIPTABLE bool cancel(quint64 animationId); Q_SCRIPTABLE bool cancel(const QList &animationIds); Q_SCRIPTABLE QList touchEdgesForAction(const QString &action) const; Q_SCRIPTABLE uint addFragmentShader(ShaderTrait traits, const QString &fragmentShaderFile = {}); Q_SCRIPTABLE void setUniform(uint shaderId, const QString &name, const QJSValue &value); QHash &screenEdgeCallbacks() { return m_screenEdgeCallbacks; } QHash &realtimeScreenEdgeCallbacks() { return m_realtimeScreenEdgeCallbacks; } QString pluginId() const; bool isActiveFullScreenEffect() const; public Q_SLOTS: bool borderActivated(ElectricBorder border) override; Q_SIGNALS: /** * Signal emitted whenever the effect's config changed. */ void configChanged(); void animationEnded(KWin::EffectWindow *w, quint64 animationId); void isActiveFullScreenEffectChanged(); protected: ScriptedEffect(); QJSEngine *engine() const; bool init(const QString &effectName, const QString &pathToScript); void animationEnded(KWin::EffectWindow *w, Attribute a, uint meta) override; private: enum class AnimationType { Animate, Set }; QJSValue animate_helper(const QJSValue &object, AnimationType animationType); GLShader *findShader(uint shaderId) const; QJSEngine *m_engine; QString m_effectName; QString m_scriptFile; QString m_exclusiveCategory; QHash m_screenEdgeCallbacks; QHash m_realtimeScreenEdgeCallbacks; KConfigLoader *m_config; int m_chainPosition; QHash m_touchScreenEdgeCallbacks; Effect *m_activeFullScreenEffect = nullptr; std::map> m_shaders; uint m_nextShaderId{1u}; }; }