From cb142954c54b7a6e391950d9209b5cea9252092b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 14 Dec 2017 14:15:34 +0100 Subject: 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 --- src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 56 +++++++++++++++++++++++ src/plugins/platforms/xcb/qxcbnativeinterface.h | 2 + src/plugins/platforms/xcb/qxcbscreen.cpp | 12 +---- src/plugins/platforms/xcb/qxcbwindow.cpp | 13 ++++++ src/plugins/platforms/xcb/qxcbwindow.h | 2 + 5 files changed, 75 insertions(+), 10 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index d989761297..22d90d6ac2 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -673,4 +673,60 @@ void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray 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 diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index fb0db727aa..6a752c68ca 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -127,6 +127,8 @@ public: Q_INVOKABLE bool systrayVisualHasAlphaChannel(); Q_INVOKABLE bool requestSystemTrayWindowDock(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 removeHandler(QXcbNativeInterfaceHandler *handler); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index e3d9bc7a3d..49bf5181cc 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -91,16 +91,8 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) { xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get())); - if (windowManager != XCB_WINDOW_NONE) { - auto windowManagerReply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), - 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())); - } - } + if (windowManager != XCB_WINDOW_NONE) + m_windowManagerName = QXcbWindow::windowTitle(connection, windowManager); } const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 46698de158..89ace781ae 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2835,5 +2835,18 @@ QXcbScreen *QXcbWindow::xcbScreen() const return static_cast(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(xcb_get_property_value(reply.get())); + return QString::fromUtf8(name); + } + return QString(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 638ab26cea..65221394ea 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -182,6 +182,8 @@ public: virtual void create(); virtual void destroy(); + static QString windowTitle(const QXcbConnection *conn, xcb_window_t window); + public Q_SLOTS: void updateSyncRequestCounter(); -- cgit v1.2.3 From 74045f8b9a21da412bc121e9b962cda385654911 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Fri, 2 Feb 2018 19:49:18 +0300 Subject: Use new QString::remove(QLatin1String) Change-Id: I5b3560709a8fb230a177511c701fd0bf25938f0f Reviewed-by: Thiago Macieira --- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 7ea3d130f7..98b9f7c9ba 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -198,7 +198,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); static QString strippedText(QString s) { - s.remove( QString::fromLatin1("...") ); + s.remove(QLatin1String("...")); return QPlatformTheme::removeMnemonics(s).trimmed(); } -- cgit v1.2.3 From f4765ff5f6b93e7018693c599dd0a6d8ecd81d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 18 Jan 2018 22:28:33 +0100 Subject: Modernize logging in CoreFoundation and iOS event dispatchers Instead of manually handling logging enablement, we use Qt's categorized logging system. Change-Id: I8d942601f76876030084c9fb130b7215ff6cc404 Reviewed-by: Thiago Macieira --- src/plugins/platforms/ios/qioseventdispatcher.mm | 39 ++++++++++++------------ 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index de2c30cdfb..a6f6a7aac9 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -228,7 +228,7 @@ extern "C" int qt_main_wrapper(int argc, char *argv[]) } } - qEventDispatcherDebug() << "Running UIApplicationMain"; qIndent(); + qCDebug(lcEventDispatcher) << "Running UIApplicationMain"; return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSApplicationDelegate class])); } } @@ -263,7 +263,7 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline() int exitCode = main(argc, argv); delete[] argv; - qEventDispatcherDebug() << "Returned from main with exit code " << exitCode; + qCDebug(lcEventDispatcher) << "Returned from main with exit code " << exitCode; if (Q_UNLIKELY(debugStackUsage)) userMainStack.printUsage(); @@ -322,7 +322,7 @@ static bool rootLevelRunLoopIntegration() + (void)applicationDidFinishLaunching:(NSNotification *)notification { - qCDebug(lcQpaApplication) << "Application launched with options" << notification.userInfo; + qCDebug(lcEventDispatcher) << "Application launched with options" << notification.userInfo; if (!isQtApplication()) return; @@ -331,7 +331,7 @@ static bool rootLevelRunLoopIntegration() // We schedule the main-redirection for the next run-loop pass, so that we // can return from this function and let UIApplicationMain finish its job. // This results in running Qt's application eventloop as a nested runloop. - qCDebug(lcQpaApplication) << "Scheduling main() on next run-loop pass"; + qCDebug(lcEventDispatcher) << "Scheduling main() on next run-loop pass"; CFRunLoopTimerRef userMainTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, ^(CFRunLoopTimerRef) { user_main_trampoline(); }); CFRunLoopAddTimer(CFRunLoopGetMain(), userMainTimer, kCFRunLoopCommonModes); @@ -339,10 +339,10 @@ static bool rootLevelRunLoopIntegration() return; } + switch (setjmp(processEventEnterJumpPoint)) { case kJumpPointSetSuccessfully: - qCDebug(lcQpaApplication) << "Running main() on separate stack"; qIndent(); - + qCDebug(lcEventDispatcher) << "Running main() on separate stack"; // Redirect the stack pointer to the start of the reserved stack. This ensures // that when we longjmp out of the event dispatcher and continue execution, the // 'Qt main' call-stack will not be smashed, as it lives in a part of the stack @@ -360,7 +360,7 @@ static bool rootLevelRunLoopIntegration() case kJumpedFromEventDispatcherProcessEvents: // We've returned from the longjmp in the event dispatcher, // and the stack has been restored to its old self. - qUnIndent(); qCDebug(lcQpaApplication) << "Returned from processEvents"; + qCDebug(lcEventDispatcher) << "↳ Jumped from processEvents due to exec"; if (Q_UNLIKELY(debugStackUsage)) userMainStack.printUsage(); @@ -396,18 +396,18 @@ static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80); applicationAboutToTerminate = true; switch (setjmp(applicationWillTerminateJumpPoint)) { case kJumpPointSetSuccessfully: - qEventDispatcherDebug() << "Exiting qApp with SIGTERM exit code"; qIndent(); + qCDebug(lcEventDispatcher) << "Exiting qApp with SIGTERM exit code"; qApp->exit(kApplicationWillTerminateExitCode); // The runloop will not exit when the application is about to terminate, // so we'll never see the exit activity and have a chance to return from // QEventLoop::exec(). We initiate the return manually as a workaround. - qEventDispatcherDebug() << "Manually triggering return from event loop exec"; + qCDebug(lcEventDispatcher) << "Manually triggering return from event loop exec"; static_cast(qApp->eventDispatcher())->interruptEventLoopExec(); break; case kJumpedFromUserMainTrampoline: // The user's main has returned, so we're ready to let iOS terminate the application - qUnIndent(); qEventDispatcherDebug() << "kJumpedFromUserMainTrampoline, allowing iOS to terminate"; + qCDebug(lcEventDispatcher) << "kJumpedFromUserMainTrampoline, allowing iOS to terminate"; break; default: qFatal("Unexpected jump result in event loop integration"); @@ -434,13 +434,15 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo return QEventDispatcherCoreFoundation::processEvents(flags); if (applicationAboutToTerminate) { - qEventDispatcherDebug() << "Detected QEventLoop exec after application termination"; + qCDebug(lcEventDispatcher) << "Detected QEventLoop exec after application termination"; // Re-issue exit, and return immediately qApp->exit(kApplicationWillTerminateExitCode); return false; } if (!m_processEventLevel && (flags & QEventLoop::EventLoopExec)) { + qCDebug(lcEventDispatcher) << "Processing events with flags" << flags; + ++m_processEventLevel; m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes); @@ -449,7 +451,7 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo // is asked to exit, so that we can return from QEventLoop::exec(). switch (setjmp(processEventExitJumpPoint)) { case kJumpPointSetSuccessfully: - qEventDispatcherDebug() << "QEventLoop exec detected, jumping back to native runloop"; + qCDebug(lcEventDispatcher) << "QEventLoop exec detected, jumping back to system runloop ↵"; longjmp(processEventEnterJumpPoint, kJumpedFromEventDispatcherProcessEvents); break; case kJumpedFromEventLoopExecInterrupt: @@ -457,7 +459,7 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo // signal), and we jumped back though processEventExitJumpPoint. We return from processEvents, // which will emit aboutToQuit if it's QApplication's event loop, and then return to the user's // main, which can do whatever it wants, including calling exec() on the application again. - qEventDispatcherDebug() << "kJumpedFromEventLoopExecInterrupt, returning with eventsProcessed = true"; + qCDebug(lcEventDispatcher) << "⇢ System runloop exited, returning with eventsProcessed = true"; return true; default: qFatal("Unexpected jump result in event loop integration"); @@ -485,9 +487,8 @@ bool QIOSEventDispatcher::processPostedEvents() if (!QEventDispatcherCoreFoundation::processPostedEvents()) return false; - qEventDispatcherDebug() << "Sending window system events for " << m_processEvents.flags; qIndent(); + qCDebug(lcEventDispatcher) << "Sending window system events for" << m_processEvents.flags; QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags); - qUnIndent(); return true; } @@ -497,10 +498,8 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity) Q_UNUSED(activity); Q_ASSERT(activity == kCFRunLoopExit); - if (m_processEventLevel == 1 && !currentEventLoop()->isRunning()) { - qEventDispatcherDebug() << "Root runloop level exited"; + if (m_processEventLevel == 1 && !currentEventLoop()->isRunning()) interruptEventLoopExec(); - } } void QIOSEventDispatcher::interruptEventLoopExec() @@ -516,12 +515,12 @@ void QIOSEventDispatcher::interruptEventLoopExec() // processEvents, instead of back in didFinishLaunchingWithOptions. switch (setjmp(processEventEnterJumpPoint)) { case kJumpPointSetSuccessfully: - qEventDispatcherDebug() << "Jumping back to processEvents"; + qCDebug(lcEventDispatcher) << "Jumping into processEvents due to system runloop exit ⇢"; longjmp(processEventExitJumpPoint, kJumpedFromEventLoopExecInterrupt); break; case kJumpedFromEventDispatcherProcessEvents: // QEventLoop was re-executed - qEventDispatcherDebug() << "kJumpedFromEventDispatcherProcessEvents"; + qCDebug(lcEventDispatcher) << "↳ Jumped from processEvents due to re-exec"; break; default: qFatal("Unexpected jump result in event loop integration"); -- cgit v1.2.3