From 9cec2def90c9644cc75b26d3c9bd38739b9307da Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 21 Sep 2012 13:47:16 +0200 Subject: [PATCH] xcb: better error handling if no randr or screen resources query fails MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Marc Mutz already reported problems with ssh -X fowarding. Now all such errors are treated the same: if we can't get screen output attributes, just assume there is only one. Change-Id: I96802fc90072c623de3370ed2898893daf58198a Reviewed-by: Marc Mutz Reviewed-by: Samuel Rødal --- src/plugins/platforms/xcb/qxcbconnection.cpp | 100 ++++++++++++++------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 9e394d6..b82a17d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -141,68 +141,74 @@ void QXcbConnection::updateScreens() // which will become virtual siblings. xcb_screen_t *xcbScreen = it.data; QList siblings; + int outputCount = 0; if (has_randr_extension) { + xcb_generic_error_t *error = NULL; xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary_unchecked(xcb_connection(), xcbScreen->root); + xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), xcbScreen->root); + xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root); xcb_randr_get_output_primary_reply_t *primary = - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, NULL); - xcb_randr_get_screen_resources_current_reply_t *resources = - xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL); - xcb_timestamp_t timestamp = resources->config_timestamp; - int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources); - xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(resources); - - if (outputCount == 0) { - // This happens on VNC for example. But there is actually a screen anyway. -#ifdef Q_XCB_DEBUG - qDebug("Found a screen with zero outputs"); -#endif - QXcbScreen* screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen); - siblings << screen; - activeScreens << screen; - if (!primaryScreen) - primaryScreen = screen; - ++screenNumber; - } - for (int i = 0; i < outputCount; i++) { - xcb_randr_get_output_info_reply_t *output = - xcb_randr_get_output_info_reply(xcb_connection(), - xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL); - if (output == NULL) - continue; + xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error); + if (!primary || error) { + qWarning("QXcbConnection: Failed to get the primary output of the screen"); + free(error); + } else { + xcb_randr_get_screen_resources_current_reply_t *resources = + xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error); + if (!resources || error) { + qWarning("QXcbConnection: Failed to get the screen resources"); + free(error); + } else { + xcb_timestamp_t timestamp = resources->config_timestamp; + outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources); + xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(resources); + + for (int i = 0; i < outputCount; i++) { + xcb_randr_get_output_info_reply_t *output = + xcb_randr_get_output_info_reply(xcb_connection(), + xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL); + if (output == NULL) + continue; #ifdef Q_XCB_DEBUG - QString outputName = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), - xcb_randr_get_output_info_name_length(output)); + QString outputName = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), + xcb_randr_get_output_info_name_length(output)); #endif - if (output->crtc == XCB_NONE) { + if (output->crtc == XCB_NONE) { #ifdef Q_XCB_DEBUG - qDebug("Screen output %s is not connected", qPrintable(outputName)); + qDebug("Screen output %s is not connected", qPrintable(outputName)); #endif - continue; - } - - QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output); - siblings << screen; - activeScreens << screen; - ++screenNumber; - if (!primaryScreen && primary) { - if (primary->output == XCB_NONE || outputs[i] == primary->output) { - primaryScreen = screen; - siblings.prepend(siblings.takeLast()); + continue; + } + + QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output); + siblings << screen; + activeScreens << screen; + ++screenNumber; + if (!primaryScreen && primary) { + if (primary->output == XCB_NONE || outputs[i] == primary->output) { + primaryScreen = screen; + siblings.prepend(siblings.takeLast()); #ifdef Q_XCB_DEBUG - qDebug("Primary output is %d: %s", primary->output, qPrintable(outputName)); + qDebug("Primary output is %d: %s", primary->output, qPrintable(outputName)); #endif + } + } + free(output); } } - free(output); + free(resources); } free(primary); - free(resources); - } else { + } + // If there's no randr extension, or there was some error above, or the screen + // doesn't have outputs for some other reason (e.g. on VNC or ssh -X), just assume there is one screen. + if (outputCount == 0) { +#ifdef Q_XCB_DEBUG + qDebug("Found a screen with zero outputs"); +#endif QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen); siblings << screen; activeScreens << screen; @@ -214,7 +220,7 @@ void QXcbConnection::updateScreens() ((QXcbScreen*)s)->setVirtualSiblings(siblings); xcb_screen_next(&it); ++xcbScreenNumber; - } + } // for each xcb screen // Now activeScreens is the complete set of screens which are active at this time. // Delete any existing screens which are not in activeScreens -- 2.7.4