Lionel Ulmer lionel.ulmer@free.fr writes:
PS for Alexandre: we once discussed how we could 'streamline' this X error handling (ie to prevent doing the same kind of code at three different locations in the Wine code). Did you progress on this issue or not ?
Yes, here's what I came up with. Basically you have to wrap the call that might fail with X11DRV_expect_error/X11DRV_check_error. Would this work for what you need to do?
Index: dlls/x11drv/x11drv_main.c =================================================================== RCS file: /opt/cvs-commit/wine/dlls/x11drv/x11drv_main.c,v retrieving revision 1.47 diff -u -r1.47 x11drv_main.c --- dlls/x11drv/x11drv_main.c 2001/11/30 23:15:32 1.47 +++ dlls/x11drv/x11drv_main.c 2002/01/21 18:58:48 @@ -63,6 +63,12 @@ static char *desktop_geometry; static XVisualInfo *desktop_vi;
+static x11drv_error_callback err_callback; /* current callback for error */ +static Display *err_callback_display; /* display callback is set for */ +static void *err_callback_arg; /* error callback argument */ +static int err_callback_result; /* error callback result */ +static int (*old_error_handler)( Display *, XErrorEvent * ); + #define IS_OPTION_TRUE(ch) \ ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1') #define IS_OPTION_FALSE(ch) \ @@ -97,12 +103,57 @@ } #endif /* NO_REENTRANT_X11 */
+ +/*********************************************************************** + * X11DRV_expect_error + * + * Setup a callback function that will be called on an X error. The + * callback must return non-zero if the error is the one it expected. + * This function acquires the x11 lock; X11DRV_check_error must be + * called in all cases to release it. + */ +void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg ) +{ + wine_tsx11_lock(); + XSync( display, False ); + err_callback = callback; + err_callback_display = display; + err_callback_arg = arg; + err_callback_result = 0; +} + + +/*********************************************************************** + * X11DRV_check_error + * + * Check if an expected X11 error occurred; return non-zero if yes. + * Also release the x11 lock obtained in X11DRV_expect_error. + */ +int X11DRV_check_error(void) +{ + int ret = err_callback_result; + XSync( err_callback_display, False ); + err_callback = NULL; + wine_tsx11_unlock(); + return ret; +} + + /*********************************************************************** * error_handler */ -static int error_handler(Display *display, XErrorEvent *error_evt) +static int error_handler( Display *display, XErrorEvent *error_evt ) { - DebugBreak(); /* force an entry in the debugger */ + if (err_callback && display == err_callback_display) + { + if ((err_callback_result = err_callback( display, error_evt, err_callback_arg ))) + { + TRACE( "got expected error\n" ); + return 0; + } + } + if (synchronous) DebugBreak(); /* force an entry in the debugger */ + old_error_handler( display, error_evt ); return 0; }
@@ -297,6 +348,7 @@ screen = DefaultScreenOfDisplay( display ); visual = DefaultVisual( display, DefaultScreen(display) ); root_window = DefaultRootWindow( display ); + old_error_handler = XSetErrorHandler( error_handler );
/* Initialize screen depth */
@@ -328,11 +380,7 @@ */ TSXOpenIM( display, NULL, NULL, NULL);
- if (synchronous) - { - XSetErrorHandler( error_handler ); - XSynchronize( display, True ); - } + if (synchronous) XSynchronize( display, True );
screen_width = WidthOfScreen( screen ); screen_height = HeightOfScreen( screen ); Index: include/x11drv.h =================================================================== RCS file: /opt/cvs-commit/wine/include/x11drv.h,v retrieving revision 1.95 diff -u -r1.95 x11drv.h --- include/x11drv.h 2002/01/04 18:27:45 1.95 +++ include/x11drv.h 2002/01/21 18:59:08 @@ -391,7 +391,9 @@ extern void X11DRV_SetFocus( HWND hwnd ); extern Cursor X11DRV_GetCursor( Display *display, struct tagCURSORICONINFO *ptr );
-extern void X11DRV_expect_error( unsigned char request, unsigned char error, XID id ); +typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void *arg ); + +extern void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg ); extern int X11DRV_check_error(void); extern void X11DRV_register_window( Display *display, HWND hwnd, struct x11drv_win_data *data ); extern void X11DRV_set_iconic_state( WND *win );