fix for blender quitting in X11 if you start blender with a tablet, unplug it, then open a new window.

This commit is contained in:
Campbell Barton
2013-01-23 10:32:09 +00:00
parent 45fb9f9f09
commit 47f23c1372
3 changed files with 41 additions and 7 deletions

View File

@@ -69,8 +69,10 @@
#include <stdio.h> /* for fprintf only */
#include <cstdlib> /* for exit */
static GHOST_TKey
convertXKey(KeySym key);
/* for debugging - so we can breakpoint X11 errors */
// #define USE_X11_ERROR_HANDLERS
static GHOST_TKey convertXKey(KeySym key);
/* these are for copy and select copy */
static char *txt_cut_buffer = NULL;
@@ -91,6 +93,11 @@ GHOST_SystemX11(
abort(); /* was return before, but this would just mean it will crash later */
}
#ifdef USE_X11_ERROR_HANDLERS
(void) XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
(void) XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
#endif
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
/* note -- don't open connection to XIM server here, because the locale
* has to be set before opening the connection but setlocale() has not
@@ -1726,7 +1733,7 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
* Basically it will not crash blender now if you have a X device that
* is configured but not plugged in.
*/
static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
{
fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
theEvent->error_code, theEvent->request_code);
@@ -1735,6 +1742,14 @@ static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
return 0;
}
int GHOST_X11_ApplicationIOErrorHandler(Display *display)
{
fprintf(stderr, "Ignoring Xlib error: error IO\n");
/* No exit! - but keep lint happy */
return 0;
}
/* These C functions are copied from Wine 1.1.13's wintab.c */
#define BOOL int
#define TRUE 1
@@ -1832,7 +1847,9 @@ static BOOL is_eraser(const char *name, const char *type)
void GHOST_SystemX11::initXInputDevices()
{
static XErrorHandler old_handler = (XErrorHandler) 0;
static XErrorHandler old_handler = (XErrorHandler) 0;
static XIOErrorHandler old_handler_io = (XIOErrorHandler) 0;
XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
@@ -1843,7 +1860,8 @@ void GHOST_SystemX11::initXInputDevices()
m_xtablet.EraserDevice = NULL;
/* Install our error handler to override Xlib's termination behavior */
old_handler = XSetErrorHandler(ApplicationErrorHandler);
old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
for (int i = 0; i < device_count; ++i) {
char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL;
@@ -1893,6 +1911,7 @@ void GHOST_SystemX11::initXInputDevices()
/* Restore handler */
(void) XSetErrorHandler(old_handler);
(void) XSetIOErrorHandler(old_handler_io);
XFreeDeviceList(device_info);
}

View File

@@ -49,6 +49,9 @@
# define GHOST_X11_RES_CLASS "Blender" /* res_class */
#endif
/* generic error handlers */
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
int GHOST_X11_ApplicationIOErrorHandler(Display *display);
class GHOST_WindowX11;

View File

@@ -1210,6 +1210,13 @@ installDrawingContext(
GHOST_TSuccess success;
switch (type) {
case GHOST_kDrawingContextTypeOpenGL:
{
/* use our own event handlers to avoid exiting blender,
* this would happen for eg:
* if you open blender, unplug a tablet, then open a new window. */
XErrorHandler old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
if (m_context != NULL) {
if (!s_firstContext) {
@@ -1224,12 +1231,17 @@ installDrawingContext(
success = GHOST_kFailure;
}
break;
/* Restore handler */
(void) XSetErrorHandler(old_handler);
(void) XSetIOErrorHandler(old_handler_io);
break;
}
case GHOST_kDrawingContextTypeNone:
{
success = GHOST_kSuccess;
break;
}
default:
success = GHOST_kFailure;
}