winex11: Allow retrieving the window data structure from another thread, with appropriate locking.

This commit is contained in:
Alexandre Julliard 2012-09-17 13:03:52 +02:00
parent c8ea1e50dc
commit 4289c74f50
2 changed files with 81 additions and 26 deletions

View File

@ -85,6 +85,15 @@ static const char whole_window_prop[] = "__wine_x11_whole_window";
static const char clip_window_prop[] = "__wine_x11_clip_window";
static const char managed_prop[] = "__wine_x11_managed";
static CRITICAL_SECTION win_data_section;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &win_data_section,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": win_data_section") }
};
static CRITICAL_SECTION win_data_section = { &critsect_debug, -1, 0, 0, 0, 0 };
/***********************************************************************
* http://standards.freedesktop.org/startup-notification-spec
@ -1478,17 +1487,17 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd )
struct x11drv_thread_data *thread_data = x11drv_thread_data();
struct x11drv_win_data *data;
if (!(data = X11DRV_get_win_data( hwnd ))) return;
if (!(data = get_win_data( hwnd ))) return;
destroy_gl_drawable( hwnd );
destroy_whole_window( thread_data->display, data, FALSE );
if (thread_data->last_focus == hwnd) thread_data->last_focus = 0;
if (thread_data->last_xic_hwnd == hwnd) thread_data->last_xic_hwnd = 0;
if (data->icon_pixmap) XFreePixmap( gdi_display, data->icon_pixmap );
if (data->icon_mask) XFreePixmap( gdi_display, data->icon_mask );
XDeleteContext( thread_data->display, (XID)hwnd, win_data_context );
XDeleteContext( gdi_display, (XID)hwnd, win_data_context );
release_win_data( data );
HeapFree( GetProcessHeap(), 0, data );
destroy_gl_drawable( hwnd );
}
@ -1499,12 +1508,15 @@ void X11DRV_DestroyNotify( HWND hwnd, XEvent *event )
{
Display *display = event->xdestroywindow.display;
struct x11drv_win_data *data;
BOOL embedded;
if (!(data = X11DRV_get_win_data( hwnd ))) return;
if (!data->embedded) FIXME( "window %p/%lx destroyed from the outside\n", hwnd, data->whole_window );
if (!(data = get_win_data( hwnd ))) return;
embedded = data->embedded;
if (!embedded) FIXME( "window %p/%lx destroyed from the outside\n", hwnd, data->whole_window );
destroy_whole_window( display, data, TRUE );
if (data->embedded) SendMessageW( hwnd, WM_CLOSE, 0, 0 );
release_win_data( data );
if (embedded) SendMessageW( hwnd, WM_CLOSE, 0, 0 );
}
@ -1515,24 +1527,26 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd )
if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
{
data->hwnd = hwnd;
XSaveContext( display, (XID)hwnd, win_data_context, (char *)data );
EnterCriticalSection( &win_data_section );
XSaveContext( gdi_display, (XID)hwnd, win_data_context, (char *)data );
}
return data;
}
/* initialize the desktop window id in the desktop manager process */
static struct x11drv_win_data *create_desktop_win_data( Display *display, HWND hwnd )
static BOOL create_desktop_win_data( Display *display, HWND hwnd )
{
struct x11drv_win_data *data;
if (!(data = alloc_win_data( display, hwnd ))) return NULL;
if (!(data = alloc_win_data( display, hwnd ))) return FALSE;
data->whole_window = root_window;
data->managed = TRUE;
SetPropA( data->hwnd, managed_prop, (HANDLE)1 );
SetPropA( data->hwnd, whole_window_prop, (HANDLE)root_window );
release_win_data( data );
set_initial_wm_hints( hwnd );
return data;
return TRUE;
}
/**********************************************************************
@ -1606,6 +1620,35 @@ BOOL CDECL X11DRV_CreateWindow( HWND hwnd )
}
/***********************************************************************
* get_win_data
*
* Lock and return the X11 data structure associated with a window.
*/
struct x11drv_win_data *get_win_data( HWND hwnd )
{
char *data;
if (!hwnd) return NULL;
EnterCriticalSection( &win_data_section );
if (!XFindContext( gdi_display, (XID)hwnd, win_data_context, &data ))
return (struct x11drv_win_data *)data;
LeaveCriticalSection( &win_data_section );
return NULL;
}
/***********************************************************************
* release_win_data
*
* Release the data returned by get_win_data.
*/
void release_win_data( struct x11drv_win_data *data )
{
if (data) LeaveCriticalSection( &win_data_section );
}
/***********************************************************************
* X11DRV_get_win_data
*
@ -1613,13 +1656,14 @@ BOOL CDECL X11DRV_CreateWindow( HWND hwnd )
*/
struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd )
{
struct x11drv_thread_data *thread_data = x11drv_thread_data();
char *data;
struct x11drv_win_data *data = get_win_data( hwnd );
if (!thread_data) return NULL;
if (!hwnd) return NULL;
if (XFindContext( thread_data->display, (XID)hwnd, win_data_context, &data )) data = NULL;
return (struct x11drv_win_data *)data;
if (data)
{
release_win_data( data );
if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId()) data = NULL;
}
return data;
}
@ -1640,11 +1684,14 @@ static struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd, const RECT *wi
/* don't create win data for HWND_MESSAGE windows */
if (parent != GetDesktopWindow() && !GetAncestor( parent, GA_PARENT )) return NULL;
if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId()) return NULL;
display = thread_init_display();
if (!(data = alloc_win_data( display, hwnd ))) return NULL;
data->whole_rect = data->window_rect = *window_rect;
data->client_rect = *client_rect;
release_win_data( data );
if (parent == GetDesktopWindow())
{
@ -1775,14 +1822,17 @@ HWND create_foreign_window( Display *display, Window xwin )
*/
Window X11DRV_get_whole_window( HWND hwnd )
{
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
struct x11drv_win_data *data = get_win_data( hwnd );
Window ret;
if (!data)
{
if (hwnd == GetDesktopWindow()) return root_window;
return (Window)GetPropA( hwnd, whole_window_prop );
}
return data->whole_window;
ret = data->whole_window;
release_win_data( data );
return ret;
}
@ -1793,15 +1843,18 @@ Window X11DRV_get_whole_window( HWND hwnd )
*/
XIC X11DRV_get_ic( HWND hwnd )
{
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
struct x11drv_win_data *data = get_win_data( hwnd );
XIM xim;
XIC ret = 0;
if (!data) return 0;
x11drv_thread_data()->last_xic_hwnd = hwnd;
if (data->xic) return data->xic;
if (!(xim = x11drv_thread_data()->xim)) return 0;
return X11DRV_CreateIC( xim, data );
if (data)
{
x11drv_thread_data()->last_xic_hwnd = hwnd;
ret = data->xic;
if (!ret && (xim = x11drv_thread_data()->xim)) ret = X11DRV_CreateIC( xim, data );
release_win_data( data );
}
return ret;
}

View File

@ -553,6 +553,8 @@ struct x11drv_win_data
Pixmap icon_mask;
};
extern struct x11drv_win_data *get_win_data( HWND hwnd ) DECLSPEC_HIDDEN;
extern void release_win_data( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
extern struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd ) DECLSPEC_HIDDEN;
extern Window X11DRV_get_whole_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;