From cd820c166188e6237dca86872c892f3b5868d31b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 28 Sep 2012 14:12:45 -0400 Subject: [PATCH] Add a safety net X11 error handler, to reset the vidmodes before crashing. --- src/video/x11/SDL_x11video.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index ba047fb64..44fff3159 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -116,6 +116,35 @@ X11_DeleteDevice(SDL_VideoDevice * device) 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 @@ X11_CreateDevice(int devindex) 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;