kwineffects.h 137 KB
Newer Older
Vlad Zahorodnii's avatar
Vlad Zahorodnii committed
1 2 3
/*
    KWin - the KDE window manager
    This file is part of the KDE project.
4

Vlad Zahorodnii's avatar
Vlad Zahorodnii committed
5 6 7 8
    SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
    SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
    SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
    SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
9

Vlad Zahorodnii's avatar
Vlad Zahorodnii committed
10 11
    SPDX-License-Identifier: GPL-2.0-or-later
*/
12

13 14
#ifndef KWINEFFECTS_H
#define KWINEFFECTS_H
15

16
#include <kwinconfig.h>
17
#include <kwineffects_export.h>
18 19
#include <kwinglobals.h>

20
#include <QEasingCurve>
21
#include <QIcon>
22 23 24
#include <QPair>
#include <QSet>
#include <QRect>
25 26 27
#include <QRegion>
#include <QVector2D>
#include <QVector3D>
28

29
#include <QVector>
30
#include <QLoggingCategory>
31 32 33
#include <QList>
#include <QHash>
#include <QStack>
34
#include <QScopedPointer>
35

36
#include <KPluginFactory>
37
#include <KSharedConfig>
Bernhard Loos's avatar
Bernhard Loos committed
38

Thomas Lübking's avatar
Thomas Lübking committed
39
#include <netwm.h>
40

41
#include <climits>
42 43
#include <functional>

44
class KConfigGroup;
Martin Flöser's avatar
Martin Flöser committed
45
class QFont;
46
class QKeyEvent;
47
class QMatrix4x4;
48
class QAction;
49

50 51 52
/**
 * Logging category to be used inside the KWin effects.
 * Do not use in this library.
53
 */
Allen Winter's avatar
Allen Winter committed
54
Q_DECLARE_LOGGING_CATEGORY(KWINEFFECTS)
55

56 57 58
namespace KWaylandServer {
    class SurfaceInterface;
    class Display;
59 60
}

