mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 10:41:12 +00:00
Added support for installing an error callback when expecting an X11
error.
This commit is contained in:
parent
54ba272090
commit
64896d03da
3 changed files with 58 additions and 69 deletions
|
@ -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 <errno.h> 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 <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue