KWin
Loading...
Searching...
No Matches
windowitem.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "scene/windowitem.h"
9#include "internalwindow.h"
11#include "scene/shadowitem.h"
15#include "virtualdesktops.h"
16#include "wayland_server.h"
17#include "window.h"
18#include "workspace.h"
19#include "x11window.h"
20
21#include <KDecoration2/Decoration>
22
23namespace KWin
24{
25
26WindowItem::WindowItem(Window *window, Scene *scene, Item *parent)
27 : Item(scene, parent)
28 , m_window(window)
29{
30 connect(window, &Window::decorationChanged, this, &WindowItem::updateDecorationItem);
31 updateDecorationItem();
32
33 connect(window, &Window::shadowChanged, this, &WindowItem::updateShadowItem);
34 updateShadowItem();
35
36 connect(window, &Window::frameGeometryChanged, this, &WindowItem::updatePosition);
37 updatePosition();
38
39 if (waylandServer()) {
40 connect(waylandServer(), &WaylandServer::lockStateChanged, this, &WindowItem::updateVisibility);
41 }
42 if (!window->readyForPainting()) {
43 connect(window, &Window::readyForPaintingChanged, this, &WindowItem::updateVisibility);
44 }
45 connect(window, &Window::lockScreenOverlayChanged, this, &WindowItem::updateVisibility);
46 connect(window, &Window::minimizedChanged, this, &WindowItem::updateVisibility);
47 connect(window, &Window::hiddenChanged, this, &WindowItem::updateVisibility);
48 connect(window, &Window::hiddenByShowDesktopChanged, this, &WindowItem::updateVisibility);
49 connect(window, &Window::activitiesChanged, this, &WindowItem::updateVisibility);
50 connect(window, &Window::desktopsChanged, this, &WindowItem::updateVisibility);
51 connect(workspace(), &Workspace::currentActivityChanged, this, &WindowItem::updateVisibility);
52 connect(workspace(), &Workspace::currentDesktopChanged, this, &WindowItem::updateVisibility);
53 updateVisibility();
54
55 connect(window, &Window::opacityChanged, this, &WindowItem::updateOpacity);
56 updateOpacity();
57
58 connect(window, &Window::stackingOrderChanged, this, &WindowItem::updateStackingOrder);
59 updateStackingOrder();
60
61 connect(window, &Window::closed, this, &WindowItem::freeze);
62
63 m_effectWindow = std::make_unique<EffectWindow>(this);
64}
65
69
71{
72 return m_surfaceItem.get();
73}
74
76{
77 return m_decorationItem.get();
78}
79
81{
82 return m_shadowItem.get();
83}
84
86{
87 return m_window;
88}
89
91{
92 return m_effectWindow.get();
93}
94
95void WindowItem::refVisible(int reason)
96{
97 if (reason & PAINT_DISABLED_BY_HIDDEN) {
98 m_forceVisibleByHiddenCount++;
99 }
100 if (reason & PAINT_DISABLED_BY_DESKTOP) {
101 m_forceVisibleByDesktopCount++;
102 }
103 if (reason & PAINT_DISABLED_BY_MINIMIZE) {
104 m_forceVisibleByMinimizeCount++;
105 }
106 if (reason & PAINT_DISABLED_BY_ACTIVITY) {
107 m_forceVisibleByActivityCount++;
108 }
109 updateVisibility();
110}
111
113{
114 if (reason & PAINT_DISABLED_BY_HIDDEN) {
115 Q_ASSERT(m_forceVisibleByHiddenCount > 0);
116 m_forceVisibleByHiddenCount--;
117 }
118 if (reason & PAINT_DISABLED_BY_DESKTOP) {
119 Q_ASSERT(m_forceVisibleByDesktopCount > 0);
120 m_forceVisibleByDesktopCount--;
121 }
122 if (reason & PAINT_DISABLED_BY_MINIMIZE) {
123 Q_ASSERT(m_forceVisibleByMinimizeCount > 0);
124 m_forceVisibleByMinimizeCount--;
125 }
126 if (reason & PAINT_DISABLED_BY_ACTIVITY) {
127 Q_ASSERT(m_forceVisibleByActivityCount > 0);
128 m_forceVisibleByActivityCount--;
129 }
130 updateVisibility();
131}
132
134{
135 // Not ideal, but it's also highly unlikely that there are more than 1000 windows. The
136 // elevation constantly increases so it's possible to force specific stacking order. It
137 // can potentially overflow, but it's unlikely to happen because windows are elevated
138 // rarely.
139 static int elevation = 1000;
140
141 m_elevation = elevation++;
142 updateStackingOrder();
143}
144
146{
147 m_elevation.reset();
148 updateStackingOrder();
149}
150
151bool WindowItem::computeVisibility() const
152{
153 if (!m_window->readyForPainting()) {
154 return false;
155 }
156 if (waylandServer() && waylandServer()->isScreenLocked()) {
157 return m_window->isLockScreen() || m_window->isInputMethod() || m_window->isLockScreenOverlay();
158 }
159 if (!m_window->isOnCurrentDesktop()) {
160 if (m_forceVisibleByDesktopCount == 0) {
161 return false;
162 }
163 }
164 if (!m_window->isOnCurrentActivity()) {
165 if (m_forceVisibleByActivityCount == 0) {
166 return false;
167 }
168 }
169 if (m_window->isMinimized()) {
170 if (m_forceVisibleByMinimizeCount == 0) {
171 return false;
172 }
173 }
174 if (m_window->isHidden() || m_window->isHiddenByShowDesktop()) {
175 if (m_forceVisibleByHiddenCount == 0) {
176 return false;
177 }
178 }
179 return true;
180}
181
182void WindowItem::updateVisibility()
183{
184 const bool visible = computeVisibility();
185 setVisible(visible);
186
187 if (m_window->readyForPainting()) {
188 m_window->setSuspended(!visible);
189 }
190}
191
192void WindowItem::updatePosition()
193{
194 setPosition(m_window->pos());
195}
196
197void WindowItem::addSurfaceItemDamageConnects(Item *item)
198{
199 auto surfaceItem = static_cast<SurfaceItem *>(item);
200 connect(surfaceItem, &SurfaceItem::damaged, this, &WindowItem::markDamaged);
201 connect(surfaceItem, &SurfaceItem::childAdded, this, &WindowItem::addSurfaceItemDamageConnects);
202 const auto childItems = item->childItems();
203 for (const auto &child : childItems) {
204 addSurfaceItemDamageConnects(child);
205 }
206}
207
208void WindowItem::updateSurfaceItem(std::unique_ptr<SurfaceItem> &&surfaceItem)
209{
210 m_surfaceItem = std::move(surfaceItem);
211
212 if (m_surfaceItem) {
213 connect(m_window, &Window::shadeChanged, this, &WindowItem::updateSurfaceVisibility);
214 connect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition);
215 connect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition);
216 addSurfaceItemDamageConnects(m_surfaceItem.get());
217
218 updateSurfacePosition();
219 updateSurfaceVisibility();
220 } else {
221 disconnect(m_window, &Window::shadeChanged, this, &WindowItem::updateSurfaceVisibility);
222 disconnect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition);
223 disconnect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition);
224 }
225}
226
227void WindowItem::updateSurfacePosition()
228{
229 const QRectF bufferGeometry = m_window->bufferGeometry();
230 const QRectF frameGeometry = m_window->frameGeometry();
231
232 m_surfaceItem->setPosition(bufferGeometry.topLeft() - frameGeometry.topLeft());
233}
234
235void WindowItem::updateSurfaceVisibility()
236{
237 m_surfaceItem->setVisible(!m_window->isShade());
238}
239
240void WindowItem::updateShadowItem()
241{
242 Shadow *shadow = m_window->shadow();
243 if (shadow) {
244 if (!m_shadowItem || m_shadowItem->shadow() != shadow) {
245 m_shadowItem = std::make_unique<ShadowItem>(shadow, m_window, scene(), this);
246 }
247 if (m_decorationItem) {
248 m_shadowItem->stackBefore(m_decorationItem.get());
249 } else if (m_surfaceItem) {
250 m_shadowItem->stackBefore(m_surfaceItem.get());
251 }
252 markDamaged();
253 } else {
254 m_shadowItem.reset();
255 }
256}
257
258void WindowItem::updateDecorationItem()
259{
260 if (m_window->isDeleted()) {
261 return;
262 }
263 if (m_window->decoration()) {
264 m_decorationItem = std::make_unique<DecorationItem>(m_window->decoration(), m_window, scene(), this);
265 if (m_shadowItem) {
266 m_decorationItem->stackAfter(m_shadowItem.get());
267 } else if (m_surfaceItem) {
268 m_decorationItem->stackBefore(m_surfaceItem.get());
269 }
270 connect(m_window->decoration(), &KDecoration2::Decoration::damaged, this, &WindowItem::markDamaged);
271 markDamaged();
272 } else {
273 m_decorationItem.reset();
274 }
275}
276
277void WindowItem::updateOpacity()
278{
279 setOpacity(m_window->opacity());
280}
281
282void WindowItem::updateStackingOrder()
283{
284 if (m_elevation.has_value()) {
285 setZ(m_elevation.value());
286 } else {
287 setZ(m_window->stackingOrder());
288 }
289}
290
291void WindowItem::markDamaged()
292{
293 Q_EMIT m_window->damaged(m_window);
294}
295
296void WindowItem::freeze()
297{
298 if (m_surfaceItem) {
299 m_surfaceItem->freeze();
300 }
301}
302
304 : WindowItem(window, scene, parent)
305{
306 initialize();
307
308 // Xwayland windows and Wayland surfaces are associated asynchronously.
309 connect(window, &Window::surfaceChanged, this, &WindowItemX11::initialize);
310}
311
312void WindowItemX11::initialize()
313{
314 switch (kwinApp()->operationMode()) {
316 updateSurfaceItem(std::make_unique<SurfaceItemX11>(static_cast<X11Window *>(window()), scene(), this));
317 break;
319 if (!window()->surface()) {
320 updateSurfaceItem(nullptr);
321 } else {
322 updateSurfaceItem(std::make_unique<SurfaceItemXwayland>(static_cast<X11Window *>(window()), scene(), this));
323 }
324 break;
326 Q_UNREACHABLE();
327 }
328}
329
331 : WindowItem(window, scene, parent)
332{
333 updateSurfaceItem(std::make_unique<SurfaceItemWayland>(window->surface(), scene, this));
334}
335
337 : WindowItem(window, scene, parent)
338{
339 updateSurfaceItem(std::make_unique<SurfaceItemInternal>(window, scene, this));
340}
341
342} // namespace KWin
343
344#include "moc_windowitem.cpp"
@ OperationModeXwayland
KWin uses Wayland and controls a nested Xwayland server.
Definition main.h:95
@ OperationModeX11
KWin uses only X11 for managing windows and compositing.
Definition main.h:87
@ OperationModeWaylandOnly
KWin uses only Wayland.
Definition main.h:91
Representation of a window used by/for Effect classes.
void childAdded(Item *item)
Scene * scene() const
Definition item.cpp:32
void setVisible(bool visible)
Definition item.cpp:388
QList< Item * > childItems() const
Definition item.cpp:112
void setZ(int z)
Definition item.cpp:55
void setOpacity(qreal opacity)
Definition item.cpp:42
void setPosition(const QPointF &point)
Definition item.cpp:122
QPointF pos
Definition window.h:79
void stackingOrderChanged()
QRectF frameGeometry
Definition window.h:431
QRectF bufferGeometry
Definition window.h:69
bool isShade() const
Definition window.h:1034
SurfaceInterface * surface() const
Definition window.cpp:342
void lockScreenOverlayChanged()
void decorationChanged()
Shadow * shadow() const
Definition window.cpp:259
void readyForPaintingChanged()
bool isHidden() const
Definition window.cpp:4237
bool readyForPainting() const
Definition window.h:1917
bool isOnCurrentActivity() const
Definition window.cpp:3097
std::shared_ptr< KDecoration2::Decoration > decoration
Definition window.h:1820
bool isHiddenByShowDesktop() const
Definition window.cpp:4257
void surfaceChanged()
void opacityChanged(KWin::Window *window, qreal oldOpacity)
void shadeChanged()
bool isOnCurrentDesktop() const
Definition window.cpp:848
bool isLockScreenOverlay() const
Definition window.cpp:4181
bool isMinimized() const
Definition window.h:988
void desktopsChanged()
void setSuspended(bool suspended)
Definition window.cpp:4276
virtual bool isLockScreen() const
Definition window.h:2007
void hiddenByShowDesktopChanged()
void bufferGeometryChanged(const QRectF &oldGeometry)
void minimizedChanged()
int stackingOrder
Definition window.h:271
qreal opacity
Definition window.h:106
void frameGeometryChanged(const QRectF &oldGeometry)
virtual bool isInputMethod() const
Definition window.h:2012
void activitiesChanged()
void shadowChanged()
void damaged(KWin::Window *window)
void hiddenChanged()
bool isDeleted() const
Definition window.cpp:540
WindowItem(Window *window, Scene *scene, Item *parent=nullptr)
SurfaceItem * surfaceItem() const
void refVisible(int reason)
Window * window() const
~WindowItem() override
void unrefVisible(int reason)
void updateSurfaceItem(std::unique_ptr< SurfaceItem > &&surfaceItem)
EffectWindow * effectWindow() const
DecorationItem * decorationItem() const
ShadowItem * shadowItem() const
WindowItemInternal(InternalWindow *window, Scene *scene, Item *parent=nullptr)
WindowItemWayland(Window *window, Scene *scene, Item *parent=nullptr)
WindowItemX11(X11Window *window, Scene *scene, Item *parent=nullptr)
void currentDesktopChanged(KWin::VirtualDesktop *previousDesktop, KWin::Window *)
void currentActivityChanged()
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830