61 62 63
namespace KWin
{

64
class PaintDataPrivate;
65
class WindowPaintDataPrivate;
66

67 68
class EffectWindow;
class EffectWindowGroup;
69
class EffectFrame;
70
class EffectFramePrivate;
71
class EffectQuickView;
72
class Effect;
73
class WindowQuad;
74
class GLShader;
75
class XRenderPicture;
76 77 78 79 80
class WindowQuadList;
class WindowPrePaintData;
class WindowPaintData;
class ScreenPrePaintData;
class ScreenPaintData;
81 82

typedef QPair< QString, Effect* > EffectPair;
83
typedef QList< KWin::EffectWindow* > EffectWindowList;
84 85


86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/** @defgroup kwineffects KWin effects library
 * KWin effects library contains necessary classes for creating new KWin
 * compositing effects.
 *
 * @section creating Creating new effects
 * This example will demonstrate the basics of creating an effect. We'll use
 *  CoolEffect as the class name, cooleffect as internal name and
 *  "Cool Effect" as user-visible name of the effect.
 *
 * This example doesn't demonstrate how to write the effect's code. For that,
 *  see the documentation of the Effect class.
 *
 * @subsection creating-class CoolEffect class
 * First you need to create CoolEffect class which has to be a subclass of
 *  @ref KWin::Effect. In that class you can reimplement various virtual
 *  methods to control how and where the windows are drawn.
 *
103 104 105 106 107
 * @subsection creating-macro KWIN_EFFECT_FACTORY macro
 * This library provides a specialized KPluginFactory subclass and macros to
 * create a sub class. This subclass of KPluginFactory has to be used, otherwise
 * KWin won't load the plugin. Use the @ref KWIN_EFFECT_FACTORY macro to create the
 * plugin factory.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
 *
 * @subsection creating-buildsystem Buildsystem
 * To build the effect, you can use the KWIN_ADD_EFFECT() cmake macro which
 *  can be found in effects/CMakeLists.txt file in KWin's source. First
 *  argument of the macro is the name of the library that will contain
 *  your effect. Although not strictly required, it is usually a good idea to
 *  use the same name as your effect's internal name there. Following arguments
 *  to the macro are the files containing your effect's source. If our effect's
 *  source is in cooleffect.cpp, we'd use following:
 * @code
 *  KWIN_ADD_EFFECT(cooleffect cooleffect.cpp)
 * @endcode
 *
 * This macro takes care of compiling your effect. You'll also need to install
 *  your effect's .desktop file, so the example CMakeLists.txt file would be
 *  as follows:
 * @code
 *  KWIN_ADD_EFFECT(cooleffect cooleffect.cpp)
 *  install( FILES cooleffect.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
 * @endcode
 *
 * @subsection creating-desktop Effect's .desktop file
 * You will also need to create .desktop file to set name, description, icon
 *  and other properties of your effect. Important fields of the .desktop file
 *  are:
 *  @li Name User-visible name of your effect
 *  @li Icon Name of the icon of the effect
 *  @li Comment Short description of the effect
 *  @li Type must be "Service"
 *  @li X-KDE-ServiceTypes must be "KWin/Effect"
 *  @li X-KDE-PluginInfo-Name effect's internal name as passed to the KWIN_EFFECT macro plus "kwin4_effect_" prefix
 *  @li X-KDE-PluginInfo-Category effect's category. Should be one of Appearance, Accessibility, Window Management, Demos, Tests, Misc
 *  @li X-KDE-PluginInfo-EnabledByDefault whether the effect should be enabled by default (use sparingly). Default is false
 *  @li X-KDE-Library name of the library containing the effect. This is the first argument passed to the KWIN_ADD_EFFECT macro in cmake file plus "kwin4_effect_" prefix.
 *
 * Example cooleffect.desktop file follows:
 * @code
[Desktop Entry]
Name=Cool Effect
Comment=The coolest effect you've ever seen
Icon=preferences-system-windows-effect-cooleffect

Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=My Name
X-KDE-PluginInfo-Email=my@email.here
X-KDE-PluginInfo-Name=kwin4_effect_cooleffect
X-KDE-PluginInfo-Category=Misc
X-KDE-Library=kwin4_effect_cooleffect
 * @endcode
 *
 *
 * @section accessing Accessing windows and workspace
 * Effects can gain access to the properties of windows and workspace via
 *  EffectWindow and EffectsHandler classes.
 *
 * There is one global EffectsHandler object which you can access using the
 *  @ref effects pointer.
 * For each window, there is an EffectWindow object which can be used to read
 *  window properties such as position and also to change them.
 *
 * For more information about this, see the documentation of the corresponding
 *  classes.
 *
 * @{
173
 */
174 175 176

#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0
177
#define KWIN_EFFECT_API_VERSION_MINOR 232
178
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
179
        KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
180

181
enum WindowQuadType {
182 183
    WindowQuadError, // for the stupid default ctor
    WindowQuadContents,
184
    WindowQuadDecoration,
185
    // Shadow Quad types
Fredrik Höglund's avatar
Fredrik Höglund committed
186
    WindowQuadShadow,             // OpenGL only. The other shadow types are only used by Xrender
187 188 189 190 191 192 193 194
    WindowQuadShadowTop,
    WindowQuadShadowTopRight,
    WindowQuadShadowRight,
    WindowQuadShadowBottomRight,
    WindowQuadShadowBottom,
    WindowQuadShadowBottomLeft,
    WindowQuadShadowLeft,
    WindowQuadShadowTopLeft,
195
    EFFECT_QUAD_TYPE_START = 100 ///< @internal
196
};
197

198 199 200
/**
 * EffectWindow::setData() and EffectWindow::data() global roles.
 * All values between 0 and 999 are reserved for global roles.
201
 */
202
enum DataRole {
203 204 205 206 207
    // 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,
208
    WindowUnminimizedGrabRole,
209
    WindowForceBlurRole, ///< For fullscreen effects to enforce blurring of windows,
210
    WindowBlurBehindRole, ///< For single windows to blur behind
211 212
    WindowForceBackgroundContrastRole, ///< For fullscreen effects to enforce the background contrast,
    WindowBackgroundContrastRole, ///< For single windows to enable Background contrast
213
    LanczosCacheRole
214
};
215

216 217 218
/**
 * Style types used by @ref EffectFrame.
 * @since 4.6
219
 */
220
enum EffectFrameStyle {
221 222 223
    EffectFrameNone, ///< Displays no frame around the contents.
    EffectFrameUnstyled, ///< Displays a basic box around the contents.
    EffectFrameStyled ///< Displays a Plasma-styled frame around the contents.
224
};
225

226 227
/**
 * Infinite region (i.e. a special region type saying that everything needs to be painted).
228
 */
229
KWINEFFECTS_EXPORT inline
230
QRect infiniteRegion()
231 232 233 234
{
    // INT_MIN / 2 because width/height is used (INT_MIN+INT_MAX==-1)
    return QRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX);
}
235

