--- a/src/video/x11/SDL_x11video.c Fri Sep 28 04:09:06 2012 -0700
+++ b/src/video/x11/SDL_x11video.c Fri Sep 28 14:12:45 2012 -0400
@@ -116,6 +116,35 @@
SDL_X11_UnloadSymbols();
}
+/* An error handler to reset the vidmode and then call the default handler. */
+static SDL_bool safety_net_triggered = SDL_FALSE;
+static int (*orig_x11_errhandler) (Display *, XErrorEvent *) = NULL;
+static int
+X11_SafetyNetErrHandler(Display * d, XErrorEvent * e)
+{
+ /* if we trigger an error in our error handler, don't try again. */
+ if (!safety_net_triggered) {
+ safety_net_triggered = SDL_TRUE;
+ SDL_VideoDevice *device = SDL_GetVideoDevice();
+ if (device != NULL) {
+ int i;
+ for (i = 0; i < device->num_displays; i++) {
+ SDL_VideoDisplay *display = &device->displays[i];
+ if (SDL_memcmp(&display->current_mode, &display->desktop_mode,
+ sizeof (SDL_DisplayMode)) != 0) {
+ X11_SetDisplayMode(device, display, &display->desktop_mode);
+ }
+ }
+ }
+ }
+
+ if (orig_x11_errhandler != NULL) {
+ return orig_x11_errhandler(d, e); /* probably terminate. */
+ }
+
+ return 0;
+}
+
static SDL_VideoDevice *
X11_CreateDevice(int devindex)
{
@@ -173,6 +202,10 @@
XSynchronize(data->display, True);
#endif
+ /* Hook up an X11 error handler to recover the desktop resolution. */
+ safety_net_triggered = SDL_FALSE;
+ orig_x11_errhandler = XSetErrorHandler(X11_SafetyNetErrHandler);
+
/* Set the function pointers */
device->VideoInit = X11_VideoInit;
device->VideoQuit = X11_VideoQuit;