File indexing completed on 2024-05-12 17:00:19
0001 /* 0002 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "windowshadow.h" 0008 #include "logging.h" 0009 #include "waylandintegration.h" 0010 0011 #include <KWayland/Client/shm_pool.h> 0012 #include <KWayland/Client/surface.h> 0013 0014 #include <QDebug> 0015 #include <QExposeEvent> 0016 0017 WindowShadowTile::WindowShadowTile() {} 0018 WindowShadowTile::~WindowShadowTile() {} 0019 0020 bool WindowShadowTile::create() 0021 { 0022 m_shmPool.reset(WaylandIntegration::self()->createShmPool()); 0023 if (!m_shmPool) { 0024 return false; 0025 } 0026 buffer = m_shmPool->createBuffer(image); 0027 return true; 0028 } 0029 0030 void WindowShadowTile::destroy() 0031 { 0032 buffer = nullptr; 0033 } 0034 0035 WindowShadowTile *WindowShadowTile::get(const KWindowShadowTile *tile) 0036 { 0037 KWindowShadowTilePrivate *d = KWindowShadowTilePrivate::get(tile); 0038 return static_cast<WindowShadowTile *>(d); 0039 } 0040 0041 static KWayland::Client::Buffer::Ptr bufferForTile(const KWindowShadowTile::Ptr &tile) 0042 { 0043 if (!tile) { 0044 return KWayland::Client::Buffer::Ptr(); 0045 } 0046 WindowShadowTile *d = WindowShadowTile::get(tile.data()); 0047 return d->buffer; 0048 } 0049 0050 bool WindowShadow::eventFilter(QObject *watched, QEvent *event) 0051 { 0052 Q_UNUSED(watched) 0053 if (event->type() == QEvent::Expose) { 0054 QExposeEvent *exposeEvent = static_cast<QExposeEvent *>(event); 0055 if (!exposeEvent->region().isNull()) { 0056 if (!internalCreate()) { 0057 qCWarning(KWAYLAND_KWS) << "Failed to recreate shadow for" << window; 0058 } 0059 } 0060 } else if (event->type() == QEvent::Hide) { 0061 internalDestroy(); 0062 } 0063 return false; 0064 } 0065 0066 bool WindowShadow::internalCreate() 0067 { 0068 if (shadow) { 0069 return true; 0070 } 0071 KWayland::Client::ShadowManager *shadowManager = WaylandIntegration::self()->waylandShadowManager(); 0072 if (!shadowManager) { 0073 return false; 0074 } 0075 KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(window); 0076 if (!surface) { 0077 return false; 0078 } 0079 0080 shadow = shadowManager->createShadow(surface, surface); 0081 shadow->attachLeft(bufferForTile(leftTile)); 0082 shadow->attachTopLeft(bufferForTile(topLeftTile)); 0083 shadow->attachTop(bufferForTile(topTile)); 0084 shadow->attachTopRight(bufferForTile(topRightTile)); 0085 shadow->attachRight(bufferForTile(rightTile)); 0086 shadow->attachBottomRight(bufferForTile(bottomRightTile)); 0087 shadow->attachBottom(bufferForTile(bottomTile)); 0088 shadow->attachBottomLeft(bufferForTile(bottomLeftTile)); 0089 shadow->setOffsets(padding); 0090 shadow->commit(); 0091 0092 // Commit wl_surface at the next available time. 0093 window->requestUpdate(); 0094 0095 return true; 0096 } 0097 0098 bool WindowShadow::create() 0099 { 0100 KWayland::Client::ShadowManager *shadowManager = WaylandIntegration::self()->waylandShadowManager(); 0101 if (!shadowManager) { 0102 return false; 0103 } 0104 internalCreate(); 0105 window->installEventFilter(this); 0106 return true; 0107 } 0108 0109 void WindowShadow::internalDestroy() 0110 { 0111 if (!shadow) { 0112 return; 0113 } 0114 0115 KWayland::Client::ShadowManager *shadowManager = WaylandIntegration::self()->waylandShadowManager(); 0116 if (shadowManager) { 0117 KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(window); 0118 if (surface) { 0119 shadowManager->removeShadow(surface); 0120 } 0121 } 0122 0123 delete shadow; 0124 shadow = nullptr; 0125 0126 if (window) { 0127 window->requestUpdate(); 0128 } 0129 } 0130 0131 void WindowShadow::destroy() 0132 { 0133 if (window) { 0134 window->removeEventFilter(this); 0135 } 0136 internalDestroy(); 0137 }