Rivo Laks's avatar
Rivo Laks committed
236 237 238 239 240 241
/**
 * @short Base class for all KWin effects
 *
 * This is the base class for all effects. By reimplementing virtual methods
 *  of this class, you can customize how the windows are painted.
 *
242 243 244 245 246
 * The virtual methods are used for painting and need to be implemented for
 * custom painting.
 *
 * In order to react to state changes (e.g. a window gets closed) the effect
 * should provide slots for the signals emitted by the EffectsHandler.
Rivo Laks's avatar
Rivo Laks committed
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
 *
 * @section Chaining
 * Most methods of this class are called in chain style. This means that when
 *  effects A and B area active then first e.g. A::paintWindow() is called and
 *  then from within that method B::paintWindow() is called (although
 *  indirectly). To achieve this, you need to make sure to call corresponding
 *  method in EffectsHandler class from each such method (using @ref effects
 *  pointer):
 * @code
 *  void MyEffect::postPaintScreen()
 *  {
 *      // Do your own processing here
 *      ...
 *      // Call corresponding EffectsHandler method
 *      effects->postPaintScreen();
 *  }
 * @endcode
 *
 * @section Effectsptr Effects pointer
 * @ref effects pointer points to the global EffectsHandler object that you can
 *  use to interact with the windows.
 *
 * @section painting Painting stages
 * Painting of windows is done in three stages:
 * @li First, the prepaint pass.<br>
 *  Here you can specify how the windows will be painted, e.g. that they will
 *  be translucent and transformed.
 * @li Second, the paint pass.<br>
 *  Here the actual painting takes place. You can change attributes such as
 *  opacity of windows as well as apply transformations to them. You can also
 *  paint something onto the screen yourself.
 * @li Finally, the postpaint pass.<br>
 *  Here you can mark windows, part of windows or even the entire screen for
 *  repainting to create animations.
 *
 * For each stage there are *Screen() and *Window() methods. The window method
283
 *  is called for every window while the screen method is usually called just
Rivo Laks's avatar
Rivo Laks committed
284
 *  once.
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
 *
 * @section OpenGL
 * Effects can use OpenGL if EffectsHandler::isOpenGLCompositing() returns @c true.
 * The OpenGL context may not always be current when code inside the effect is
 * executed. The framework ensures that the OpenGL context is current when the Effect
 * gets created, destroyed or reconfigured and during the painting stages. All virtual
 * methods which have the OpenGL context current are documented.
 *
 * If OpenGL code is going to be executed outside the painting stages, e.g. in reaction
 * to a global shortcut, it is the task of the Effect to make the OpenGL context current:
 * @code
 * effects->makeOpenGLContextCurrent();
 * @endcode
 *
 * There is in general no need to call the matching doneCurrent method.
300
 */
301
class KWINEFFECTS_EXPORT Effect : public QObject
302
{
303
    Q_OBJECT
304 305 306 307
public:
    /** Flags controlling how painting is done. */
    // TODO: is that ok here?
    enum {
Rivo Laks's avatar
Rivo Laks committed
308
        /**
309
         * Window (or at least part of it) will be painted opaque.
310
         */
311
        PAINT_WINDOW_OPAQUE         = 1 << 0,
Rivo Laks's avatar
Rivo Laks committed
312
        /**
313
         * Window (or at least part of it) will be painted translucent.
314
         */
315
        PAINT_WINDOW_TRANSLUCENT    = 1 << 1,
316
        /**
317
         * Window will be painted with transformed geometry.
318
         */
319
        PAINT_WINDOW_TRANSFORMED    = 1 << 2,
Rivo Laks's avatar
Rivo Laks committed
320
        /**
321 322
         * Paint only a region of the screen (can be optimized, cannot
         * be used together with TRANSFORMED flags).
323
         */
324
        PAINT_SCREEN_REGION         = 1 << 3,
Rivo Laks's avatar
Rivo Laks committed
325
        /**
326 327
         * The whole screen will be painted with transformed geometry.
         * Forces the entire screen to be painted.
328
         */
329
        PAINT_SCREEN_TRANSFORMED    = 1 << 4,
Rivo Laks's avatar
Rivo Laks committed
330
        /**
331 332
         * At least one window will be painted with transformed geometry.
         * Forces the entire screen to be painted.
333
         */
334
        PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS = 1 << 5,
Rivo Laks's avatar
Rivo Laks committed
335
        /**
336
         * Clear whole background as the very first step, without optimizing it
337
         */
338
        PAINT_SCREEN_BACKGROUND_FIRST = 1 << 6,
339
        // PAINT_DECORATION_ONLY = 1 << 7 has been deprecated
340
        /**
341
         * Window will be painted with a lanczos filter.
342
         */
Laurent Montel's avatar
Laurent Montel committed
343
        PAINT_WINDOW_LANCZOS = 1 << 8
344
        // PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_WITHOUT_FULL_REPAINTS = 1 << 9 has been removed
345
    };
346

347
    enum Feature {
348 349 350 351 352 353 354 355
        Nothing = 0,
        Resize,
        GeometryTip,
        Outline, /**< @deprecated */
        ScreenInversion,
        Blur,
        Contrast,
        HighlightWindows
356
    };
357

358 359
    /**
     * Constructs new Effect object.
360 361 362
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when the Effect is constructed.
363
     */
364 365 366
    Effect();
    /**
     * Destructs the Effect object.
367 368 369
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when the Effect is destroyed.
370
     */
371
    ~Effect() override;
372 373 374

    /**
     * Flags describing which parts of configuration have changed.
375
     */
376 377
    enum ReconfigureFlag {
        ReconfigureAll = 1 << 0 /// Everything needs to be reconfigured.
378
    };
379 380 381 382
    Q_DECLARE_FLAGS(ReconfigureFlags, ReconfigureFlag)

    /**
     * Called when configuration changes (either the effect's or KWin's global).
383 384 385 386
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when the Effect is reconfigured. If this method is called from within the Effect it is
     * required to ensure that the context is current if the implementation does OpenGL calls.
387
     */
388 389 390 391
    virtual void reconfigure(ReconfigureFlags flags);

    /**
     * Called when another effect requests the proxy for this effect.
392
     */
393 394 395 396 397 398 399 400 401
    virtual void* proxy();

    /**
     * Called before starting to paint the screen.
     * In this method you can:
     * @li set whether the windows or the entire screen will be transformed
     * @li change the region of the screen that will be painted
     * @li do various housekeeping tasks such as initing your effect's variables
            for the upcoming paint pass or updating animation's progress
402 403 404
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
405
    */
406 407 408 409 410 411 412
    virtual void prePaintScreen(ScreenPrePaintData& data, int time);
    /**
     * In this method you can:
     * @li paint something on top of the windows (by painting after calling
     *      effects->paintScreen())
     * @li paint multiple desktops and/or multiple copies of the same desktop
     *      by calling effects->paintScreen() multiple times
413 414 415
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
416
     */
Albert Astals Cid's avatar
Albert Astals Cid committed
417
    virtual void paintScreen(int mask, const QRegion &region, ScreenPaintData& data);
418 419 420 421 422
    /**
     * Called after all the painting has been finished.
     * In this method you can:
     * @li schedule next repaint in case of animations
     * You shouldn't paint anything here.
423 424 425
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
426
     */
427 428 429 430 431 432 433 434 435
    virtual void postPaintScreen();

    /**
     * Called for every window before the actual paint pass
     * In this method you can:
     * @li enable or disable painting of the window (e.g. enable paiting of minimized window)
     * @li set window to be painted with translucency
     * @li set window to be transformed
     * @li request the window to be divided into multiple parts
436 437 438
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
439
     */
440 441 442 443 444 445 446
    virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time);
    /**
     * This is the main method for painting windows.
     * In this method you can:
     * @li do various transformations
     * @li change opacity of the window
     * @li change brightness and/or saturation, if it's supported
447 448 449
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
450
     */
