Create an X connection for each thread, and process X events in the
thread that created the corresponding X window.
Spawn a separate thread to run the desktop message loop in desktop
mode.

diff --git a/controls/desktop.c b/controls/desktop.c
index 2b3f836..01e1706 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -97,121 +97,25 @@
 }
 
 
-/***********************************************************************
- *           DESKTOP_DoEraseBkgnd
- *
- * Handle the WM_ERASEBKGND message.
- */
-static LRESULT DESKTOP_DoEraseBkgnd( HWND hwnd, HDC hdc,
-                                     DESKTOP *desktopPtr )
-{
-    RECT rect;
-    WND*   Wnd = WIN_FindWndPtr( hwnd );
-
-    if (Wnd->hrgnUpdate > 1) DeleteObject( Wnd->hrgnUpdate );
-    Wnd->hrgnUpdate = 0;
-
-    WIN_ReleaseWndPtr(Wnd);
-    
-    GetClientRect( hwnd, &rect );    
-
-    /* Paint desktop pattern (only if wall paper does not cover everything) */
-
-    if (!desktopPtr->hbitmapWallPaper || 
-	(!desktopPtr->fTileWallPaper && ((desktopPtr->bitmapSize.cx < rect.right) ||
-	 (desktopPtr->bitmapSize.cy < rect.bottom))))
-    {
-        HBRUSH brush = desktopPtr->hbrushPattern;
-        if (!brush) brush = GetClassLongA( hwnd, GCL_HBRBACKGROUND );
-	  /* Set colors in case pattern is a monochrome bitmap */
-	SetBkColor( hdc, RGB(0,0,0) );
-	SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
-	FillRect( hdc, &rect, brush );
-    }
-
-      /* Paint wall paper */
-
-    if (desktopPtr->hbitmapWallPaper)
-    {
-	INT x, y;
-	HDC hMemDC = CreateCompatibleDC( hdc );
-	
-	SelectObject( hMemDC, desktopPtr->hbitmapWallPaper );
-
-	if (desktopPtr->fTileWallPaper)
-	{
-	    for (y = 0; y < rect.bottom; y += desktopPtr->bitmapSize.cy)
-		for (x = 0; x < rect.right; x += desktopPtr->bitmapSize.cx)
-		    BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
-			      desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
-	}
-	else
-	{
-	    x = (rect.left + rect.right - desktopPtr->bitmapSize.cx) / 2;
-	    y = (rect.top + rect.bottom - desktopPtr->bitmapSize.cy) / 2;
-	    if (x < 0) x = 0;
-	    if (y < 0) y = 0;
-	    BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
-		      desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
-	}
-	DeleteDC( hMemDC );
-    }
-
-    return 1;
-}
-
-
-/***********************************************************************
- *           DesktopWndProc_locked
- *
- * Window procedure for the desktop window.
- */
-static inline LRESULT WINAPI DesktopWndProc_locked( WND *wndPtr, UINT message,
-                               WPARAM wParam, LPARAM lParam )
-{
-    DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
-    HWND hwnd = wndPtr->hwndSelf;
-
-      /* Most messages are ignored (we DON'T call DefWindowProc) */
-
-    switch(message)
-    {
-	/* Warning: this message is sent directly by                     */
-	/* WIN_CreateDesktopWindow() and does not contain a valid lParam */
-    case WM_NCCREATE:
-	desktopPtr->hbrushPattern = 0;
-	desktopPtr->hbitmapWallPaper = 0;
-	SetDeskPattern();
-	SetDeskWallPaper( (LPSTR)-1 );
-        return  1;
-	
-    case WM_ERASEBKGND:
-	if(!USER_Driver.pIsSingleWindow())
-            return  1;
-        return  DESKTOP_DoEraseBkgnd( hwnd, (HDC)wParam, desktopPtr );
-
-    case WM_SYSCOMMAND:
-        if ((wParam & 0xfff0) != SC_CLOSE)
-            return  0;
-	ExitWindows16( 0, 0 ); 
-
-    case WM_SETCURSOR:
-        return  (LRESULT)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
-    }
-    
-    return 0;
-}
 
 /***********************************************************************
  *           DesktopWndProc
- *
- * This is just a wrapper for the DesktopWndProc which does windows
- * locking and unlocking.
  */
 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
 {
+    LRESULT retvalue = 0;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    LRESULT retvalue = DesktopWndProc_locked(wndPtr,message,wParam,lParam);
+    DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
+
+    if (message == WM_NCCREATE)
+    {
+        desktopPtr->hbrushPattern = 0;
+        desktopPtr->hbitmapWallPaper = 0;
+        SetDeskPattern();
+        SetDeskWallPaper( (LPSTR)-1 );
+        retvalue = 1;
+    }
+    /* all other messages are ignored */
 
     WIN_ReleaseWndPtr(wndPtr);
     return retvalue;
@@ -223,14 +127,61 @@
  */
 BOOL WINAPI PaintDesktop(HDC hdc)
 {
-    BOOL retvalue;
     HWND hwnd = GetDesktopWindow();
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
-    retvalue = DESKTOP_DoEraseBkgnd( hwnd, hdc, desktopPtr );
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
 
+    /* check for a queue; otherwise don't paint anything (non-desktop mode) */
+    if (wndPtr->hmemTaskQ)
+    {
+        RECT rect;
+
+        GetClientRect( hwnd, &rect );
+
+        /* Paint desktop pattern (only if wall paper does not cover everything) */
+
+        if (!desktopPtr->hbitmapWallPaper ||
+            (!desktopPtr->fTileWallPaper && ((desktopPtr->bitmapSize.cx < rect.right) ||
+                                             (desktopPtr->bitmapSize.cy < rect.bottom))))
+        {
+            HBRUSH brush = desktopPtr->hbrushPattern;
+            if (!brush) brush = GetClassLongA( hwnd, GCL_HBRBACKGROUND );
+            /* Set colors in case pattern is a monochrome bitmap */
+            SetBkColor( hdc, RGB(0,0,0) );
+            SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
+            FillRect( hdc, &rect, brush );
+        }
+
+        /* Paint wall paper */
+
+        if (desktopPtr->hbitmapWallPaper)
+        {
+            INT x, y;
+            HDC hMemDC = CreateCompatibleDC( hdc );
+
+            SelectObject( hMemDC, desktopPtr->hbitmapWallPaper );
+
+            if (desktopPtr->fTileWallPaper)
+            {
+                for (y = 0; y < rect.bottom; y += desktopPtr->bitmapSize.cy)
+                    for (x = 0; x < rect.right; x += desktopPtr->bitmapSize.cx)
+                        BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
+                                desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
+            }
+            else
+            {
+                x = (rect.left + rect.right - desktopPtr->bitmapSize.cx) / 2;
+                y = (rect.top + rect.bottom - desktopPtr->bitmapSize.cy) / 2;
+                if (x < 0) x = 0;
+                if (y < 0) y = 0;
+                BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
+                        desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
+            }
+            DeleteDC( hMemDC );
+        }
+    }
+    WIN_ReleaseWndPtr(wndPtr);
+    return TRUE;
 }
 
 /***********************************************************************
diff --git a/dlls/ttydrv/ttydrv.spec b/dlls/ttydrv/ttydrv.spec
index 55ad8bc..ffcdc9f 100644
--- a/dlls/ttydrv/ttydrv.spec
+++ b/dlls/ttydrv/ttydrv.spec
@@ -11,7 +11,6 @@
 
 # USER driver
 
-@ cdecl UserRepaintDisable(long) TTYDRV_UserRepaintDisable
 @ cdecl InitKeyboard() TTYDRV_InitKeyboard
 @ cdecl VkKeyScan(long) TTYDRV_VkKeyScan
 @ cdecl MapVirtualKey(long long) TTYDRV_MapVirtualKey
@@ -32,7 +31,6 @@
 @ cdecl DestroyWindow(long) TTYDRV_DestroyWindow
 @ cdecl GetDC(long long long long) TTYDRV_GetDC
 @ cdecl SetWindowPos(ptr) TTYDRV_SetWindowPos
-@ cdecl IsSingleWindow() TTYDRV_IsSingleWindow
 @ cdecl AcquireClipboard() TTYDRV_AcquireClipboard
 @ cdecl ReleaseClipboard() TTYDRV_ReleaseClipboard
 @ cdecl SetClipboardData(long) TTYDRV_SetClipboardData
diff --git a/dlls/ttydrv/user.c b/dlls/ttydrv/user.c
index ca7a3c5..6d65162 100644
--- a/dlls/ttydrv/user.c
+++ b/dlls/ttydrv/user.c
@@ -11,13 +11,6 @@
 
 DEFAULT_DEBUG_CHANNEL(ttydrv);
 
-/***********************************************************************
- *		TTYDRV_UserRepaintDisable
- */
-void TTYDRV_UserRepaintDisable( BOOL bDisable )
-{
-}
-
 
 /***********************************************************************
  *		TTYDRV_InitKeyboard
@@ -170,14 +163,6 @@
 }
 
 /***********************************************************************
- *              TTYDRV_IsSingleWindow
- */
-BOOL TTYDRV_IsSingleWindow(void)
-{
-    return TRUE;
-}
-
-/***********************************************************************
  *		TTYDRV_AcquireClipboard
  */
 void TTYDRV_AcquireClipboard(void)
diff --git a/dlls/user/display.c b/dlls/user/display.c
index 822174a..e132285 100644
--- a/dlls/user/display.c
+++ b/dlls/user/display.c
@@ -76,6 +76,6 @@
  */
 VOID WINAPI UserRepaintDisable16( BOOL16 disable )
 {
-    USER_Driver.pUserRepaintDisable( disable );
+    FIXME("stub\n");
 }
 
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index 2690e8d..341c5f4 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -12,8 +12,10 @@
 #include "wine/winuser16.h"
 
 #include "controls.h"
+#include "cursoricon.h"
 #include "global.h"
 #include "input.h"
+#include "hook.h"
 #include "keyboard.h"
 #include "message.h"
 #include "queue.h"
@@ -58,7 +60,6 @@
         return FALSE;
     }
 
-    GET_USER_FUNC(UserRepaintDisable);
     GET_USER_FUNC(InitKeyboard);
     GET_USER_FUNC(VkKeyScan);
     GET_USER_FUNC(MapVirtualKey);
@@ -75,7 +76,6 @@
     GET_USER_FUNC(GetScreenSaveTimeout);
     GET_USER_FUNC(SetScreenSaveTimeout);
     GET_USER_FUNC(LoadOEMResource);
-    GET_USER_FUNC(IsSingleWindow);
     GET_USER_FUNC(AcquireClipboard);
     GET_USER_FUNC(ReleaseClipboard);
     GET_USER_FUNC(SetClipboardData);
@@ -88,6 +88,7 @@
     GET_USER_FUNC(DestroyWindow);
     GET_USER_FUNC(GetDC);
     GET_USER_FUNC(EnableWindow);
+    GET_USER_FUNC(MsgWaitForMultipleObjects);
     GET_USER_FUNC(ScrollWindowEx);
     GET_USER_FUNC(SetFocus);
     GET_USER_FUNC(SetParent);
@@ -191,13 +192,11 @@
 /***********************************************************************
  *           USER initialisation routine
  */
