File indexing completed on 2024-11-10 08:00:57
0001 /* 0002 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 #include "utils/xcbutils.h" 0007 0008 #include <QApplication> 0009 #include <QCommandLineParser> 0010 #include <QDebug> 0011 #include <QFormLayout> 0012 #include <QLabel> 0013 #include <QVBoxLayout> 0014 #include <QWidget> 0015 #include <private/qtx11extras_p.h> 0016 0017 static QList<uint32_t> readShadow(quint32 windowId) 0018 { 0019 KWin::Xcb::Atom atom(QByteArrayLiteral("_KDE_NET_WM_SHADOW"), false, QX11Info::connection()); 0020 QList<uint32_t> ret; 0021 if (windowId != XCB_WINDOW) { 0022 KWin::Xcb::Property property(false, windowId, atom, XCB_ATOM_CARDINAL, 0, 12); 0023 uint32_t *shadow = property.value<uint32_t *>(); 0024 if (shadow) { 0025 ret.reserve(12); 0026 for (int i = 0; i < 12; ++i) { 0027 ret << shadow[i]; 0028 } 0029 } else { 0030 qDebug() << "!!!! no shadow"; 0031 } 0032 } else { 0033 qDebug() << "!!!! no window"; 0034 } 0035 return ret; 0036 } 0037 0038 static QList<QPixmap> getPixmaps(const QList<uint32_t> &data) 0039 { 0040 QList<QPixmap> ret; 0041 static const int ShadowElementsCount = 8; 0042 QList<KWin::Xcb::WindowGeometry> pixmapGeometries(ShadowElementsCount); 0043 QList<xcb_get_image_cookie_t> getImageCookies(ShadowElementsCount); 0044 auto *c = KWin::connection(); 0045 for (int i = 0; i < ShadowElementsCount; ++i) { 0046 pixmapGeometries[i] = KWin::Xcb::WindowGeometry(data[i]); 0047 } 0048 auto discardReplies = [&getImageCookies](int start) { 0049 for (int i = start; i < getImageCookies.size(); ++i) { 0050 xcb_discard_reply(KWin::connection(), getImageCookies.at(i).sequence); 0051 } 0052 }; 0053 for (int i = 0; i < ShadowElementsCount; ++i) { 0054 auto &geo = pixmapGeometries[i]; 0055 if (geo.isNull()) { 0056 discardReplies(0); 0057 return QList<QPixmap>(); 0058 } 0059 getImageCookies[i] = xcb_get_image_unchecked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, data[i], 0060 0, 0, geo->width, geo->height, ~0); 0061 } 0062 for (int i = 0; i < ShadowElementsCount; ++i) { 0063 auto *reply = xcb_get_image_reply(c, getImageCookies.at(i), nullptr); 0064 if (!reply) { 0065 discardReplies(i + 1); 0066 return QList<QPixmap>(); 0067 } 0068 auto &geo = pixmapGeometries[i]; 0069 QImage image(xcb_get_image_data(reply), geo->width, geo->height, QImage::Format_ARGB32); 0070 ret << QPixmap::fromImage(image); 0071 free(reply); 0072 } 0073 return ret; 0074 } 0075 0076 int main(int argc, char **argv) 0077 { 0078 qputenv("QT_QPA_PLATFORM", "xcb"); 0079 QApplication app(argc, argv); 0080 app.setProperty("x11Connection", QVariant::fromValue<void *>(QX11Info::connection())); 0081 0082 QCommandLineParser parser; 0083 parser.addPositionalArgument(QStringLiteral("windowId"), QStringLiteral("The X11 windowId from which to read the shadow")); 0084 parser.addHelpOption(); 0085 parser.process(app); 0086 0087 if (parser.positionalArguments().count() != 1) { 0088 parser.showHelp(1); 0089 } 0090 0091 bool ok = false; 0092 const auto shadow = readShadow(parser.positionalArguments().constFirst().toULongLong(&ok, 16)); 0093 if (!ok) { 0094 qDebug() << "!!! Failed to read window id"; 0095 return 1; 0096 } 0097 if (shadow.isEmpty()) { 0098 qDebug() << "!!!! Read shadow failed"; 0099 return 1; 0100 } 0101 const auto pixmaps = getPixmaps(shadow); 0102 if (pixmaps.isEmpty()) { 0103 qDebug() << "!!!! Read pixmap failed"; 0104 return 1; 0105 } 0106 0107 std::unique_ptr<QWidget> widget(new QWidget()); 0108 QFormLayout *layout = new QFormLayout(widget.get()); 0109 for (const auto &pix : pixmaps) { 0110 QLabel *l = new QLabel(widget.get()); 0111 l->setPixmap(pix); 0112 layout->addRow(QStringLiteral("%1x%2:").arg(pix.width()).arg(pix.height()), l); 0113 } 0114 widget->setLayout(layout); 0115 widget->show(); 0116 return app.exec(); 0117 }