451 452 453 454 455 456
    virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
    /**
     * Called for every window after all painting has been finished.
     * In this method you can:
     * @li schedule next repaint for individual window(s) in case of animations
     * You shouldn't paint anything here.
457 458 459
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
460
     */
461 462 463 464 465 466 467 468 469 470 471
    virtual void postPaintWindow(EffectWindow* w);

    /**
     * This method is called directly before painting an @ref EffectFrame.
     * You can implement this method if you need to bind a shader or perform
     * other operations before the frame is rendered.
     * @param frame The EffectFrame which will be rendered
     * @param region Region to restrict painting to
     * @param opacity Opacity of text/icon
     * @param frameOpacity Opacity of background
     * @since 4.6
472 473 474
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
475
     */
Albert Astals Cid's avatar
Albert Astals Cid committed
476
    virtual void paintEffectFrame(EffectFrame* frame, const QRegion &region, double opacity, double frameOpacity);
477 478 479

    /**
     * Called on Transparent resizes.
480
     * return true if your effect substitutes questioned feature
481
     */
482 483
    virtual bool provides(Feature);

484 485 486 487 488 489 490 491 492 493
    /**
     * Performs the @p feature with the @p arguments.
     *
     * This allows to have specific protocols between KWin core and an Effect.
     *
     * The method is supposed to return @c true if it performed the features,
     * @c false otherwise.
     *
     * The default implementation returns @c false.
     * @since 5.8
494
     */
495 496
    virtual bool perform(Feature feature, const QVariantList &arguments);

497 498 499
    /**
     * Can be called to draw multiple copies (e.g. thumbnails) of a window.
     * You can change window's opacity/brightness/etc here, but you can't
500 501 502 503
     *  do any transformations.
     *
     * In OpenGL based compositing, the frameworks ensures that the context is current
     * when this method is invoked.
504
     */
Albert Astals Cid's avatar
Albert Astals Cid committed
505
    virtual void drawWindow(EffectWindow* w, int mask, const QRegion &region, WindowPaintData& data);
506 507 508 509

    /**
     * Define new window quads so that they can be transformed by other effects.
     * It's up to the effect to keep track of them.
510
     */
511 512
    virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList);

513
    virtual void windowInputMouseEvent(QEvent* e);
514 515
    virtual void grabbedKeyboardEvent(QKeyEvent* e);

516 517 518 519 520 521 522 523 524 525 526 527 528 529
    /**
     * Overwrite this method to indicate whether your effect will be doing something in
     * the next frame to be rendered. If the method returns @c false the effect will be
     * excluded from the chained methods in the next rendered frame.
     *
     * This method is called always directly before the paint loop begins. So it is totally
     * fine to e.g. react on a window event, issue a repaint to trigger an animation and
     * change a flag to indicate that this method returns @c true.
     *
     * As the method is called each frame, you should not perform complex calculations.
     * Best use just a boolean flag.
     *
     * The default implementation of this method returns @c true.
     * @since 4.8
530
     */
531 532
    virtual bool isActive() const;

533 534
    /**
     * Reimplement this method to provide online debugging.
Yuri Chornoivan's avatar
Yuri Chornoivan committed
535
     * This could be as trivial as printing specific detail information about the effect state
536 537 538 539 540 541 542
     * but could also be used to move the effect in and out of a special debug modes, clear bogus
     * data, etc.
     * Notice that the functions is const by intent! Whenever you alter the state of the object
     * due to random user input, you should do so with greatest care, hence const_cast<> your
     * object - signalling "let me alone, i know what i'm doing"
     * @param parameter A freeform string user input for your effect to interpret.
     * @since 4.11
543
     */
