XCB: Implement native window dump for diaglib
Extract a helper function to determine the window title from QXcbConnection and add an invokable function to the native interface that dumps the window tree similar to existing functionality on Windows. Change-Id: I5544d69ea2b801eb16d3b5b8d64021b3e567b0d8 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
b68dfa0348
commit
cb142954c5
@ -673,4 +673,60 @@ void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dumpNativeWindowsRecursion(const QXcbConnection *connection, xcb_window_t window,
|
||||||
|
int level, QTextStream &str)
|
||||||
|
{
|
||||||
|
if (level)
|
||||||
|
str << QByteArray(2 * level, ' ');
|
||||||
|
|
||||||
|
xcb_connection_t *conn = connection->xcb_connection();
|
||||||
|
auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window);
|
||||||
|
if (!geomReply)
|
||||||
|
return;
|
||||||
|
const QRect geom(geomReply->x, geomReply->y, geomReply->width, geomReply->height);
|
||||||
|
if (!geom.isValid() || (geom.width() <= 3 && geom.height() <= 3))
|
||||||
|
return; // Skip helper/dummy windows.
|
||||||
|
str << "0x";
|
||||||
|
const int oldFieldWidth = str.fieldWidth();
|
||||||
|
const QChar oldPadChar =str.padChar();
|
||||||
|
str.setFieldWidth(8);
|
||||||
|
str.setPadChar(QLatin1Char('0'));
|
||||||
|
str << hex << window;
|
||||||
|
str.setFieldWidth(oldFieldWidth);
|
||||||
|
str.setPadChar(oldPadChar);
|
||||||
|
str << dec << " \""
|
||||||
|
<< QXcbWindow::windowTitle(connection, window) << "\" "
|
||||||
|
<< geom.width() << 'x' << geom.height() << forcesign << geom.x() << geom.y()
|
||||||
|
<< noforcesign << '\n';
|
||||||
|
|
||||||
|
auto reply = Q_XCB_REPLY(xcb_query_tree, conn, window);
|
||||||
|
if (reply) {
|
||||||
|
const int count = xcb_query_tree_children_length(reply.get());
|
||||||
|
const xcb_window_t *children = xcb_query_tree_children(reply.get());
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
dumpNativeWindowsRecursion(connection, children[i], level + 1, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QXcbNativeInterface::dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream str(&result);
|
||||||
|
if (root) {
|
||||||
|
dumpNativeWindowsRecursion(connection, xcb_window_t(root), 0, str);
|
||||||
|
} else {
|
||||||
|
for (const QXcbScreen *screen : connection->screens()) {
|
||||||
|
str << "Screen: \"" << screen->name() << "\"\n";
|
||||||
|
dumpNativeWindowsRecursion(connection, screen->root(), 0, str);
|
||||||
|
str << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QXcbNativeInterface::dumpNativeWindows(WId root) const
|
||||||
|
{
|
||||||
|
return dumpConnectionNativeWindows(QXcbIntegration::instance()->defaultConnection(), root);
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -127,6 +127,8 @@ public:
|
|||||||
Q_INVOKABLE bool systrayVisualHasAlphaChannel();
|
Q_INVOKABLE bool systrayVisualHasAlphaChannel();
|
||||||
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
|
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
|
||||||
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
|
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
|
||||||
|
Q_INVOKABLE QString dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const;
|
||||||
|
Q_INVOKABLE QString dumpNativeWindows(WId root = 0) const;
|
||||||
|
|
||||||
void addHandler(QXcbNativeInterfaceHandler *handler);
|
void addHandler(QXcbNativeInterfaceHandler *handler);
|
||||||
void removeHandler(QXcbNativeInterfaceHandler *handler);
|
void removeHandler(QXcbNativeInterfaceHandler *handler);
|
||||||
|
@ -91,16 +91,8 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
|
|||||||
if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
|
if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
|
||||||
xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get()));
|
xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get()));
|
||||||
|
|
||||||
if (windowManager != XCB_WINDOW_NONE) {
|
if (windowManager != XCB_WINDOW_NONE)
|
||||||
auto windowManagerReply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
|
m_windowManagerName = QXcbWindow::windowTitle(connection, windowManager);
|
||||||
false, windowManager,
|
|
||||||
atom(QXcbAtom::_NET_WM_NAME),
|
|
||||||
atom(QXcbAtom::UTF8_STRING), 0, 1024);
|
|
||||||
if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
|
|
||||||
m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply.get()),
|
|
||||||
xcb_get_property_value_length(windowManagerReply.get()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
|
const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
|
||||||
|
@ -2835,5 +2835,18 @@ QXcbScreen *QXcbWindow::xcbScreen() const
|
|||||||
return static_cast<QXcbScreen *>(screen());
|
return static_cast<QXcbScreen *>(screen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window)
|
||||||
|
{
|
||||||
|
const xcb_atom_t utf8Atom = conn->atom(QXcbAtom::UTF8_STRING);
|
||||||
|
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, conn->xcb_connection(),
|
||||||
|
false, window, conn->atom(QXcbAtom::_NET_WM_NAME),
|
||||||
|
utf8Atom, 0, 1024);
|
||||||
|
if (reply && reply->format == 8 && reply->type == utf8Atom) {
|
||||||
|
const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get()));
|
||||||
|
return QString::fromUtf8(name);
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -182,6 +182,8 @@ public:
|
|||||||
virtual void create();
|
virtual void create();
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
|
||||||
|
static QString windowTitle(const QXcbConnection *conn, xcb_window_t window);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void updateSyncRequestCounter();
|
void updateSyncRequestCounter();
|
||||||
|
|
||||||
|
@ -28,10 +28,25 @@
|
|||||||
|
|
||||||
#include "nativewindowdump.h"
|
#include "nativewindowdump.h"
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
# include <QtGui/QGuiApplication>
|
||||||
|
# include <qpa/qplatformnativeinterface.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
namespace QtDiag {
|
namespace QtDiag {
|
||||||
|
|
||||||
void dumpNativeWindows(WId)
|
void dumpNativeWindows(WId wid)
|
||||||
{
|
{
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
|
||||||
|
QString result;
|
||||||
|
QMetaObject::invokeMethod(ni, "dumpNativeWindows", Qt::DirectConnection,
|
||||||
|
Q_RETURN_ARG(QString, result),
|
||||||
|
Q_ARG(WId, wid));
|
||||||
|
qDebug().noquote() << result;
|
||||||
|
#endif // Qt 5
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpNativeQtTopLevels()
|
void dumpNativeQtTopLevels()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user