From 64896d03daf8c9d8da18fdd4b42c89aa479aaa61 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 24 Apr 2002 21:32:11 +0000 Subject: [PATCH] Added support for installing an error callback when expecting an X11 error. --- dlls/x11drv/x11drv_main.c | 86 +++++++++++++++++++-------------------- graphics/x11drv/dib.c | 37 ++++++----------- include/x11drv.h | 4 +- 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/dlls/x11drv/x11drv_main.c b/dlls/x11drv/x11drv_main.c index 1c3ebe5ae48..428462aeb8a 100644 --- a/dlls/x11drv/x11drv_main.c +++ b/dlls/x11drv/x11drv_main.c @@ -21,15 +21,6 @@ #include "config.h" -#ifdef NO_REENTRANT_X11 -/* Get pointers to the static errno and h_errno variables used by Xlib. This - must be done before including makes the variables invisible. */ -extern int errno; -static int *perrno = &errno; -extern int h_errno; -static int *ph_errno = &h_errno; -#endif /* NO_REENTRANT_X11 */ - #include #include #include @@ -77,46 +68,68 @@ static BOOL synchronous; /* run in synchronous mode? */ 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) \ ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0') -#ifdef NO_REENTRANT_X11 -static int* (*old_errno_location)(void); -static int* (*old_h_errno_location)(void); - /*********************************************************************** - * x11_errno_location + * X11DRV_expect_error * - * Get the per-thread errno location. + * 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. */ -static int *x11_errno_location(void) +void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg ) { - /* Use static libc errno while running in Xlib. */ - if (X11DRV_CritSection.OwningThread == GetCurrentThreadId()) return perrno; - return old_errno_location(); + wine_tsx11_lock(); + XSync( display, False ); + err_callback = callback; + err_callback_display = display; + err_callback_arg = arg; + err_callback_result = 0; } + /*********************************************************************** - * x11_h_errno_location + * X11DRV_check_error * - * Get the per-thread h_errno location. + * Check if an expected X11 error occurred; return non-zero if yes. + * Also release the x11 lock obtained in X11DRV_expect_error. */ -static int *x11_h_errno_location(void) +int X11DRV_check_error(void) { - /* Use static libc h_errno while running in Xlib. */ - if (X11DRV_CritSection.OwningThread == GetCurrentThreadId()) return ph_errno; - return old_h_errno_location(); + int ret; + XSync( err_callback_display, False ); + err_callback = NULL; + ret = err_callback_result; + wine_tsx11_unlock(); + return ret; } -#endif /* NO_REENTRANT_X11 */ + /*********************************************************************** * 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; } @@ -289,12 +302,6 @@ static void process_attach(void) setup_options(); /* setup TSX11 locking */ -#ifdef NO_REENTRANT_X11 - old_errno_location = InterlockedExchangePointer( &wine_errno_location, - x11_errno_location ); - old_h_errno_location = InterlockedExchangePointer( &wine_h_errno_location, - x11_h_errno_location ); -#endif /* NO_REENTRANT_X11 */ old_tsx11_lock = wine_tsx11_lock; old_tsx11_unlock = wine_tsx11_unlock; wine_tsx11_lock = lock_tsx11; @@ -311,6 +318,7 @@ static void process_attach(void) screen = DefaultScreenOfDisplay( display ); visual = DefaultVisual( display, DefaultScreen(display) ); root_window = DefaultRootWindow( display ); + old_error_handler = XSetErrorHandler( error_handler ); /* Initialize screen depth */ @@ -342,11 +350,7 @@ static void process_attach(void) */ 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 ); @@ -427,10 +431,6 @@ static void process_detach(void) /* restore TSX11 locking */ wine_tsx11_lock = old_tsx11_lock; wine_tsx11_unlock = old_tsx11_unlock; -#ifdef NO_REENTRANT_X11 - wine_errno_location = old_errno_location; - wine_h_errno_location = old_h_errno_location; -#endif /* NO_REENTRANT_X11 */ RtlDeleteCriticalSection( &X11DRV_CritSection ); } diff --git a/graphics/x11drv/dib.c b/graphics/x11drv/dib.c index 39def3b25d2..28057c1d2d3 100644 --- a/graphics/x11drv/dib.c +++ b/graphics/x11drv/dib.c @@ -47,10 +47,6 @@ WINE_DECLARE_DEBUG_CHANNEL(x11drv); static int ximageDepthTable[32]; -#ifdef HAVE_LIBXXSHM -static int XShmErrorFlag = 0; -#endif - /* This structure holds the arguments for DIB_SetImageBits() */ typedef struct { @@ -5579,10 +5575,9 @@ void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit) * X11DRV_XShmErrorHandler * */ -static int XShmErrorHandler(Display *dpy, XErrorEvent *event) +static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg ) { - XShmErrorFlag = 1; - return 0; + return 1; /* FIXME: should check event contents */ } /*********************************************************************** @@ -5592,7 +5587,6 @@ static int XShmErrorHandler(Display *dpy, XErrorEvent *event) static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp, XShmSegmentInfo* shminfo) { - int (*WineXHandler)(Display *, XErrorEvent *); XImage *image; wine_tsx11_lock(); @@ -5606,26 +5600,19 @@ static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp, shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0); if( shminfo->shmaddr != (char*)-1 ) { + BOOL ok; + shminfo->readOnly = FALSE; - if( XShmAttach( gdi_display, shminfo ) != 0) + X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL ); + ok = (XShmAttach( gdi_display, shminfo ) != 0); + if (X11DRV_check_error()) ok = FALSE; + if (ok) { - /* Reset the error flag */ - XShmErrorFlag = 0; - WineXHandler = XSetErrorHandler(XShmErrorHandler); - XSync( gdi_display, 0 ); - - if (!XShmErrorFlag) - { - shmctl(shminfo->shmid, IPC_RMID, 0); - - XSetErrorHandler(WineXHandler); - wine_tsx11_unlock(); - return image; /* Success! */ - } - /* An error occurred */ - XShmErrorFlag = 0; - XSetErrorHandler(WineXHandler); + shmctl(shminfo->shmid, IPC_RMID, 0); + wine_tsx11_unlock(); + return image; /* Success! */ } + /* An error occured */ shmdt(shminfo->shmaddr); } shmctl(shminfo->shmid, IPC_RMID, 0); diff --git a/include/x11drv.h b/include/x11drv.h index 83037b3ad65..6a6e81439ed 100644 --- a/include/x11drv.h +++ b/include/x11drv.h @@ -416,7 +416,9 @@ inline static Window get_whole_window( WND *wnd ) 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 );