544 545
    virtual QString debug(const QString &parameter) const;

546 547 548 549 550 551 552 553 554 555 556
    /**
     * Reimplement this method to indicate where in the Effect chain the Effect should be placed.
     *
     * A low number indicates early chain position, thus before other Effects got called, a high
     * number indicates a late position. The returned number should be in the interval [0, 100].
     * The default value is 0.
     *
     * In KWin4 this information was provided in the Effect's desktop file as property
     * X-KDE-Ordering. In the case of Scripted Effects this property is still used.
     *
     * @since 5.0
557
     */
558 559
    virtual int requestedEffectChainPosition() const;

560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578

    /**
     * A touch point was pressed.
     *
     * If the effect wants to exclusively use the touch event it should return @c true.
     * If @c false is returned the touch event is passed to further effects.
     *
     * In general an Effect should only return @c true if it is the exclusive effect getting
     * input events. E.g. has grabbed mouse events.
     *
     * Default implementation returns @c false.
     *
     * @param id The unique id of the touch point
     * @param pos The position of the touch point in global coordinates
     * @param time Timestamp
     *
     * @see touchMotion
     * @see touchUp
     * @since 5.8
579
     */
580
    virtual bool touchDown(qint32 id, const QPointF &pos, quint32 time);
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
    /**
     * A touch point moved.
     *
     * If the effect wants to exclusively use the touch event it should return @c true.
     * If @c false is returned the touch event is passed to further effects.
     *
     * In general an Effect should only return @c true if it is the exclusive effect getting
     * input events. E.g. has grabbed mouse events.
     *
     * Default implementation returns @c false.
     *
     * @param id The unique id of the touch point
     * @param pos The position of the touch point in global coordinates
     * @param time Timestamp
     *
     * @see touchDown
     * @see touchUp
     * @since 5.8
599
     */
600
    virtual bool touchMotion(qint32 id, const QPointF &pos, quint32 time);
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
    /**
     * A touch point was released.
     *
     * If the effect wants to exclusively use the touch event it should return @c true.
     * If @c false is returned the touch event is passed to further effects.
     *
     * In general an Effect should only return @c true if it is the exclusive effect getting
     * input events. E.g. has grabbed mouse events.
     *
     * Default implementation returns @c false.
     *
     * @param id The unique id of the touch point
     * @param time Timestamp
     *
     * @see touchDown
     * @see touchMotion
     * @since 5.8
618
     */
619
    virtual bool touchUp(qint32 id, quint32 time);
620

621 622 623 624 625 626 627 628 629 630
    static QPoint cursorPos();

    /**
     * Read animation time from the configuration and possibly adjust using animationTimeFactor().
     * The configuration value in the effect should also have special value 'default' (set using
     * QSpinBox::setSpecialValueText()) with the value 0. This special value is adjusted
     * using the global animation speed, otherwise the exact time configured is returned.
     * @param cfg configuration group to read value from
     * @param key configuration key to read value from
     * @param defaultTime default animation time in milliseconds
631
     */
632 633 634 635 636
    // return type is intentionally double so that one can divide using it without losing data
    static double animationTime(const KConfigGroup& cfg, const QString& key, int defaultTime);
    /**
     * @overload Use this variant if the animation time is hardcoded and not configurable
     * in the effect itself.
637
     */
638
    static double animationTime(int defaultTime);
639 640 641
    /**
     * @overload Use this variant if animation time is provided through a KConfigXT generated class
     * having a property called "duration".
642
     */
643 644
    template <typename T>
    int animationTime(int defaultDuration);
645 646 647 648
    /**
     * Linearly interpolates between @p x and @p y.
     *
     * Returns @p x when @p a = 0; returns @p y when @p a = 1.
649
     */
650 651 652 653 654
    static double interpolate(double x, double y, double a) {
        return x * (1 - a) + y * a;
    }
    /** Helper to set WindowPaintData and QRegion to necessary transformations so that
     * a following drawWindow() would put the window at the requested geometry (useful for thumbnails)
655
     */
656 657
    static void setPositionTransformations(WindowPaintData& data, QRect& region, EffectWindow* w,
                                           const QRect& r, Qt::AspectRatioMode aspect);
658 659 660

public Q_SLOTS:
    virtual bool borderActivated(ElectricBorder border);
661 662 663 664

protected:
    xcb_connection_t *xcbConnection() const;
    xcb_window_t x11RootWindow() const;
665 666 667 668 669

    /**
     * An implementing class can call this with it's kconfig compiled singleton class.
     * This method will perform the instance on the class.
     * @since 5.9
670
     */
671 672
    template <typename T>
    void initConfig();
673
};
674 675 676


/**
677
 * Prefer the KWIN_EFFECT_FACTORY macros.
678
 */
