Alexandre Julliard : winex11: Allow retrieving the window data structure from another thread, with appropriate locking.
Alexandre Julliard
julliard at winehq.org
Mon Sep 17 14:06:34 CDT 2012
Module: wine
Branch: master
Commit: 4289c74f508f01859b7bf3fa2d1b9ca4189e45bb
URL: http://source.winehq.org/git/wine.git/?a=commit;h=4289c74f508f01859b7bf3fa2d1b9ca4189e45bb
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Sep 17 13:03:52 2012 +0200
winex11: Allow retrieving the window data structure from another thread, with appropriate locking.
---
dlls/winex11.drv/window.c | 105 ++++++++++++++++++++++++++++++++++-----------
dlls/winex11.drv/x11drv.h | 2 +
2 files changed, 81 insertions(+), 26 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 7581436..421d67d 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -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;
}
/**********************************************************************
@@ -1607,19 +1621,49 @@ 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
*
* Return the X11 data structure associated with a window.
*/
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;
}
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 05d0237..28cbe6a 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -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;
More information about the wine-cvs
mailing list