KWindowSystem

platforms/xcb/kwindowshadow.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#include "kwindowshadow_p_x11.h"
8
9#include <private/qtx11extras_p.h>
10
11static const QByteArray s_atomName = QByteArrayLiteral("_KDE_NET_WM_SHADOW");
12
13bool KWindowShadowTilePrivateX11::create()
14{
15 xcb_connection_t *connection = QX11Info::connection();
16 xcb_window_t rootWindow = QX11Info::appRootWindow();
17
18 const uint16_t width = uint16_t(image.width());
19 const uint16_t height = uint16_t(image.height());
20 const uint8_t depth = uint8_t(image.depth());
21
22 pixmap = xcb_generate_id(connection);
23 gc = xcb_generate_id(connection);
24
25 xcb_create_pixmap(connection, depth, pixmap, rootWindow, width, height);
26 xcb_create_gc(connection, gc, pixmap, 0, nullptr);
27
28 xcb_put_image(connection, //
29 XCB_IMAGE_FORMAT_Z_PIXMAP,
30 pixmap,
31 gc,
32 width,
33 height,
34 0,
35 0,
36 0,
37 depth,
38 image.sizeInBytes(),
39 image.constBits());
40
41 return true;
42}
43
44void KWindowShadowTilePrivateX11::destroy()
45{
46 xcb_connection_t *connection = QX11Info::connection();
47 if (connection) {
48 xcb_free_pixmap(connection, pixmap);
49 xcb_free_gc(connection, gc);
50 }
51 pixmap = XCB_PIXMAP_NONE;
52 gc = XCB_NONE;
53}
54
55KWindowShadowTilePrivateX11 *KWindowShadowTilePrivateX11::get(const KWindowShadowTile *tile)
56{
57 KWindowShadowTilePrivate *d = KWindowShadowTilePrivate::get(tile);
58 return static_cast<KWindowShadowTilePrivateX11 *>(d);
59}
60
61static xcb_atom_t lookupAtom(const QByteArray &atomName)
62{
63 xcb_connection_t *connection = QX11Info::connection();
64 if (!connection) {
65 return XCB_ATOM_NONE;
66 }
67
68 xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(connection, //
69 false,
70 atomName.size(),
71 atomName.constData());
72 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, atomCookie, nullptr);
73
74 if (!reply) {
75 return XCB_ATOM_NONE;
76 }
77
78 xcb_atom_t atom = reply->atom;
79 free(reply);
80
81 return atom;
82}
83
84static xcb_pixmap_t nativeHandleForTile(const KWindowShadowTile::Ptr &tile)
85{
86 const auto d = KWindowShadowTilePrivateX11::get(tile.data());
87 return d->pixmap;
88}
89
90bool KWindowShadowPrivateX11::create()
91{
92 xcb_connection_t *connection = QX11Info::connection();
93
94 const xcb_atom_t atom = lookupAtom(s_atomName);
95 if (atom == XCB_ATOM_NONE) {
96 return false;
97 }
98
99 QList<quint32> data(12);
100 int i = 0;
101
102 // Unfortunately we cannot use handle of XCB_PIXMAP_NONE for missing shadow tiles because
103 // KWin expects **all** shadow tile handles to be valid. Maybe we could address this small
104 // inconvenience and then remove the empty tile stuff.
105
106 if (topTile) {
107 data[i++] = nativeHandleForTile(topTile);
108 } else {
109 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
110 }
111
112 if (topRightTile) {
113 data[i++] = nativeHandleForTile(topRightTile);
114 } else {
115 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
116 }
117
118 if (rightTile) {
119 data[i++] = nativeHandleForTile(rightTile);
120 } else {
121 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
122 }
123
124 if (bottomRightTile) {
125 data[i++] = nativeHandleForTile(bottomRightTile);
126 } else {
127 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
128 }
129
130 if (bottomTile) {
131 data[i++] = nativeHandleForTile(bottomTile);
132 } else {
133 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
134 }
135
136 if (bottomLeftTile) {
137 data[i++] = nativeHandleForTile(bottomLeftTile);
138 } else {
139 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
140 }
141
142 if (leftTile) {
143 data[i++] = nativeHandleForTile(leftTile);
144 } else {
145 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
146 }
147
148 if (topLeftTile) {
149 data[i++] = nativeHandleForTile(topLeftTile);
150 } else {
151 data[i++] = nativeHandleForTile(getOrCreateEmptyTile());
152 }
153
154 if (topLeftTile || topTile || topRightTile) {
155 data[i++] = uint32_t(padding.top());
156 } else {
157 data[i++] = 1;
158 }
159
160 if (topRightTile || rightTile || bottomRightTile) {
161 data[i++] = uint32_t(padding.right());
162 } else {
163 data[i++] = 1;
164 }
165
166 if (bottomRightTile || bottomTile || bottomLeftTile) {
167 data[i++] = uint32_t(padding.bottom());
168 } else {
169 data[i++] = 1;
170 }
171
172 if (bottomLeftTile || leftTile || topLeftTile) {
173 data[i++] = uint32_t(padding.left());
174 } else {
175 data[i++] = 1;
176 }
177
178 xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window->winId(), atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData());
179 xcb_flush(connection);
180
181 return true;
182}
183
184void KWindowShadowPrivateX11::destroy()
185{
186 emptyTile = nullptr;
187
188 // For some reason, QWindow changes visibility of QSurface::surfaceHandle().
189 const QSurface *surface = window;
190
191 // Attempting to uninstall the shadow after the platform window had been destroyed.
192 if (!(surface && surface->surfaceHandle())) {
193 return;
194 }
195
196 xcb_connection_t *connection = QX11Info::connection();
197
198 const xcb_atom_t atom = lookupAtom(s_atomName);
199 if (atom == XCB_ATOM_NONE) {
200 return;
201 }
202
203 xcb_delete_property(connection, window->winId(), atom);
204}
205
206KWindowShadowTile::Ptr KWindowShadowPrivateX11::getOrCreateEmptyTile()
207{
208 if (!emptyTile) {
209 QImage image(QSize(1, 1), QImage::Format_ARGB32);
210 image.fill(Qt::transparent);
211
212 emptyTile = KWindowShadowTile::Ptr::create();
213 emptyTile->setImage(image);
214 emptyTile->create();
215 }
216
217 return emptyTile;
218}
The KWindowShadowTile class provides a platform-indendent shadow tile representation.
QWidget * window(QObject *job)
const char * constData() const const
qsizetype size() const const
QSharedPointer< T > create(Args &&... args)
T * data() const const
virtual QPlatformSurface * surfaceHandle() const const=0
transparent
WId winId() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:04 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.