679 680 681 682
class KWINEFFECTS_EXPORT EffectPluginFactory : public KPluginFactory
{
    Q_OBJECT
public:
683
    EffectPluginFactory();
684
    ~EffectPluginFactory() override;
685 686 687 688 689 690 691 692
    /**
     * Returns whether the Effect is supported.
     *
     * An Effect can implement this method to determine at runtime whether the Effect is supported.
     *
     * If the current compositing backend is not supported it should return @c false.
     *
     * This method is optional, by default @c true is returned.
693
     */
694 695 696 697 698 699 700 701 702 703 704 705 706
    virtual bool isSupported() const;
    /**
     * Returns whether the Effect should get enabled by default.
     *
     * This function provides a way for an effect to override the default at runtime,
     * e.g. based on the capabilities of the hardware.
     *
     * This method is optional; the effect doesn't have to provide it.
     *
     * Note that this function is only called if the supported() function returns true,
     * and if X-KDE-PluginInfo-EnabledByDefault is set to true in the .desktop file.
     *
     * This method is optional, by default @c true is returned.
707
     */
708 709 710
    virtual bool enabledByDefault() const;
    /**
     * This method returns the created Effect.
711
     */
712 713
    virtual KWin::Effect *createEffect() const = 0;
};
714 715

/**
716
 * Defines an EffectPluginFactory sub class with customized isSupported and enabledByDefault methods.
717
 *
718 719 720
 * If the Effect to be created does not need the isSupported or enabledByDefault methods prefer
 * the simplified KWIN_EFFECT_FACTORY, KWIN_EFFECT_FACTORY_SUPPORTED or KWIN_EFFECT_FACTORY_ENABLED
 * macros which create an EffectPluginFactory with a useable default value.
721
 *
722 723 724 725
 * The macro also adds a useable K_EXPORT_PLUGIN_VERSION to the definition. KWin will not load
 * any Effect with a non-matching plugin version. This API is not providing binary compatibility
 * and thus the effect plugin must be compiled against the same kwineffects library version as
 * KWin.
726
 *
727 728 729 730 731
 * @param factoryName The name to be used for the EffectPluginFactory
 * @param className The class name of the Effect sub class which is to be created by the factory
 * @param jsonFile Name of the json file to be compiled into the plugin as metadata
 * @param supported Source code to go into the isSupported() method, must return a boolean
 * @param enabled Source code to go into the enabledByDefault() method, must return a boolean
732
 */
733 734 735 736 737 738 739
#define KWIN_EFFECT_FACTORY_SUPPORTED_ENABLED( factoryName, className, jsonFile, supported, enabled ) \
    class factoryName : public KWin::EffectPluginFactory \
    { \
        Q_OBJECT \
        Q_PLUGIN_METADATA(IID KPluginFactory_iid FILE jsonFile) \
        Q_INTERFACES(KPluginFactory) \
    public: \
740
        explicit factoryName() {} \
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
        ~factoryName() {} \
        bool isSupported() const override { \
            supported \
        } \
        bool enabledByDefault() const override { \
            enabled \
        } \
        KWin::Effect *createEffect() const override { \
            return new className(); \
        } \
    }; \
    K_EXPORT_PLUGIN_VERSION(quint32(KWIN_EFFECT_API_VERSION))

#define KWIN_EFFECT_FACTORY_ENABLED( factoryName, className, jsonFile, enabled ) \
    KWIN_EFFECT_FACTORY_SUPPORTED_ENABLED( factoryName, className, jsonFile, return true;, enabled )

Nicolas Fella's avatar
Nicolas Fella committed
757
#define KWIN_EFFECT_FACTORY_SUPPORTED( factoryName, className, jsonFile, supported ) \
758 759
    KWIN_EFFECT_FACTORY_SUPPORTED_ENABLED( factoryName, className, jsonFile, supported, return true; )

Nicolas Fella's avatar
Nicolas Fella committed
760
#define KWIN_EFFECT_FACTORY( factoryName, className, jsonFile ) \
761 762
    KWIN_EFFECT_FACTORY_SUPPORTED_ENABLED( factoryName, className, jsonFile, return true;, return true; )

763

764

Rivo Laks's avatar
Rivo Laks committed
765 766 767 768 769 770 771 772 773
/**
 * @short Manager class that handles all the effects.
 *
 * This class creates Effect objects and calls it's appropriate methods.
 *
 * Effect objects can call methods of this class to interact with the
 *  workspace, e.g. to activate or move a specific window, change current
 *  desktop or create a special input window to receive mouse and keyboard
 *  events.
774
 */
