xcb: better error handling if no randr or screen resources query fails

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 <marc.mutz@kdab.com>
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
This commit is contained in:
Shawn Rutledge 2012-09-21 13:47:16 +02:00 committed by The Qt Project
parent 1e39e8f53b
commit 9cec2def90

View File

@ -141,68 +141,74 @@ void QXcbConnection::updateScreens()
// which will become virtual siblings.
xcb_screen_t *xcbScreen = it.data;
QList<QPlatformScreen *> 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);
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);
if (outputCount == 0) {
// This happens on VNC for example. But there is actually a screen anyway.
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));
#endif
if (output->crtc == XCB_NONE) {
#ifdef Q_XCB_DEBUG
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());
#ifdef Q_XCB_DEBUG
qDebug("Primary output is %d: %s", primary->output, qPrintable(outputName));
#endif
}
}
free(output);
}
}
free(resources);
}
free(primary);
}
// 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;
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;
#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));
#endif
if (output->crtc == XCB_NONE) {
#ifdef Q_XCB_DEBUG
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());
#ifdef Q_XCB_DEBUG
qDebug("Primary output is %d: %s", primary->output, qPrintable(outputName));
#endif
}
}
free(output);
}
free(primary);
free(resources);
} else {
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