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 
69 QT_BEGIN_NAMESPACE
70 
71 // return QXcbNativeInterface::ResourceType for the key.
resourceType(const QByteArray & key)72 static 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 
QXcbNativeInterface()95 QXcbNativeInterface::QXcbNativeInterface()
96 {
97 }
98 
systemTrayTracker(const QScreen * s)99 static 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 
nativeResourceForIntegration(const QByteArray & resourceString)107 void *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 
nativeResourceForContext(const QByteArray & resourceString,QOpenGLContext * context)140 void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
141 {
142     QByteArray lowerCaseResource = resourceString.toLower();
143     void *result = handlerNativeResourceForContext(lowerCaseResource, context);
144     return result;
145 }
146 
nativeResourceForScreen(const QByteArray & resourceString,QScreen * screen)147 void *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 
nativeResourceForWindow(const QByteArray & resourceString,QWindow * window)201 void *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 
nativeResourceForBackingStore(const QByteArray & resourceString,QBackingStore * backingStore)233 void *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
nativeResourceForCursor(const QByteArray & resource,const QCursor & cursor)241 void *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 
nativeResourceFunctionForIntegration(const QByteArray & resource)255 QPlatformNativeInterface::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 nullptr;
272 }
273 
nativeResourceFunctionForContext(const QByteArray & resource)274 QPlatformNativeInterface::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 
nativeResourceFunctionForScreen(const QByteArray & resource)283 QPlatformNativeInterface::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 nullptr;
295 }
296 
nativeResourceFunctionForWindow(const QByteArray & resource)297 QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::nativeResourceFunctionForWindow(const QByteArray &resource)
298 {
299     const QByteArray lowerCaseResource = resource.toLower();
300     NativeResourceForWindowFunction func = handlerNativeResourceFunctionForWindow(lowerCaseResource);
301     return func;
302 }
303 
nativeResourceFunctionForBackingStore(const QByteArray & resource)304 QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::nativeResourceFunctionForBackingStore(const QByteArray &resource)
305 {
306     const QByteArray lowerCaseResource = resource.toLower();
307     NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(lowerCaseResource);
308     return func;
309 }
310 
platformFunction(const QByteArray & function) const311 QFunctionPointer 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 
appTime(const QXcbScreen * screen)338 void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
339 {
340     if (!screen)
341         return nullptr;
342 
343     return reinterpret_cast<void *>(quintptr(screen->connection()->time()));
344 }
345 
appUserTime(const QXcbScreen * screen)346 void *QXcbNativeInterface::appUserTime(const QXcbScreen *screen)
347 {
348     if (!screen)
349         return nullptr;
350 
351     return reinterpret_cast<void *>(quintptr(screen->connection()->netWmUserTime()));
352 }
353 
getTimestamp(const QXcbScreen * screen)354 void *QXcbNativeInterface::getTimestamp(const QXcbScreen *screen)
355 {
356     if (!screen)
357         return nullptr;
358 
359     return reinterpret_cast<void *>(quintptr(screen->connection()->getTimestamp()));
360 }
361 
startupId()362 void *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 nullptr;
369 }
370 
x11Screen()371 void *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 nullptr;
378 }
379 
rootWindow()380 void *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 nullptr;
387 }
388 
display()389 void *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 
connection()400 void *QXcbNativeInterface::connection()
401 {
402     QXcbIntegration *integration = QXcbIntegration::instance();
403     return integration->defaultConnection()->xcb_connection();
404 }
405 
atspiBus()406 void *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 
setAppTime(QScreen * screen,xcb_timestamp_t time)426 void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time)
427 {
428     if (screen) {
429         static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time);
430     }
431 }
432 
setAppUserTime(QScreen * screen,xcb_timestamp_t time)433 void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
434 {
435     if (screen) {
436         static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
437     }
438 }
439 
generatePeekerId()440 qint32 QXcbNativeInterface::generatePeekerId()
441 {
442     QXcbIntegration *integration = QXcbIntegration::instance();
443     return integration->defaultConnection()->eventQueue()->generatePeekerId();
444 }
445 
removePeekerId(qint32 peekerId)446 bool QXcbNativeInterface::removePeekerId(qint32 peekerId)
447 {
448     QXcbIntegration *integration = QXcbIntegration::instance();
449     return integration->defaultConnection()->eventQueue()->removePeekerId(peekerId);
450 }
451 
peekEventQueue(QXcbEventQueue::PeekerCallback peeker,void * peekerData,QXcbEventQueue::PeekOptions option,qint32 peekerId)452 bool 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 
setStartupId(const char * data)459 void 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 
qPlatformScreenForWindow(QWindow * window)468 QXcbScreen *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 
displayForWindow(QWindow * window)481 void *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 
connectionForWindow(QWindow * window)492 void *QXcbNativeInterface::connectionForWindow(QWindow *window)
493 {
494     QXcbScreen *screen = qPlatformScreenForWindow(window);
495     return screen ? screen->xcb_connection() : nullptr;
496 }
497 
screenForWindow(QWindow * window)498 void *QXcbNativeInterface::screenForWindow(QWindow *window)
499 {
500     QXcbScreen *screen = qPlatformScreenForWindow(window);
501     return screen ? screen->screen() : nullptr;
502 }
503 
addHandler(QXcbNativeInterfaceHandler * handler)504 void QXcbNativeInterface::addHandler(QXcbNativeInterfaceHandler *handler)
505 {
506     m_handlers.removeAll(handler);
507     m_handlers.prepend(handler);
508 }
509 
removeHandler(QXcbNativeInterfaceHandler * handler)510 void QXcbNativeInterface::removeHandler(QXcbNativeInterfaceHandler *handler)
511 {
512     m_handlers.removeAll(handler);
513 }
514 
handlerNativeResourceFunctionForIntegration(const QByteArray & resource) const515 QPlatformNativeInterface::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 
handlerNativeResourceFunctionForContext(const QByteArray & resource) const526 QPlatformNativeInterface::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 
handlerNativeResourceFunctionForScreen(const QByteArray & resource) const537 QPlatformNativeInterface::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 
handlerNativeResourceFunctionForWindow(const QByteArray & resource) const548 QPlatformNativeInterface::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 
handlerNativeResourceFunctionForBackingStore(const QByteArray & resource) const559 QPlatformNativeInterface::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 
handlerPlatformFunction(const QByteArray & function) const570 QFunctionPointer 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 
handlerNativeResourceForIntegration(const QByteArray & resource) const581 void *QXcbNativeInterface::handlerNativeResourceForIntegration(const QByteArray &resource) const
582 {
583     NativeResourceForIntegrationFunction func = handlerNativeResourceFunctionForIntegration(resource);
584     if (func)
585         return func();
586     return nullptr;
587 }
588 
handlerNativeResourceForContext(const QByteArray & resource,QOpenGLContext * context) const589 void *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 
handlerNativeResourceForScreen(const QByteArray & resource,QScreen * screen) const597 void *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 
handlerNativeResourceForWindow(const QByteArray & resource,QWindow * window) const605 void *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 
handlerNativeResourceForBackingStore(const QByteArray & resource,QBackingStore * backingStore) const613 void *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 
dumpNativeWindowsRecursion(const QXcbConnection * connection,xcb_window_t window,int level,QTextStream & str)621 static 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 
dumpConnectionNativeWindows(const QXcbConnection * connection,WId root) const656 QString 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 
dumpNativeWindows(WId root) const672 QString QXcbNativeInterface::dumpNativeWindows(WId root) const
673 {
674     return dumpConnectionNativeWindows(QXcbIntegration::instance()->defaultConnection(), root);
675 }
676 
677 QT_END_NAMESPACE
678