775
class KWINEFFECTS_EXPORT EffectsHandler : public QObject
776
{
777
    Q_OBJECT
778
    Q_PROPERTY(int currentDesktop READ currentDesktop WRITE setCurrentDesktop NOTIFY desktopChanged)
779
    Q_PROPERTY(QString currentActivity READ currentActivity NOTIFY currentActivityChanged)
780 781 782 783 784 785 786 787
    Q_PROPERTY(KWin::EffectWindow *activeWindow READ activeWindow WRITE activateWindow NOTIFY windowActivated)
    Q_PROPERTY(QSize desktopGridSize READ desktopGridSize)
    Q_PROPERTY(int desktopGridWidth READ desktopGridWidth)
    Q_PROPERTY(int desktopGridHeight READ desktopGridHeight)
    Q_PROPERTY(int workspaceWidth READ workspaceWidth)
    Q_PROPERTY(int workspaceHeight READ workspaceHeight)
    /**
     * The number of desktops currently used. Minimum number of desktops is 1, maximum 20.
788
     */
789 790 791
    Q_PROPERTY(int desktops READ numberOfDesktops WRITE setNumberOfDesktops NOTIFY numberDesktopsChanged)
    Q_PROPERTY(bool optionRollOverDesktops READ optionRollOverDesktops)
    Q_PROPERTY(int activeScreen READ activeScreen)
792
    Q_PROPERTY(int numScreens READ numScreens NOTIFY numberScreensChanged)
793 794 795 796 797 798
    /**
     * Factor by which animation speed in the effect should be modified (multiplied).
     * If configurable in the effect itself, the option should have also 'default'
     * animation speed. The actual value should be determined using animationTime().
     * Note: The factor can be also 0, so make sure your code can cope with 0ms time
     * if used manually.
799
     */
800
    Q_PROPERTY(qreal animationTimeFactor READ animationTimeFactor)
801
    Q_PROPERTY(QList< KWin::EffectWindow* > stackingOrder READ stackingOrder)
802 803
    /**
     * Whether window decorations use the alpha channel.
804
     */
805 806 807
    Q_PROPERTY(bool decorationsHaveAlpha READ decorationsHaveAlpha)
    /**
     * Whether the window decorations support blurring behind the decoration.
808
     */
809 810 811
    Q_PROPERTY(bool decorationSupportsBlurBehind READ decorationSupportsBlurBehind)
    Q_PROPERTY(CompositingType compositingType READ compositingType CONSTANT)
    Q_PROPERTY(QPoint cursorPos READ cursorPos)
812 813
    Q_PROPERTY(QSize virtualScreenSize READ virtualScreenSize NOTIFY virtualScreenSizeChanged)
    Q_PROPERTY(QRect virtualScreenGeometry READ virtualScreenGeometry NOTIFY virtualScreenGeometryChanged)
814
    Q_PROPERTY(bool hasActiveFullScreenEffect READ hasActiveFullScreenEffect NOTIFY hasActiveFullScreenEffectChanged)
815 816 817 818 819 820 821

    /**
     * The status of the session i.e if the user is logging out
     * @since 5.18
     */
    Q_PROPERTY(KWin::SessionState sessionState READ sessionState NOTIFY sessionStateChanged)

822
    friend class Effect;
823
public:
824
    explicit EffectsHandler(CompositingType type);
825
    ~EffectsHandler() override;
826 827
    // for use by effects
    virtual void prePaintScreen(ScreenPrePaintData& data, int time) = 0;
Albert Astals Cid's avatar
Albert Astals Cid committed
828
    virtual void paintScreen(int mask, const QRegion &region, ScreenPaintData& data) = 0;
829 830
    virtual void postPaintScreen() = 0;
    virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) = 0;
Albert Astals Cid's avatar
Albert Astals Cid committed
831
    virtual void paintWindow(EffectWindow* w, int mask, const QRegion &region, WindowPaintData& data) = 0;
832
    virtual void postPaintWindow(EffectWindow* w) = 0;
Albert Astals Cid's avatar
Albert Astals Cid committed
833 834
    virtual void paintEffectFrame(EffectFrame* frame, const QRegion &region, double opacity, double frameOpacity) = 0;
    virtual void drawWindow(EffectWindow* w, int mask, const QRegion &region, WindowPaintData& data) = 0;
835
    virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList) = 0;
836
    virtual QVariant kwinOption(KWinOption kwopt) = 0;
837 838 839 840
    /**
     * Sets the cursor while the mouse is intercepted.
     * @see startMouseInterception
     * @since 4.11
841
     */
842
    virtual void defineCursor(Qt::CursorShape shape) = 0;
843 844 845
    virtual QPoint cursorPos() const = 0;
    virtual bool grabKeyboard(Effect* effect) = 0;
    virtual void ungrabKeyboard() = 0;
846 847 848 849 850
    /**
     * Ensures that all mouse events are sent to the @p effect.
     * No window will get the mouse events. Only fullscreen effects providing a custom user interface should
     * be using this method. The input events are delivered to Effect::windowInputMouseEvent.
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
851
     * @note This method does not perform an X11 mouse grab. On X11 a fullscreen input window is raised above
852 853
     * all other windows, but no grab is performed.
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
854
     * @param effect The effect
855 856 857 858
     * @param shape Sets the cursor to be used while the mouse is intercepted
     * @see stopMouseInterception
     * @see Effect::windowInputMouseEvent
     * @since 4.11
859
     */
860 861 862 863 864
    virtual void startMouseInterception(Effect *effect, Qt::CursorShape shape) = 0;
    /**
     * Releases the hold mouse interception for @p effect
     * @see startMouseInterception
     * @since 4.11
865
     */
866
    virtual void stopMouseInterception(Effect *effect) = 0;
867

