20#include <KDecoration2/Decoration>
21#include <KDecoration2/DecorationShadow>
32 , m_cachedSize(window->size())
33 , m_decorationShadow(nullptr)
44 auto shadow = createShadowFromDecoration(
window);
46 shadow = createShadowFromWayland(
window);
48 if (!shadow && kwinApp()->x11Connection()) {
49 shadow = createShadowFromX11(
window);
52 shadow = createShadowFromInternalWindow(
window);
57std::unique_ptr<Shadow> Shadow::createShadowFromX11(
Window *window)
63 auto data = Shadow::readX11ShadowProperty(x11Window->
window());
64 if (!data.isEmpty()) {
65 auto shadow = std::make_unique<Shadow>(
window);
66 if (!shadow->init(data)) {
75std::unique_ptr<Shadow> Shadow::createShadowFromDecoration(
Window *window)
80 auto shadow = std::make_unique<Shadow>(
window);
87std::unique_ptr<Shadow> Shadow::createShadowFromWayland(
Window *window)
93 const auto s = surface->
shadow();
97 auto shadow = std::make_unique<Shadow>(
window);
98 if (!shadow->init(s)) {
104std::unique_ptr<Shadow> Shadow::createShadowFromInternalWindow(
Window *window)
106 const InternalWindow *internalWindow = qobject_cast<InternalWindow *>(
window);
107 if (!internalWindow) {
110 const QWindow *handle = internalWindow->handle();
114 auto shadow = std::make_unique<Shadow>(
window);
115 if (!shadow->init(handle)) {
121QList<uint32_t> Shadow::readX11ShadowProperty(xcb_window_t
id)
124 if (
id != XCB_WINDOW_NONE) {
126 uint32_t *shadow =
property.value<uint32_t *>();
129 for (
int i = 0; i < 12; ++i) {
137bool Shadow::init(
const QList<uint32_t> &data)
141 auto *c = kwinApp()->x11Connection();
143 pixmapGeometries[i] = Xcb::WindowGeometry(data[i]);
145 auto discardReplies = [&getImageCookies](
int start) {
146 for (
int i = start; i < getImageCookies.size(); ++i) {
147 xcb_discard_reply(kwinApp()->x11Connection(), getImageCookies.at(i).sequence);
151 auto &geo = pixmapGeometries[i];
156 getImageCookies[i] = xcb_get_image_unchecked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, data[i],
157 0, 0, geo->width, geo->height, ~0);
160 auto *reply = xcb_get_image_reply(c, getImageCookies.at(i),
nullptr);
162 discardReplies(i + 1);
165 auto &geo = pixmapGeometries[i];
166 QImage image(xcb_get_image_data(reply), geo->width, geo->height, QImage::Format_ARGB32);
167 m_shadowElements[i] = image.copy();
179bool Shadow::init(KDecoration2::Decoration *decoration)
181 if (m_decorationShadow) {
183 disconnect(m_decorationShadow.get(), &KDecoration2::DecorationShadow::innerShadowRectChanged, m_window, &
Window::updateShadow);
184 disconnect(m_decorationShadow.get(), &KDecoration2::DecorationShadow::shadowChanged, m_window, &
Window::updateShadow);
185 disconnect(m_decorationShadow.get(), &KDecoration2::DecorationShadow::paddingChanged, m_window, &
Window::updateShadow);
187 m_decorationShadow = decoration->shadow();
188 if (!m_decorationShadow) {
192 connect(m_decorationShadow.get(), &KDecoration2::DecorationShadow::innerShadowRectChanged, m_window, &
Window::updateShadow);
193 connect(m_decorationShadow.get(), &KDecoration2::DecorationShadow::shadowChanged, m_window, &
Window::updateShadow);
194 connect(m_decorationShadow.get(), &KDecoration2::DecorationShadow::paddingChanged, m_window, &
Window::updateShadow);
196 m_offset = m_decorationShadow->padding();
202static QImage shadowTileForBuffer(GraphicsBuffer *buffer)
205 const GraphicsBufferView view(buffer);
206 if (
const QImage *image = view.image()) {
207 return image->copy();
213bool Shadow::init(
const QPointer<ShadowInterface> &shadow)
228 m_offset = shadow->offset().toMargins();
234bool Shadow::init(
const QWindow *window)
236 const bool isEnabled =
window->property(
"kwin_shadow_enabled").toBool();
241 const QImage leftTile =
window->property(
"kwin_shadow_left_tile").value<QImage>();
242 const QImage topLeftTile =
window->property(
"kwin_shadow_top_left_tile").value<QImage>();
243 const QImage topTile =
window->property(
"kwin_shadow_top_tile").value<QImage>();
244 const QImage topRightTile =
window->property(
"kwin_shadow_top_right_tile").value<QImage>();
245 const QImage rightTile =
window->property(
"kwin_shadow_right_tile").value<QImage>();
246 const QImage bottomRightTile =
window->property(
"kwin_shadow_bottom_right_tile").value<QImage>();
247 const QImage bottomTile =
window->property(
"kwin_shadow_bottom_tile").value<QImage>();
248 const QImage bottomLeftTile =
window->property(
"kwin_shadow_bottom_left_tile").value<QImage>();
259 m_offset =
window->property(
"kwin_shadow_padding").value<QMargins>();
271 if (m_decorationShadow) {
283 if (m_window && m_window->
surface()) {
293 if (init(
window->handle())) {
299 auto data = Shadow::readX11ShadowProperty(
window->window());
300 if (!data.isEmpty()) {
316 if (m_cachedSize == m_window->
size()) {
319 m_cachedSize = m_window->
size();
325 if (!m_decorationShadow) {
328 return m_decorationShadow->shadow();
333 if (m_decorationShadow) {
336 return m_decorationShadow->topGeometry().size();
338 return m_decorationShadow->topRightGeometry().size();
340 return m_decorationShadow->rightGeometry().size();
342 return m_decorationShadow->bottomRightGeometry().size();
344 return m_decorationShadow->bottomGeometry().size();
346 return m_decorationShadow->bottomLeftGeometry().size();
348 return m_decorationShadow->leftGeometry().size();
350 return m_decorationShadow->topLeftGeometry().size();
355 return m_shadowElements[element].size();
361#include "moc_shadow.cpp"
Xcb::Atom kde_net_wm_shadow
QSize elementSize(ShadowElements element) const
static std::unique_ptr< Shadow > createShadow(Window *window)
@ ShadowElementBottomLeft
@ ShadowElementBottomRight
QImage decorationShadowImage() const
ShadowInterface * shadow() const
SurfaceInterface * surface() const
std::shared_ptr< KDecoration2::Decoration > decoration
void frameGeometryChanged(const QRectF &oldGeometry)
xcb_window_t window() const
WaylandServer * waylandServer()
KWIN_EXPORT Atoms * atoms