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