868 869 870 871 872
    /**
     * @brief Registers a global shortcut with the provided @p action.
     *
     * @param shortcut The global shortcut which should trigger the action
     * @param action The action which gets triggered when the shortcut matches
873
     */
874
    virtual void registerGlobalShortcut(const QKeySequence &shortcut, QAction *action) = 0;
875 876 877 878 879 880
    /**
     * @brief Registers a global pointer shortcut with the provided @p action.
     *
     * @param modifiers The keyboard modifiers which need to be holded
     * @param pointerButtons The pointer buttons which need to be pressed
     * @param action The action which gets triggered when the shortcut matches
881
     */
882
    virtual void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) = 0;
883 884 885 886 887 888
    /**
     * @brief Registers a global axis shortcut with the provided @p action.
     *
     * @param modifiers The keyboard modifiers which need to be holded
     * @param axis The direction in which the axis needs to be moved
     * @param action The action which gets triggered when the shortcut matches
889
     */
890
    virtual void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) = 0;
891

892 893 894 895 896 897
    /**
     * @brief Registers a global touchpad swipe gesture shortcut with the provided @p action.
     *
     * @param direction The direction for the swipe
     * @param action The action which gets triggered when the gesture triggers
     * @since 5.10
898
     */
899 900
    virtual void registerTouchpadSwipeShortcut(SwipeDirection direction, QAction *action) = 0;

901 902 903
    /**
     * Retrieve the proxy class for an effect if it has one. Will return NULL if
     * the effect isn't loaded or doesn't have a proxy class.
904
     */
905 906 907 908 909 910
    virtual void* getProxy(QString name) = 0;

    // Mouse polling
    virtual void startMousePolling() = 0;
    virtual void stopMousePolling() = 0;

911 912
    virtual void reserveElectricBorder(ElectricBorder border, Effect *effect) = 0;
    virtual void unreserveElectricBorder(ElectricBorder border, Effect *effect) = 0;
913

914 915 916 917
    /**
     * Registers the given @p action for the given @p border to be activated through
     * a touch swipe gesture.
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
918
     * If the @p border gets triggered through a touch swipe gesture the QAction::triggered
919 920 921
     * signal gets invoked.
     *
     * To unregister the touch screen action either delete the @p action or
Yuri Chornoivan's avatar
Yuri Chornoivan committed
922
     * invoke unregisterTouchBorder.
923 924 925
     *
     * @see unregisterTouchBorder
     * @since 5.10
926
     */
927 928 929 930 931 932
    virtual void registerTouchBorder(ElectricBorder border, QAction *action) = 0;
    /**
     * Unregisters the given @p action for the given touch @p border.
     *
     * @see registerTouchBorder
     * @since 5.10
933
     */
934 935
    virtual void unregisterTouchBorder(ElectricBorder border, QAction *action) = 0;

936
    // functions that allow controlling windows/desktop
937 938
    virtual void activateWindow(KWin::EffectWindow* c) = 0;
    virtual KWin::EffectWindow* activeWindow() const = 0 ;
939
    Q_SCRIPTABLE virtual void moveWindow(KWin::EffectWindow* w, const QPoint& pos, bool snap = false, double snapAdjust = 1.0) = 0;
940 941 942 943

    /**
     * Moves the window to the specific desktop
     * Setting desktop to NET::OnAllDesktops will set the window on all desktops
944
     */
945
    Q_SCRIPTABLE virtual void windowToDesktop(KWin::EffectWindow* w, int desktop) = 0;
946

947
    /**
948 949 950 951 952
     * Moves a window to the given desktops
     * On X11, the window will end up on the last window in the list
     * Setting this to an empty list will set the window on all desktops
     *
     * @arg desktopIds a list of desktops the window should be placed on. NET::OnAllDesktops is not a valid desktop X11Id
953
     */
954 955
    Q_SCRIPTABLE virtual void windowToDesktops(KWin::EffectWindow* w, const QVector<uint> &desktopIds) = 0;

956
    Q_SCRIPTABLE virtual void windowToScreen(KWin::EffectWindow* w, int screen) = 0;
957 958
    virtual void setShowingDesktop(bool showing) = 0;

959 960 961
    // Activities
    /**
     * @returns The ID of the current activity.
962
     */
963
    virtual QString currentActivity() const = 0;
964 965 966
    // Desktops
    /**
     * @returns The ID of the current desktop.
967
     */
968 969 970
    virtual int currentDesktop() const = 0;
    /**
     * @returns Total number of desktops currently in existence.
971
     */
972 973 974
    virtual int numberOfDesktops() const = 0;
    /**
     * Set the current desktop to @a desktop.
975
     */
976 977
    virtual void setCurrentDesktop(int desktop) = 0;
    /**
Vlad Zahorodnii's avatar
Vlad Zahorodnii committed
978
     * Sets the total number of desktops to @a desktops.
979
     */
980 981 982
    virtual void setNumberOfDesktops(int desktops) = 0;
    /**
     * @returns The size of desktop layout in grid units.
983
     */
984 985 986
    virtual QSize desktopGridSize() const = 0;
    /**
     * @returns The width of desktop layout in grid units.
987
     */
Martin Flöser's avatar