1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qxcbnativeinterface.h"
41
42#include "qxcbcursor.h"
43#include "qxcbscreen.h"
44#include "qxcbwindow.h"
45#include "qxcbintegration.h"
46#include "qxcbsystemtraytracker.h"
47
48#include <private/qguiapplication_p.h>
49#include <QtCore/QMap>
50
51#include <QtCore/QDebug>
52
53#include <QtGui/qopenglcontext.h>
54#include <QtGui/qscreen.h>
55
56#include <QtPlatformHeaders/qxcbwindowfunctions.h>
57#include <QtPlatformHeaders/qxcbscreenfunctions.h>
58
59#include <stdio.h>
60
61#include <algorithm>
62
63#include "qxcbnativeinterfacehandler.h"
64
65#if QT_CONFIG(vulkan)
66#include "qxcbvulkanwindow.h"
67#endif
68
69QT_BEGIN_NAMESPACE
70
71// return QXcbNativeInterface::ResourceType for the key.
72static int resourceType(const QByteArray &key)
73{
74 static const QByteArray names[] = { // match QXcbNativeInterface::ResourceType
75 QByteArrayLiteral("display"),
76 QByteArrayLiteral("connection"), QByteArrayLiteral("screen"),
77 QByteArrayLiteral("apptime"),
78 QByteArrayLiteral("appusertime"), QByteArrayLiteral("hintstyle"),
79 QByteArrayLiteral("startupid"), QByteArrayLiteral("traywindow"),
80 QByteArrayLiteral("gettimestamp"), QByteArrayLiteral("x11screen"),
81 QByteArrayLiteral("rootwindow"),
82 QByteArrayLiteral("subpixeltype"), QByteArrayLiteral("antialiasingenabled"),
83 QByteArrayLiteral("atspibus"),
84 QByteArrayLiteral("compositingenabled"),
85 QByteArrayLiteral("vksurface"),
86 QByteArrayLiteral("generatepeekerid"),
87 QByteArrayLiteral("removepeekerid"),
88 QByteArrayLiteral("peekeventqueue")
89 };
90 const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
91 const QByteArray *result = std::find(names, end, key);
92 return int(result - names);
93}
94
95QXcbNativeInterface::QXcbNativeInterface()
96{
97}
98
99static inline QXcbSystemTrayTracker *systemTrayTracker(const QScreen *s)
100{
101 if (!s)
102 return nullptr;
103
104 return static_cast<const QXcbScreen *>(s->handle())->connection()->systemTrayTracker();
105}
106
107void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
108{
109 QByteArray lowerCaseResource = resourceString.toLower();
110 void *result = handlerNativeResourceForIntegration(lowerCaseResource);
111 if (result)
112 return result;
113
114 switch (resourceType(lowerCaseResource)) {
115 case StartupId:
116 result = startupId();
117 break;
118 case X11Screen:
119 result = x11Screen();
120 break;
121 case RootWindow:
122 result = rootWindow();
123 break;
124 case Display:
125 result = display();
126 break;
127 case AtspiBus:
128 result = atspiBus();
129 break;
130 case Connection:
131 result = connection();
132 break;
133 default:
134 break;
135 }
136
137 return result;
138}
139
140void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
141{
142 QByteArray lowerCaseResource = resourceString.toLower();
143 void *result = handlerNativeResourceForContext(lowerCaseResource, context);
144 return result;
145}
146
147void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resourceString, QScreen *screen)
148{
149 if (!screen) {
150 qWarning("nativeResourceForScreen: null screen");
151 return nullptr;
152 }
153
154 QByteArray lowerCaseResource = resourceString.toLower();
155 void *result = handlerNativeResourceForScreen(lowerCaseResource, screen);
156 if (result)
157 return result;
158
159 const QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(screen->handle());
160 switch (resourceType(lowerCaseResource)) {
161 case Display:
162#if QT_CONFIG(xcb_xlib)
163 result = xcbScreen->connection()->xlib_display();
164#endif
165 break;
166 case AppTime:
167 result = appTime(xcbScreen);
168 break;
169 case AppUserTime:
170 result = appUserTime(xcbScreen);
171 break;
172 case ScreenHintStyle:
173 result = reinterpret_cast<void *>(xcbScreen->hintStyle() + 1);
174 break;
175 case ScreenSubpixelType:
176 result = reinterpret_cast<void *>(xcbScreen->subpixelType() + 1);
177 break;
178 case ScreenAntialiasingEnabled:
179 result = reinterpret_cast<void *>(xcbScreen->antialiasingEnabled() + 1);
180 break;
181 case TrayWindow:
182 if (QXcbSystemTrayTracker *s = systemTrayTracker(screen))
183 result = (void *)quintptr(s->trayWindow());
184 break;
185 case GetTimestamp:
186 result = getTimestamp(xcbScreen);
187 break;
188 case RootWindow:
189 result = reinterpret_cast<void *>(xcbScreen->root());
190 break;
191 case CompositingEnabled:
192 if (QXcbVirtualDesktop *vd = xcbScreen->virtualDesktop())
193 result = vd->compositingActive() ? this : nullptr;
194 break;
195 default:
196 break;
197 }
198 return result;
199}
200
201void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
202{
203 QByteArray lowerCaseResource = resourceString.toLower();
204 void *result = handlerNativeResourceForWindow(lowerCaseResource, window);
205 if (result)
206 return result;
207
208 switch (resourceType(lowerCaseResource)) {
209 case Display:
210 result = displayForWindow(window);
211 break;
212 case Connection:
213 result = connectionForWindow(window);
214 break;
215 case Screen:
216 result = screenForWindow(window);
217 break;
218#if QT_CONFIG(vulkan)
219 case VkSurface:
220 if (window->surfaceType() == QSurface::VulkanSurface && window->handle()) {
221 // return a pointer to the VkSurfaceKHR value, not the value itself
222 result = static_cast<QXcbVulkanWindow *>(window->handle())->surface();
223 }
224 break;
225#endif
226 default:
227 break;
228 }
229
230 return result;
231}
232
233void *QXcbNativeInterface::nativeResourceForBackingStore(const QByteArray &resourceString, QBackingStore *backingStore)
234{
235 const QByteArray lowerCaseResource = resourceString.toLower();
236 void *result = handlerNativeResourceForBackingStore(lowerCaseResource,backingStore);
237 return result;
238}
239
240#ifndef QT_NO_CURSOR
241void *QXcbNativeInterface::nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor)
242{
243 if (resource == QByteArrayLiteral("xcbcursor")) {
244 if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) {
245 if (const QPlatformCursor *pCursor= primaryScreen->handle()->cursor()) {
246 xcb_cursor_t xcbCursor = static_cast<const QXcbCursor *>(pCursor)->xcbCursor(cursor);
247 return reinterpret_cast<void *>(quintptr(xcbCursor));
248 }
249 }
250 }
251 return nullptr;
252}
253#endif // !QT_NO_CURSOR
254
255QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
256{
257 const QByteArray lowerCaseResource = resource.toLower();
258 QPlatformNativeInterface::NativeResourceForIntegrationFunction func = handlerNativeResourceFunctionForIntegration(lowerCaseResource);
259 if (func)
260 return func;
261
262 if (lowerCaseResource == "setstartupid")
263 return NativeResourceForIntegrationFunction(reinterpret_cast<void *>(setStartupId));
264 if (lowerCaseResource == "generatepeekerid")
265 return NativeResourceForIntegrationFunction(reinterpret_cast<void *>(generatePeekerId));
266 if (lowerCaseResource == "removepeekerid")
267 return NativeResourceForIntegrationFunction(reinterpret_cast<void *>(removePeekerId));
268 if (lowerCaseResource == "peekeventqueue")
269 return NativeResourceForIntegrationFunction(reinterpret_cast<void *>(peekEventQueue));
270
271 return 0;
272}
273
274QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
275{
276 const QByteArray lowerCaseResource = resource.toLower();
277 QPlatformNativeInterface::NativeResourceForContextFunction func = handlerNativeResourceFunctionForContext(lowerCaseResource);
278 if (func)
279 return func;
280 return nullptr;
281}
282
283QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource)
284{
285 const QByteArray lowerCaseResource = resource.toLower();
286 NativeResourceForScreenFunction func = handlerNativeResourceFunctionForScreen(lowerCaseResource);
287 if (func)
288 return func;
289
290 if (lowerCaseResource == "setapptime")
291 return NativeResourceForScreenFunction(reinterpret_cast<void *>(setAppTime));
292 else if (lowerCaseResource == "setappusertime")
293 return NativeResourceForScreenFunction(reinterpret_cast<void *>(setAppUserTime));
294 return 0;
295}
296
297QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::nativeResourceFunctionForWindow(const QByteArray &resource)
298{
299 const QByteArray lowerCaseResource = resource.toLower();
300 NativeResourceForWindowFunction func = handlerNativeResourceFunctionForWindow(lowerCaseResource);
301 return func;
302}
303
304QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::nativeResourceFunctionForBackingStore(const QByteArray &resource)
305{
306 const QByteArray lowerCaseResource = resource.toLower();
307 NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(lowerCaseResource);
308 return func;
309}
310
311QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &function) const
312{
313 const QByteArray lowerCaseFunction = function.toLower();
314 QFunctionPointer func = handlerPlatformFunction(lowerCaseFunction);
315 if (func)
316 return func;
317
318 //case sensitive
319 if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier())
320 return QFunctionPointer(QXcbWindowFunctions::SetWmWindowType(QXcbWindow::setWmWindowTypeStatic));
321
322 if (function == QXcbWindowFunctions::setWmWindowRoleIdentifier())
323 return QFunctionPointer(QXcbWindowFunctions::SetWmWindowRole(QXcbWindow::setWmWindowRoleStatic));
324
325 if (function == QXcbWindowFunctions::setWmWindowIconTextIdentifier())
326 return QFunctionPointer(QXcbWindowFunctions::SetWmWindowIconText(QXcbWindow::setWindowIconTextStatic));
327
328 if (function == QXcbWindowFunctions::visualIdIdentifier()) {
329 return QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic));
330 }
331
332 if (function == QXcbScreenFunctions::virtualDesktopNumberIdentifier())
333 return QFunctionPointer(QXcbScreenFunctions::VirtualDesktopNumber(reinterpret_cast<void *>(QXcbScreen::virtualDesktopNumberStatic)));
334
335 return nullptr;
336}
337
338void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
339{
340 if (!screen)
341 return nullptr;
342
343 return reinterpret_cast<void *>(quintptr(screen->connection()->time()));
344}
345
346void *QXcbNativeInterface::appUserTime(const QXcbScreen *screen)
347{
348 if (!screen)
349 return nullptr;
350
351 return reinterpret_cast<void *>(quintptr(screen->connection()->netWmUserTime()));
352}
353
354void *QXcbNativeInterface::getTimestamp(const QXcbScreen *screen)
355{
356 if (!screen)
357 return nullptr;
358
359 return reinterpret_cast<void *>(quintptr(screen->connection()->getTimestamp()));
360}
361
362void *QXcbNativeInterface::startupId()
363{
364 QXcbIntegration* integration = QXcbIntegration::instance();
365 QXcbConnection *defaultConnection = integration->defaultConnection();
366 if (defaultConnection)
367 return reinterpret_cast<void *>(const_cast<char *>(defaultConnection->startupId().constData()));
368 return 0;
369}
370
371void *QXcbNativeInterface::x11Screen()
372{
373 QXcbIntegration *integration = QXcbIntegration::instance();
374 QXcbConnection *defaultConnection = integration->defaultConnection();
375 if (defaultConnection)
376 return reinterpret_cast<void *>(defaultConnection->primaryScreenNumber());
377 return 0;
378}
379
380void *QXcbNativeInterface::rootWindow()
381{
382 QXcbIntegration *integration = QXcbIntegration::instance();
383 QXcbConnection *defaultConnection = integration->defaultConnection();
384 if (defaultConnection)
385 return reinterpret_cast<void *>(defaultConnection->rootWindow());
386 return 0;
387}
388
389void *QXcbNativeInterface::display()
390{
391#if QT_CONFIG(xcb_xlib)
392 QXcbIntegration *integration = QXcbIntegration::instance();
393 QXcbConnection *defaultConnection = integration->defaultConnection();
394 if (defaultConnection)
395 return defaultConnection->xlib_display();
396#endif
397 return nullptr;
398}
399
400void *QXcbNativeInterface::connection()
401{
402 QXcbIntegration *integration = QXcbIntegration::instance();
403 return integration->defaultConnection()->xcb_connection();
404}
405
406void *QXcbNativeInterface::atspiBus()
407{
408 QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
409 QXcbConnection *defaultConnection = integration->defaultConnection();
410 if (defaultConnection) {
411 auto atspiBusAtom = defaultConnection->atom(QXcbAtom::AT_SPI_BUS);
412 auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(),
413 false, defaultConnection->rootWindow(),
414 atspiBusAtom, XCB_ATOM_STRING, 0, 128);
415 if (!reply)
416 return nullptr;
417
418 char *data = (char *)xcb_get_property_value(reply.get());
419 int length = xcb_get_property_value_length(reply.get());
420 return new QByteArray(data, length);
421 }
422
423 return nullptr;
424}
425
426void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time)
427{
428 if (screen) {
429 static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time);
430 }
431}
432
433void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
434{
435 if (screen) {
436 static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
437 }
438}
439
440qint32 QXcbNativeInterface::generatePeekerId()
441{
442 QXcbIntegration *integration = QXcbIntegration::instance();
443 return integration->defaultConnection()->eventQueue()->generatePeekerId();
444}
445
446bool QXcbNativeInterface::removePeekerId(qint32 peekerId)
447{
448 QXcbIntegration *integration = QXcbIntegration::instance();
449 return integration->defaultConnection()->eventQueue()->removePeekerId(peekerId);
450}
451
452bool QXcbNativeInterface::peekEventQueue(QXcbEventQueue::PeekerCallback peeker, void *peekerData,
453 QXcbEventQueue::PeekOptions option, qint32 peekerId)
454{
455 QXcbIntegration *integration = QXcbIntegration::instance();
456 return integration->defaultConnection()->eventQueue()->peekEventQueue(peeker, peekerData, option, peekerId);
457}
458
459void QXcbNativeInterface::setStartupId(const char *data)
460{
461 QByteArray startupId(data);
462 QXcbIntegration *integration = QXcbIntegration::instance();
463 QXcbConnection *defaultConnection = integration->defaultConnection();
464 if (defaultConnection)
465 defaultConnection->setStartupId(startupId);
466}
467
468QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window)
469{
470 QXcbScreen *screen;
471 if (window) {
472 QScreen *qs = window->screen();
473 screen = static_cast<QXcbScreen *>(qs ? qs->handle() : nullptr);
474 } else {
475 QScreen *qs = QGuiApplication::primaryScreen();
476 screen = static_cast<QXcbScreen *>(qs ? qs->handle() : nullptr);
477 }
478 return screen;
479}
480
481void *QXcbNativeInterface::displayForWindow(QWindow *window)
482{
483#if QT_CONFIG(xcb_xlib)
484 QXcbScreen *screen = qPlatformScreenForWindow(window);
485 return screen ? screen->connection()->xlib_display() : nullptr;
486#else
487 Q_UNUSED(window);
488 return nullptr;
489#endif
490}
491
492void *QXcbNativeInterface::connectionForWindow(QWindow *window)
493{
494 QXcbScreen *screen = qPlatformScreenForWindow(window);
495 return screen ? screen->xcb_connection() : nullptr;
496}
497
498void *QXcbNativeInterface::screenForWindow(QWindow *window)
499{
500 QXcbScreen *screen = qPlatformScreenForWindow(window);
501 return screen ? screen->screen() : nullptr;
502}
503
504void QXcbNativeInterface::addHandler(QXcbNativeInterfaceHandler *handler)
505{
506 m_handlers.removeAll(handler);
507 m_handlers.prepend(handler);
508}
509
510void QXcbNativeInterface::removeHandler(QXcbNativeInterfaceHandler *handler)
511{
512 m_handlers.removeAll(handler);
513}
514
515QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::handlerNativeResourceFunctionForIntegration(const QByteArray &resource) const
516{
517 for (int i = 0; i < m_handlers.size(); i++) {
518 QXcbNativeInterfaceHandler *handler = m_handlers.at(i);
519 NativeResourceForIntegrationFunction result = handler->nativeResourceFunctionForIntegration(resource);
520 if (result)
521 return result;
522 }
523 return nullptr;
524}
525
526QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::handlerNativeResourceFunctionForContext(const QByteArray &resource) const
527{
528 for (int i = 0; i < m_handlers.size(); i++) {
529 QXcbNativeInterfaceHandler *handler = m_handlers.at(i);
530 NativeResourceForContextFunction result = handler->nativeResourceFunctionForContext(resource);
531 if (result)
532 return result;
533 }
534 return nullptr;
535}
536
537QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::handlerNativeResourceFunctionForScreen(const QByteArray &resource) const
538{
539 for (int i = 0; i < m_handlers.size(); i++) {
540 QXcbNativeInterfaceHandler *handler = m_handlers.at(i);
541 NativeResourceForScreenFunction result = handler->nativeResourceFunctionForScreen(resource);
542 if (result)
543 return result;
544 }
545 return nullptr;
546}
547
548QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::handlerNativeResourceFunctionForWindow(const QByteArray &resource) const
549{
550 for (int i = 0; i < m_handlers.size(); i++) {
551 QXcbNativeInterfaceHandler *handler = m_handlers.at(i);
552 NativeResourceForWindowFunction result = handler->nativeResourceFunctionForWindow(resource);
553 if (result)
554 return result;
555 }
556 return nullptr;
557}
558
559QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::handlerNativeResourceFunctionForBackingStore(const QByteArray &resource) const
560{
561 for (int i = 0; i < m_handlers.size(); i++) {
562 QXcbNativeInterfaceHandler *handler = m_handlers.at(i);
563 NativeResourceForBackingStoreFunction result = handler->nativeResourceFunctionForBackingStore(resource);
564 if (result)
565 return result;
566 }
567 return nullptr;
568}
569
570QFunctionPointer QXcbNativeInterface::handlerPlatformFunction(const QByteArray &function) const
571{
572 for (int i = 0; i < m_handlers.size(); i++) {
573 QXcbNativeInterfaceHandler *handler = m_handlers.at(i);
574 QFunctionPointer func = handler->platformFunction(function);
575 if (func)
576 return func;
577 }
578 return nullptr;
579}
580
581void *QXcbNativeInterface::handlerNativeResourceForIntegration(const QByteArray &resource) const
582{
583 NativeResourceForIntegrationFunction func = handlerNativeResourceFunctionForIntegration(resource);
584 if (func)
585 return func();
586 return nullptr;
587}
588
589void *QXcbNativeInterface::handlerNativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) const
590{
591 NativeResourceForContextFunction func = handlerNativeResourceFunctionForContext(resource);
592 if (func)
593 return func(context);
594 return nullptr;
595}
596
597void *QXcbNativeInterface::handlerNativeResourceForScreen(const QByteArray &resource, QScreen *screen) const
598{
599 NativeResourceForScreenFunction func = handlerNativeResourceFunctionForScreen(resource);
600 if (func)
601 return func(screen);
602 return nullptr;
603}
604
605void *QXcbNativeInterface::handlerNativeResourceForWindow(const QByteArray &resource, QWindow *window) const
606{
607 NativeResourceForWindowFunction func = handlerNativeResourceFunctionForWindow(resource);
608 if (func)
609 return func(window);
610 return nullptr;
611}
612
613void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore) const
614{
615 NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(resource);
616 if (func)
617 return func(backingStore);
618 return nullptr;
619}
620
621static void dumpNativeWindowsRecursion(const QXcbConnection *connection, xcb_window_t window,
622 int level, QTextStream &str)
623{
624 if (level)
625 str << QByteArray(2 * level, ' ');
626
627 xcb_connection_t *conn = connection->xcb_connection();
628 auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window);
629 if (!geomReply)
630 return;
631 const QRect geom(geomReply->x, geomReply->y, geomReply->width, geomReply->height);
632 if (!geom.isValid() || (geom.width() <= 3 && geom.height() <= 3))
633 return; // Skip helper/dummy windows.
634 str << "0x";
635 const int oldFieldWidth = str.fieldWidth();
636 const QChar oldPadChar =str.padChar();
637 str.setFieldWidth(8);
638 str.setPadChar(QLatin1Char('0'));
639 str << Qt::hex << window;
640 str.setFieldWidth(oldFieldWidth);
641 str.setPadChar(oldPadChar);
642 str << Qt::dec << " \""
643 << QXcbWindow::windowTitle(connection, window) << "\" "
644 << geom.width() << 'x' << geom.height() << Qt::forcesign << geom.x() << geom.y()
645 << Qt::noforcesign << '\n';
646
647 auto reply = Q_XCB_REPLY(xcb_query_tree, conn, window);
648 if (reply) {
649 const int count = xcb_query_tree_children_length(reply.get());
650 const xcb_window_t *children = xcb_query_tree_children(reply.get());
651 for (int i = 0; i < count; ++i)
652 dumpNativeWindowsRecursion(connection, children[i], level + 1, str);
653 }
654}
655
656QString QXcbNativeInterface::dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const
657{
658 QString result;
659 QTextStream str(&result);
660 if (root) {
661 dumpNativeWindowsRecursion(connection, xcb_window_t(root), 0, str);
662 } else {
663 for (const QXcbScreen *screen : connection->screens()) {
664 str << "Screen: \"" << screen->name() << "\"\n";
665 dumpNativeWindowsRecursion(connection, screen->root(), 0, str);
666 str << '\n';
667 }
668 }
669 return result;
670}
671
672QString QXcbNativeInterface::dumpNativeWindows(WId root) const
673{
674 return dumpConnectionNativeWindows(QXcbIntegration::instance()->defaultConnection(), root);
675}
676
677QT_END_NAMESPACE
678