KWin
Loading...
Searching...
No Matches
effectwindow.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
3 SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
4 SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
5 SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "effect/effectwindow.h"
11#include "core/output.h"
13#include "group.h"
14#include "internalwindow.h"
15#include "scene/windowitem.h"
16#include "virtualdesktops.h"
17#include "waylandwindow.h"
18#include "x11window.h"
19
20namespace KWin
21{
22
23class Q_DECL_HIDDEN EffectWindow::Private
24{
25public:
27
30 WindowItem *m_windowItem; // This one is used only during paint pass.
31 QHash<int, QVariant> dataMap;
32 bool managed = false;
35};
36
37EffectWindow::Private::Private(EffectWindow *q, WindowItem *windowItem)
38 : q(q)
39 , m_window(windowItem->window())
40 , m_windowItem(windowItem)
41{
42}
43
45 : d(new Private(this, windowItem))
46{
47 // Deleted windows are not managed. So, when windowClosed signal is
48 // emitted, effects can't distinguish managed windows from unmanaged
49 // windows(e.g. combo box popups, popup menus, etc). Save value of the
50 // managed property during construction of EffectWindow. At that time,
51 // parent can be Client, XdgShellClient, or Unmanaged. So, later on, when
52 // an instance of Deleted becomes parent of the EffectWindow, effects
53 // can still figure out whether it is/was a managed window.
54 d->managed = d->m_window->isClient();
55
56 d->m_waylandWindow = qobject_cast<KWin::WaylandWindow *>(d->m_window) != nullptr;
57 d->m_x11Window = qobject_cast<KWin::X11Window *>(d->m_window) != nullptr;
58
59 connect(d->m_window, &Window::windowShown, this, [this]() {
60 Q_EMIT windowShown(this);
61 });
62 connect(d->m_window, &Window::windowHidden, this, [this]() {
63 Q_EMIT windowHidden(this);
64 });
65 connect(d->m_window, &Window::maximizedChanged, this, [this]() {
66 const MaximizeMode mode = d->m_window->maximizeMode();
67 Q_EMIT windowMaximizedStateChanged(this, mode & MaximizeHorizontal, mode & MaximizeVertical);
68 });
69 connect(d->m_window, &Window::maximizedAboutToChange, this, [this](MaximizeMode m) {
70 Q_EMIT windowMaximizedStateAboutToChange(this, m & MaximizeHorizontal, m & MaximizeVertical);
71 });
72 connect(d->m_window, &Window::frameGeometryAboutToChange, this, [this]() {
73 Q_EMIT windowFrameGeometryAboutToChange(this);
74 });
75 connect(d->m_window, &Window::interactiveMoveResizeStarted, this, [this]() {
76 Q_EMIT windowStartUserMovedResized(this);
77 });
78 connect(d->m_window, &Window::interactiveMoveResizeStepped, this, [this](const QRectF &geometry) {
79 Q_EMIT windowStepUserMovedResized(this, geometry);
80 });
81 connect(d->m_window, &Window::interactiveMoveResizeFinished, this, [this]() {
82 Q_EMIT windowFinishUserMovedResized(this);
83 });
84 connect(d->m_window, &Window::opacityChanged, this, [this](Window *window, qreal oldOpacity) {
85 Q_EMIT windowOpacityChanged(this, oldOpacity, window->opacity());
86 });
87 connect(d->m_window, &Window::minimizedChanged, this, [this]() {
88 Q_EMIT minimizedChanged(this);
89 });
90 connect(d->m_window, &Window::modalChanged, this, [this]() {
91 Q_EMIT windowModalityChanged(this);
92 });
93 connect(d->m_window, &Window::frameGeometryChanged, this, [this](const QRectF &oldGeometry) {
94 Q_EMIT windowFrameGeometryChanged(this, oldGeometry);
95 });
96 connect(d->m_window, &Window::damaged, this, [this]() {
97 Q_EMIT windowDamaged(this);
98 });
99 connect(d->m_window, &Window::unresponsiveChanged, this, [this](bool unresponsive) {
100 Q_EMIT windowUnresponsiveChanged(this, unresponsive);
101 });
102 connect(d->m_window, &Window::keepAboveChanged, this, [this]() {
103 Q_EMIT windowKeepAboveChanged(this);
104 });
105 connect(d->m_window, &Window::keepBelowChanged, this, [this]() {
106 Q_EMIT windowKeepBelowChanged(this);
107 });
108 connect(d->m_window, &Window::fullScreenChanged, this, [this]() {
109 Q_EMIT windowFullScreenChanged(this);
110 });
111 connect(d->m_window, &Window::visibleGeometryChanged, this, [this]() {
112 Q_EMIT windowExpandedGeometryChanged(this);
113 });
114 connect(d->m_window, &Window::decorationChanged, this, [this]() {
115 Q_EMIT windowDecorationChanged(this);
116 });
117 connect(d->m_window, &Window::desktopsChanged, this, [this]() {
118 Q_EMIT windowDesktopsChanged(this);
119 });
120}
121
125
127{
128 return d->m_window;
129}
130
132{
133 return d->m_windowItem;
134}
135
136bool EffectWindow::isOnActivity(const QString &activity) const
137{
138 const QStringList _activities = activities();
139 return _activities.isEmpty() || _activities.contains(activity);
140}
141
143{
144 return activities().isEmpty();
145}
146
148{
149 if (min) {
150 minimize();
151 } else {
152 unminimize();
153 }
154}
155
160
165
167{
168 const QList<VirtualDesktop *> ds = desktops();
169 return ds.isEmpty() || ds.contains(desktop);
170}
171
173{
174 return desktops().isEmpty();
175}
176
178{
179 return contentsRect() != QRect(0, 0, width(), height());
180}
181
183{
184 return !isMinimized()
187}
188
190{
191 d->m_windowItem->refVisible(holder->reason());
192}
193
195{
196 d->m_windowItem->unrefVisible(holder->reason());
197}
198
199void EffectWindow::addRepaint(const QRect &r)
200{
201 d->m_windowItem->scheduleRepaint(QRegion(r));
202}
203
205{
206 d->m_windowItem->scheduleRepaint(d->m_windowItem->boundingRect());
207}
208
210{
211 d->m_windowItem->scheduleRepaint(d->m_windowItem->mapFromGlobal(r));
212}
213
215{
216 if (Group *group = d->m_window->group()) {
217 return group->effectGroup();
218 }
219 return nullptr;
220}
221
223{
224 d->m_window->ref();
225}
226
228{
229 d->m_window->unref();
230}
231
233{
234 return d->m_window->output();
235}
236
237#define WINDOW_HELPER(rettype, prototype, toplevelPrototype) \
238 rettype EffectWindow::prototype() const \
239 { \
240 return d->m_window->toplevelPrototype(); \
241 }
242
243WINDOW_HELPER(double, opacity, opacity)
244WINDOW_HELPER(qreal, x, x)
245WINDOW_HELPER(qreal, y, y)
246WINDOW_HELPER(qreal, width, width)
247WINDOW_HELPER(qreal, height, height)
248WINDOW_HELPER(QPointF, pos, pos)
249WINDOW_HELPER(QSizeF, size, size)
250WINDOW_HELPER(QRectF, frameGeometry, frameGeometry)
251WINDOW_HELPER(QRectF, bufferGeometry, bufferGeometry)
252WINDOW_HELPER(QRectF, clientGeometry, clientGeometry)
253WINDOW_HELPER(QRectF, expandedGeometry, visibleGeometry)
254WINDOW_HELPER(QRectF, rect, rect)
255WINDOW_HELPER(bool, isDesktop, isDesktop)
256WINDOW_HELPER(bool, isDock, isDock)
257WINDOW_HELPER(bool, isToolbar, isToolbar)
258WINDOW_HELPER(bool, isMenu, isMenu)
259WINDOW_HELPER(bool, isNormalWindow, isNormalWindow)
260WINDOW_HELPER(bool, isDialog, isDialog)
261WINDOW_HELPER(bool, isSplash, isSplash)
262WINDOW_HELPER(bool, isUtility, isUtility)
263WINDOW_HELPER(bool, isDropdownMenu, isDropdownMenu)
264WINDOW_HELPER(bool, isPopupMenu, isPopupMenu)
265WINDOW_HELPER(bool, isTooltip, isTooltip)
266WINDOW_HELPER(bool, isNotification, isNotification)
267WINDOW_HELPER(bool, isCriticalNotification, isCriticalNotification)
268WINDOW_HELPER(bool, isAppletPopup, isAppletPopup)
269WINDOW_HELPER(bool, isOnScreenDisplay, isOnScreenDisplay)
270WINDOW_HELPER(bool, isComboBox, isComboBox)
271WINDOW_HELPER(bool, isDNDIcon, isDNDIcon)
272WINDOW_HELPER(bool, isDeleted, isDeleted)
273WINDOW_HELPER(QString, windowRole, windowRole)
274WINDOW_HELPER(QStringList, activities, activities)
275WINDOW_HELPER(bool, skipsCloseAnimation, skipsCloseAnimation)
276WINDOW_HELPER(SurfaceInterface *, surface, surface)
277WINDOW_HELPER(bool, isPopupWindow, isPopupWindow)
278WINDOW_HELPER(bool, isOutline, isOutline)
279WINDOW_HELPER(bool, isLockScreen, isLockScreen)
280WINDOW_HELPER(pid_t, pid, pid)
281WINDOW_HELPER(QUuid, internalId, internalId)
282WINDOW_HELPER(bool, isMinimized, isMinimized)
283WINDOW_HELPER(bool, isHidden, isHidden)
284WINDOW_HELPER(bool, isHiddenByShowDesktop, isHiddenByShowDesktop)
285WINDOW_HELPER(bool, isModal, isModal)
286WINDOW_HELPER(bool, isFullScreen, isFullScreen)
287WINDOW_HELPER(bool, keepAbove, keepAbove)
288WINDOW_HELPER(bool, keepBelow, keepBelow)
289WINDOW_HELPER(QString, caption, caption)
290WINDOW_HELPER(bool, isMovable, isMovable)
291WINDOW_HELPER(bool, isMovableAcrossScreens, isMovableAcrossScreens)
292WINDOW_HELPER(bool, isUserMove, isInteractiveMove)
293WINDOW_HELPER(bool, isUserResize, isInteractiveResize)
294WINDOW_HELPER(QRectF, iconGeometry, iconGeometry)
295WINDOW_HELPER(bool, isSpecialWindow, isSpecialWindow)
296WINDOW_HELPER(bool, acceptsFocus, wantsInput)
297WINDOW_HELPER(QIcon, icon, icon)
298WINDOW_HELPER(bool, isSkipSwitcher, skipSwitcher)
299WINDOW_HELPER(bool, decorationHasAlpha, decorationHasAlpha)
300WINDOW_HELPER(bool, isUnresponsive, unresponsive)
301WINDOW_HELPER(QList<VirtualDesktop *>, desktops, desktops)
302WINDOW_HELPER(bool, isInputMethod, isInputMethod)
303
304#undef WINDOW_HELPER
305
306qlonglong EffectWindow::windowId() const
307{
308 if (X11Window *x11Window = qobject_cast<X11Window *>(d->m_window)) {
309 return x11Window->window();
310 }
311 return 0;
312}
313
315{
316 return d->m_window->resourceName() + QLatin1Char(' ') + d->m_window->resourceClass();
317}
318
320{
321 return d->m_window->clientGeometry().translated(-d->m_window->bufferGeometry().topLeft());
322}
323
324NET::WindowType EffectWindow::windowType() const
325{
326 return d->m_window->windowType();
327}
328
330{
331 if (auto window = qobject_cast<X11Window *>(d->m_window)) {
332 return window->basicUnit();
333 }
334 return QSize(1, 1);
335}
336
338{
339 return d->m_window->rect() - d->m_window->frameMargins();
340}
341
342KDecoration2::Decoration *EffectWindow::decoration() const
343{
344 return d->m_window->decoration();
345}
346
347QByteArray EffectWindow::readProperty(long atom, long type, int format) const
348{
349 auto x11Window = qobject_cast<X11Window *>(d->m_window);
350 if (!x11Window) {
351 return QByteArray();
352 }
353 if (!kwinApp()->x11Connection()) {
354 return QByteArray();
355 }
356 uint32_t len = 32768;
357 for (;;) {
358 Xcb::Property prop(false, x11Window->window(), atom, XCB_ATOM_ANY, 0, len);
359 if (prop.isNull()) {
360 // get property failed
361 return QByteArray();
362 }
363 if (prop->bytes_after > 0) {
364 len *= 2;
365 continue;
366 }
367 return prop.toByteArray(format, type);
368 }
369}
370
371void EffectWindow::deleteProperty(long int atom) const
372{
373 auto x11Window = qobject_cast<X11Window *>(d->m_window);
374 if (!x11Window) {
375 return;
376 }
377 if (!kwinApp()->x11Connection()) {
378 return;
379 }
380 xcb_delete_property(kwinApp()->x11Connection(), x11Window->window(), atom);
381}
382
384{
385 Window *modal = d->m_window->findModal();
386 if (modal) {
387 return modal->effectWindow();
388 }
389
390 return nullptr;
391}
392
394{
395 Window *transientFor = d->m_window->transientFor();
396 if (transientFor) {
397 return transientFor->effectWindow();
398 }
399
400 return nullptr;
401}
402
404{
405 if (auto window = qobject_cast<InternalWindow *>(d->m_window)) {
406 return window->handle();
407 }
408 return nullptr;
409}
410
411template<typename T>
412QList<EffectWindow *> getMainWindows(T *c)
413{
414 const auto mainwindows = c->mainWindows();
415 QList<EffectWindow *> ret;
416 ret.reserve(mainwindows.size());
417 std::transform(std::cbegin(mainwindows), std::cend(mainwindows),
418 std::back_inserter(ret),
419 [](auto window) {
420 return window->effectWindow();
421 });
422 return ret;
423}
424
425QList<EffectWindow *> EffectWindow::mainWindows() const
426{
427 return getMainWindows(d->m_window);
428}
429
430void EffectWindow::setData(int role, const QVariant &data)
431{
432 if (!data.isNull()) {
433 d->dataMap[role] = data;
434 } else {
435 d->dataMap.remove(role);
436 }
437 Q_EMIT effects->windowDataChanged(this, role);
438}
439
440QVariant EffectWindow::data(int role) const
441{
442 return d->dataMap.value(role);
443}
444
445void EffectWindow::elevate(bool elevate)
446{
448}
449
451{
452 if (d->m_window->isClient()) {
453 d->m_window->setMinimized(true);
454 }
455}
456
458{
459 if (d->m_window->isClient()) {
460 d->m_window->setMinimized(false);
461 }
462}
463
465{
466 if (d->m_window->isClient()) {
467 d->m_window->closeWindow();
468 }
469}
470
472{
473 return d->managed;
474}
475
477{
478 return d->m_waylandWindow;
479}
480
482{
483 return d->m_x11Window;
484}
485
486//****************************************
487// EffectWindowGroup
488//****************************************
489
491 : m_group(group)
492{
493}
494
498
499QList<EffectWindow *> EffectWindowGroup::members() const
500{
501 const auto memberList = m_group->members();
502 QList<EffectWindow *> ret;
503 ret.reserve(memberList.size());
504 std::transform(std::cbegin(memberList), std::cend(memberList), std::back_inserter(ret), [](auto window) {
505 return window->effectWindow();
506 });
507 return ret;
508}
509
510} // namespace KWin
511
512#include "moc_effectwindow.cpp"
EffectWindowGroup(Group *group)
QList< EffectWindow * > members() const
Representation of a window used by/for Effect classes.
bool isX11Client() const
bool isManaged() const
void elevate(bool elevate)
Q_SCRIPTABLE void addRepaint(const QRect &r)
const EffectWindowGroup * group() const
Q_SCRIPTABLE void addLayerRepaint(const QRect &r)
Q_SCRIPTABLE KWin::EffectWindow * transientFor()
bool isMinimized() const
bool isWaylandClient() const
WindowItem * m_windowItem
bool isOnCurrentActivity() const
bool isVisible() const
WindowItem * windowItem() const
bool isOnAllActivities() const
bool isOnAllDesktops() const
void unrefVisible(const EffectWindowVisibleRef *holder)
Q_SCRIPTABLE void addRepaintFull()
Window * window() const
Q_SCRIPTABLE bool isOnDesktop(KWin::VirtualDesktop *desktop) const
bool isOnCurrentDesktop() const
Q_SCRIPTABLE void setData(int role, const QVariant &data)
Q_SCRIPTABLE QVariant data(int role) const
EffectWindow * q
QStringList activities
Q_SCRIPTABLE void closeWindow()
Q_SCRIPTABLE QList< KWin::EffectWindow * > mainWindows() const
QByteArray readProperty(long atom, long type, int format) const
void refVisible(const EffectWindowVisibleRef *holder)
void setMinimized(bool minimize)
QList< KWin::VirtualDesktop * > desktops
qlonglong windowId() const
Private(EffectWindow *q, WindowItem *windowItem)
QHash< int, QVariant > dataMap
void deleteProperty(long atom) const
KWin::Output * screen
Q_SCRIPTABLE KWin::EffectWindow * findModal()
KDecoration2::Decoration * decoration() const
EffectWindow(WindowItem *windowItem)
QWindow * internalWindow
Q_SCRIPTABLE bool isOnActivity(const QString &id) const
Q_SCRIPTABLE void setElevatedWindow(KWin::EffectWindow *w, bool set)
KWin::VirtualDesktop * currentDesktop
void windowDataChanged(KWin::EffectWindow *w, int role)
const QList< X11Window * > & members() const
Definition group.h:68
void interactiveMoveResizeStarted()
void maximizedChanged()
void frameGeometryAboutToChange()
virtual QList< Window * > mainWindows() const
Definition window.cpp:2256
void interactiveMoveResizeStepped(const QRectF &geometry)
void decorationChanged()
void fullScreenChanged()
void windowShown(KWin::Window *window)
void opacityChanged(KWin::Window *window, qreal oldOpacity)
void modalChanged()
void interactiveMoveResizeFinished()
void keepAboveChanged(bool)
void desktopsChanged()
void maximizedAboutToChange(MaximizeMode mode)
void minimizedChanged()
void frameGeometryChanged(const QRectF &oldGeometry)
void keepBelowChanged(bool)
void windowHidden(KWin::Window *window)
void unresponsiveChanged(bool)
void damaged(KWin::Window *window)
void visibleGeometryChanged()
QByteArray toByteArray(uint8_t format=8, xcb_atom_t type=XCB_ATOM_STRING, bool *ok=nullptr)
Reads the property as string and returns a QByteArray.
Definition xcbutils.h:838
#define WINDOW_HELPER(rettype, prototype, toplevelPrototype)
Session::Type type
Definition session.cpp:17
MaximizeMode
Definition common.h:74
GLenum format
Definition gltexture.cpp:49
QList< EffectWindow * > getMainWindows(T *c)
EffectsHandler * effects