-BOOL WINAPI USER_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+static BOOL process_attach(void)
 {
     HINSTANCE16 instance;
     int queueSize;
 
-    if ( USER_HeapSel ) return TRUE;
-
     /* Create USER heap */
     if ((instance = LoadLibrary16( "USER.EXE" )) < 32) return FALSE;
     USER_HeapSel = instance | 7;
@@ -250,8 +249,66 @@
     /* Initialize mouse driver */
     MOUSE_Enable( mouse_event );
 
-    /* Start processing X events */
-    USER_Driver.pUserRepaintDisable( FALSE );
-
     return TRUE;
 }
+
+
+/**********************************************************************
+ *           thread
+ */
+static void thread_detach(void)
+{
+    HQUEUE16 hQueue = GetThreadQueue16( 0 );
+
+    if (hQueue)
+    {
+        WND* desktop = WIN_GetDesktop();
+
+        TIMER_RemoveQueueTimers( hQueue );
+
+        HOOK_FreeQueueHooks( hQueue );
+
+        QUEUE_SetExitingQueue( hQueue );
+        WIN_ResetQueueWindows( desktop, hQueue, 0 );
+        QUEUE_SetExitingQueue( 0 );
+        QUEUE_DeleteMsgQueue( hQueue );
+
+        WIN_ReleaseDesktop();
+        SetThreadQueue16( 0, 0 );
+    }
+
+    if (!(NtCurrentTeb()->tibflags & TEBF_WIN32))
+    {
+        HMODULE16 hModule = GetExePtr( MapHModuleLS(0) );
+
+        /* FIXME: maybe destroy menus (Windows only complains about them
+         * but does nothing);
+         */
+        if (GetModuleUsage16( hModule ) <= 1)
+        {
+            /* ModuleUnload() in "Internals" */
+            HOOK_FreeModuleHooks( hModule );
+            CLASS_FreeModuleClasses( hModule );
+            CURSORICON_FreeModuleIcons( hModule );
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           USER initialisation routine
+ */
+BOOL WINAPI USER_Init( HINSTANCE inst, DWORD reason, LPVOID reserved )
+{
+    BOOL ret = TRUE;
+    switch(reason)
+    {
+    case DLL_PROCESS_ATTACH:
+        ret = process_attach();
+        break;
+    case DLL_THREAD_DETACH:
+        thread_detach();
+        break;
+    }
+    return ret;
+}
diff --git a/dlls/x11drv/Makefile.in b/dlls/x11drv/Makefile.in
index 10a3f9a..e98cdd5 100644
--- a/dlls/x11drv/Makefile.in
+++ b/dlls/x11drv/Makefile.in
@@ -7,6 +7,7 @@
 IMPORTS   = user32 gdi32 kernel32
 
 C_SRCS = \
+	desktop.c \
 	dga2.c \
 	window.c \
 	winpos.c \
diff --git a/dlls/x11drv/desktop.c b/dlls/x11drv/desktop.c
new file mode 100644
index 0000000..1376899
--- /dev/null
+++ b/dlls/x11drv/desktop.c
@@ -0,0 +1,158 @@
+/*
+ * X11DRV desktop window handling
+ *
+ * Copyright 2001 Alexandre Julliard
+ */
+
+#include "config.h"
+#include <X11/cursorfont.h>
+
+#include "ts_xlib.h"
+
+#include "win.h"
+#include "x11drv.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(x11drv);
+
+
+/* desktop window procedure */
+static LRESULT WINAPI desktop_winproc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+    switch(message)
+    {
+    case WM_ERASEBKGND:
+        PaintDesktop( (HDC)wParam );
+        ValidateRect( hwnd, NULL );
+        break;
+
+    case WM_SYSCOMMAND:
+        if ((wParam & 0xfff0) == SC_CLOSE) ExitWindows( 0, 0 );
+        break;
+
+    case WM_SETCURSOR:
+        return SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
+
+    case WM_NCHITTEST:
+        return HTCLIENT;
+    }
+    return 0;
+}
+
+
+/* desktop window manager thread */
+static DWORD CALLBACK desktop_thread( LPVOID driver_data )
+{
+    Display *display;
+    MSG msg;
+    HWND hwnd;
+    WND *win;
+
+    NtCurrentTeb()->driver_data = driver_data;
+    display = thread_display();
+    hwnd = GetDesktopWindow();
+
+    /* patch the desktop window queue to point to our queue */
+    win = WIN_FindWndPtr( hwnd );
+    win->hmemTaskQ = GetFastQueue16();
+    WIN_ReleaseWndPtr( win );
+
+    SetWindowLongW( hwnd, GWL_WNDPROC, (LONG)desktop_winproc );
+    X11DRV_register_window( display, hwnd, root_window );
+    TSXMapWindow( display, root_window );
+
+    while (GetMessageW( &msg, hwnd, 0, 0 )) DispatchMessageW( &msg );
+    return 0;
+}
+
+
+/***********************************************************************
+ *		X11DRV_create_desktop_thread
+ *
+ * Create the thread that manages the desktop window
+ */
+void X11DRV_create_desktop_thread(void)
+{
+    HANDLE handle = CreateThread( NULL, 0, desktop_thread, NtCurrentTeb()->driver_data, 0, NULL );
+    if (!handle)
+    {
+        MESSAGE( "Could not create desktop thread\n" );
+        ExitProcess(1);
+    }
+    /* we transferred our driver data to the new thread */
+    NtCurrentTeb()->driver_data = NULL;
+    CloseHandle( handle );
+}
+
+
+/***********************************************************************
+ *		X11DRV_create_desktop
+ *
+ * Create the X11 desktop window for the desktop mode.
+ */
+Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry )
+{
+    int x = 0, y = 0, flags;
+    unsigned int width = 640, height = 480;  /* Default size = 640x480 */
+    char *name = "Wine desktop";
+    XSizeHints *size_hints;
+    XWMHints   *wm_hints;
+    XClassHint *class_hints;
+    XSetWindowAttributes win_attr;
+    XTextProperty window_name;
+    Window win;
+    Display *display = thread_display();
+
+    wine_tsx11_lock();
+    flags = XParseGeometry( geometry, &x, &y, &width, &height );
+    screen_width  = width;
+    screen_height = height;
+
+    /* Create window */
+    win_attr.background_pixel = BlackPixel(display, 0);
+    win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
+                          PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
+    win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
+
+    if (desktop_vi)
+        win_attr.colormap = XCreateColormap( display, DefaultRootWindow(display),
+                                             visual, AllocNone );
+    else
+        win_attr.colormap = None;
+
+    win = XCreateWindow( display, DefaultRootWindow(display),
+                         x, y, width, height, 0, screen_depth, InputOutput, visual,
+                         CWBackPixel | CWEventMask | CWCursor | CWColormap, &win_attr );
+
+    /* Set window manager properties */
+    size_hints  = XAllocSizeHints();
+    wm_hints    = XAllocWMHints();
+    class_hints = XAllocClassHint();
+    if (!size_hints || !wm_hints || !class_hints)
+    {
+        MESSAGE("Not enough memory for window manager hints.\n" );
+        ExitProcess(1);
+    }
+    size_hints->min_width = size_hints->max_width = width;
+    size_hints->min_height = size_hints->max_height = height;
+    size_hints->flags = PMinSize | PMaxSize;
+    if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
+    if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
+    else size_hints->flags |= PSize;
+
+    wm_hints->flags = InputHint | StateHint;
+    wm_hints->input = True;
+    wm_hints->initial_state = NormalState;
+    class_hints->res_name  = "wine";
+    class_hints->res_class = "Wine";
+
+    XStringListToTextProperty( &name, 1, &window_name );
+    XSetWMProperties( display, win, &window_name, &window_name,
+                      NULL, 0, size_hints, wm_hints, class_hints );
+    XFree( size_hints );
+    XFree( wm_hints );
+    XFree( class_hints );
+    XFlush( display );
+    wine_tsx11_unlock();
+    return win;
+}
diff --git a/dlls/x11drv/dga2.c b/dlls/x11drv/dga2.c
index 939cb6a..bf9fc0a 100644
--- a/dlls/x11drv/dga2.c
+++ b/dlls/x11drv/dga2.c
@@ -51,7 +51,7 @@
   if (xf86dga2_modes) return; /* already initialized? */
 
   /* if in desktop mode, don't use DGA */
-  if (X11DRV_GetXRootWindow() != DefaultRootWindow(display)) return;
+  if (root_window != DefaultRootWindow(display)) return;
 
   if (!usedga) return;
 
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index 4508b99..ed3e966 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -23,7 +23,6 @@
 
 DEFAULT_DEBUG_CHANNEL(win);
 
-extern Cursor X11DRV_MOUSE_XCursor;  /* current X cursor */
 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
 
 #define HAS_DLGFRAME(style,exStyle) \
@@ -42,11 +41,11 @@
 
 
 /***********************************************************************
- *		register_window
+ *		X11DRV_register_window
  *
  * Associate an X window to a HWND.
  */
-static void register_window( HWND hwnd, Window win )
+void X11DRV_register_window( Display *display, HWND hwnd, Window win )
 {
     if (!winContext) winContext = TSXUniqueContext();
     TSXSaveContext( display, win, winContext, (char *)hwnd );
@@ -59,7 +58,7 @@
  *
  * Set a window manager hint.
  */
-static void set_wm_hint( Window win, int hint, int val )
+static void set_wm_hint( Display *display, Window win, int hint, int val )
 {
     XWMHints* wm_hints = TSXGetWMHints( display, win );
     if (!wm_hints) wm_hints = TSXAllocWMHints();
@@ -95,7 +94,7 @@
  *
  * Set the icon wm hints
  */
-static void set_icon_hints( WND *wndPtr, XWMHints *hints )
+static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
 {
     X11DRV_WND_DATA *data = wndPtr->pDriverData;
     HICON hIcon = GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
@@ -155,7 +154,7 @@
  *
  * all others: to be added ;)
  */
-inline static void dock_window( Window win )
+inline static void dock_window( Display *display, Window win )
 {
     int data = 1;
     if (kwmDockWindow != None)
@@ -170,7 +169,7 @@
 /**********************************************************************
  *		create_desktop
  */
-static void create_desktop(WND *wndPtr)
+static void create_desktop( Display *display, WND *wndPtr )
 {
     X11DRV_WND_DATA *data = wndPtr->pDriverData;
 
@@ -183,8 +182,11 @@
     _kde_net_wm_system_tray_window_for = TSXInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
 
     data->window = root_window;
-    if (root_window != DefaultRootWindow(display)) wndPtr->flags |= WIN_NATIVE;
-    register_window( wndPtr->hwndSelf, root_window );
+    if (root_window != DefaultRootWindow(display))
+    {
+        wndPtr->flags |= WIN_NATIVE;
+        X11DRV_create_desktop_thread();
+    }
 }
 
 
@@ -193,6 +195,7 @@
  */
 BOOL X11DRV_CreateWindow( HWND hwnd )
 {
+    Display *display = thread_display();
     X11DRV_WND_DATA *data;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     int x = wndPtr->rectWindow.left;
@@ -210,7 +213,7 @@
 
     if (!wndPtr->parent)
     {
-        create_desktop( wndPtr );
+        create_desktop( display, wndPtr );
         WIN_ReleaseWndPtr( wndPtr );
         return TRUE;
     }
@@ -246,11 +249,13 @@
         }
         wndPtr->flags |= WIN_NATIVE;
 
+        wine_tsx11_lock();
+
         win_attr.bit_gravity   = (wndPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ? ForgetGravity : NorthWestGravity;
         win_attr.colormap      = X11DRV_PALETTE_PaletteXColormap;
         win_attr.backing_store = NotUseful;
         win_attr.save_under    = ((wndPtr->clsStyle & CS_SAVEBITS) != 0);
-        win_attr.cursor        = X11DRV_MOUSE_XCursor;
+        win_attr.cursor        = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
 
         data->hWMIconBitmap = 0;
         data->hWMIconMask = 0;
@@ -262,7 +267,7 @@
         if (cx <= 0) cx = 1;
         if (cy <= 0) cy = 1;
 
-        data->window = TSXCreateWindow( display, root_window,
+        data->window = XCreateWindow( display, root_window,
                                         x, y, cx, cy,
                                         0, screen_depth,
                                         InputOutput, visual,
@@ -271,7 +276,10 @@
                                         CWBackingStore | CWBitGravity,
                                         &win_attr );
 
-        if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
+        if (win_attr.cursor) XFreeCursor( display, win_attr.cursor );
+        wine_tsx11_unlock();
+
+        if(!(wGroupLeader = data->window))
         {
             HeapFree( GetProcessHeap(), 0, data );
             WIN_ReleaseWndPtr( wndPtr );
@@ -279,7 +287,7 @@
         }
 
         /* If we are the systray, we need to be managed to be noticed by KWM */
-        if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW) dock_window( data->window );
+        if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW) dock_window( display, data->window );
 
         if (wndPtr->dwExStyle & WS_EX_MANAGED)
         {
@@ -331,7 +339,7 @@
 
             if (wndPtr->dwExStyle & WS_EX_MANAGED)
             {
-                set_icon_hints( wndPtr, wm_hints );
+                set_icon_hints( display, wndPtr, wm_hints );
                 wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
                     ? IconicState : NormalState;
             }
@@ -342,7 +350,8 @@
             TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
             TSXFree(wm_hints);
         }
-        register_window( hwnd, data->window );
+        X11DRV_register_window( display, hwnd, data->window );
+        TSXFlush( display );
     }
     WIN_ReleaseWndPtr( wndPtr );
     return TRUE;
@@ -354,6 +363,7 @@
  */
 BOOL X11DRV_DestroyWindow( HWND hwnd )
 {
+    Display *display = thread_display();
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     X11DRV_WND_DATA *data = wndPtr->pDriverData;
     Window w;
@@ -361,9 +371,12 @@
     if (data && (w = data->window))
     {
         XEvent xe;
-        TSXDeleteContext( display, w, winContext );
-        TSXDestroyWindow( display, w );
-        while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
+        wine_tsx11_lock();
+        XSync( gdi_display, False );  /* flush any reference to this drawable in GDI queue */
+        XDeleteContext( display, w, winContext );
+        XDestroyWindow( display, w );
+        while( XCheckWindowEvent(display, w, NoEventMask, &xe) );
+        wine_tsx11_unlock();
 
         data->window = None;
         if( data->hWMIconBitmap )
@@ -389,6 +402,7 @@
  */
 HWND X11DRV_SetParent( HWND hwnd, HWND parent )
 {
+    Display *display = thread_display();
     WND *wndPtr;
     WND *pWndParent;
     DWORD dwStyle;
@@ -464,6 +478,7 @@
  */
 BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
 {
+    Display *display = thread_display();
     WND *wndPtr;
     BOOL retvalue;
     Window w;
@@ -478,7 +493,7 @@
         wndPtr->dwStyle &= ~WS_DISABLED;
 
         if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
-            set_wm_hint( w, InputHint, TRUE );
+            set_wm_hint( display, w, InputHint, TRUE );
 
         SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
     }
@@ -490,7 +505,7 @@
         wndPtr->dwStyle |= WS_DISABLED;
 
         if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
-            set_wm_hint( w, InputHint, FALSE );
+            set_wm_hint( display, w, InputHint, FALSE );
 
         if (hwnd == GetFocus())
             SetFocus( 0 );  /* A disabled window can't have the focus */
@@ -513,6 +528,7 @@
  */
 void X11DRV_SetFocus( HWND hwnd )
 {
+    Display *display = thread_display();
     XWindowAttributes win_attr;
     Window win;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
@@ -558,6 +574,7 @@
  */
 BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
 {
+    Display *display = thread_display();
     UINT count;
     char *buffer;
     static UINT text_cp = (UINT)-1;
@@ -604,6 +621,7 @@
  */
 HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
 {
+    Display *display = thread_display();
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     int index = small ? GCL_HICONSM : GCL_HICON;
     HICON old;
@@ -624,7 +642,7 @@
         if (!wm_hints) wm_hints = TSXAllocWMHints();
         if (wm_hints)
         {
-            set_icon_hints( wndPtr, wm_hints );
+            set_icon_hints( display, wndPtr, wm_hints );
             TSXSetWMHints( display, win, wm_hints );
             TSXFree( wm_hints );
         }
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index 1f110a5..721bd7b 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -405,7 +405,7 @@
         }
         else
         {
-            if ((hwnd == GetDesktopWindow()) && (root_window != DefaultRootWindow(display)))
+            if ((hwnd == GetDesktopWindow()) && (root_window != DefaultRootWindow(thread_display())))
                 hrgnVisible = CreateRectRgn( 0, 0, GetSystemMetrics(SM_CXSCREEN),
                                              GetSystemMetrics(SM_CYSCREEN) );
             else
@@ -1280,6 +1280,7 @@
                             SWP_NOZORDER | (redraw ? 0 : SWP_NOREDRAW) );
 #ifdef HAVE_LIBXSHAPE
     {
+        Display *display = thread_display();
         Window win = X11DRV_WND_GetXWindow(wndPtr);
 
         if (win)
@@ -1474,7 +1475,10 @@
     BOOL    moved = FALSE;
     DWORD     dwPoint = GetMessagePos ();
     BOOL DragFullWindows = FALSE;
+    BOOL grab;
     int iWndsLocks;
+    Display *old_gdi_display = NULL;
+    Display *display = thread_display();
 
     SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
 
@@ -1563,9 +1567,18 @@
     RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
 
     /* grab the server only when moving top-level windows without desktop */
-    if ((root_window == DefaultRootWindow(display)) &&
-        (wndPtr->parent->hwndSelf == GetDesktopWindow()))
-        TSXGrabServer( display );
+    grab = (!DragFullWindows && (root_window == DefaultRootWindow(gdi_display)) &&
+            (wndPtr->parent->hwndSelf == GetDesktopWindow()));
+    if (grab)
+    {
+        wine_tsx11_lock();
+        XSync( gdi_display, False );
+        XGrabServer( display );
+        /* switch gdi display to the thread display, since the server is grabbed */
+        old_gdi_display = gdi_display;
+        gdi_display = display;
+        wine_tsx11_unlock();
+    }
 
     while(1)
     {
@@ -1673,9 +1686,14 @@
     else
         ReleaseDC( 0, hdc );
 
-    if ((root_window == DefaultRootWindow(display)) &&
-        (wndPtr->parent->hwndSelf == GetDesktopWindow()))
-        TSXUngrabServer( display );
+    if (grab)
+    {
+        wine_tsx11_lock();
+        XSync( display, False );
+        XUngrabServer( display );
+        gdi_display = old_gdi_display;
+        wine_tsx11_unlock();
+    }
 
     if (HOOK_CallHooksA( WH_CBT, HCBT_MOVESIZE, hwnd, (LPARAM)&sizingRect ))
         sizingRect = wndPtr->rectWindow;
diff --git a/dlls/x11drv/x11ddraw.c b/dlls/x11drv/x11ddraw.c
index 378cdbd..a867222 100644
--- a/dlls/x11drv/x11ddraw.c
+++ b/dlls/x11drv/x11ddraw.c
@@ -48,6 +48,7 @@
 
 static void GrabPointer(HWND hWnd)
 {
+  Display *display = thread_display();
   if (hWnd) {
     WND *tmpWnd;
     Window win;
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index abfdac3..ac91214 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -11,7 +11,6 @@
 
 # USER driver
 
-@ cdecl UserRepaintDisable(long) X11DRV_UserRepaintDisable
 @ cdecl InitKeyboard() X11DRV_InitKeyboard
 @ cdecl VkKeyScan(long) X11DRV_VkKeyScan
 @ cdecl MapVirtualKey(long long) X11DRV_MapVirtualKey
@@ -32,6 +31,7 @@
 @ cdecl DestroyWindow(long) X11DRV_DestroyWindow
 @ cdecl GetDC(long long long long) X11DRV_GetDC
 @ cdecl EnableWindow(long long) X11DRV_EnableWindow
+@ cdecl MsgWaitForMultipleObjects(long ptr long long) X11DRV_MsgWaitForMultipleObjects
 @ cdecl ScrollWindowEx(long long long ptr ptr long ptr long) X11DRV_ScrollWindowEx
 @ cdecl SetFocus(long) X11DRV_SetFocus
 @ cdecl SetParent(long long) X11DRV_SetParent
@@ -40,7 +40,6 @@
 @ cdecl SetWindowIcon(long long long) X11DRV_SetWindowIcon
 @ cdecl SetWindowText(long wstr) X11DRV_SetWindowText
 @ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove
-@ cdecl IsSingleWindow() X11DRV_IsSingleWindow
 @ cdecl AcquireClipboard() X11DRV_AcquireClipboard
 @ cdecl ReleaseClipboard() X11DRV_ReleaseClipboard
 @ cdecl SetClipboardData(long) X11DRV_SetClipboardData
diff --git a/dlls/x11drv/x11drv_main.c b/dlls/x11drv/x11drv_main.c
index a788543..50b0ac2 100644
--- a/dlls/x11drv/x11drv_main.c
+++ b/dlls/x11drv/x11drv_main.c
@@ -33,6 +33,7 @@
 
 #include "debugtools.h"
 #include "gdi.h"
+#include "file.h"
 #include "options.h"
 #include "user.h"
 #include "win.h"
@@ -48,7 +49,6 @@
 
 static CRITICAL_SECTION X11DRV_CritSection = CRITICAL_SECTION_INIT;
 
-Display *display;
 Screen *screen;
 Visual *visual;
 unsigned int screen_width;
@@ -61,6 +61,7 @@
 
 static BOOL synchronous;  /* run in synchronous mode? */
 static char *desktop_geometry;
+static XVisualInfo *desktop_vi;
 
 #ifdef NO_REENTRANT_X11
 static int* (*old_errno_location)(void);
@@ -232,9 +233,8 @@
  * window (if it exists).  If OpenGL isn't available, the visual is simply 
  * set to the default visual for the display
  */
-XVisualInfo *desktop_vi = NULL;
 #ifdef HAVE_OPENGL
-static void setup_opengl_visual( void )
+static void setup_opengl_visual( Display *display )
 {
     int err_base, evt_base;
 
@@ -257,88 +257,13 @@
 #endif /* HAVE_OPENGL */    
 
 /***********************************************************************
- *		create_desktop
- *
- * Create the desktop window for the --desktop mode.
- */
-static void create_desktop( const char *geometry )
-{
-    int x = 0, y = 0, flags;
-    unsigned int width = 640, height = 480;  /* Default size = 640x480 */
-    char *name = "Wine desktop";
-    XSizeHints *size_hints;
-    XWMHints   *wm_hints;
-    XClassHint *class_hints;
-    XSetWindowAttributes win_attr;
-    XTextProperty window_name;
-    Atom XA_WM_DELETE_WINDOW;
-
-    flags = TSXParseGeometry( geometry, &x, &y, &width, &height );
-    screen_width  = width;
-    screen_height = height;
-
-    /* Create window */
-    win_attr.background_pixel = BlackPixel(display, 0);
-    win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
-                          PointerMotionMask | ButtonPressMask |
-                          ButtonReleaseMask | EnterWindowMask;
-    win_attr.cursor = TSXCreateFontCursor( display, XC_top_left_arrow );
-
-    if (desktop_vi != NULL) {
-      win_attr.colormap = XCreateColormap(display, RootWindow(display,desktop_vi->screen),
-						desktop_vi->visual, AllocNone);
-    }
-    root_window = TSXCreateWindow( display,
-                                   (desktop_vi == NULL ? DefaultRootWindow(display) : RootWindow(display, desktop_vi->screen)),
-                                   x, y, width, height, 0,
-                                   (desktop_vi == NULL ? CopyFromParent : desktop_vi->depth),
-                                   InputOutput,
-                                   (desktop_vi == NULL ? CopyFromParent : desktop_vi->visual),
-                                   CWBackPixel | CWEventMask | CWCursor | (desktop_vi == NULL ? 0 : CWColormap),
-                                   &win_attr );
-  
-    /* Set window manager properties */
-    size_hints  = TSXAllocSizeHints();
-    wm_hints    = TSXAllocWMHints();
-    class_hints = TSXAllocClassHint();
-    if (!size_hints || !wm_hints || !class_hints)
-    {
-        MESSAGE("Not enough memory for window manager hints.\n" );
-        ExitProcess(1);
-    }
-    size_hints->min_width = size_hints->max_width = width;
-    size_hints->min_height = size_hints->max_height = height;
-    size_hints->flags = PMinSize | PMaxSize;
-    if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
-    if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
-    else size_hints->flags |= PSize;
-
-    wm_hints->flags = InputHint | StateHint;
-    wm_hints->input = True;
-    wm_hints->initial_state = NormalState;
-    class_hints->res_name  = "wine";
-    class_hints->res_class = "Wine";
-
-    TSXStringListToTextProperty( &name, 1, &window_name );
-    TSXSetWMProperties( display, root_window, &window_name, &window_name,
-                        NULL, 0, size_hints, wm_hints, class_hints );
-    XA_WM_DELETE_WINDOW = TSXInternAtom( display, "WM_DELETE_WINDOW", False );
-    TSXSetWMProtocols( display, root_window, &XA_WM_DELETE_WINDOW, 1 );
-    TSXFree( size_hints );
-    TSXFree( wm_hints );
-    TSXFree( class_hints );
-
-    /* Map window */
-    TSXMapWindow( display, root_window );
-}
-
-
-/***********************************************************************
  *           X11DRV process initialisation routine
  */
 static void process_attach(void)
 {
-    WND_Driver       = &X11DRV_WND_Driver;
+    Display *display;
+
+    WND_Driver = &X11DRV_WND_Driver;
 
     get_server_startup();
     setup_options();
@@ -386,7 +311,7 @@
 
     /* If OpenGL is available, change the default visual, etc as necessary */
 #ifdef HAVE_OPENGL
-    setup_opengl_visual();
+    setup_opengl_visual( display );
 #endif /* HAVE_OPENGL */
 
     /* tell the libX11 that we will do input method handling ourselves
@@ -409,7 +334,7 @@
     if (desktop_geometry)
     {
         Options.managed = FALSE;
-        create_desktop( desktop_geometry );
+        root_window = X11DRV_create_desktop( desktop_vi, desktop_geometry );
     }
 
     /* initialize GDI */
@@ -419,9 +344,6 @@
         ExitProcess(1);
     }
 
-    /* initialize event handling */
-    X11DRV_EVENT_Init();
-
 #ifdef HAVE_LIBXXF86VM
     /* initialize XVidMode */
     X11DRV_XF86VM_Init();
@@ -441,6 +363,24 @@
 
 
 /***********************************************************************
+ *           X11DRV thread termination routine
+ */
+static void thread_detach(void)
+{
+    struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
+
+    if (data)
+    {
+        CloseHandle( data->display_fd );
+        wine_tsx11_lock();
+        XCloseDisplay( data->display );
+        wine_tsx11_unlock();
+        HeapFree( GetProcessHeap(), 0, data );
+    }
+}
+
+
+/***********************************************************************
  *           X11DRV process termination routine
  */
 static void process_detach(void)
@@ -458,12 +398,11 @@
     X11DRV_XF86VM_Cleanup();
 #endif
 
-    /* cleanup event handling */
-    X11DRV_EVENT_Cleanup();
+    /* FIXME: should detach all threads */
+    thread_detach();
 
     /* cleanup GDI */
     X11DRV_GDI_Finalize();
-    display = NULL;
 
     /* restore TSX11 locking */
     wine_tsx11_lock = old_tsx11_lock;
@@ -477,6 +416,36 @@
 
 
 /***********************************************************************
+ *           X11DRV thread initialisation routine
+ */
+struct x11drv_thread_data *x11drv_init_thread_data(void)
+{
+    struct x11drv_thread_data *data;
+
+    if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) )))
+    {
+        ERR( "could not create data\n" );
+        ExitProcess(1);
+    }
+    wine_tsx11_lock();
+    if (!(data->display = XOpenDisplay(NULL)))
+    {
+        wine_tsx11_unlock();
+        MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
+        ExitProcess(1);
+    }
+    fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
+    if (synchronous) XSynchronize( data->display, True );
+    wine_tsx11_unlock();
+    data->display_fd = FILE_DupUnixHandle( ConnectionNumber(data->display),
+                                           GENERIC_READ | SYNCHRONIZE );
+    data->process_event_count = 0;
+    NtCurrentTeb()->driver_data = data;
+    return data;
+}
+
+
+/***********************************************************************
  *           X11DRV initialisation routine
  */
 BOOL WINAPI X11DRV_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
@@ -486,6 +455,9 @@
     case DLL_PROCESS_ATTACH:
         process_attach();
         break;
+    case DLL_THREAD_DETACH:
+        thread_detach();
+        break;
     case DLL_PROCESS_DETACH:
         process_detach();
         break;
@@ -542,11 +514,3 @@
     if (nTimeout>32767) nTimeout = 32767;
     TSXSetScreenSaver(gdi_display, nTimeout, 60, DefaultBlanking, DefaultExposures);
 }
-
-/***********************************************************************
- *              X11DRV_IsSingleWindow
- */
-BOOL X11DRV_IsSingleWindow(void)
-{
-    return (root_window != DefaultRootWindow(gdi_display));
-}
diff --git a/include/thread.h b/include/thread.h
index 264c2fb..6f46457 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -101,10 +101,11 @@
     void        *debug_info;     /* --3 21c Info for debugstr functions */
     void        *pthread_data;   /* --3 220 Data for pthread emulation */
     struct async_private *pending_list;   /* --3 224 list of pending async operations */
+    void        *driver_data;    /* --3 228 Graphics driver private data */
     /* here is plenty space for wine specific fields (don't forget to change pad6!!) */
 
     /* the following are nt specific fields */
-    DWORD        pad6[628];                  /* --n 228 */
+    DWORD        pad6[627];                  /* --n 22c */
     UNICODE_STRING StaticUnicodeString;      /* -2- bf8 used by advapi32 */
     USHORT       StaticUnicodeBuffer[261];   /* -2- c00 used by advapi32 */
     DWORD        pad7;                       /* --n e0c */
diff --git a/include/user.h b/include/user.h
index 6837989..8e1b92e 100644
--- a/include/user.h
+++ b/include/user.h
@@ -38,8 +38,6 @@
 struct tagWND;
 
 typedef struct tagUSER_DRIVER {
-    /* event functions */
-    void   (*pUserRepaintDisable)(BOOL);
     /* keyboard functions */
     void   (*pInitKeyboard)(void);
     WORD   (*pVkKeyScan)(CHAR);
@@ -75,6 +73,7 @@
     BOOL   (*pDestroyWindow)(HWND);
     BOOL   (*pGetDC)(HWND,HDC,HRGN,DWORD);
     BOOL   (*pEnableWindow)(HWND,BOOL);
+    DWORD  (*pMsgWaitForMultipleObjects)(DWORD,HANDLE*,BOOL,DWORD);
     INT    (*pScrollWindowEx)(HWND,INT,INT,const RECT*,const RECT*,HRGN,LPRECT,UINT);
     void   (*pSetFocus)(HWND);
     HWND   (*pSetParent)(HWND,HWND);
@@ -83,7 +82,6 @@
     HICON  (*pSetWindowIcon)(HWND,HICON,BOOL);
     BOOL   (*pSetWindowText)(HWND,LPCWSTR);
     void   (*pSysCommandSizeMove)(HWND,WPARAM);
-    BOOL   (*pIsSingleWindow)(void);
 } USER_DRIVER;
 
 extern USER_DRIVER USER_Driver;
diff --git a/include/x11drv.h b/include/x11drv.h
index 0006cef..ea8c479 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -19,12 +19,11 @@
 #include "winbase.h"
 #include "gdi.h"
 #include "user.h"
+#include "thread.h"
 
 #define MAX_PIXELFORMATS 8
 
 struct tagBITMAPOBJ;
-struct tagCLASS;
-struct tagCREATESTRUCTA;
 struct tagCURSORICONINFO;
 struct tagDC;
 struct tagDeviceCaps;
@@ -304,18 +303,32 @@
  * X11 USER driver
  */
 
-extern Display *display;
-extern Screen *screen;
+struct x11drv_thread_data
+{
+    Display *display;
+    HANDLE   display_fd;
+    int      process_event_count;
+};
+
+extern struct x11drv_thread_data *x11drv_init_thread_data(void);
+
+inline static struct x11drv_thread_data *x11drv_thread_data(void)
+{
+    struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
+    if (!data) data = x11drv_init_thread_data();
+    return data;
+}
+
+inline static Display *thread_display(void) { return x11drv_thread_data()->display; }
+
 extern Visual *visual;
 extern Window root_window;
 extern unsigned int screen_width;
 extern unsigned int screen_height;
 extern unsigned int screen_depth;
 
-static inline Screen *X11DRV_GetXScreen(void)    { return screen; }
 static inline Visual *X11DRV_GetVisual(void)     { return visual; }
 static inline Window X11DRV_GetXRootWindow(void) { return root_window; }
-static inline unsigned int X11DRV_GetDepth(void) { return screen_depth; }
 
 /* X11 clipboard driver */
 
@@ -332,8 +345,6 @@
 
 extern WORD X11DRV_EVENT_XStateToKeyState( int state ) ;
 
-extern void X11DRV_EVENT_Init(void);
-extern void X11DRV_EVENT_Cleanup(void);
 extern void X11DRV_Synchronize( void );
 
 typedef enum {
@@ -388,5 +399,10 @@
 extern BOOL X11DRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
 
 extern void X11DRV_SetFocus( HWND hwnd );
+extern Cursor X11DRV_GetCursor( Display *display, struct tagCURSORICONINFO *ptr );
+
+extern void X11DRV_register_window( Display *display, HWND hwnd, Window win );
+extern void X11DRV_create_desktop_thread(void);
+extern Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry );
 
 #endif  /* __WINE_X11DRV_H */
diff --git a/windows/message.c b/windows/message.c
index 5a22e67..5648db3 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -22,6 +22,7 @@
 #include "dde.h"
 #include "queue.h"
 #include "winproc.h"
+#include "user.h"
 #include "thread.h"
 #include "options.h"
 #include "controls.h"
@@ -147,7 +148,7 @@
         
 	/* stop if not the right queue */
 
-    if (pWnd->hmemTaskQ != hQ)
+    if (pWnd->hmemTaskQ && pWnd->hmemTaskQ != hQ)
     {
         /* Not for the current task */
         if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
@@ -377,7 +378,7 @@
     if ( !hWnd ) return SYSQ_MSG_ABANDON;
     pWnd = WIN_FindWndPtr( hWnd );
 
-    if (pWnd && (pWnd->hmemTaskQ != GetFastQueue16()))
+    if (pWnd && pWnd->hmemTaskQ && (pWnd->hmemTaskQ != GetFastQueue16()))
     {
         /* Not for the current task */
         MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
@@ -1252,6 +1253,10 @@
 #if 0  /* FIXME */
             if (!(flags & PM_NOYIELD)) UserYield16();
 #endif
+            /* check for graphics events */
+            if (USER_Driver.pMsgWaitForMultipleObjects)
+                USER_Driver.pMsgWaitForMultipleObjects( 0, NULL, FALSE, 0 );
+
             QUEUE_Unlock( msgQueue );
             WIN_RestoreWndsLock(iWndsLocks);
             return FALSE;
@@ -1860,7 +1865,7 @@
     else
         SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
 
-    if (wndPtr->hmemTaskQ != GetFastQueue16())
+    if (wndPtr->hmemTaskQ && wndPtr->hmemTaskQ != GetFastQueue16())
         ret = MSG_SendMessageInterThread( wndPtr->hmemTaskQ, hwnd, msg,
                                           wParam, lParam, timeout, flags, pRes );
     else
@@ -2064,7 +2069,13 @@
     /* Add the thread event to the handle list */
     for (i = 0; i < nCount; i++) handles[i] = pHandles[i];
     handles[nCount] = msgQueue->server_queue;
-    ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
+    if (USER_Driver.pMsgWaitForMultipleObjects)
+    {
+        ret = USER_Driver.pMsgWaitForMultipleObjects(nCount+1, handles, fWaitAll, dwMilliseconds);
+        if (ret == nCount+1) ret = nCount; /* pretend the msg queue is ready */
+    }
+    else
+        ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
 
     QUEUE_Unlock( msgQueue );
     return ret;
diff --git a/windows/queue.c b/windows/queue.c
index 14a55ce..b66c53b 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -13,6 +13,7 @@
 #include "wine/winuser16.h"
 #include "queue.h"
 #include "win.h"
+#include "user.h"
 #include "hook.h"
 #include "thread.h"
 #include "debugtools.h"
@@ -731,12 +732,16 @@
         }
 
         queue->wakeMask = bits | QS_SENDMESSAGE;
-	TRACE_(msg)("%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
+        TRACE_(msg)("%04x: wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
         LeaveCriticalSection( &queue->cSection );
 
         ReleaseThunkLock( &dwlc );
         if (dwlc) TRACE_(msg)("had win16 lock\n");
-        WaitForSingleObject( queue->server_queue, timeout );
+
+        if (USER_Driver.pMsgWaitForMultipleObjects)
+            USER_Driver.pMsgWaitForMultipleObjects( 1, &queue->server_queue, FALSE, timeout );
+        else
+            WaitForSingleObject( queue->server_queue, timeout );
         if (dwlc) RestoreThunkLock( dwlc );
     }
 }
@@ -1095,6 +1100,7 @@
 }
 
 
+#if 0
 /***********************************************************************
  *           QUEUE_WakeSomeone
  *
@@ -1161,6 +1167,7 @@
 
     WARN_(msg)("couldn't find queue\n"); 
 }
+#endif
 
 
 /***********************************************************************
@@ -1174,6 +1181,7 @@
 {
     MSG *msg;
     QMSG  *qmsg;
+    MESSAGEQUEUE *queue;
     int  mergeMsg = 0;
 
     if (!sysMsgQueue) return;
@@ -1237,10 +1245,19 @@
 
     LeaveCriticalSection( &sysMsgQueue->cSection );
 
-    QUEUE_WakeSomeone( message );
+    if ((queue = QUEUE_Lock( GetFastQueue16() )))
+    {
+        WORD wakeBit;
+
+        if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) wakeBit = QS_KEY;
+        else wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+
+        QUEUE_SetWakeBit( queue, wakeBit );
+        QUEUE_Unlock( queue );
+    }
 }
 
-		    
+
 /***********************************************************************
  *	     QUEUE_GetQueueTask
  */
diff --git a/windows/user.c b/windows/user.c
index f012e91..7dba9ae 100644
--- a/windows/user.c
+++ b/windows/user.c
@@ -13,7 +13,6 @@
 #include "winuser.h"
 #include "heap.h"
 #include "user.h"
-#include "task.h"
 #include "queue.h"
 #include "win.h"
 #include "controls.h"
@@ -101,56 +100,6 @@
     CURSORICON_FreeModuleIcons( hModule );
 }
 
-/**********************************************************************
- *           USER_QueueCleanup
- */
-static void USER_QueueCleanup( HQUEUE16 hQueue )
-{
-    if ( hQueue )
-    {
-        WND* desktop = WIN_GetDesktop();
-
-        /* Patch desktop window */
-        if ( desktop->hmemTaskQ == hQueue )
-        {
-            HTASK16 nextTask = TASK_GetNextTask( GetCurrentTask() );
-            desktop->hmemTaskQ = GetTaskQueue16( nextTask );
-        }
-
-        TIMER_RemoveQueueTimers( hQueue );
-
-        HOOK_FreeQueueHooks( hQueue );
-
-        QUEUE_SetExitingQueue( hQueue );
-        WIN_ResetQueueWindows( desktop, hQueue, (HQUEUE16)0);
-        QUEUE_SetExitingQueue( 0 );
-
-        /* Free the message queue */
-        QUEUE_DeleteMsgQueue( hQueue );
-
-        WIN_ReleaseDesktop();
-    }
-}
-
-/**********************************************************************
- *           USER_AppExit
- */
-static void USER_AppExit(void)
-{
-    HINSTANCE16 hInstance = MapHModuleLS(0);
-
-    /* FIXME: maybe destroy menus (Windows only complains about them
-     * but does nothing);
-     */
-
-    /* ModuleUnload() in "Internals" */
-
-    hInstance = GetExePtr( hInstance );
-    if( GetModuleUsage16( hInstance ) <= 1 ) 
-	USER_ModuleUnload( hInstance );
-}
-
-
 /***********************************************************************
  *		SignalProc (USER.314)
  */
@@ -190,34 +139,16 @@
         break;
 
     case USIG_DLL_UNLOAD_ORPHANS:
-        break;
-
     case USIG_FAULT_DIALOG_PUSH:
     case USIG_FAULT_DIALOG_POP:
-        break;
-
     case USIG_THREAD_INIT:
-        break;
-
     case USIG_THREAD_EXIT:
-        USER_QueueCleanup( GetThreadQueue16( dwThreadOrProcessID ) );
-        SetThreadQueue16( dwThreadOrProcessID, 0 );
-        break;
-
     case USIG_PROCESS_CREATE:
-      break;
-
     case USIG_PROCESS_INIT:
     case USIG_PROCESS_LOADED:
-      break;
     case USIG_PROCESS_RUNNING:
-        break;
-
     case USIG_PROCESS_EXIT:
-        break;
-
     case USIG_PROCESS_DESTROY:
-      USER_AppExit();
       break;
 
     default:
diff --git a/windows/win.c b/windows/win.c
index f16ff60..a31f756 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -359,6 +359,7 @@
      * The real reason why is because Windows DesktopWndProc
      * does ValidateRgn inside WM_ERASEBKGND handler.
      */
+    if (hwnd == GetDesktopWindow()) hwnd = 0;
 
     pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
 
@@ -601,7 +602,7 @@
     pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
     pWndDesktop->rectClient        = pWndDesktop->rectWindow;
     pWndDesktop->text              = NULL;
-    pWndDesktop->hmemTaskQ         = GetFastQueue16();
+    pWndDesktop->hmemTaskQ         = 0;
     pWndDesktop->hrgnUpdate        = 0;
     pWndDesktop->hwndLastActive    = hwndDesktop;
     pWndDesktop->dwStyle           = WS_VISIBLE | WS_CLIPCHILDREN |
diff --git a/windows/winpos.c b/windows/winpos.c
index ce533d1..500391b 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -1987,13 +1987,7 @@
 
   bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
 
-  /* switch desktop queue to current active */
-  if( pWndTo )
-  {
-      WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
-      WIN_ReleaseWndPtr(pWndTo);
-      WIN_ReleaseDesktop();
-  }
+  if( pWndTo ) WIN_ReleaseWndPtr(pWndTo);
 
   hwndPrevActive = 0;
   return bRet;  
@@ -2005,7 +1999,7 @@
  */
 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
 {
-    WND *wndPtr, *wndTemp;
+    WND *wndPtr;
     BOOL retvalue;
     HWND hwndActive = 0;
 
@@ -2045,12 +2039,6 @@
         goto end;
     }
 
-    /* switch desktop queue to current active */
-    wndTemp = WIN_GetDesktop();
-    if( wndPtr->parent == wndTemp)
-        wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
-    WIN_ReleaseDesktop();
-
     retvalue = TRUE;
 end:
     WIN_ReleaseWndPtr(wndPtr);
diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c
index aece6ca..b0b7f13 100644
--- a/windows/x11drv/clipboard.c
+++ b/windows/x11drv/clipboard.c
@@ -176,7 +176,7 @@
             if (fmtName)
             {
                 strncat(str, fmtName, sizeof(str) - strlen(FMT_PREFIX));
-                prop = TSXInternAtom(display, str, False);
+                prop = TSXInternAtom(thread_display(), str, False);
             }
             break;
         }
@@ -196,7 +196,7 @@
  */
 BOOL X11DRV_CLIPBOARD_IsNativeProperty(Atom prop)
 {
-    char *itemFmtName = TSXGetAtomName(display, prop);
+    char *itemFmtName = TSXGetAtomName(thread_display(), prop);
     BOOL bRet = FALSE;
     
     if ( 0 == strncmp(itemFmtName, FMT_PREFIX, strlen(FMT_PREFIX)) )
@@ -217,6 +217,7 @@
 BOOL X11DRV_CLIPBOARD_LaunchServer()
 {
     int iWndsLocks;
+    char clearSelection[8];
 
     /* If persistant selection has been disabled in the .winerc Clipboard section,
      * don't launch the server
@@ -224,6 +225,9 @@
     if ( !PROFILE_GetWineIniInt("Clipboard", "PersistentSelection", 1) )
         return FALSE;
 
+    /* Get the clear selection preference */
+    sprintf(clearSelection, "%d", PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0));
+
     /*  Start up persistant WINE X clipboard server process which will
      *  take ownership of the X selection and continue to service selection
      *  requests from other apps.
@@ -234,16 +238,8 @@
         /* NOTE: This code only executes in the context of the child process
          * Do note make any Wine specific calls here.
          */
-        
         int dbgClasses = 0;
-        char selMask[8], dbgClassMask[8], clearSelection[8];
-	int i;
-
-	/* Don't inherit wine's X sockets to the wineclipsrv, otherwise
-	 * windows stay around when you have to kill a hanging wine...
-	 */
-	for (i = 3; i < 256; ++i)
-		fcntl(i, F_SETFD, 1);
+        char selMask[8], dbgClassMask[8];
 
         sprintf(selMask, "%d", selectionAcquired);
 
@@ -256,10 +252,6 @@
         dbgClasses |= TRACE_ON(clipboard) ? 8 : 0;
         sprintf(dbgClassMask, "%d", dbgClasses);
 
-        /* Get the clear selection preference */
-        sprintf(clearSelection, "%d",
-                PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0));
-
         /* Exec the clipboard server passing it the selection and debug class masks */
         execl( BINDIR "/wineclipsrv", "wineclipsrv",
                selMask, dbgClassMask, clearSelection, NULL );
@@ -295,7 +287,7 @@
 
         TRACE("Waiting for clipboard server to acquire selection\n");
 
-        if ( WaitForSingleObject( selectionClearEvent, 60000 ) != WAIT_OBJECT_0 )
+        if ( MsgWaitForMultipleObjects( 1, &selectionClearEvent, FALSE, 60000, QS_ALLINPUT ) != WAIT_OBJECT_0 )
             TRACE("Server could not acquire selection, or a timeout occurred!\n");
         else
             TRACE("Server successfully acquired selection\n");
@@ -320,6 +312,7 @@
  */
 int X11DRV_CLIPBOARD_CacheDataFormats( Atom SelectionName )
 {
+    Display *display = thread_display();
     HWND           hWnd = 0;
     HWND           hWndClipWindow = GetOpenClipboardWindow();
     WND*           wnd = NULL;
@@ -458,6 +451,7 @@
  */
 static BOOL X11DRV_CLIPBOARD_ReadSelection(UINT wFormat, Window w, Atom prop, Atom reqType)
 {
+    Display *display = thread_display();
     Atom	      atype=AnyPropertyType;
     int		      aformat;
     unsigned long     total,nitems,remain,itemSize,val_cnt;
@@ -685,6 +679,7 @@
  */
 void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
 {
+    Display *display = thread_display();
     Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
     int clearAllSelections = PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0);
     
@@ -797,6 +792,7 @@
  */
 void X11DRV_ReleaseClipboard(void)
 {
+    Display *display = thread_display();
     if( selectionAcquired )
     {
 	XEvent xe;
@@ -847,6 +843,7 @@
  */
 void X11DRV_AcquireClipboard(void)
 {
+    Display *display = thread_display();
     Window       owner;
     HWND         hWndClipWindow = GetOpenClipboardWindow();
 
@@ -900,6 +897,7 @@
  */
 BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
 {
+    Display *display = thread_display();
     Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
     Window ownerPrimary = TSXGetSelectionOwner(display,XA_PRIMARY);
     Window ownerClipboard = TSXGetSelectionOwner(display,xaClipboard);
@@ -957,6 +955,7 @@
  */
 BOOL X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
 {
+    Display *display = thread_display();
     Atom prop = None;
     char str[256];
     
@@ -1009,6 +1008,7 @@
  */
 BOOL X11DRV_GetClipboardData(UINT wFormat)
 {
+    Display *display = thread_display();
     BOOL bRet = selectionAcquired;
     HWND hWndClipWindow = GetOpenClipboardWindow();
     HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
@@ -1087,6 +1087,7 @@
  */
 void X11DRV_ResetSelectionOwner(WND *pWnd, BOOL bFooBar)
 {
+    Display *display = thread_display();
     HWND hWndClipOwner = 0;
     Window XWnd = X11DRV_WND_GetXWindow(pWnd);
     Atom xaClipboard;
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
index ef1c597..743f894 100644
--- a/windows/x11drv/event.c
+++ b/windows/x11drv/event.c
@@ -34,7 +34,6 @@
 #include "queue.h"
 #include "win.h"
 #include "winpos.h"
-#include "services.h"
 #include "file.h"
 #include "windef.h"
 #include "x11drv.h"
@@ -87,8 +86,6 @@
 };
 
 
-static void CALLBACK EVENT_Flush( ULONG_PTR arg );
-static void CALLBACK EVENT_ProcessAllEvents( ULONG_PTR arg );
 static void EVENT_ProcessEvent( XEvent *event );
 static BOOL X11DRV_CheckFocus(void);
 
@@ -129,60 +126,21 @@
 static void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event );
 */
 
-static void EVENT_GetGeometry( Window win, int *px, int *py,
+static void EVENT_GetGeometry( Display *display, Window win, int *px, int *py,
                                unsigned int *pwidth, unsigned int *pheight );
 
 
-static BOOL bUserRepaintDisabled = TRUE;
-
 /* Static used for the current input method */
 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
 static BOOL in_transition = FALSE; /* This is not used as for today */
 
-static HANDLE service_object, service_timer;
 
 /***********************************************************************
- *           EVENT_Init
+ *           process_events
  */
-void X11DRV_EVENT_Init(void)
-{
-    /* Install the X event processing callback */
-    if ((service_object = SERVICE_AddObject( FILE_DupUnixHandle( ConnectionNumber(display), GENERIC_READ|SYNCHRONIZE ),
-                           EVENT_ProcessAllEvents, 0 )) == INVALID_HANDLE_VALUE)
-    {
-        ERR("cannot add service object\n");
-        ExitProcess(1);
-    }
-
-    /* Install the XFlush timer callback */
-    service_timer = SERVICE_AddTimer( 200, EVENT_Flush, 0 );
-}
-
-/***********************************************************************
- *           X11DRV_EVENT_Cleanup
- */
-void X11DRV_EVENT_Cleanup(void)
-{
-    SERVICE_Delete( service_timer );
-    SERVICE_Delete( service_object );
-}
-
-/***********************************************************************
- *           EVENT_Flush
- */
-static void CALLBACK EVENT_Flush( ULONG_PTR arg )
-{
-    TSXFlush( display );
-}
-
-/***********************************************************************
- *           EVENT_ProcessAllEvents
- */
-static void CALLBACK EVENT_ProcessAllEvents( ULONG_PTR arg )
+static void process_events( Display *display )
 {
     XEvent event;
-  
-    TRACE( "called (thread %lx).\n", GetCurrentThreadId() );
 
     wine_tsx11_lock();
     while ( XPending( display ) )
@@ -196,24 +154,46 @@
 }
 
 /***********************************************************************
- *		Synchronize (X11DRV.@)
+ *		X11DRV_Synchronize
  *
  * Synchronize with the X server. Should not be used too often.
  */
 void X11DRV_Synchronize( void )
 {
+    Display *display = thread_display();
     TSXSync( display, False );
-    EVENT_ProcessAllEvents( 0 );
+    process_events( display );
 }
 
+
 /***********************************************************************
- *		UserRepaintDisable (X11DRV.@)
+ *           MsgWaitForMultipleObjects   (X11DRV.@)
  */
-void X11DRV_UserRepaintDisable( BOOL bDisabled )
+DWORD X11DRV_MsgWaitForMultipleObjects( DWORD count, HANDLE *handles,
+                                        BOOL wait_all, DWORD timeout )
 {
-    bUserRepaintDisabled = bDisabled;
+    HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1];  /* FIXME! */
+    DWORD i, ret;
+    struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
+
+    if (!data || data->process_event_count)
+        return WaitForMultipleObjects( count, handles, wait_all, timeout );
+
+    for (i = 0; i < count; i++) new_handles[i] = handles[i];
+    new_handles[count] = data->display_fd;
+
+    data->process_event_count++;
+    wine_tsx11_lock();
+    XFlush( gdi_display );
+    XFlush( data->display );
+    wine_tsx11_unlock();
+    ret = WaitForMultipleObjects( count+1, new_handles, wait_all, timeout );
+    if (ret == count) process_events( data->display );
+    data->process_event_count--;
+    return ret;
 }
 
+
 /***********************************************************************
  *           EVENT_ProcessEvent
  *
@@ -222,6 +202,7 @@
 static void EVENT_ProcessEvent( XEvent *event )
 {
   HWND hWnd;
+  Display *display = event->xany.display;
 
   TRACE( "called.\n" );
 
@@ -302,7 +283,7 @@
       Window   	root, child;
       int      	root_x, root_y, child_x, child_y;
       unsigned	u;
-      TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
+      TSXQueryPointer( display, root_window, &root, &child,
 		       &root_x, &root_y, &child_x, &child_y, &u);
       if (TSXFindContext( display, child, winContext, (char **)&hWnd ) != 0)
 	return;
@@ -311,7 +292,7 @@
     }
   }
 
-  if ( !hWnd && event->xany.window != X11DRV_GetXRootWindow()
+  if ( !hWnd && event->xany.window != root_window
              && event->type != PropertyNotify 
              && event->type != MappingNotify)
       ERR("Got event %s for unknown Window %08lx\n",
@@ -359,7 +340,7 @@
       BOOL bIsDisabled;
       XFocusChangeEvent *xfocChange = (XFocusChangeEvent*)event;
 
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
 
       bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
 
@@ -393,34 +374,32 @@
       /* Save the last window which had the focus */
       XFocusChangeEvent *xfocChange = (XFocusChangeEvent*)event;
       glastXFocusWin = xfocChange->window;
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
       EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
       break;
     }
       
     case Expose:
-      if (bUserRepaintDisabled) return;
       EVENT_Expose( hWnd, (XExposeEvent *)event );
       break;
       
     case GraphicsExpose:
-      if (bUserRepaintDisabled) return;
       EVENT_GraphicsExpose( hWnd, (XGraphicsExposeEvent *)event );
       break;
       
     case ConfigureNotify:
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       EVENT_ConfigureNotify( hWnd, (XConfigureEvent*)event );
       break;
 
     case SelectionRequest:
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
       break;
 
     case SelectionClear:
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
       break;
       
@@ -429,7 +408,7 @@
       break;
 
     case ClientMessage:
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
       break;
 
@@ -443,12 +422,12 @@
       break;
       
     case MapNotify:
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       EVENT_MapNotify( hWnd, (XMapEvent *)event );
       break;
 
     case UnmapNotify:
-      if (!hWnd || bUserRepaintDisabled) return;
+      if (!hWnd) return;
       EVENT_UnmapNotify( hWnd, (XUnmapEvent *)event );
       break;
 
@@ -483,7 +462,7 @@
   return ((*pWndB) != NULL);
 }
 
-static Window __get_common_ancestor( Window A, Window B,
+static Window __get_common_ancestor( Display *display, Window A, Window B,
                                      Window** children, unsigned* total )
 {
     /* find the real root window */
@@ -507,7 +486,7 @@
     return 0 ;
 }
 
-static Window __get_top_decoration( Window w, Window ancestor )
+static Window __get_top_decoration( Display *display, Window w, Window ancestor )
 {
   Window*     children, root, prev = w, parent = w;
   unsigned    total;
@@ -529,7 +508,7 @@
   return i;
 }
 
-static HWND EVENT_QueryZOrder( HWND hWndCheck)
+static HWND EVENT_QueryZOrder( Display *display, HWND hWndCheck)
 {
   HWND      hwndInsertAfter = HWND_TOP;
   WND      *pWndCheck = WIN_FindWndPtr(hWndCheck);
@@ -550,14 +529,14 @@
   WIN_ReleaseWndPtr(pDesktop->child);
   WIN_ReleaseDesktop();
   
-  parent = __get_common_ancestor( X11DRV_WND_GetXWindow(pWndZ), 
+  parent = __get_common_ancestor( display, X11DRV_WND_GetXWindow(pWndZ),
 				  X11DRV_WND_GetXWindow(pWnd),
 				  &children, &total );
   if( parent && children )
   {
       /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
 
-      w = __get_top_decoration( X11DRV_WND_GetXWindow(pWndCheck), parent );
+      w = __get_top_decoration( display, X11DRV_WND_GetXWindow(pWndCheck), parent );
 
       if( w != children[total-1] ) /* check if at the top */
       {
@@ -572,7 +551,7 @@
 	      if( pWnd != pWndCheck )
               {
 		  if( !(pWnd->dwExStyle & WS_EX_MANAGED) ||
-		      !(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) )
+		      !(w = __get_top_decoration( display, X11DRV_WND_GetXWindow(pWnd), parent )) )
 		    continue;
 		  pos = __td_lookup( w, children, total );
 		  if( pos < best && pos > check )
@@ -856,6 +835,7 @@
  */
 static BOOL X11DRV_CheckFocus(void)
 {
+    Display *display = thread_display();
   HWND   hWnd;
   Window xW;
   int	   state;
@@ -873,7 +853,7 @@
  * Helper function for ConfigureNotify handling.
  * Get the new geometry of a window relative to the root window.
  */
-static void EVENT_GetGeometry( Window win, int *px, int *py,
+static void EVENT_GetGeometry( Display *display, Window win, int *px, int *py,
                                unsigned int *pwidth, unsigned int *pheight )
 {
     Window root, top;
@@ -911,8 +891,8 @@
   
     /* Get geometry and Z-order according to X */
 
-    EVENT_GetGeometry( event->window, &x, &y, &width, &height );
-    newInsertAfter = EVENT_QueryZOrder( hWnd );
+    EVENT_GetGeometry( event->display, event->window, &x, &y, &width, &height );
+    newInsertAfter = EVENT_QueryZOrder( event->display, hWnd );
 
     /* Get geometry and Z-order according to Wine */
 
@@ -966,7 +946,8 @@
  *           EVENT_SelectionRequest_TARGETS
  *  Service a TARGETS selection request event
  */
-static Atom EVENT_SelectionRequest_TARGETS( Window requestor, Atom target, Atom rprop )
+static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
+                                            Atom target, Atom rprop )
 {
     Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
     Atom* targets;
@@ -1057,7 +1038,8 @@
  *           EVENT_SelectionRequest_STRING
  *  Service a STRING selection request event
  */
-static Atom EVENT_SelectionRequest_STRING( Window requestor, Atom target, Atom rprop )
+static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
+                                           Atom target, Atom rprop )
 {
     static UINT text_cp = (UINT)-1;
     HANDLE hUnicodeText;
@@ -1123,7 +1105,8 @@
  *           EVENT_SelectionRequest_PIXMAP
  *  Service a PIXMAP selection request event
  */
-static Atom EVENT_SelectionRequest_PIXMAP( Window requestor, Atom target, Atom rprop )
+static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
+                                           Atom target, Atom rprop )
 {
     HANDLE hClipData = 0;
     Pixmap pixmap = 0;
@@ -1222,7 +1205,8 @@
  *  Service a Wine Clipboard Format selection request event.
  *  For <WCF>* data types we simply copy the data to X without conversion.
  */
-static Atom EVENT_SelectionRequest_WCF( Window requestor, Atom target, Atom rprop )
+static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
+                                        Atom target, Atom rprop )
 {
     HANDLE hClipData = 0;
     void*  lpClipData;
@@ -1281,6 +1265,7 @@
  */
 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
 {
+    Display *display = pevent->display;
     Atom           rprop;
     Atom           atype=AnyPropertyType;
     int		   aformat;
@@ -1375,6 +1360,7 @@
  */
 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
 {
+    Display *display = event->display;
   XSelectionEvent result;
   Atom 	          rprop = None;
   Window          request = event->requestor;
@@ -1406,32 +1392,32 @@
   if(event->target == xaTargets)  /*  Return a list of all supported targets */
   {
       /* TARGETS selection request */
-      rprop = EVENT_SelectionRequest_TARGETS( request, event->target, rprop );
+      rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
   }
   else if(event->target == xaMultiple)  /*  rprop contains a list of (target, property) atom pairs */
   {
       /* MULTIPLE selection request */
-      rprop = EVENT_SelectionRequest_MULTIPLE(  hWnd, event );
+      rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
   }
   else if(event->target == XA_STRING)  /* treat CF_TEXT as Unix text */
   {
       /* XA_STRING selection request */
-      rprop = EVENT_SelectionRequest_STRING( request, event->target, rprop );
+      rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
   }
   else if(event->target == XA_PIXMAP)  /*  Convert DIB's to Pixmaps */
   {
       /* XA_PIXMAP selection request */
-      rprop = EVENT_SelectionRequest_PIXMAP( request, event->target, rprop );
+      rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
   }
   else if(event->target == XA_BITMAP)  /*  Convert DIB's to 1-bit Pixmaps */
   {
       /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
-      rprop = EVENT_SelectionRequest_PIXMAP( request, XA_PIXMAP, rprop );
+      rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
   }
   else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
   {
       /* All <WCF> selection requests */
-      rprop = EVENT_SelectionRequest_WCF( request, event->target, rprop );
+      rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
   }
   else
       rprop = None;  /* Don't support this format */
@@ -1465,7 +1451,7 @@
  */
 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
 {
-  Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
+  Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
     
   if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
       X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
@@ -1536,7 +1522,7 @@
   
   pWnd = WIN_FindWndPtr(hWnd);
   
-  TSXQueryPointer( display, X11DRV_WND_GetXWindow(pWnd), &w_aux_root, &w_aux_child, 
+  TSXQueryPointer( event->display, X11DRV_WND_GetXWindow(pWnd), &w_aux_root, &w_aux_child, 
                    &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
                    (unsigned int*)&aux_long);
   
@@ -1560,7 +1546,7 @@
   
   if( bAccept )
     {
-      TSXGetWindowProperty( display, DefaultRootWindow(display),
+      TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
 			    dndSelection, 0, 65535, FALSE,
 			    AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
 			    &data_length, &aux_long, &p_data);
@@ -1660,7 +1646,7 @@
   }
   WIN_ReleaseWndPtr(pWnd);
 
-  TSXGetWindowProperty( display, DefaultRootWindow(display),
+  TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
 			dndSelection, 0, 65535, FALSE,
 			AnyPropertyType, &u.atom_aux, &u.i,
 			&data_length, &aux_long, &p_data);
@@ -1688,7 +1674,7 @@
     }
     
     if( drop_len && drop_len < 65535 ) {
-      TSXQueryPointer( display, X11DRV_GetXRootWindow(), &u.w_aux, &u.w_aux, 
+      TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
 		       &x, &y, &u.i, &u.i, &u.i);
 
       pDropWnd = WIN_FindWndPtr( hWnd );
@@ -1780,7 +1766,7 @@
 	int            	i;
 	Atom		atom;
       } u; /* unused */
-      TSXGetWindowProperty( display, DefaultRootWindow(display),
+      TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
 			    dndSelection, 0, 65535, FALSE,
 			    AnyPropertyType, &u.atom, &u.i,
 			    &u.l, &u.l, &p_data);
@@ -1803,9 +1789,9 @@
 #if 0
 void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event )
 {
-  if( !Options.managed && X11DRV_GetXRootWindow() == DefaultRootWindow(display) &&
+  if( !Options.managed && root_window == DefaultRootWindow(event->display) &&
       (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus() )
-    TSXInstallColormap( display, X11DRV_PALETTE_GetColormap() );
+    TSXInstallColormap( event->display, X11DRV_PALETTE_GetColormap() );
 }
 #endif
 
diff --git a/windows/x11drv/keyboard.c b/windows/x11drv/keyboard.c
index 9bc5242..3fc1e1f 100644
--- a/windows/x11drv/keyboard.c
+++ b/windows/x11drv/keyboard.c
@@ -691,7 +691,7 @@
     char keys_return[32];
 
     TRACE("called\n");
-    if (!TSXQueryKeymap(display, keys_return)) {
+    if (!TSXQueryKeymap(thread_display(), keys_return)) {
         ERR("Error getting keymap !\n");
         return;
     }
@@ -839,6 +839,7 @@
 static void
 X11DRV_KEYBOARD_DetectLayout (void)
 {
+  Display *display = thread_display();
   unsigned current, match, mismatch, seq;
   int score, keyc, i, key, pkey, ok, syms;
   KeySym keysym;
@@ -937,6 +938,7 @@
 #ifdef HAVE_XKB
     int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
 #endif
+    Display *display = thread_display();
     KeySym *ksp;
     XModifierKeymap *mmp;
     KeySym keysym;
@@ -1164,6 +1166,7 @@
  */
 WORD X11DRV_VkKeyScan(CHAR cChar)
 {
+        Display *display = thread_display();
 	KeyCode keycode;
 	KeySym keysym;    	
 	int i,index;
@@ -1212,6 +1215,8 @@
  */
 UINT16 X11DRV_MapVirtualKey(UINT16 wCode, UINT16 wMapType)
 {
+    Display *display = thread_display();
+
 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
 
 	TRACE("MapVirtualKey wCode=0x%x wMapType=%d ... \n", wCode,wMapType);
@@ -1366,7 +1371,7 @@
          break;
   if (keyc <= max_keycode)
   {
-      keys = TSXKeycodeToKeysym(display, keyc, 0);
+      keys = TSXKeycodeToKeysym(thread_display(), keyc, 0);
       name = TSXKeysymToString(keys);
       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
             scanCode, keyc, (int)keys, name);
@@ -1484,6 +1489,7 @@
 INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
 		     LPWSTR bufW, int bufW_size, UINT flags)
 {
+    Display *display = thread_display();
     XKeyEvent e;
     KeySym keysym;
     INT ret;
@@ -1628,7 +1634,7 @@
  */
 void X11DRV_Beep(void)
 {
-  TSXBell(display, 0);
+  TSXBell(thread_display(), 0);
 }
 
 /***********************************************************************
diff --git a/windows/x11drv/mouse.c b/windows/x11drv/mouse.c
index 0c68c0b..255972a 100644
--- a/windows/x11drv/mouse.c
+++ b/windows/x11drv/mouse.c
@@ -20,15 +20,13 @@
 
 /**********************************************************************/
 
-Cursor X11DRV_MOUSE_XCursor = None;    /* Current X cursor */
-
 static LONG X11DRV_MOUSE_WarpPointer = 0;  /* hack; see DISPLAY_MoveCursor */
 static LPMOUSE_EVENT_PROC DefMouseEventProc = NULL;
 
 /***********************************************************************
- *		X11DRV_MOUSE_DoSetCursor
+ *		X11DRV_GetCursor
  */
-static BOOL X11DRV_MOUSE_DoSetCursor( CURSORICONINFO *ptr )
+Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
 {
     Pixmap pixmapBits, pixmapMask, pixmapMaskInv, pixmapAll;
     XColor fg, bg;
@@ -39,7 +37,7 @@
         static const char data[] = { 0 };
 
         bg.red = bg.green = bg.blue = 0x0000;
-        pixmapBits = XCreateBitmapFromData( display, X11DRV_GetXRootWindow(), data, 1, 1 );
+        pixmapBits = XCreateBitmapFromData( display, root_window, data, 1, 1 );
         if (pixmapBits)
         {
             cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
@@ -50,11 +48,12 @@
     else  /* Create the X cursor from the bits */
     {
         XImage *image;
+        GC gc;
 
         if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
         {
             WARN("Cursor has more than 1 bpp!\n" );
-            return FALSE;
+            return 0;
         }
 
         /* Create a pixmap and transfer all the bits to it */
@@ -64,36 +63,31 @@
          *       as the Windows cursor data). Perhaps use a more generic
          *       algorithm here.
          */
-        pixmapAll = XCreatePixmap( display, X11DRV_GetXRootWindow(),
-                                   ptr->nWidth, ptr->nHeight * 2, 1 );
-        image = XCreateImage( display, X11DRV_GetVisual(),
-                              1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
-                              ptr->nHeight * 2, 16, ptr->nWidthBytes);
-        if (image)
-        {
-            image->byte_order = MSBFirst;
-            image->bitmap_bit_order = MSBFirst;
-            image->bitmap_unit = 16;
-            _XInitImageFuncPtrs(image);
-            if (pixmapAll)
-                XPutImage( display, pixmapAll, BITMAP_monoGC, image,
-                           0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
-            image->data = NULL;
-            XDestroyImage( image );
-        }
+        if (!(pixmapAll = XCreatePixmap( display, root_window,
+                                         ptr->nWidth, ptr->nHeight * 2, 1 ))) return 0;
+        if (!(image = XCreateImage( display, visual,
+                                    1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
+                                    ptr->nHeight * 2, 16, ptr->nWidthBytes))) return 0;
+        gc = XCreateGC( display, pixmapAll, 0, NULL );
+        XSetGraphicsExposures( display, gc, False );
+        image->byte_order = MSBFirst;
+        image->bitmap_bit_order = MSBFirst;
+        image->bitmap_unit = 16;
+        _XInitImageFuncPtrs(image);
+        XPutImage( display, pixmapAll, gc, image,
+                   0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
+        image->data = NULL;
+        XDestroyImage( image );
 
         /* Now create the 2 pixmaps for bits and mask */
 
-        pixmapBits = XCreatePixmap( display, X11DRV_GetXRootWindow(),
-                                    ptr->nWidth, ptr->nHeight, 1 );
-        pixmapMask = XCreatePixmap( display, X11DRV_GetXRootWindow(),
-                                    ptr->nWidth, ptr->nHeight, 1 );
-        pixmapMaskInv = XCreatePixmap( display, X11DRV_GetXRootWindow(),
-                                    ptr->nWidth, ptr->nHeight, 1 );
+        pixmapBits = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
+        pixmapMask = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
+        pixmapMaskInv = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
 
         /* Make sure everything went OK so far */
 
-        if (pixmapBits && pixmapMask && pixmapAll)
+        if (pixmapBits && pixmapMask && pixmapMaskInv)
         {
             /* We have to do some magic here, as cursors are not fully
              * compatible between Windows and X11. Under X11, there
@@ -117,29 +111,29 @@
              * I don't know if it's correct per the X spec, but maybe
              * we ought to take advantage of it.  -- AJ
              */
-            XSetFunction( display, BITMAP_monoGC, GXcopy );
-            XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
+            XSetFunction( display, gc, GXcopy );
+            XCopyArea( display, pixmapAll, pixmapBits, gc,
                        0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
-            XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
+            XCopyArea( display, pixmapAll, pixmapMask, gc,
                        0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
-            XCopyArea( display, pixmapAll, pixmapMaskInv, BITMAP_monoGC,
+            XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
                        0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
-            XSetFunction( display, BITMAP_monoGC, GXand );
-            XCopyArea( display, pixmapAll, pixmapMaskInv, BITMAP_monoGC,
+            XSetFunction( display, gc, GXand );
+            XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
                        0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
-            XSetFunction( display, BITMAP_monoGC, GXandReverse );
-            XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
+            XSetFunction( display, gc, GXandReverse );
+            XCopyArea( display, pixmapAll, pixmapBits, gc,
                        0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
-            XSetFunction( display, BITMAP_monoGC, GXorReverse );
-            XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
+            XSetFunction( display, gc, GXorReverse );
+            XCopyArea( display, pixmapAll, pixmapMask, gc,
                        0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
             /* Additional white */
-            XSetFunction( display, BITMAP_monoGC, GXor );
-            XCopyArea( display, pixmapMaskInv, pixmapMask, BITMAP_monoGC,
+            XSetFunction( display, gc, GXor );
+            XCopyArea( display, pixmapMaskInv, pixmapMask, gc,
                        0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
-            XCopyArea( display, pixmapMaskInv, pixmapBits, BITMAP_monoGC,
+            XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
                        0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
-            XSetFunction( display, BITMAP_monoGC, GXcopy );
+            XSetFunction( display, gc, GXcopy );
             fg.red = fg.green = fg.blue = 0xffff;
             bg.red = bg.green = bg.blue = 0x0000;
             cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
@@ -152,12 +146,21 @@
         if (pixmapBits) XFreePixmap( display, pixmapBits );
         if (pixmapMask) XFreePixmap( display, pixmapMask );
         if (pixmapMaskInv) XFreePixmap( display, pixmapMaskInv );
+        XFreeGC( display, gc );
     }
+    return cursor;
+}
 
-    if (cursor == None) return FALSE;
-    if (X11DRV_MOUSE_XCursor != None) XFreeCursor( display, X11DRV_MOUSE_XCursor );
-    X11DRV_MOUSE_XCursor = cursor;
-
+/* set the cursor of a window; helper for X11DRV_SetCursor */
+static BOOL CALLBACK set_win_cursor( HWND hwnd, LPARAM cursor )
+{
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    if (wndPtr)
+    {
+        Window win = X11DRV_WND_GetXWindow(wndPtr);
+        if (win) TSXDefineCursor( thread_display(), win, (Cursor)cursor );
+    }
+    WIN_ReleaseWndPtr( wndPtr );
     return TRUE;
 }
 
@@ -166,35 +169,33 @@
  */
 void X11DRV_SetCursor( CURSORICONINFO *lpCursor )
 {
-    BOOL success;
+    Cursor cursor;
 
-    wine_tsx11_lock();
-    success = X11DRV_MOUSE_DoSetCursor( lpCursor );
-    wine_tsx11_unlock();
-    if ( !success ) return;
-
-    if (X11DRV_GetXRootWindow() != DefaultRootWindow(display))
+    if (root_window != DefaultRootWindow(gdi_display))
     {
         /* If in desktop mode, set the cursor on the desktop window */
 
-        TSXDefineCursor( display, X11DRV_GetXRootWindow(), X11DRV_MOUSE_XCursor );
-    }
-    else
-    {
-        /* Else, set the same cursor for all top-level windows */
-
-        /* FIXME: we should not reference USER internals here, but native USER 
-                  works only in desktop mode anyway, so this should not matter */
-
-        HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
-        while(hwnd)
+        wine_tsx11_lock();
+        cursor = X11DRV_GetCursor( gdi_display, lpCursor );
+        if (cursor)
         {
-            WND *tmpWnd = WIN_FindWndPtr(hwnd);
-            Window win = X11DRV_WND_FindXWindow(tmpWnd );
-            if (win && win!=DefaultRootWindow(display))
-                TSXDefineCursor( display, win, X11DRV_MOUSE_XCursor );
-            hwnd = GetWindow( hwnd, GW_HWNDNEXT );
-            WIN_ReleaseWndPtr(tmpWnd);
+            XDefineCursor( gdi_display, root_window, cursor );
+            XFreeCursor( gdi_display, cursor );
+        }
+        wine_tsx11_unlock();
+    }
+    else /* set the same cursor for all top-level windows of the current thread */
+    {
+        Display *display = thread_display();
+
+        wine_tsx11_lock();
+        cursor = X11DRV_GetCursor( display, lpCursor );
+        wine_tsx11_unlock();
+        if (cursor)
+        {
+/*            EnumThreadWindows( GetCurrentThreadId(), set_win_cursor, (LPARAM)cursor );*/
+            EnumWindows( set_win_cursor, (LPARAM)cursor );
+            TSXFreeCursor( display, cursor );
         }
     }
 }
@@ -205,7 +206,7 @@
 void X11DRV_MoveCursor(WORD wAbsX, WORD wAbsY)
 {
   /* 
-   * We do not want the to create MotionNotify events here, 
+   * We do not want to create MotionNotify events here, 
    * otherwise we will get an endless recursion:
    * XMotionEvent -> MOUSEEVENTF_MOVE -> mouse_event -> DisplayMoveCursor
    * -> XWarpPointer -> XMotionEvent -> ...
@@ -221,14 +222,15 @@
    * But first of all, we check whether we already are at the position
    * are supposed to move to; if so, we don't need to do anything.
    */
-  
+
+    Display *display = thread_display();
   Window root, child;
   int rootX, rootY, winX, winY;
   unsigned int xstate;
   
   if (X11DRV_MOUSE_WarpPointer < 0) return;
 
-  if (!TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
+  if (!TSXQueryPointer( display, root_window, &root, &child,
 			&rootX, &rootY, &winX, &winY, &xstate ))
     return;
   
@@ -237,8 +239,7 @@
   
   TRACE("(%d,%d): moving from (%d,%d)\n", wAbsX, wAbsY, winX, winY );
   
-  TSXWarpPointer( display, X11DRV_GetXRootWindow(), X11DRV_GetXRootWindow(), 
-		  0, 0, 0, 0, wAbsX, wAbsY );
+  TSXWarpPointer( display, root_window, root_window, 0, 0, 0, 0, wAbsX, wAbsY );
 }
 
 /***********************************************************************
@@ -259,7 +260,7 @@
         init_done = 1;
         /* Get the current mouse position and simulate an absolute mouse
            movement to initialize the mouse global variables */
-        TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
+        TSXQueryPointer( thread_display(), root_window, &root, &child,
                          &root_x, &root_y, &child_x, &child_y, &KeyState);
         X11DRV_SendEvent(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
                                root_x, root_y, X11DRV_EVENT_XStateToKeyState(KeyState),
diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c
index 263a9f4..901a13b 100644
--- a/windows/x11drv/wnd.c
+++ b/windows/x11drv/wnd.c
@@ -115,7 +115,7 @@
   while (wndPtr)
     {
       if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr) && X11DRV_WND_GetXWindow(wndPtr) )         
-         TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
+         TSXReconfigureWMWindow( thread_display(), X11DRV_WND_GetXWindow(wndPtr), 0,
 				CWStackMode, &winChanges );
 
       wndPrev = pDesktop->child;
@@ -144,7 +144,7 @@
       window = X11DRV_WND_GetXWindow(wndPtr);
       for (;;)
         {
-	  TSXQueryTree( display, window, &root, &parent,
+	  TSXQueryTree( thread_display(), window, &root, &parent,
                         &children, &nchildren );
 	  TSXFree( children );
 	  if (parent == root)
@@ -162,6 +162,7 @@
 void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
 {
     XWindowChanges winChanges;
+    Display *display = thread_display();
     int changeMask = 0;
     BOOL isZeroSizeWnd = FALSE;
     BOOL forceMapWindow = FALSE;
@@ -392,7 +393,7 @@
         XSetWindowAttributes win_attr;
         win_attr.bit_gravity = value;
         data->bit_gravity = value;
-        TSXChangeWindowAttributes( display, data->window, CWBitGravity, &win_attr );
+        TSXChangeWindowAttributes( thread_display(), data->window, CWBitGravity, &win_attr );
     }
 }
 
@@ -410,6 +411,7 @@
 
     if( (w = X11DRV_WND_GetXWindow(wnd)) )
     {
+        Display *display = thread_display();
 	switch( ha )
 	{
 	case HAK_ICONICSTATE: /* called when a window is minimized/restored */
@@ -435,8 +437,7 @@
 				ev.data.l[0] = IconicState;
 				ev.window = w;
 
-				if( TSXSendEvent (display,
-		RootWindow( display, XScreenNumberOfScreen(X11DRV_GetXScreen()) ), 
+				if( TSXSendEvent (display, DefaultRootWindow(display),
 		True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
 				{
 				    XEvent xe;