File indexing completed on 2024-05-19 16:34:47
0001 /* 0002 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "scene/windowitem.h" 0008 #include "deleted.h" 0009 #include "internalwindow.h" 0010 #include "scene/decorationitem.h" 0011 #include "scene/shadowitem.h" 0012 #include "scene/surfaceitem_internal.h" 0013 #include "scene/surfaceitem_wayland.h" 0014 #include "scene/surfaceitem_x11.h" 0015 #include "wayland_server.h" 0016 #include "window.h" 0017 #include "workspace.h" 0018 0019 #include <KDecoration2/Decoration> 0020 0021 namespace KWin 0022 { 0023 0024 WindowItem::WindowItem(Window *window, Scene *scene, Item *parent) 0025 : Item(scene, parent) 0026 , m_window(window) 0027 { 0028 connect(window, &Window::decorationChanged, this, &WindowItem::updateDecorationItem); 0029 updateDecorationItem(); 0030 0031 connect(window, &Window::shadowChanged, this, &WindowItem::updateShadowItem); 0032 updateShadowItem(); 0033 0034 connect(window, &Window::frameGeometryChanged, this, &WindowItem::updatePosition); 0035 updatePosition(); 0036 0037 if (waylandServer()) { 0038 connect(waylandServer(), &WaylandServer::lockStateChanged, this, &WindowItem::updateVisibility); 0039 } 0040 connect(window, &Window::lockScreenOverlayChanged, this, &WindowItem::updateVisibility); 0041 connect(window, &Window::minimizedChanged, this, &WindowItem::updateVisibility); 0042 connect(window, &Window::hiddenChanged, this, &WindowItem::updateVisibility); 0043 connect(window, &Window::activitiesChanged, this, &WindowItem::updateVisibility); 0044 connect(window, &Window::desktopChanged, this, &WindowItem::updateVisibility); 0045 connect(workspace(), &Workspace::currentActivityChanged, this, &WindowItem::updateVisibility); 0046 connect(workspace(), &Workspace::currentDesktopChanged, this, &WindowItem::updateVisibility); 0047 updateVisibility(); 0048 0049 connect(window, &Window::opacityChanged, this, &WindowItem::updateOpacity); 0050 updateOpacity(); 0051 0052 connect(window, &Window::windowClosed, this, &WindowItem::handleWindowClosed); 0053 } 0054 0055 WindowItem::~WindowItem() 0056 { 0057 } 0058 0059 SurfaceItem *WindowItem::surfaceItem() const 0060 { 0061 return m_surfaceItem.get(); 0062 } 0063 0064 DecorationItem *WindowItem::decorationItem() const 0065 { 0066 return m_decorationItem.get(); 0067 } 0068 0069 ShadowItem *WindowItem::shadowItem() const 0070 { 0071 return m_shadowItem.get(); 0072 } 0073 0074 Window *WindowItem::window() const 0075 { 0076 return m_window; 0077 } 0078 0079 void WindowItem::refVisible(int reason) 0080 { 0081 if (reason & PAINT_DISABLED_BY_HIDDEN) { 0082 m_forceVisibleByHiddenCount++; 0083 } 0084 if (reason & PAINT_DISABLED_BY_DELETE) { 0085 m_forceVisibleByDeleteCount++; 0086 } 0087 if (reason & PAINT_DISABLED_BY_DESKTOP) { 0088 m_forceVisibleByDesktopCount++; 0089 } 0090 if (reason & PAINT_DISABLED_BY_MINIMIZE) { 0091 m_forceVisibleByMinimizeCount++; 0092 } 0093 if (reason & PAINT_DISABLED_BY_ACTIVITY) { 0094 m_forceVisibleByActivityCount++; 0095 } 0096 updateVisibility(); 0097 } 0098 0099 void WindowItem::unrefVisible(int reason) 0100 { 0101 if (reason & PAINT_DISABLED_BY_HIDDEN) { 0102 Q_ASSERT(m_forceVisibleByHiddenCount > 0); 0103 m_forceVisibleByHiddenCount--; 0104 } 0105 if (reason & PAINT_DISABLED_BY_DELETE) { 0106 Q_ASSERT(m_forceVisibleByDeleteCount > 0); 0107 m_forceVisibleByDeleteCount--; 0108 } 0109 if (reason & PAINT_DISABLED_BY_DESKTOP) { 0110 Q_ASSERT(m_forceVisibleByDesktopCount > 0); 0111 m_forceVisibleByDesktopCount--; 0112 } 0113 if (reason & PAINT_DISABLED_BY_MINIMIZE) { 0114 Q_ASSERT(m_forceVisibleByMinimizeCount > 0); 0115 m_forceVisibleByMinimizeCount--; 0116 } 0117 if (reason & PAINT_DISABLED_BY_ACTIVITY) { 0118 Q_ASSERT(m_forceVisibleByActivityCount > 0); 0119 m_forceVisibleByActivityCount--; 0120 } 0121 updateVisibility(); 0122 } 0123 0124 void WindowItem::handleWindowClosed(Window *original, Deleted *deleted) 0125 { 0126 m_window = deleted; 0127 } 0128 0129 bool WindowItem::computeVisibility() const 0130 { 0131 if (!m_window->readyForPainting()) { 0132 return false; 0133 } 0134 if (waylandServer() && waylandServer()->isScreenLocked()) { 0135 return m_window->isLockScreen() || m_window->isInputMethod() || m_window->isLockScreenOverlay(); 0136 } 0137 if (m_window->isDeleted()) { 0138 if (m_forceVisibleByDeleteCount == 0) { 0139 return false; 0140 } 0141 } 0142 if (!m_window->isOnCurrentDesktop()) { 0143 if (m_forceVisibleByDesktopCount == 0) { 0144 return false; 0145 } 0146 } 0147 if (!m_window->isOnCurrentActivity()) { 0148 if (m_forceVisibleByActivityCount == 0) { 0149 return false; 0150 } 0151 } 0152 if (m_window->isMinimized()) { 0153 if (m_forceVisibleByMinimizeCount == 0) { 0154 return false; 0155 } 0156 } 0157 if (m_window->isHiddenInternal()) { 0158 if (m_forceVisibleByHiddenCount == 0) { 0159 return false; 0160 } 0161 } 0162 return true; 0163 } 0164 0165 void WindowItem::updateVisibility() 0166 { 0167 setVisible(computeVisibility()); 0168 } 0169 0170 void WindowItem::updatePosition() 0171 { 0172 setPosition(m_window->pos()); 0173 } 0174 0175 void WindowItem::addSurfaceItemDamageConnects(Item *item) 0176 { 0177 auto surfaceItem = static_cast<SurfaceItem *>(item); 0178 connect(surfaceItem, &SurfaceItem::damaged, this, &WindowItem::markDamaged); 0179 connect(surfaceItem, &SurfaceItem::childAdded, this, &WindowItem::addSurfaceItemDamageConnects); 0180 const auto childItems = item->childItems(); 0181 for (const auto &child : childItems) { 0182 addSurfaceItemDamageConnects(child); 0183 } 0184 } 0185 0186 void WindowItem::updateSurfaceItem(SurfaceItem *surfaceItem) 0187 { 0188 m_surfaceItem.reset(surfaceItem); 0189 0190 if (m_surfaceItem) { 0191 connect(m_window, &Window::shadeChanged, this, &WindowItem::updateSurfaceVisibility); 0192 connect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition); 0193 connect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition); 0194 addSurfaceItemDamageConnects(surfaceItem); 0195 0196 updateSurfacePosition(); 0197 updateSurfaceVisibility(); 0198 } else { 0199 disconnect(m_window, &Window::shadeChanged, this, &WindowItem::updateSurfaceVisibility); 0200 disconnect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition); 0201 disconnect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition); 0202 } 0203 } 0204 0205 void WindowItem::updateSurfacePosition() 0206 { 0207 const QRectF bufferGeometry = m_window->bufferGeometry(); 0208 const QRectF frameGeometry = m_window->frameGeometry(); 0209 0210 m_surfaceItem->setPosition(bufferGeometry.topLeft() - frameGeometry.topLeft()); 0211 } 0212 0213 void WindowItem::updateSurfaceVisibility() 0214 { 0215 m_surfaceItem->setVisible(!m_window->isShade()); 0216 } 0217 0218 void WindowItem::updateShadowItem() 0219 { 0220 Shadow *shadow = m_window->shadow(); 0221 if (shadow) { 0222 if (!m_shadowItem || m_shadowItem->shadow() != shadow) { 0223 m_shadowItem.reset(new ShadowItem(shadow, m_window, scene(), this)); 0224 } 0225 if (m_decorationItem) { 0226 m_shadowItem->stackBefore(m_decorationItem.get()); 0227 } else if (m_surfaceItem) { 0228 m_shadowItem->stackBefore(m_surfaceItem.get()); 0229 } 0230 markDamaged(); 0231 } else { 0232 m_shadowItem.reset(); 0233 } 0234 } 0235 0236 void WindowItem::updateDecorationItem() 0237 { 0238 if (m_window->isDeleted() || m_window->isZombie()) { 0239 return; 0240 } 0241 if (m_window->decoration()) { 0242 m_decorationItem.reset(new DecorationItem(m_window->decoration(), m_window, scene(), this)); 0243 if (m_shadowItem) { 0244 m_decorationItem->stackAfter(m_shadowItem.get()); 0245 } else if (m_surfaceItem) { 0246 m_decorationItem->stackBefore(m_surfaceItem.get()); 0247 } 0248 connect(m_window->decoration(), &KDecoration2::Decoration::damaged, this, &WindowItem::markDamaged); 0249 markDamaged(); 0250 } else { 0251 m_decorationItem.reset(); 0252 } 0253 } 0254 0255 void WindowItem::updateOpacity() 0256 { 0257 setOpacity(m_window->opacity()); 0258 } 0259 0260 void WindowItem::markDamaged() 0261 { 0262 Q_EMIT m_window->damaged(m_window); 0263 } 0264 0265 WindowItemX11::WindowItemX11(Window *window, Scene *scene, Item *parent) 0266 : WindowItem(window, scene, parent) 0267 { 0268 initialize(); 0269 0270 // Xwayland windows and Wayland surfaces are associated asynchronously. 0271 connect(window, &Window::surfaceChanged, this, &WindowItemX11::initialize); 0272 } 0273 0274 void WindowItemX11::initialize() 0275 { 0276 switch (kwinApp()->operationMode()) { 0277 case Application::OperationModeX11: 0278 updateSurfaceItem(new SurfaceItemX11(window(), scene(), this)); 0279 break; 0280 case Application::OperationModeXwayland: 0281 if (!window()->surface()) { 0282 updateSurfaceItem(nullptr); 0283 } else { 0284 updateSurfaceItem(new SurfaceItemXwayland(window(), scene(), this)); 0285 } 0286 break; 0287 case Application::OperationModeWaylandOnly: 0288 Q_UNREACHABLE(); 0289 } 0290 } 0291 0292 WindowItemWayland::WindowItemWayland(Window *window, Scene *scene, Item *parent) 0293 : WindowItem(window, scene, parent) 0294 { 0295 updateSurfaceItem(new SurfaceItemWayland(window->surface(), scene, this)); 0296 } 0297 0298 WindowItemInternal::WindowItemInternal(InternalWindow *window, Scene *scene, Item *parent) 0299 : WindowItem(window, scene, parent) 0300 { 0301 updateSurfaceItem(new SurfaceItemInternal(window, scene, this)); 0302 } 0303 0304 } // namespace KWin