Changeset View
Changeset View
Standalone View
Standalone View
shadow.cpp
1 | /******************************************************************** | 1 | /******************************************************************** | ||
---|---|---|---|---|---|
2 | KWin - the KDE window manager | 2 | KWin - the KDE window manager | ||
3 | This file is part of the KDE project. | 3 | This file is part of the KDE project. | ||
4 | 4 | | |||
5 | Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org> | 5 | Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org> | ||
6 | Copyright (C) 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> | ||||
6 | 7 | | |||
7 | This program is free software; you can redistribute it and/or modify | 8 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | 9 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | 10 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | 11 | (at your option) any later version. | ||
11 | 12 | | |||
12 | This program is distributed in the hope that it will be useful, | 13 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | 16 | GNU General Public License for more details. | ||
16 | 17 | | |||
17 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 20 | *********************************************************************/ | ||
20 | #include "shadow.h" | 21 | #include "shadow.h" | ||
21 | // kwin | 22 | // kwin | ||
22 | #include "atoms.h" | 23 | #include "atoms.h" | ||
23 | #include "abstract_client.h" | 24 | #include "abstract_client.h" | ||
24 | #include "composite.h" | 25 | #include "composite.h" | ||
25 | #include "effects.h" | 26 | #include "effects.h" | ||
27 | #include "internal_client.h" | ||||
26 | #include "toplevel.h" | 28 | #include "toplevel.h" | ||
27 | #include "wayland_server.h" | 29 | #include "wayland_server.h" | ||
28 | 30 | | |||
29 | #include <KDecoration2/Decoration> | 31 | #include <KDecoration2/Decoration> | ||
30 | #include <KDecoration2/DecorationShadow> | 32 | #include <KDecoration2/DecorationShadow> | ||
31 | 33 | | |||
32 | #include <KWayland/Server/buffer_interface.h> | 34 | #include <KWayland/Server/buffer_interface.h> | ||
33 | #include <KWayland/Server/shadow_interface.h> | 35 | #include <KWayland/Server/shadow_interface.h> | ||
34 | #include <KWayland/Server/surface_interface.h> | 36 | #include <KWayland/Server/surface_interface.h> | ||
35 | 37 | | |||
38 | #include <QWindow> | ||||
39 | | ||||
40 | Q_DECLARE_METATYPE(QMargins) | ||||
41 | | ||||
36 | namespace KWin | 42 | namespace KWin | ||
37 | { | 43 | { | ||
38 | 44 | | |||
39 | Shadow::Shadow(Toplevel *toplevel) | 45 | Shadow::Shadow(Toplevel *toplevel) | ||
40 | : m_topLevel(toplevel) | 46 | : m_topLevel(toplevel) | ||
41 | , m_cachedSize(toplevel->size()) | 47 | , m_cachedSize(toplevel->size()) | ||
42 | , m_decorationShadow(nullptr) | 48 | , m_decorationShadow(nullptr) | ||
43 | { | 49 | { | ||
Show All 12 Lines | 58 | { | |||
56 | Shadow *shadow = createShadowFromDecoration(toplevel); | 62 | Shadow *shadow = createShadowFromDecoration(toplevel); | ||
57 | if (!shadow && waylandServer()) { | 63 | if (!shadow && waylandServer()) { | ||
58 | shadow = createShadowFromWayland(toplevel); | 64 | shadow = createShadowFromWayland(toplevel); | ||
59 | } | 65 | } | ||
60 | if (!shadow && kwinApp()->x11Connection()) { | 66 | if (!shadow && kwinApp()->x11Connection()) { | ||
61 | shadow = createShadowFromX11(toplevel); | 67 | shadow = createShadowFromX11(toplevel); | ||
62 | } | 68 | } | ||
63 | if (!shadow) { | 69 | if (!shadow) { | ||
70 | shadow = createShadowFromInternalWindow(toplevel); | ||||
71 | } | ||||
72 | if (!shadow) { | ||||
64 | return nullptr; | 73 | return nullptr; | ||
65 | } | 74 | } | ||
66 | if (toplevel->effectWindow() && toplevel->effectWindow()->sceneWindow()) { | 75 | if (toplevel->effectWindow() && toplevel->effectWindow()->sceneWindow()) { | ||
67 | toplevel->effectWindow()->sceneWindow()->updateShadow(shadow); | 76 | toplevel->effectWindow()->sceneWindow()->updateShadow(shadow); | ||
68 | emit toplevel->shadowChanged(); | 77 | emit toplevel->shadowChanged(); | ||
69 | } | 78 | } | ||
70 | return shadow; | 79 | return shadow; | ||
71 | } | 80 | } | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 116 | { | |||
116 | Shadow *shadow = Compositor::self()->scene()->createShadow(toplevel); | 125 | Shadow *shadow = Compositor::self()->scene()->createShadow(toplevel); | ||
117 | if (!shadow->init(s)) { | 126 | if (!shadow->init(s)) { | ||
118 | delete shadow; | 127 | delete shadow; | ||
119 | return nullptr; | 128 | return nullptr; | ||
120 | } | 129 | } | ||
121 | return shadow; | 130 | return shadow; | ||
122 | } | 131 | } | ||
123 | 132 | | |||
133 | Shadow *Shadow::createShadowFromInternalWindow(Toplevel *toplevel) | ||||
134 | { | ||||
135 | const InternalClient *client = qobject_cast<InternalClient *>(toplevel); | ||||
136 | if (!client) { | ||||
137 | return nullptr; | ||||
138 | } | ||||
139 | const QWindow *window = client->internalWindow(); | ||||
140 | if (!window) { | ||||
141 | return nullptr; | ||||
142 | } | ||||
143 | Shadow *shadow = Compositor::self()->scene()->createShadow(toplevel); | ||||
144 | if (!shadow->init(window)) { | ||||
145 | delete shadow; | ||||
146 | return nullptr; | ||||
147 | } | ||||
148 | return shadow; | ||||
149 | } | ||||
150 | | ||||
124 | QVector< uint32_t > Shadow::readX11ShadowProperty(xcb_window_t id) | 151 | QVector< uint32_t > Shadow::readX11ShadowProperty(xcb_window_t id) | ||
125 | { | 152 | { | ||
126 | QVector<uint32_t> ret; | 153 | QVector<uint32_t> ret; | ||
127 | if (id != XCB_WINDOW_NONE) { | 154 | if (id != XCB_WINDOW_NONE) { | ||
128 | Xcb::Property property(false, id, atoms->kde_net_wm_shadow, XCB_ATOM_CARDINAL, 0, 12); | 155 | Xcb::Property property(false, id, atoms->kde_net_wm_shadow, XCB_ATOM_CARDINAL, 0, 12); | ||
129 | uint32_t *shadow = property.value<uint32_t*>(); | 156 | uint32_t *shadow = property.value<uint32_t*>(); | ||
130 | if (shadow) { | 157 | if (shadow) { | ||
131 | ret.reserve(12); | 158 | ret.reserve(12); | ||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Line(s) | 243 | { | |||
235 | updateShadowRegion(); | 262 | updateShadowRegion(); | ||
236 | if (!prepareBackend()) { | 263 | if (!prepareBackend()) { | ||
237 | return false; | 264 | return false; | ||
238 | } | 265 | } | ||
239 | buildQuads(); | 266 | buildQuads(); | ||
240 | return true; | 267 | return true; | ||
241 | } | 268 | } | ||
242 | 269 | | |||
270 | bool Shadow::init(const QWindow *window) | ||||
271 | { | ||||
272 | const bool isEnabled = window->property("kwin_shadow_enabled").toBool(); | ||||
273 | if (!isEnabled) { | ||||
274 | return false; | ||||
275 | } | ||||
276 | | ||||
277 | const QImage leftTile = window->property("kwin_shadow_left_tile").value<QImage>(); | ||||
278 | const QImage topLeftTile = window->property("kwin_shadow_top_left_tile").value<QImage>(); | ||||
279 | const QImage topTile = window->property("kwin_shadow_top_tile").value<QImage>(); | ||||
280 | const QImage topRightTile = window->property("kwin_shadow_top_right_tile").value<QImage>(); | ||||
281 | const QImage rightTile = window->property("kwin_shadow_right_tile").value<QImage>(); | ||||
282 | const QImage bottomRightTile = window->property("kwin_shadow_bottom_right_tile").value<QImage>(); | ||||
283 | const QImage bottomTile = window->property("kwin_shadow_bottom_tile").value<QImage>(); | ||||
284 | const QImage bottomLeftTile = window->property("kwin_shadow_bottom_left_tile").value<QImage>(); | ||||
285 | | ||||
286 | m_shadowElements[ShadowElementLeft] = QPixmap::fromImage(leftTile); | ||||
287 | m_shadowElements[ShadowElementTopLeft] = QPixmap::fromImage(topLeftTile); | ||||
288 | m_shadowElements[ShadowElementTop] = QPixmap::fromImage(topTile); | ||||
289 | m_shadowElements[ShadowElementTopRight] = QPixmap::fromImage(topRightTile); | ||||
290 | m_shadowElements[ShadowElementRight] = QPixmap::fromImage(rightTile); | ||||
291 | m_shadowElements[ShadowElementBottomRight] = QPixmap::fromImage(bottomRightTile); | ||||
292 | m_shadowElements[ShadowElementBottom] = QPixmap::fromImage(bottomTile); | ||||
293 | m_shadowElements[ShadowElementBottomLeft] = QPixmap::fromImage(bottomLeftTile); | ||||
294 | | ||||
295 | const QMargins padding = window->property("kwin_shadow_padding").value<QMargins>(); | ||||
296 | | ||||
297 | m_leftOffset = padding.left(); | ||||
298 | m_topOffset = padding.top(); | ||||
299 | m_rightOffset = padding.right(); | ||||
300 | m_bottomOffset = padding.bottom(); | ||||
301 | | ||||
302 | updateShadowRegion(); | ||||
303 | | ||||
304 | if (!prepareBackend()) { | ||||
305 | return false; | ||||
306 | } | ||||
307 | | ||||
308 | buildQuads(); | ||||
309 | | ||||
310 | return true; | ||||
311 | } | ||||
312 | | ||||
243 | void Shadow::updateShadowRegion() | 313 | void Shadow::updateShadowRegion() | ||
244 | { | 314 | { | ||
245 | const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset); | 315 | const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset); | ||
246 | const QRect right(m_topLevel->width(), - m_topOffset, m_rightOffset, m_topLevel->height() + m_topOffset + m_bottomOffset); | 316 | const QRect right(m_topLevel->width(), - m_topOffset, m_rightOffset, m_topLevel->height() + m_topOffset + m_bottomOffset); | ||
247 | const QRect bottom(0, m_topLevel->height(), m_topLevel->width(), m_bottomOffset); | 317 | const QRect bottom(0, m_topLevel->height(), m_topLevel->width(), m_bottomOffset); | ||
248 | const QRect left(- m_leftOffset, - m_topOffset, m_leftOffset, m_topLevel->height() + m_topOffset + m_bottomOffset); | 318 | const QRect left(- m_leftOffset, - m_topOffset, m_leftOffset, m_topLevel->height() + m_topOffset + m_bottomOffset); | ||
249 | m_shadowRegion = QRegion(top).united(right).united(bottom).united(left); | 319 | m_shadowRegion = QRegion(top).united(right).united(bottom).united(left); | ||
250 | } | 320 | } | ||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Line(s) | 420 | if (m_topLevel && m_topLevel->surface()) { | |||
351 | if (const auto &s = m_topLevel->surface()->shadow()) { | 421 | if (const auto &s = m_topLevel->surface()->shadow()) { | ||
352 | if (init(s)) { | 422 | if (init(s)) { | ||
353 | return true; | 423 | return true; | ||
354 | } | 424 | } | ||
355 | } | 425 | } | ||
356 | } | 426 | } | ||
357 | } | 427 | } | ||
358 | 428 | | |||
429 | if (InternalClient *client = qobject_cast<InternalClient *>(m_topLevel)) { | ||||
430 | if (init(client->internalWindow())) { | ||||
431 | return true; | ||||
432 | } | ||||
433 | } | ||||
434 | | ||||
359 | auto data = Shadow::readX11ShadowProperty(m_topLevel->window()); | 435 | auto data = Shadow::readX11ShadowProperty(m_topLevel->window()); | ||
360 | if (data.isEmpty()) { | 436 | if (data.isEmpty()) { | ||
361 | return false; | 437 | return false; | ||
362 | } | 438 | } | ||
363 | 439 | | |||
364 | init(data); | 440 | init(data); | ||
365 | 441 | | |||
366 | return true; | 442 | return true; | ||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |