1/********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*********************************************************************/
20
21#ifndef KWIN_TOPLEVEL_H
22#define KWIN_TOPLEVEL_H
23
24// kwin libs
25#include <kdecoration.h>
26// kwin
27#include "utils.h"
28#include "virtualdesktops.h"
29// KDE
30#include <KDE/NETWinInfo>
31// Qt
32#include <QObject>
33// xcb
34#include <xcb/damage.h>
35#include <xcb/xfixes.h>
36// system
37#include <assert.h>
38
39namespace KWin
40{
41
42class ClientMachine;
43class EffectWindowImpl;
44class Shadow;
45
46class Toplevel
47 : public QObject, public KDecorationDefines
48{
49 Q_OBJECT
50 Q_PROPERTY(bool alpha READ hasAlpha CONSTANT)
51 Q_PROPERTY(qulonglong frameId READ frameId)
52 Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
53 Q_PROPERTY(QRect visibleRect READ visibleRect)
54 Q_PROPERTY(int height READ height)
55 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
56 Q_PROPERTY(QPoint pos READ pos)
57 Q_PROPERTY(int screen READ screen NOTIFY screenChanged)
58 Q_PROPERTY(QSize size READ size)
59 Q_PROPERTY(int width READ width)
60 Q_PROPERTY(qulonglong windowId READ window CONSTANT)
61 Q_PROPERTY(int x READ x)
62 Q_PROPERTY(int y READ y)
63 Q_PROPERTY(int desktop READ desktop)
64 /**
65 * Whether the window is on all desktops. That is desktop is -1.
66 **/
67 Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops)
68 Q_PROPERTY(QRect rect READ rect)
69 Q_PROPERTY(QPoint clientPos READ clientPos)
70 Q_PROPERTY(QSize clientSize READ clientSize)
71 Q_PROPERTY(QByteArray resourceName READ resourceName)
72 Q_PROPERTY(QByteArray resourceClass READ resourceClass)
73 Q_PROPERTY(QByteArray windowRole READ windowRole)
74 /**
75 * Returns whether the window is a desktop background window (the one with wallpaper).
76 * See _NET_WM_WINDOW_TYPE_DESKTOP at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
77 */
78 Q_PROPERTY(bool desktopWindow READ isDesktop)
79 /**
80 * Returns whether the window is a dock (i.e. a panel).
81 * See _NET_WM_WINDOW_TYPE_DOCK at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
82 */
83 Q_PROPERTY(bool dock READ isDock)
84 /**
85 * Returns whether the window is a standalone (detached) toolbar window.
86 * See _NET_WM_WINDOW_TYPE_TOOLBAR at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
87 */
88 Q_PROPERTY(bool toolbar READ isToolbar)
89 /**
90 * Returns whether the window is a torn-off menu.
91 * See _NET_WM_WINDOW_TYPE_MENU at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
92 */
93 Q_PROPERTY(bool menu READ isMenu)
94 /**
95 * Returns whether the window is a "normal" window, i.e. an application or any other window
96 * for which none of the specialized window types fit.
97 * See _NET_WM_WINDOW_TYPE_NORMAL at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
98 */
99 Q_PROPERTY(bool normalWindow READ isNormalWindow)
100 /**
101 * Returns whether the window is a dialog window.
102 * See _NET_WM_WINDOW_TYPE_DIALOG at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
103 */
104 Q_PROPERTY(bool dialog READ isDialog)
105 /**
106 * Returns whether the window is a splashscreen. Note that many (especially older) applications
107 * do not support marking their splash windows with this type.
108 * See _NET_WM_WINDOW_TYPE_SPLASH at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
109 */
110 Q_PROPERTY(bool splash READ isSplash)
111 /**
112 * Returns whether the window is a utility window, such as a tool window.
113 * See _NET_WM_WINDOW_TYPE_UTILITY at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
114 */
115 Q_PROPERTY(bool utility READ isUtility)
116 /**
117 * Returns whether the window is a dropdown menu (i.e. a popup directly or indirectly open
118 * from the applications menubar).
119 * See _NET_WM_WINDOW_TYPE_DROPDOWN_MENU at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
120 */
121 Q_PROPERTY(bool dropdownMenu READ isDropdownMenu)
122 /**
123 * Returns whether the window is a popup menu (that is not a torn-off or dropdown menu).
124 * See _NET_WM_WINDOW_TYPE_POPUP_MENU at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
125 */
126 Q_PROPERTY(bool popupMenu READ isPopupMenu)
127 /**
128 * Returns whether the window is a tooltip.
129 * See _NET_WM_WINDOW_TYPE_TOOLTIP at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
130 */
131 Q_PROPERTY(bool tooltip READ isTooltip)
132 /**
133 * Returns whether the window is a window with a notification.
134 * See _NET_WM_WINDOW_TYPE_NOTIFICATION at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
135 */
136 Q_PROPERTY(bool notification READ isNotification)
137 /**
138 * Returns whether the window is a combobox popup.
139 * See _NET_WM_WINDOW_TYPE_COMBO at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
140 */
141 Q_PROPERTY(bool comboBox READ isComboBox)
142 /**
143 * Returns whether the window is a Drag&Drop icon.
144 * See _NET_WM_WINDOW_TYPE_DND at http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
145 */
146 Q_PROPERTY(bool dndIcon READ isDNDIcon)
147 /**
148 * Returns the NETWM window type
149 * See http://standards.freedesktop.org/wm-spec/wm-spec-latest.html .
150 */
151 Q_PROPERTY(int windowType READ windowType)
152 Q_PROPERTY(QStringList activities READ activities NOTIFY activitiesChanged)
153 /**
154 * Whether this Toplevel is managed by KWin (it has control over its placement and other
155 * aspects, as opposed to override-redirect windows that are entirely handled by the application).
156 **/
157 Q_PROPERTY(bool managed READ isClient CONSTANT)
158 /**
159 * Whether this Toplevel represents an already deleted window and only kept for the compositor for animations.
160 **/
161 Q_PROPERTY(bool deleted READ isDeleted CONSTANT)
162 /**
163 * Whether the window has an own shape
164 **/
165 Q_PROPERTY(bool shaped READ shape NOTIFY shapedChanged)
166 /**
167 * Whether the window does not want to be animated on window close.
168 * There are legit reasons for this like a screenshot application which does not want it's
169 * window being captured.
170 **/
171 Q_PROPERTY(bool skipsCloseAnimation READ skipsCloseAnimation WRITE setSkipCloseAnimation NOTIFY skipCloseAnimationChanged)
172public:
173 explicit Toplevel();
174 Window frameId() const;
175 Window window() const;
176 QRect geometry() const;
177 QSize size() const;
178 QPoint pos() const;
179 QRect rect() const;
180 int x() const;
181 int y() const;
182 int width() const;
183 int height() const;
184 bool isOnScreen(int screen) const; // true if it's at least partially there
185 bool isOnActiveScreen() const;
186 int screen() const; // the screen where the center is
187 virtual QPoint clientPos() const = 0; // inside of geometry()
188 virtual QSize clientSize() const = 0;
189 virtual QRect visibleRect() const; // the area the window occupies on the screen
190 virtual QRect decorationRect() const; // rect including the decoration shadows
191 virtual QRect transparentRect() const = 0;
192 virtual QRegion decorationPendingRegion() const; // decoration region that needs to be repainted
193 virtual bool isClient() const;
194 virtual bool isDeleted() const;
195
196 // prefer isXXX() instead
197 // 0 for supported types means default for managed/unmanaged types
198 virtual NET::WindowType windowType(bool direct = false, int supported_types = 0) const = 0;
199 bool hasNETSupport() const;
200 bool isDesktop() const;
201 bool isDock() const;
202 bool isToolbar() const;
203 bool isMenu() const;
204 bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient'
205 bool isDialog() const;
206 bool isSplash() const;
207 bool isUtility() const;
208 bool isDropdownMenu() const;
209 bool isPopupMenu() const; // a context popup, not dropdown, not torn-off
210 bool isTooltip() const;
211 bool isNotification() const;
212 bool isComboBox() const;
213 bool isDNDIcon() const;
214
215 virtual int desktop() const = 0;
216 virtual QStringList activities() const = 0;
217 bool isOnDesktop(int d) const;
218 bool isOnActivity(const QString &activity) const;
219 bool isOnCurrentDesktop() const;
220 bool isOnCurrentActivity() const;
221 bool isOnAllDesktops() const;
222 bool isOnAllActivities() const;
223
224 QByteArray windowRole() const;
225 QByteArray sessionId() const;
226 QByteArray resourceName() const;
227 QByteArray resourceClass() const;
228 QByteArray wmCommand();
229 QByteArray wmClientMachine(bool use_localhost) const;
230 const ClientMachine *clientMachine() const;
231 Window wmClientLeader() const;
232 pid_t pid() const;
233 static bool resourceMatch(const Toplevel* c1, const Toplevel* c2);
234
235 bool readyForPainting() const; // true if the window has been already painted its contents
236 Visual* visual() const;
237 bool shape() const;
238 void setOpacity(double opacity);
239 double opacity() const;
240 int depth() const;
241 bool hasAlpha() const;
242 virtual bool setupCompositing();
243 virtual void finishCompositing();
244 bool updateUnredirectedState();
245 bool unredirected() const;
246 void suspendUnredirect(bool suspend);
247 Q_INVOKABLE void addRepaint(const QRect& r);
248 Q_INVOKABLE void addRepaint(const QRegion& r);
249 Q_INVOKABLE void addRepaint(int x, int y, int w, int h);
250 Q_INVOKABLE void addLayerRepaint(const QRect& r);
251 Q_INVOKABLE void addLayerRepaint(const QRegion& r);
252 Q_INVOKABLE void addLayerRepaint(int x, int y, int w, int h);
253 Q_INVOKABLE virtual void addRepaintFull();
254 // these call workspace->addRepaint(), but first transform the damage if needed
255 void addWorkspaceRepaint(const QRect& r);
256 void addWorkspaceRepaint(int x, int y, int w, int h);
257 QRegion repaints() const;
258 void resetRepaints();
259 QRegion damage() const;
260 void resetDamage();
261 EffectWindowImpl* effectWindow();
262 const EffectWindowImpl* effectWindow() const;
263 /**
264 * Window will be temporarily painted as if being at the top of the stack.
265 * Only available if Compositor is active, if not active, this method is a no-op.
266 **/
267 void elevate(bool elevate);
268
269 /**
270 * @returns Whether the Toplevel has a Shadow or not
271 * @see shadow
272 **/
273 bool hasShadow() const;
274 /**
275 * Returns the pointer to the Toplevel's Shadow. A Shadow
276 * is only available if Compositing is enabled and the corresponding X window
277 * has the Shadow property set.
278 * If a shadow is available @link hasShadow returns @c true.
279 * @returns The Shadow belonging to this Toplevel, may be @c NULL.
280 * @see hasShadow
281 **/
282 const Shadow *shadow() const;
283 Shadow *shadow();
284 /**
285 * Updates the Shadow associated with this Toplevel from X11 Property.
286 * Call this method when the Property changes or Compositing is started.
287 **/
288 void getShadow();
289
290 /**
291 * This method returns the area that the Toplevel window reports to be opaque.
292 * It is supposed to only provide valuable information if @link hasAlpha is @c true .
293 * @see hasAlpha
294 **/
295 const QRegion& opaqueRegion() const;
296
297 virtual Layer layer() const = 0;
298
299 /**
300 * Resets the damage state and sends a request for the damage region.
301 * A call to this function must be followed by a call to getDamageRegionReply(),
302 * or the reply will be leaked.
303 *
304 * Returns true if the window was damaged, and false otherwise.
305 */
306 bool resetAndFetchDamage();
307
308 /**
309 * Gets the reply from a previous call to resetAndFetchDamage().
310 * Calling this function is a no-op if there is no pending reply.
311 * Call damage() to return the fetched region.
312 */
313 void getDamageRegionReply();
314
315 bool skipsCloseAnimation() const;
316 void setSkipCloseAnimation(bool set);
317
318signals:
319 void opacityChanged(KWin::Toplevel* toplevel, qreal oldOpacity);
320 void damaged(KWin::Toplevel* toplevel, const QRect& damage);
321 void propertyNotify(KWin::Toplevel* toplevel, long a);
322 void geometryChanged();
323 void geometryShapeChanged(KWin::Toplevel* toplevel, const QRect& old);
324 void paddingChanged(KWin::Toplevel* toplevel, const QRect& old);
325 void windowClosed(KWin::Toplevel* toplevel, KWin::Deleted* deleted);
326 void windowShown(KWin::Toplevel* toplevel);
327 /**
328 * Signal emitted when the window's shape state changed. That is if it did not have a shape
329 * and received one or if the shape was withdrawn. Think of Chromium enabling/disabling KWin's
330 * decoration.
331 **/
332 void shapedChanged();
333 /**
334 * Emitted whenever the state changes in a way, that the Compositor should
335 * schedule a repaint of the scene.
336 **/
337 void needsRepaint();
338 void activitiesChanged(KWin::Toplevel* toplevel);
339 /**
340 * Emitted whenever the Toplevel's screen changes. This can happen either in consequence to
341 * a screen being removed/added or if the Toplevel's geometry changes.
342 * @since 4.11
343 **/
344 void screenChanged();
345 void skipCloseAnimationChanged();
346
347protected Q_SLOTS:
348 /**
349 * Checks whether the screen number for this Toplevel changed and updates if needed.
350 * Any method changing the geometry of the Toplevel should call this method.
351 **/
352 void checkScreen();
353 void setupCheckScreenConnection();
354 void removeCheckScreenConnection();
355 void setReadyForPainting();
356
357protected:
358 virtual ~Toplevel();
359 void setWindowHandles(Window client, Window frame);
360 void detectShape(Window id);
361 virtual void propertyNotifyEvent(XPropertyEvent* e);
362 virtual void damageNotifyEvent();
363 void discardWindowPixmap();
364 void addDamageFull();
365 void getWmClientLeader();
366 void getWmClientMachine();
367 /**
368 * @returns Whether there is a compositor and it is active.
369 **/
370 bool compositing() const;
371
372 /**
373 * This function fetches the opaque region from this Toplevel.
374 * Will only be called on corresponding property changes and for initialization.
375 **/
376 void getWmOpaqueRegion();
377
378 void getResourceClass();
379 void getWindowRole();
380 void getSkipCloseAnimation();
381 virtual void debug(QDebug& stream) const = 0;
382 void copyToDeleted(Toplevel* c);
383 void disownDataPassedToDeleted();
384 friend QDebug& operator<<(QDebug& stream, const Toplevel*);
385 void deleteEffectWindow();
386 virtual bool shouldUnredirect() const = 0;
387 QRect geom;
388 Visual* vis;
389 int bit_depth;
390 NETWinInfo2* info;
391 bool ready_for_painting;
392 QRegion repaints_region; // updating, repaint just requires repaint of that area
393 QRegion layer_repaints_region;
394
395protected:
396 bool m_isDamaged;
397
398private:
399 static QByteArray staticWindowRole(WId);
400 static QByteArray staticSessionId(WId);
401 static QByteArray staticWmCommand(WId);
402 static QByteArray staticWmClientMachine(WId);
403 static Window staticWmClientLeader(WId);
404 // when adding new data members, check also copyToDeleted()
405 Window client;
406 Window frame;
407 xcb_damage_damage_t damage_handle;
408 QRegion damage_region; // damage is really damaged window (XDamage) and texture needs
409 bool is_shape;
410 EffectWindowImpl* effect_window;
411 QByteArray resource_name;
412 QByteArray resource_class;
413 ClientMachine *m_clientMachine;
414 WId wmClientLeaderWin;
415 QByteArray window_role;
416 bool unredirect;
417 bool unredirectSuspend; // when unredirected, but pixmap is needed temporarily
418 bool m_damageReplyPending;
419 QRegion opaque_region;
420 xcb_xfixes_fetch_region_cookie_t m_regionCookie;
421 int m_screen;
422 bool m_skipCloseAnimation;
423 // when adding new data members, check also copyToDeleted()
424};
425
426inline Window Toplevel::window() const
427{
428 return client;
429}
430
431inline Window Toplevel::frameId() const
432{
433 return frame;
434}
435
436inline void Toplevel::setWindowHandles(Window w, Window f)
437{
438 assert(client == None && w != None);
439 client = w;
440 assert(frame == None && f != None);
441 frame = f;
442}
443
444inline QRect Toplevel::geometry() const
445{
446 return geom;
447}
448
449inline QSize Toplevel::size() const
450{
451 return geom.size();
452}
453
454inline QPoint Toplevel::pos() const
455{
456 return geom.topLeft();
457}
458
459inline int Toplevel::x() const
460{
461 return geom.x();
462}
463
464inline int Toplevel::y() const
465{
466 return geom.y();
467}
468
469inline int Toplevel::width() const
470{
471 return geom.width();
472}
473
474inline int Toplevel::height() const
475{
476 return geom.height();
477}
478
479inline QRect Toplevel::rect() const
480{
481 return QRect(0, 0, width(), height());
482}
483
484inline QRegion Toplevel::decorationPendingRegion() const
485{
486 return QRegion();
487}
488
489inline bool Toplevel::readyForPainting() const
490{
491 return ready_for_painting;
492}
493
494inline Visual* Toplevel::visual() const
495{
496 return vis;
497}
498
499inline bool Toplevel::isDesktop() const
500{
501 return windowType() == NET::Desktop;
502}
503
504inline bool Toplevel::isDock() const
505{
506 return windowType() == NET::Dock;
507}
508
509inline bool Toplevel::isMenu() const
510{
511 return windowType() == NET::Menu;
512}
513
514inline bool Toplevel::isToolbar() const
515{
516 return windowType() == NET::Toolbar;
517}
518
519inline bool Toplevel::isSplash() const
520{
521 return windowType() == NET::Splash;
522}
523
524inline bool Toplevel::isUtility() const
525{
526 return windowType() == NET::Utility;
527}
528
529inline bool Toplevel::isDialog() const
530{
531 return windowType() == NET::Dialog;
532}
533
534inline bool Toplevel::isNormalWindow() const
535{
536 return windowType() == NET::Normal;
537}
538
539inline bool Toplevel::isDropdownMenu() const
540{
541 return windowType() == NET::DropdownMenu;
542}
543
544inline bool Toplevel::isPopupMenu() const
545{
546 return windowType() == NET::PopupMenu;
547}
548
549inline bool Toplevel::isTooltip() const
550{
551 return windowType() == NET::Tooltip;
552}
553
554inline bool Toplevel::isNotification() const
555{
556 return windowType() == NET::Notification;
557}
558
559inline bool Toplevel::isComboBox() const
560{
561 return windowType() == NET::ComboBox;
562}
563
564inline bool Toplevel::isDNDIcon() const
565{
566 return windowType() == NET::DNDIcon;
567}
568
569inline QRegion Toplevel::damage() const
570{
571 return damage_region;
572}
573
574inline QRegion Toplevel::repaints() const
575{
576 return repaints_region.translated(pos()) | layer_repaints_region;
577}
578
579inline bool Toplevel::shape() const
580{
581 return is_shape;
582}
583
584inline int Toplevel::depth() const
585{
586 return bit_depth;
587}
588
589inline bool Toplevel::hasAlpha() const
590{
591 return depth() == 32;
592}
593
594inline const QRegion& Toplevel::opaqueRegion() const
595{
596 return opaque_region;
597}
598
599inline
600EffectWindowImpl* Toplevel::effectWindow()
601{
602 return effect_window;
603}
604
605inline
606const EffectWindowImpl* Toplevel::effectWindow() const
607{
608 return effect_window;
609}
610
611inline bool Toplevel::isOnAllDesktops() const
612{
613 return desktop() == NET::OnAllDesktops;
614}
615
616inline bool Toplevel::isOnAllActivities() const
617{
618 return activities().isEmpty();
619}
620
621inline bool Toplevel::isOnDesktop(int d) const
622{
623 return desktop() == d || /*desk == 0 ||*/ isOnAllDesktops();
624}
625
626inline bool Toplevel::isOnActivity(const QString &activity) const
627{
628 return activities().isEmpty() || activities().contains(activity);
629}
630
631inline bool Toplevel::isOnCurrentDesktop() const
632{
633 return isOnDesktop(VirtualDesktopManager::self()->current());
634}
635
636inline QByteArray Toplevel::resourceName() const
637{
638 return resource_name; // it is always lowercase
639}
640
641inline QByteArray Toplevel::resourceClass() const
642{
643 return resource_class; // it is always lowercase
644}
645
646inline QByteArray Toplevel::windowRole() const
647{
648 return window_role;
649}
650
651inline bool Toplevel::unredirected() const
652{
653 return unredirect;
654}
655
656inline const ClientMachine *Toplevel::clientMachine() const
657{
658 return m_clientMachine;
659}
660
661QDebug& operator<<(QDebug& stream, const Toplevel*);
662QDebug& operator<<(QDebug& stream, const ToplevelList&);
663
664KWIN_COMPARE_PREDICATE(WindowMatchPredicate, Toplevel, Window, cl->window() == value);
665KWIN_COMPARE_PREDICATE(FrameIdMatchPredicate, Toplevel, Window, cl->frameId() == value);
666
667} // namespace
668Q_DECLARE_METATYPE(KWin::Toplevel*)
669
670#endif
671