1 /*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
6 SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #ifndef KWIN_EFFECTSIMPL_H
12 #define KWIN_EFFECTSIMPL_H
13
14 #include "kwineffects.h"
15
16 #include "scene.h"
17
18 #include <QHash>
19 #include <Plasma/FrameSvg>
20
21 #include <memory>
22
23 class QMouseEvent;
24 class QWheelEvent;
25
26 namespace Plasma {
27 class Theme;
28 }
29
30 namespace KWaylandServer
31 {
32 class Display;
33 }
34
35 class QDBusPendingCallWatcher;
36 class QDBusServiceWatcher;
37
38
39 namespace KWin
40 {
41 class AbstractClient;
42 class Compositor;
43 class Deleted;
44 class EffectLoader;
45 class Group;
46 class Toplevel;
47 class Unmanaged;
48 class WindowPropertyNotifyX11Filter;
49
50 class KWIN_EXPORT EffectsHandlerImpl : public EffectsHandler
51 {
52 Q_OBJECT
53 Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Effects")
54 Q_PROPERTY(QStringList activeEffects READ activeEffects)
55 Q_PROPERTY(QStringList loadedEffects READ loadedEffects)
56 Q_PROPERTY(QStringList listOfEffects READ listOfEffects)
57 public:
58 EffectsHandlerImpl(Compositor *compositor, Scene *scene);
59 ~EffectsHandlerImpl() override;
60 void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override;
61 void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override;
62 /**
63 * Special hook to perform a paintScreen but just with the windows on @p desktop.
64 */
65 void paintDesktop(int desktop, int mask, QRegion region, ScreenPaintData& data);
66 void postPaintScreen() override;
67 void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override;
68 void paintWindow(EffectWindow* w, int mask, const QRegion ®ion, WindowPaintData& data) override;
69 void postPaintWindow(EffectWindow* w) override;
70 void paintEffectFrame(EffectFrame* frame, const QRegion ®ion, double opacity, double frameOpacity) override;
71
72 Effect *provides(Effect::Feature ef);
73
74 void drawWindow(EffectWindow* w, int mask, const QRegion ®ion, WindowPaintData& data) override;
75
76 void activateWindow(EffectWindow* c) override;
77 EffectWindow* activeWindow() const override;
78 void moveWindow(EffectWindow* w, const QPoint& pos, bool snap = false, double snapAdjust = 1.0) override;
79 void windowToDesktop(EffectWindow* w, int desktop) override;
80 void windowToScreen(EffectWindow* w, int screen) override;
81 void setShowingDesktop(bool showing) override;
82
83 QString currentActivity() const override;
84 int currentDesktop() const override;
85 int numberOfDesktops() const override;
86 void setCurrentDesktop(int desktop) override;
87 void setNumberOfDesktops(int desktops) override;
88 QSize desktopGridSize() const override;
89 int desktopGridWidth() const override;
90 int desktopGridHeight() const override;
91 int workspaceWidth() const override;
92 int workspaceHeight() const override;
93 int desktopAtCoords(QPoint coords) const override;
94 QPoint desktopGridCoords(int id) const override;
95 QPoint desktopCoords(int id) const override;
96 int desktopAbove(int desktop = 0, bool wrap = true) const override;
97 int desktopToRight(int desktop = 0, bool wrap = true) const override;
98 int desktopBelow(int desktop = 0, bool wrap = true) const override;
99 int desktopToLeft(int desktop = 0, bool wrap = true) const override;
100 QString desktopName(int desktop) const override;
101 bool optionRollOverDesktops() const override;
102
103 QPoint cursorPos() const override;
104 bool grabKeyboard(Effect* effect) override;
105 void ungrabKeyboard() override;
106 // not performing XGrabPointer
107 void startMouseInterception(Effect *effect, Qt::CursorShape shape) override;
108 void stopMouseInterception(Effect *effect) override;
109 bool isMouseInterception() const;
110 void registerGlobalShortcut(const QKeySequence &shortcut, QAction *action) override;
111 void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) override;
112 void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) override;
113 void registerRealtimeTouchpadSwipeShortcut(SwipeDirection dir, QAction* onUp, std::function<void(qreal)> progressCallback) override;
114 void registerTouchpadSwipeShortcut(SwipeDirection direction, QAction *action) override;
115 void* getProxy(QString name) override;
116 void startMousePolling() override;
117 void stopMousePolling() override;
118 EffectWindow* findWindow(WId id) const override;
119 EffectWindow* findWindow(KWaylandServer::SurfaceInterface *surf) const override;
120 EffectWindow *findWindow(QWindow *w) const override;
121 EffectWindow *findWindow(const QUuid &id) const override;
122 EffectWindowList stackingOrder() const override;
123 void setElevatedWindow(KWin::EffectWindow* w, bool set) override;
124
125 void setTabBoxWindow(EffectWindow*) override;
126 void setTabBoxDesktop(int) override;
127 EffectWindowList currentTabBoxWindowList() const override;
128 void refTabBox() override;
129 void unrefTabBox() override;
130 void closeTabBox() override;
131 QList< int > currentTabBoxDesktopList() const override;
132 int currentTabBoxDesktop() const override;
133 EffectWindow* currentTabBoxWindow() const override;
134
135 void setActiveFullScreenEffect(Effect* e) override;
136 Effect* activeFullScreenEffect() const override;
137 bool hasActiveFullScreenEffect() const override;
138
139 void addRepaintFull() override;
140 void addRepaint(const QRect& r) override;
141 void addRepaint(const QRegion& r) override;
142 void addRepaint(int x, int y, int w, int h) override;
143 int activeScreen() const override;
144 int numScreens() const override;
145 int screenNumber(const QPoint& pos) const override;
146 QRect clientArea(clientAreaOption, int screen, int desktop) const override;
147 QRect clientArea(clientAreaOption, const EffectWindow* c) const override;
148 QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const override;
149 QSize virtualScreenSize() const override;
150 QRect virtualScreenGeometry() const override;
151 double animationTimeFactor() const override;
152
153 void defineCursor(Qt::CursorShape shape) override;
154 bool checkInputWindowEvent(QMouseEvent *e);
155 bool checkInputWindowEvent(QWheelEvent *e);
156 void checkInputWindowStacking();
157
158 void reserveElectricBorder(ElectricBorder border, Effect *effect) override;
159 void unreserveElectricBorder(ElectricBorder border, Effect *effect) override;
160
161 void registerTouchBorder(ElectricBorder border, QAction *action) override;
162 void unregisterTouchBorder(ElectricBorder border, QAction *action) override;
163
164 QPainter* scenePainter() override;
165 void reconfigure() override;
166 QByteArray readRootProperty(long atom, long type, int format) const override;
167 xcb_atom_t announceSupportProperty(const QByteArray& propertyName, Effect* effect) override;
168 void removeSupportProperty(const QByteArray& propertyName, Effect* effect) override;
169
170 bool hasDecorationShadows() const override;
171
172 bool decorationsHaveAlpha() const override;
173
174 bool decorationSupportsBlurBehind() const override;
175
176 EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const override;
177
178 QVariant kwinOption(KWinOption kwopt) override;
179 bool isScreenLocked() const override;
180
181 bool makeOpenGLContextCurrent() override;
182 void doneOpenGLContextCurrent() override;
183
184 xcb_connection_t *xcbConnection() const override;
185 xcb_window_t x11RootWindow() const override;
186
187 // internal (used by kwin core or compositing code)
188 void startPaint();
189 void grabbedKeyboardEvent(QKeyEvent* e);
190 bool hasKeyboardGrab() const;
191
192 void reloadEffect(Effect *effect) override;
193 QStringList loadedEffects() const;
194 QStringList listOfEffects() const;
195 void unloadAllEffects();
196
197 QList<EffectWindow*> elevatedWindows() const;
198 QStringList activeEffects() const;
199
200 /**
201 * @returns whether or not any effect is currently active where KWin should not use direct scanout
202 */
203 bool blocksDirectScanout() const;
204
205 /**
206 * @returns Whether we are currently in a desktop rendering process triggered by paintDesktop hook
207 */
isDesktopRendering()208 bool isDesktopRendering() const {
209 return m_desktopRendering;
210 }
211 /**
212 * @returns the desktop currently being rendered in the paintDesktop hook.
213 */
currentRenderedDesktop()214 int currentRenderedDesktop() const {
215 return m_currentRenderedDesktop;
216 }
217
218 KWaylandServer::Display *waylandDisplay() const override;
219
220 bool animationsSupported() const override;
221
222 PlatformCursorImage cursorImage() const override;
223
224 void hideCursor() override;
225 void showCursor() override;
226
227 void startInteractiveWindowSelection(std::function<void(KWin::EffectWindow*)> callback) override;
228 void startInteractivePositionSelection(std::function<void(const QPoint &)> callback) override;
229
230 void showOnScreenMessage(const QString &message, const QString &iconName = QString()) override;
231 void hideOnScreenMessage(OnScreenMessageHideFlags flags = OnScreenMessageHideFlags()) override;
232
233 KSharedConfigPtr config() const override;
234 KSharedConfigPtr inputConfig() const override;
235
scene()236 Scene *scene() const {
237 return m_scene;
238 }
239
240 bool touchDown(qint32 id, const QPointF &pos, quint32 time);
241 bool touchMotion(qint32 id, const QPointF &pos, quint32 time);
242 bool touchUp(qint32 id, quint32 time);
243
244 void highlightWindows(const QVector<EffectWindow *> &windows);
245
isPropertyTypeRegistered(xcb_atom_t atom)246 bool isPropertyTypeRegistered(xcb_atom_t atom) const {
247 return registered_atoms.contains(atom);
248 }
249
250 void windowToDesktops(EffectWindow *w, const QVector<uint> &desktops) override;
251
252 /**
253 * Finds an effect with the given name.
254 *
255 * @param name The name of the effect.
256 * @returns The effect with the given name @p name, or nullptr if there
257 * is no such effect loaded.
258 */
259 Effect *findEffect(const QString &name) const;
260
261 void renderEffectQuickView(EffectQuickView *effectQuickView) const override;
262
263 SessionState sessionState() const override;
264 QList<EffectScreen *> screens() const override;
265 EffectScreen *screenAt(const QPoint &point) const override;
266 EffectScreen *findScreen(const QString &name) const override;
267 EffectScreen *findScreen(int screenId) const override;
268 void renderScreen(EffectScreen *screen) override;
269
270 public Q_SLOTS:
271 void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
272 void slotTabAdded(EffectWindow* from, EffectWindow* to);
273 void slotTabRemoved(EffectWindow* c, EffectWindow* newActiveWindow);
274
275 // slots for D-Bus interface
276 Q_SCRIPTABLE void reconfigureEffect(const QString& name);
277 Q_SCRIPTABLE bool loadEffect(const QString& name);
278 Q_SCRIPTABLE void toggleEffect(const QString& name);
279 Q_SCRIPTABLE void unloadEffect(const QString& name);
280 Q_SCRIPTABLE bool isEffectLoaded(const QString& name) const;
281 Q_SCRIPTABLE bool isEffectSupported(const QString& name);
282 Q_SCRIPTABLE QList<bool> areEffectsSupported(const QStringList &names);
283 Q_SCRIPTABLE QString supportInformation(const QString& name) const;
284 Q_SCRIPTABLE QString debug(const QString& name, const QString& parameter = QString()) const;
285
286 protected Q_SLOTS:
287 void slotClientShown(KWin::Toplevel*);
288 void slotUnmanagedShown(KWin::Toplevel*);
289 void slotWindowClosed(KWin::Toplevel *c, KWin::Deleted *d);
290 void slotClientMaximized(KWin::AbstractClient *c, MaximizeMode maxMode);
291 void slotOpacityChanged(KWin::Toplevel *t, qreal oldOpacity);
292 void slotClientModalityChanged();
293 void slotGeometryShapeChanged(KWin::Toplevel *t, const QRect &old);
294 void slotFrameGeometryChanged(Toplevel *toplevel, const QRect &oldGeometry);
295 void slotWindowDamaged(KWin::Toplevel *t, const QRegion& r);
296 void slotOutputEnabled(AbstractOutput *output);
297 void slotOutputDisabled(AbstractOutput *output);
298
299 protected:
300 void connectNotify(const QMetaMethod &signal) override;
301 void disconnectNotify(const QMetaMethod &signal) override;
302 void effectsChanged();
303 void setupClientConnections(KWin::AbstractClient *client);
304 void setupUnmanagedConnections(KWin::Unmanaged *u);
305
306 /**
307 * Default implementation does nothing and returns @c true.
308 */
309 virtual bool doGrabKeyboard();
310 /**
311 * Default implementation does nothing.
312 */
313 virtual void doUngrabKeyboard();
314
315 /**
316 * Default implementation sets Effects override cursor on the PointerInputRedirection.
317 */
318 virtual void doStartMouseInterception(Qt::CursorShape shape);
319
320 /**
321 * Default implementation removes the Effects override cursor on the PointerInputRedirection.
322 */
323 virtual void doStopMouseInterception();
324
325 /**
326 * Default implementation does nothing
327 */
328 virtual void doCheckInputWindowStacking();
329
330 Effect* keyboard_grab_effect;
331 Effect* fullscreen_effect;
332 QList<EffectWindow*> elevated_windows;
333 QMultiMap< int, EffectPair > effect_order;
334 QHash< long, int > registered_atoms;
335
336 private:
337 void registerPropertyType(long atom, bool reg);
338 void destroyEffect(Effect *effect);
339
340 typedef QVector< Effect*> EffectsList;
341 typedef EffectsList::const_iterator EffectsIterator;
342 EffectsList m_activeEffects;
343 EffectsIterator m_currentDrawWindowIterator;
344 EffectsIterator m_currentPaintWindowIterator;
345 EffectsIterator m_currentPaintEffectFrameIterator;
346 EffectsIterator m_currentPaintScreenIterator;
347 typedef QHash< QByteArray, QList< Effect*> > PropertyEffectMap;
348 PropertyEffectMap m_propertiesForEffects;
349 QHash<QByteArray, qulonglong> m_managedProperties;
350 Compositor *m_compositor;
351 Scene *m_scene;
352 bool m_desktopRendering;
353 int m_currentRenderedDesktop;
354 QList<Effect*> m_grabbedMouseEffects;
355 EffectLoader *m_effectLoader;
356 int m_trackingCursorChanges;
357 std::unique_ptr<WindowPropertyNotifyX11Filter> m_x11WindowPropertyNotify;
358 QList<EffectScreen *> m_effectScreens;
359 };
360
361 class EffectScreenImpl : public EffectScreen
362 {
363 Q_OBJECT
364
365 public:
366 explicit EffectScreenImpl(AbstractOutput *output, QObject *parent = nullptr);
367
368 AbstractOutput *platformOutput() const;
369
370 QString name() const override;
371 qreal devicePixelRatio() const override;
372 QRect geometry() const override;
373 Transform transform() const override;
374
375 private:
376 AbstractOutput *m_platformOutput;
377 };
378
379 class EffectWindowImpl : public EffectWindow
380 {
381 Q_OBJECT
382 public:
383 explicit EffectWindowImpl(Toplevel *toplevel);
384 ~EffectWindowImpl() override;
385
386 void enablePainting(int reason) override;
387 void disablePainting(int reason) override;
388 bool isPaintingEnabled() override;
389
390 void addRepaint(const QRect &r) override;
391 void addRepaint(int x, int y, int w, int h) override;
392 void addRepaintFull() override;
393 void addLayerRepaint(const QRect &r) override;
394 void addLayerRepaint(int x, int y, int w, int h) override;
395
396 void refWindow() override;
397 void unrefWindow() override;
398
399 const EffectWindowGroup* group() const override;
400
401 bool isDeleted() const override;
402 bool isMinimized() const override;
403 double opacity() const override;
404 bool hasAlpha() const override;
405
406 QStringList activities() const override;
407 int desktop() const override;
408 QVector<uint> desktops() const override;
409 int x() const override;
410 int y() const override;
411 int width() const override;
412 int height() const override;
413
414 QSize basicUnit() const override;
415 QRect geometry() const override;
416 QRect frameGeometry() const override;
417 QRect bufferGeometry() const override;
418 QRect clientGeometry() const override;
419
420 QString caption() const override;
421
422 QRect expandedGeometry() const override;
423 int screen() const override;
424 QPoint pos() const override;
425 QSize size() const override;
426 QRect rect() const override;
427
428 bool isMovable() const override;
429 bool isMovableAcrossScreens() const override;
430 bool isUserMove() const override;
431 bool isUserResize() const override;
432 QRect iconGeometry() const override;
433
434 bool isDesktop() const override;
435 bool isDock() const override;
436 bool isToolbar() const override;
437 bool isMenu() const override;
438 bool isNormalWindow() const override;
439 bool isSpecialWindow() const override;
440 bool isDialog() const override;
441 bool isSplash() const override;
442 bool isUtility() const override;
443 bool isDropdownMenu() const override;
444 bool isPopupMenu() const override;
445 bool isTooltip() const override;
446 bool isNotification() const override;
447 bool isCriticalNotification() const override;
448 bool isOnScreenDisplay() const override;
449 bool isComboBox() const override;
450 bool isDNDIcon() const override;
451 bool skipsCloseAnimation() const override;
452
453 bool acceptsFocus() const override;
454 bool keepAbove() const override;
455 bool keepBelow() const override;
456 bool isModal() const override;
457 bool isPopupWindow() const override;
458 bool isOutline() const override;
459 bool isLockScreen() const override;
460
461 KWaylandServer::SurfaceInterface *surface() const override;
462 bool isFullScreen() const override;
463 bool isUnresponsive() const override;
464
465 QRect contentsRect() const override;
466 bool decorationHasAlpha() const override;
467 QIcon icon() const override;
468 QString windowClass() const override;
469 NET::WindowType windowType() const override;
470 bool isSkipSwitcher() const override;
471 bool isCurrentTab() const override;
472 QString windowRole() const override;
473
474 bool isManaged() const override;
475 bool isWaylandClient() const override;
476 bool isX11Client() const override;
477
478 pid_t pid() const override;
479 qlonglong windowId() const override;
480
481 QRect decorationInnerRect() const override;
482 QByteArray readProperty(long atom, long type, int format) const override;
483 void deleteProperty(long atom) const override;
484
485 EffectWindow* findModal() override;
486 EffectWindow* transientFor() override;
487 EffectWindowList mainWindows() const override;
488
489 void minimize() override;
490 void unminimize() override;
491 void closeWindow() override;
492
493 void referencePreviousWindowPixmap() override;
494 void unreferencePreviousWindowPixmap() override;
495
496 QWindow *internalWindow() const override;
497
498 const Toplevel* window() const;
499 Toplevel* window();
500
501 void setWindow(Toplevel* w); // internal
502 void setSceneWindow(Scene::Window* w); // internal
503 const Scene::Window* sceneWindow() const; // internal
504 Scene::Window* sceneWindow(); // internal
505
506 void elevate(bool elevate);
507
508 void setData(int role, const QVariant &data) override;
509 QVariant data(int role) const override;
510
511 private:
512 Toplevel* toplevel;
513 Scene::Window* sw; // This one is used only during paint pass.
514 QHash<int, QVariant> dataMap;
515 bool managed = false;
516 bool waylandClient;
517 bool x11Client;
518 };
519
520 class EffectWindowGroupImpl
521 : public EffectWindowGroup
522 {
523 public:
524 explicit EffectWindowGroupImpl(Group* g);
525 EffectWindowList members() const override;
526 private:
527 Group* group;
528 };
529
530 class KWIN_EXPORT EffectFrameImpl
531 : public QObject, public EffectFrame
532 {
533 Q_OBJECT
534 public:
535 explicit EffectFrameImpl(EffectFrameStyle style, bool staticSize = true, QPoint position = QPoint(-1, -1),
536 Qt::Alignment alignment = Qt::AlignCenter);
537 ~EffectFrameImpl() override;
538
539 void free() override;
540 void render(const QRegion ®ion = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0) override;
541 Qt::Alignment alignment() const override;
542 void setAlignment(Qt::Alignment alignment) override;
543 const QFont& font() const override;
544 void setFont(const QFont& font) override;
545 const QRect& geometry() const override;
546 void setGeometry(const QRect& geometry, bool force = false) override;
547 const QIcon& icon() const override;
548 void setIcon(const QIcon& icon) override;
549 const QSize& iconSize() const override;
550 void setIconSize(const QSize& size) override;
551 void setPosition(const QPoint& point) override;
552 const QString& text() const override;
553 void setText(const QString& text) override;
style()554 EffectFrameStyle style() const override {
555 return m_style;
556 }
frame()557 Plasma::FrameSvg& frame() {
558 return m_frame;
559 }
isStatic()560 bool isStatic() const {
561 return m_static;
562 }
563 void finalRender(QRegion region, double opacity, double frameOpacity) const;
setShader(GLShader * shader)564 void setShader(GLShader* shader) override {
565 m_shader = shader;
566 }
shader()567 GLShader* shader() const override {
568 return m_shader;
569 }
570 void setSelection(const QRect& selection) override;
selection()571 const QRect& selection() const {
572 return m_selectionGeometry;
573 }
selectionFrame()574 Plasma::FrameSvg& selectionFrame() {
575 return m_selection;
576 }
577 /**
578 * The foreground text color as specified by the default Plasma theme.
579 */
580 QColor styledTextColor();
581
582 private Q_SLOTS:
583 void plasmaThemeChanged();
584
585 private:
586 Q_DISABLE_COPY(EffectFrameImpl) // As we need to use Qt slots we cannot copy this class
587 void align(QRect &geometry); // positions geometry around m_point respecting m_alignment
588 void autoResize(); // Auto-resize if not a static size
589
590 EffectFrameStyle m_style;
591 Plasma::FrameSvg m_frame; // TODO: share between all EffectFrames
592 Plasma::FrameSvg m_selection;
593
594 // Position
595 bool m_static;
596 QPoint m_point;
597 Qt::Alignment m_alignment;
598 QRect m_geometry;
599
600 // Contents
601 QString m_text;
602 QFont m_font;
603 QIcon m_icon;
604 QSize m_iconSize;
605 QRect m_selectionGeometry;
606
607 Scene::EffectFrame* m_sceneFrame;
608 GLShader* m_shader;
609
610 Plasma::Theme *m_theme;
611 };
612
613 inline
elevatedWindows()614 QList<EffectWindow*> EffectsHandlerImpl::elevatedWindows() const
615 {
616 if (isScreenLocked())
617 return QList<EffectWindow*>();
618 return elevated_windows;
619 }
620
621 inline
x11RootWindow()622 xcb_window_t EffectsHandlerImpl::x11RootWindow() const
623 {
624 return rootWindow();
625 }
626
627 inline
xcbConnection()628 xcb_connection_t *EffectsHandlerImpl::xcbConnection() const
629 {
630 return connection();
631 }
632
633 inline
EffectWindowGroupImpl(Group * g)634 EffectWindowGroupImpl::EffectWindowGroupImpl(Group* g)
635 : group(g)
636 {
637 }
638
639 EffectWindow* effectWindow(Toplevel* w);
640 EffectWindow* effectWindow(Scene::Window* w);
641
642 inline
sceneWindow()643 const Scene::Window* EffectWindowImpl::sceneWindow() const
644 {
645 return sw;
646 }
647
648 inline
sceneWindow()649 Scene::Window* EffectWindowImpl::sceneWindow()
650 {
651 return sw;
652 }
653
654 inline
window()655 const Toplevel* EffectWindowImpl::window() const
656 {
657 return toplevel;
658 }
659
660 inline
window()661 Toplevel* EffectWindowImpl::window()
662 {
663 return toplevel;
664 }
665
666
667 } // namespace
668
669 #endif
670