Lionel Ulmer <lionel.ulmer(a)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 );
--
Alexandre Julliard
julliard(a)winehq.com