Moved more code to the X11 driver.

diff --git a/include/clipboard.h b/include/clipboard.h
index 69ef1d7..4bda664 100644
--- a/include/clipboard.h
+++ b/include/clipboard.h
@@ -1,10 +1,33 @@
 #ifndef __WINE_CLIPBOARD_H
 #define __WINE_CLIPBOARD_H
 
-void CLIPBOARD_ResetLock(HQUEUE16 hqRef, HQUEUE16 hqNew);
-void CLIPBOARD_ResetOwner(WND* pWnd);
-void CLIPBOARD_ReadSelection(Window w, Atom prop);
-void CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd);
-BOOL32 CLIPBOARD_IsPresent(WORD wFormat);
+#include "win.h"
+#include "wintypes.h"
+
+typedef struct tagCLIPFORMAT {
+    WORD	wFormatID;
+    WORD	wRefCount;
+    WORD	wDataPresent;
+    LPSTR	Name;
+    HANDLE32	hData32;
+    DWORD	BufSize;
+    struct tagCLIPFORMAT *PrevFormat;
+    struct tagCLIPFORMAT *NextFormat;
+    HANDLE16    hData16;
+} CLIPFORMAT, *LPCLIPFORMAT;
+
+typedef struct _CLIPBOARD_DRIVER
+{
+    void (*pEmptyClipboard)();
+    void (*pSetClipboardData)(UINT32);
+    BOOL32 (*pRequestSelection)();
+    void (*pResetOwner)(WND *);
+} CLIPBOARD_DRIVER;
+
+CLIPBOARD_DRIVER *CLIPBOARD_GetDriver();
+
+extern void CLIPBOARD_ResetLock(HQUEUE16 hqRef, HQUEUE16 hqNew);
+extern void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange);
+extern BOOL32 CLIPBOARD_IsPresent(WORD wFormat);
 
 #endif /* __WINE_CLIPBOARD_H */
diff --git a/include/keyboard.h b/include/keyboard.h
index 26049b1..45ed3bb 100644
--- a/include/keyboard.h
+++ b/include/keyboard.h
@@ -7,6 +7,8 @@
 #ifndef __WINE_KEYBOARD_H
 #define __WINE_KEYBOARD_H
 
+#include "wintypes.h"
+
 #pragma pack(1)
 typedef struct _KBINFO
 {
@@ -27,8 +29,17 @@
 
 /* Wine internals */
 
-extern void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event );
-extern void KEYBOARD_UpdateState( void );
+typedef struct _KEYBOARD_DRIVER {
+  void   (*pInit)();
+  WORD   (*pVkKeyScan)(CHAR);
+  UINT16 (*pMapVirtualKey)(UINT16, UINT16);
+  INT16  (*pGetKeyNameText)(LONG, LPSTR, INT16);
+  INT16  (*pToAscii)(UINT16, UINT16, LPBYTE, LPVOID, UINT16);
+} KEYBOARD_DRIVER;
+
+extern KEYBOARD_DRIVER *KEYBOARD_GetDriver();
+
+extern void KEYBOARD_SendEvent(BYTE bVk, BYTE bScan, DWORD dwFlags, DWORD posX, DWORD posY, DWORD time);
 
 #define WINE_KEYBDEVENT_MAGIC  ( ('K'<<24)|('E'<<16)|('Y'<<8)|'B' )
 typedef struct _WINE_KEYBDEVENT
diff --git a/include/message.h b/include/message.h
index 909235c..0251997 100644
--- a/include/message.h
+++ b/include/message.h
@@ -9,6 +9,7 @@
 
 #include "win.h"
 #include "queue.h"
+#include "wintypes.h"
 
 extern DWORD MSG_WineStartTicks;  /* Ticks at Wine startup */
 
@@ -31,16 +32,32 @@
 #define EVENT_IO_EXCEPT		2
 
 /* event.c */
+
+typedef struct _EVENT_DRIVER {
+  BOOL32 (*pInit)(void);
+  void   (*pAddIO)(int, unsigned);
+  void   (*pDeleteIO)(int, unsigned);
+  BOOL32 (*pWaitNetEvent)(BOOL32, BOOL32);
+  void   (*pSynchronize)(void);
+  BOOL32 (*pCheckFocus)(void);
+  BOOL32 (*pQueryPointer)(DWORD *, DWORD *, DWORD *);
+  void   (*pDummyMotionNotify)(void);
+  BOOL32 (*pPending)(void);
+  BOOL16 (*pIsUserIdle)(void);
+} EVENT_DRIVER;
+
 extern void EVENT_AddIO( int fd, unsigned flag );
-extern BOOL32 EVENT_CheckFocus( void );
 extern void EVENT_DeleteIO( int fd, unsigned flag );
 extern BOOL32 EVENT_Init( void );
 extern BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek );
 extern void EVENT_Synchronize(void);
-extern void EVENT_ProcessEvent( XEvent *event );
-extern void EVENT_RegisterWindow( WND *pWnd );
-extern void EVENT_DestroyWindow( WND *pWnd );
+extern BOOL32 EVENT_CheckFocus( void );
+extern BOOL32 EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state);
 extern void EVENT_DummyMotionNotify(void);
+extern BOOL32 EVENT_Pending(void);
+
+/* input.c */
+
 extern HWND32 EVENT_Capture( HWND32, INT16 );
 extern INT16 EVENT_GetCaptureInfo(void);
 extern BOOL32 EVENT_QueryPointer( DWORD *posX, DWORD *posY, DWORD *state );
diff --git a/include/win.h b/include/win.h
index 586e693..a7c4821 100644
--- a/include/win.h
+++ b/include/win.h
@@ -7,7 +7,11 @@
 #ifndef __WINE_WIN_H
 #define __WINE_WIN_H
 
-#include "ts_xlib.h"
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+#include <X11/Xlib.h>
+#endif /* !defined(X_DISPLAY_MISSING) */
 
 #include "ldt.h"
 #include "class.h"
@@ -89,14 +93,18 @@
 
 typedef struct _WND_DRIVER
 {
+    BOOL32 (*pCreateDesktopWindow)(WND *, CLASS *, BOOL32);
     BOOL32 (*pCreateWindow)(WND *, CLASS *, CREATESTRUCT32A *, BOOL32);
+    BOOL32 (*pDestroyWindow)(WND *);
     WND*   (*pSetParent)(WND *, WND *);
+    void   (*pForceWindowRaise)(WND *);
+    void   (*pSetWindowPos)(WND *, const WINDOWPOS32 *, BOOL32);
+    void   (*pSetText)(WND *, LPCSTR);
+    void   (*pSetFocus)(WND *);
+    void   (*pPreSizeMove)(WND *);
+    void   (*pPostSizeMove)(WND *);
 } WND_DRIVER;
 
-/* X11 windows driver */
-/* FIXME: does not belong here */
-extern WND_DRIVER X11DRV_WND_Driver;
-
 typedef struct
 {
     RECT16	   rectNormal;
@@ -130,7 +138,6 @@
 extern WND*   WIN_GetDesktop(void);
 extern void   WIN_DumpWindow( HWND32 hwnd );
 extern void   WIN_WalkWindows( HWND32 hwnd, int indent );
-extern Window WIN_GetXWindow( HWND32 hwnd );
 extern BOOL32 WIN_UnlinkWindow( HWND32 hwnd );
 extern BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter );
 extern HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue );
@@ -164,7 +171,6 @@
 extern BOOL32 ICONTITLE_Init( void );
 
 /* windows/focus.c */
-extern void FOCUS_SetXFocus( HWND32 );
 extern void FOCUS_SwitchFocus( HWND32 , HWND32 );
 
 extern Display * display;
diff --git a/include/x11drv.h b/include/x11drv.h
index dc9fb22..61f43b2 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -5,12 +5,18 @@
 #ifndef __WINE_X11DRV_H
 #define __WINE_X11DRV_H
 
+#include "config.h"
 #include "ts_xlib.h"
 #include "ts_xutil.h"
+
 #include "winbase.h"
 #include "windows.h"
 #include "gdi.h"
 #include "xmalloc.h" /* for XCREATEIMAGE macro */
+#include "clipboard.h"
+#include "keyboard.h"
+#include "message.h"
+#include "win.h"
 
   /* X physical pen */
 typedef struct
@@ -181,7 +187,6 @@
                            (width), (height), 32, width_bytes ); \
 }
 
-
 /* exported dib functions for now */
 
 /* This structure holds the arguments for DIB_SetImageBits() */
@@ -213,6 +218,63 @@
 				      WORD depth, const BITMAPINFO *info,
 				      int *nColors );
 
+/* X11 windows driver */
+extern WND_DRIVER X11DRV_WND_Driver;
+
+extern Window X11DRV_WND_GetXWindow(HWND32 hwnd);
+
+extern BOOL32 X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL32 bUnicode);
+extern BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode);
+extern BOOL32 X11DRV_WND_DestroyWindow(WND *pWnd);
+extern WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent);
+extern void X11DRV_WND_ForceWindowRaise(WND *pWnd);
+extern void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS);
+extern void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text);
+extern void X11DRV_WND_SetFocus(WND *wndPtr);
+extern void X11DRV_WND_PreSizeMove(WND *wndPtr);
+extern void X11DRV_WND_PostSizeMove(WND *wndPtr);
+
+/* X11 clipboard driver */
+
+extern CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver;
+
+extern void X11DRV_CLIPBOARD_EmptyClipboard();
+extern void X11DRV_CLIPBOARD_SetClipboardData(UINT32 wFormat);
+extern BOOL32 X11DRV_CLIPBOARD_RequestSelection();
+extern void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd);
+
+void X11DRV_CLIPBOARD_ReadSelection(Window w, Atom prop);
+void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd);
+
+/* X11 keyboard driver */
+
+extern KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver;
+
+extern void X11DRV_KEYBOARD_Init(void);
+extern WORD X11DRV_KEYBOARD_VkKeyScan(CHAR cChar);
+extern UINT16 X11DRV_KEYBOARD_MapVirtualKey(UINT16 wCode, UINT16 wMapType);
+extern INT16 X11DRV_KEYBOARD_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT16 nSize);
+extern INT16 X11DRV_KEYBOARD_ToAscii(UINT16 virtKey, UINT16 scanCode, LPBYTE lpKeyState, LPVOID lpChar, UINT16 flags);
+
+/* X11 mouse driver */
+
+#if 0 
+extern MOUSE_DRIVER X11DRV_MOUSE_Driver;
+#endif
+
+/* X11 event driver */
+
+extern EVENT_DRIVER X11DRV_EVENT_Driver;
+
+extern BOOL32 X11DRV_EVENT_Init(void);
+extern void X11DRV_EVENT_AddIO(int fd, unsigned flag);
+extern void X11DRV_EVENT_DeleteIO(int fd, unsigned flag);
+extern BOOL32 X11DRV_EVENT_WaitNetEvent(BOOL32 sleep, BOOL32 peek);
+extern void X11DRV_EVENT_Synchronize(void);
+extern BOOL32 X11DRV_EVENT_CheckFocus( void );
+extern BOOL32 X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state);
+extern void X11DRV_EVENT_DummyMotionNotify(void);
+extern BOOL32 X11DRV_EVENT_Pending(void);
+extern BOOL16 X11DRV_EVENT_IsUserIdle(void);
 
 #endif  /* __WINE_X11DRV_H */
-
diff --git a/windows/clipboard.c b/windows/clipboard.c
index e8fa56a..99382f9 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -12,8 +12,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
-#include "ts_xlib.h"
-#include <X11/Xatom.h>
 #include "windows.h"
 #include "win.h"
 #include "heap.h"
@@ -22,39 +20,24 @@
 #include "xmalloc.h"
 #include "debug.h"
 
+extern CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver;
+
 #define  CF_REGFORMATBASE 	0xC000
 
-typedef struct tagCLIPFORMAT {
-    WORD	wFormatID;
-    WORD	wRefCount;
-    WORD	wDataPresent;
-    LPSTR	Name;
-    HANDLE32	hData32;
-    DWORD	BufSize;
-    struct tagCLIPFORMAT *PrevFormat;
-    struct tagCLIPFORMAT *NextFormat;
-    HANDLE16    hData16;
-} CLIPFORMAT, *LPCLIPFORMAT;
-
-/* *************************************************************************
+/**************************************************************************
  *			internal variables
  */
 
 static HQUEUE16 hqClipLock   = 0;
 static BOOL32 bCBHasChanged  = FALSE;
 
-static HWND32 hWndClipOwner  = 0;   /* current clipboard owner */
-static HWND32 hWndClipWindow = 0;   /* window that opened clipboard */
+HWND32 hWndClipOwner  = 0;   /* current clipboard owner */
+HWND32 hWndClipWindow = 0;   /* window that opened clipboard */
 static HWND32 hWndViewer     = 0;   /* start of viewers chain */
 
 static WORD LastRegFormat = CF_REGFORMATBASE;
 
-static Bool   selectionWait = False;
-static Bool   selectionAcquired = False;
-static Window selectionWindow = None;
-static Window selectionPrevWindow = None;
-
-static CLIPFORMAT ClipFormats[16]  = {
+CLIPFORMAT ClipFormats[16]  = {
     { CF_TEXT, 1, 0, "Text", (HANDLE32)NULL, 0, NULL, &ClipFormats[1] , (HANDLE16)NULL},
     { CF_BITMAP, 1, 0, "Bitmap", (HANDLE32)NULL, 0, &ClipFormats[0], &ClipFormats[2] , (HANDLE16)NULL},
     { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE32)NULL, 0, &ClipFormats[1], &ClipFormats[3] , (HANDLE16)NULL},
@@ -84,39 +67,14 @@
     return lpFormat;
 }
 
+
 /**************************************************************************
- *                      CLIPBOARD_CheckSelection
- *
- * Prevent X selection from being lost when a top level window is
- * destroyed.
+ *		CLIPBOARD_GetDriver
  */
-static void CLIPBOARD_CheckSelection(WND* pWnd)
+CLIPBOARD_DRIVER *CLIPBOARD_GetDriver()
 {
-    TRACE(clipboard,"\tchecking %08x\n", (unsigned)pWnd->window);
-
-    if( selectionAcquired && selectionWindow != None &&
-        pWnd->window == selectionWindow )
-    {
-	selectionPrevWindow = selectionWindow;
-	selectionWindow = None;
-
-	if( pWnd->next ) 
-	    selectionWindow = pWnd->next->window;
-	else if( pWnd->parent )
-             if( pWnd->parent->child != pWnd ) 
-                 selectionWindow = pWnd->parent->child->window;
-
-	TRACE(clipboard,"\tswitching selection from %08x to %08x\n", 
-                    (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
-
-	if( selectionWindow != None )
-	{
-	    TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
-	    if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
-		selectionWindow = None;
-	}
-    }
-}
+    return &X11DRV_CLIPBOARD_Driver;
+};
 
 /**************************************************************************
  *                      CLIPBOARD_ResetLock
@@ -137,46 +95,11 @@
     }
 }
 
-/**************************************************************************
- *			CLIPBOARD_ResetOwner
- *
- * Called from DestroyWindow().
- */
-void CLIPBOARD_ResetOwner(WND* pWnd)
-{
-    LPCLIPFORMAT lpFormat = ClipFormats;
-
-    TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n", 
-				hWndClipOwner, (unsigned)selectionWindow);
-
-    if( pWnd->hwndSelf == hWndClipOwner)
-    {
-	SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
-
-	/* check if all formats were rendered */
-
-	while(lpFormat)
-	{
-	    if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
-	    {
-		TRACE(clipboard,"\tdata missing for clipboard format %i\n", 
-				   lpFormat->wFormatID); 
-		lpFormat->wDataPresent = 0;
-	    }
-	    lpFormat = lpFormat->NextFormat;
-	}
-	hWndClipOwner = 0;
-    }
-
-    /* now try to salvage current selection from being destroyed by X */
-
-    if( pWnd->window ) CLIPBOARD_CheckSelection(pWnd);
-}
 
 /**************************************************************************
  *			CLIPBOARD_DeleteRecord
  */
-static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange)
+void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange)
 {
     if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
 	 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP )
@@ -221,41 +144,6 @@
 }
 
 /**************************************************************************
- *			CLIPBOARD_RequestXSelection
- */
-static BOOL32 CLIPBOARD_RequestXSelection()
-{
-    HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32();
-
-    if( !hWnd ) return FALSE;
-
-    TRACE(clipboard,"Requesting selection...\n");
-
-  /* request data type XA_STRING, later
-   * CLIPBOARD_ReadSelection() will be invoked 
-   * from the SelectionNotify event handler */
-
-    TSXConvertSelection(display,XA_PRIMARY,XA_STRING,
-                      TSXInternAtom(display,"PRIMARY_TEXT",False),
-                      WIN_GetXWindow(hWnd),CurrentTime);
-
-  /* wait until SelectionNotify is processed 
-   *
-   * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the 
-   *	    CLIPBOARD_CheckSelection() ). 
-   */
-
-    selectionWait=True;
-    while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE );
-
-  /* we treat Unix text as CF_OEMTEXT */
-    TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n", 
-		      ClipFormats[CF_OEMTEXT-1].wDataPresent);
-
-    return (BOOL32)ClipFormats[CF_OEMTEXT-1].wDataPresent;
-}
-
-/**************************************************************************
  *			CLIPBOARD_IsPresent
  */
 BOOL32 CLIPBOARD_IsPresent(WORD wFormat)
@@ -370,17 +258,8 @@
 
     hWndClipOwner = hWndClipWindow;
 
-    if(selectionAcquired)
-    {
-	selectionAcquired	= False;
-	selectionPrevWindow 	= selectionWindow;
-	selectionWindow 	= None;
+    CLIPBOARD_GetDriver()->pEmptyClipboard();
 
-	TRACE(clipboard, "\tgiving up selection (spw = %08x)\n", 
-				 	(unsigned)selectionPrevWindow);
-
-	TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
-    }
     return TRUE;
 }
 
@@ -409,7 +288,6 @@
 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
 {
     LPCLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
-    Window       owner;
 
     TRACE(clipboard, "(%04X, %04x) !\n", wFormat, hData);
 
@@ -423,22 +301,7 @@
     if( (hqClipLock != GetTaskQueue(0)) || !lpFormat ||
 	(!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) ) return 0; 
 
-    /* Acquire X selection if text format */
-
-    if( !selectionAcquired && 
-	(wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
-    {
-	owner = WIN_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() );
-	TSXSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime);
-	if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
-	{
-	    selectionAcquired = True;
-	    selectionWindow = owner;
-
-	    TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n", 
-						(unsigned) owner);
-	}
-    }
+    CLIPBOARD_GetDriver()->pSetClipboardData(wFormat);
 
     if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) 
     {
@@ -473,7 +336,6 @@
 HANDLE32 WINAPI SetClipboardData32( UINT32 wFormat, HANDLE32 hData )
 {
     LPCLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
-    Window       owner;
 
     TRACE(clipboard, "(%08X, %08x) !\n", wFormat, hData);
 
@@ -487,22 +349,7 @@
     if( (hqClipLock != GetTaskQueue(0)) || !lpFormat ||
 	(!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) ) return 0; 
 
-    /* Acquire X selection if text format */
-
-    if( !selectionAcquired && 
-	(wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
-    {
-	owner = WIN_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() );
-	TSXSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime);
-	if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
-	{
-	    selectionAcquired = True;
-	    selectionWindow = owner;
-
-	    TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n", 
-						(unsigned) owner);
-	}
-    }
+    CLIPBOARD_GetDriver()->pSetClipboardData(wFormat);
 
     if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) 
     {
@@ -769,7 +616,8 @@
 
     TRACE(clipboard,"(void)\n");
 
-    if( !selectionAcquired ) CLIPBOARD_RequestXSelection();
+    /* FIXME: Returns BOOL32 */
+    CLIPBOARD_GetDriver()->pRequestSelection();
 
     FormatCount += abs(lpFormat[CF_TEXT-1].wDataPresent -
 		       lpFormat[CF_OEMTEXT-1].wDataPresent); 
@@ -810,8 +658,8 @@
 
     if( hqClipLock != GetTaskQueue(0) ) return 0;
 
-    if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) 
-	 && !selectionAcquired) CLIPBOARD_RequestXSelection();
+    if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) 
+        CLIPBOARD_GetDriver()->pRequestSelection();
 
     if (wFormat == 0)
     {
@@ -1037,8 +885,8 @@
 {
     TRACE(clipboard,"(%04X) !\n", wFormat);
 
-    if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) &&
-        !selectionAcquired ) CLIPBOARD_RequestXSelection();
+    if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
+        CLIPBOARD_GetDriver()->pRequestSelection();
 
     return CLIPBOARD_IsPresent(wFormat);
 }
@@ -1094,117 +942,4 @@
 }
 
 
-/**************************************************************************
- *			CLIPBOARD_ReadSelection
- *
- * Called from the SelectionNotify event handler. 
- */
-void CLIPBOARD_ReadSelection(Window w,Atom prop)
-{
-    HANDLE32 	 hText = 0;
-    LPCLIPFORMAT lpFormat = ClipFormats; 
-
-    TRACE(clipboard,"ReadSelection callback\n");
-
-    if(prop != None)
-    {
-	Atom		atype=AnyPropertyType;
-	int		aformat;
-	unsigned long 	nitems,remain;
-	unsigned char*	val=NULL;
-
-        TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop));
-
-        /* TODO: Properties longer than 64K */
-
-	if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
-	    &atype, &aformat, &nitems, &remain, &val) != Success)
-	    WARN(clipboard, "\tcouldn't read property\n");
-	else
-	{
-           TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n",
-		             TSXGetAtomName(display,atype),aformat,nitems,val);
-
-	   if(atype == XA_STRING && aformat == 8)
-	   {
-	      int 	i,inlcount = 0;
-	      char*	lpstr;
-
-	      TRACE(clipboard,"\tselection is '%s'\n",val);
-
-	      for(i=0; i <= nitems; i++)
-		  if( val[i] == '\n' ) inlcount++;
-
-	      if( nitems )
-	      {
-	        hText=GlobalAlloc32(GMEM_MOVEABLE, nitems + inlcount + 1);
-	        if( (lpstr = (char*)GlobalLock32(hText)) )
-	          for(i=0,inlcount=0; i <= nitems; i++)
-	          {
-	  	     if( val[i] == '\n' ) lpstr[inlcount++]='\r';
-		     lpstr[inlcount++]=val[i];
-		  }
-	        else hText = 0;
-	      }
-	   }
-	   TSXFree(val);
-	}
-   }
-
-   /* delete previous CF_TEXT and CF_OEMTEXT data */
-
-   if( hText )
-   {
-     lpFormat = &ClipFormats[CF_TEXT-1];
-     if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) 
-         CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
-     lpFormat = &ClipFormats[CF_OEMTEXT-1];
-     if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)  
-         CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
-
-     lpFormat->wDataPresent = 1;
-     lpFormat->hData32 = hText;
-     lpFormat->hData16 = 0;
-   }
-
-   selectionWait=False;
-}
-
-/**************************************************************************
- *			CLIPBOARD_ReleaseSelection
- *
- * Wine might have lost XA_PRIMARY selection because of
- * EmptyClipboard() or other client. 
- */
-void CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd)
-{
-    /* w is the window that lost selection,
-     * 
-     * selectionPrevWindow is nonzero if CheckSelection() was called. 
-     */
-
-    TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n", 
-	  (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
-
-    if( selectionAcquired )
-    {
-	if( w == selectionWindow || selectionPrevWindow == None)
-	{
-	    /* alright, we really lost it */
-
-	    selectionAcquired = False;
-	    selectionWindow = None; 
-
-	    /* but we'll keep existing data for internal use */
-	}
-	else if( w == selectionPrevWindow )
-	{
-	    w = TSXGetSelectionOwner(display, XA_PRIMARY);
-	    if( w == None )
-		TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
-	}
-    }
-
-    selectionPrevWindow = None;
-}
 
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 5fdba8c..879ff50 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -60,12 +60,8 @@
 {
     if (!text) text = "";
     if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text );
-    wndPtr->text = HEAP_strdupA( SystemHeap, 0, text );
-    if (wndPtr->window)
-    {
-	TSXStoreName( display, wndPtr->window, wndPtr->text );
-	TSXSetIconName( display, wndPtr->window, wndPtr->text );
-    }
+    wndPtr->text = HEAP_strdupA( SystemHeap, 0, text );    
+    wndPtr->pDriver->pSetText(wndPtr, wndPtr->text);
 }
 
 /***********************************************************************
diff --git a/windows/dinput.c b/windows/dinput.c
index fbc2fc0..d2db6d0 100644
--- a/windows/dinput.c
+++ b/windows/dinput.c
@@ -18,11 +18,12 @@
  *	   an utter mess.)
  */
 
+#include "ts_xlib.h"
+
 #include "config.h"
 #include <string.h>
 #include <unistd.h>
 #include <assert.h>
-#include <X11/Xlib.h>
 #include <sys/signal.h>
 
 #include "windows.h"
@@ -470,17 +471,15 @@
   if (df->dwFlags == DIDF_ABSAXIS)
     mthis->absolute = 1;
   else {
-    Window rw, cr;
-    int rx, ry, cx, cy;
-    unsigned int mask;
+    DWORD rx, ry;
     
     /* We need to get the initial "previous" position to be able
        to return deltas */
     mthis->absolute = 0;
   
     /* Get the mouse position */
-    TSXQueryPointer(display, rootWindow, &rw, &cr,
-		    &rx, &ry, &cx, &cy, &mask);
+    EVENT_QueryPointer(&rx, &ry, NULL);
+
     /* Fill the initial mouse state structure */
     mthis->prevX = rx;
     mthis->prevY = ry;
@@ -498,9 +497,7 @@
 static HRESULT WINAPI SysMouseA_GetDeviceState(
 	LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
 ) {
-  Window rw, cr;
-  int rx, ry, cx, cy;
-  unsigned int mask;
+  DWORD rx, ry, state;
   struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
   
@@ -513,8 +510,7 @@
   }
   
   /* Get the mouse position */
-  TSXQueryPointer(display, rootWindow, &rw, &cr,
-		  &rx, &ry, &cx, &cy, &mask);
+  EVENT_QueryPointer(&rx, &ry, &state);
   TRACE(dinput,"(X:%d - Y:%d)\n", rx, ry);
 
   /* Fill the mouse state structure */
@@ -529,10 +525,10 @@
     mthis->prevY = ry;
   }
   mstate->lZ = 0;
-  mstate->rgbButtons[0] = (mask & Button1Mask ? 0xFF : 0x00);
-  mstate->rgbButtons[1] = (mask & Button3Mask ? 0xFF : 0x00); /* Windows button two is X button 3 */
-  mstate->rgbButtons[2] = (mask & Button2Mask ? 0xFF : 0x00);
-  mstate->rgbButtons[3] = (mask & Button4Mask ? 0xFF : 0x00);
+  mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
+  mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
+  mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
+  mstate->rgbButtons[3] = 0x00;
   
   return 0;
 }
diff --git a/windows/display.c b/windows/display.c
index c34a145..8282ccc 100644
--- a/windows/display.c
+++ b/windows/display.c
@@ -5,13 +5,13 @@
  *
  */
 
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
 #include "ts_xlib.h"
 #include "ts_xresource.h"
 #include "ts_xutil.h"
 
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 #include "windows.h"
 #include "win.h"
 #include "gdi.h"
@@ -169,7 +169,7 @@
         HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
         while(hwnd)
         {
-            Window win = WIN_GetXWindow( hwnd );
+            Window win = X11DRV_WND_GetXWindow( hwnd );
             if (win && win!=DefaultRootWindow(display))
                 XDefineCursor( display, win, cursor );
             hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
diff --git a/windows/event.c b/windows/event.c
index 3c96220..0a54bb0 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -5,1404 +5,107 @@
  * 
  */
 
-#include <assert.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <X11/keysym.h>
-#include "ts_xlib.h"
-#include "ts_xresource.h"
-#include "ts_xutil.h"
-#include <X11/Xatom.h>
-
-#include "windows.h"
-#include "winnt.h"
-#include "gdi.h"
-#include "heap.h"
-#include "queue.h"
-#include "win.h"
-#include "class.h"
-#include "clipboard.h"
-#include "dce.h"
 #include "message.h"
-#include "module.h"
-#include "options.h"
-#include "queue.h"
-#include "winpos.h"
-#include "drive.h"
-#include "shell.h"
-#include "keyboard.h"
-#include "mouse.h"
-#include "debug.h"
-#include "dde_proc.h"
-#include "winsock.h"
-#include "mouse.h"
-#include "x11drv.h"
 
-#define NB_BUTTONS      3     /* Windows can handle 3 buttons */
-
-#define DndNotDnd       -1    /* OffiX drag&drop */
-#define DndUnknown      0
-#define DndRawData      1
-#define DndFile         2
-#define DndFiles        3
-#define DndText         4
-#define DndDir          5
-#define DndLink         6
-#define DndExe          7
-
-#define DndEND          8
-
-#define DndURL          128   /* KDE drag&drop */
-
-
-  /* X context to associate a hwnd to an X window */
-static XContext winContext = 0;
-
-static Atom wmProtocols = None;
-static Atom wmDeleteWindow = None;
-static Atom dndProtocol = None;
-static Atom dndSelection = None;
-
-/* EVENT_WaitNetEvent() master fd sets */
-
-static fd_set __event_io_set[3];
-static int    __event_max_fd = 0;
-static int    __event_x_connection = 0;
-
-static const char * const event_names[] =
-{
-    "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
-    "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
-    "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
-    "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
-    "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
-    "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
-    "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
-    "ClientMessage", "MappingNotify"
-};
-
-  /* Event handlers */
-static void EVENT_Key( WND *pWnd, XKeyEvent *event );
-static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event );
-static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event );
-static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event );
-static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event );
-static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event );
-static int  EVENT_Expose( WND *pWnd, XExposeEvent *event );
-static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
-static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event );
-static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
-static void EVENT_SelectionNotify( XSelectionEvent *event);
-static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
-static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
-static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event );
-
-/* Usable only with OLVWM - compile option perhaps?
-static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
-*/
-
-static void EVENT_GetGeometry( Window win, int *px, int *py,
-                               unsigned int *pwidth, unsigned int *pheight );
+extern EVENT_DRIVER X11DRV_EVENT_Driver;
 
 /***********************************************************************
- *           EVENT_Init
+ *		EVENT_GetDriver
+ */
+EVENT_DRIVER *EVENT_GetDriver(void)
+{
+  return &X11DRV_EVENT_Driver;
+}
+
+/***********************************************************************
+ *		EVENT_Init
  *
  * Initialize network IO.
  */
 BOOL32 EVENT_Init(void)
 {
-    int  i;
-    for( i = 0; i < 3; i++ )
-	FD_ZERO( __event_io_set + i );
-
-    __event_max_fd = __event_x_connection = ConnectionNumber(display);
-    FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] );
-    __event_max_fd++;
-    return TRUE;
+  return EVENT_GetDriver()->pInit();
 }
 
 /***********************************************************************
- *          EVENT_AddIO 
+ *		EVENT_AddIO 
  */
-void EVENT_AddIO( int fd, unsigned io_type )
+void EVENT_AddIO(int fd, unsigned io_type)
 {
-    FD_SET( fd, &__event_io_set[io_type] );
-    if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
-}
-
-void EVENT_DeleteIO( int fd, unsigned io_type )
-{
-    FD_CLR( fd, &__event_io_set[io_type] );
+  EVENT_GetDriver()->pAddIO(fd, io_type);
 }
 
 /***********************************************************************
- *           EVENT_ProcessEvent
- *
- * Process an X event.
+ *		EVENT_DeleteIO 
  */
-void EVENT_ProcessEvent( XEvent *event )
+void EVENT_DeleteIO(int fd, unsigned io_type)
 {
-    WND *pWnd;
-    
-    if ( TSXFindContext( display, event->xany.window, winContext,
-			 (char **)&pWnd ) != 0) {
-      if ( event->type == ClientMessage) {
-	/* query window (drag&drop event contains only drag window) */
-	Window   	root, child;
-	int      	root_x, root_y, child_x, child_y;
-	unsigned	u;
-	TSXQueryPointer( display, rootWindow, &root, &child,
-			 &root_x, &root_y, &child_x, &child_y, &u);
-	if (TSXFindContext( display, child, winContext, (char **)&pWnd ) != 0)
-	  return;
-      } else {
-	pWnd = NULL;  /* Not for a registered window */
-      }
-    }
-
-    TRACE(event, "Got event %s for hwnd %04x\n",
-	  event_names[event->type], pWnd? pWnd->hwndSelf : 0 );
-
-    switch(event->type)
-    {
-    case KeyPress:
-    case KeyRelease:
-        EVENT_Key( pWnd, (XKeyEvent*)event );
-	break;
-	
-    case ButtonPress:
-        EVENT_ButtonPress( pWnd, (XButtonEvent*)event );
-	break;
-
-    case ButtonRelease:
-        EVENT_ButtonRelease( pWnd, (XButtonEvent*)event );
-	break;
-
-    case MotionNotify:
-        /* Wine between two fast machines across the overloaded campus
-	   ethernet gets very boged down in MotionEvents. The following
-	   simply finds the last motion event in the queue and drops
-	   the rest. On a good link events are servered before they build
-	   up so this doesn't take place. On a slow link this may cause
-	   problems if the event order is important. I'm not yet seen
-	   of any problems. Jon 7/6/96.
-	 */
-        while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
-                                        MotionNotify, event));    
-        EVENT_MotionNotify( pWnd, (XMotionEvent*)event );
-	break;
-
-    case FocusIn:
-        if (!pWnd) return;
-        EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event );
-	break;
-
-    case FocusOut:
-        if (!pWnd) return;
-	EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event );
-	break;
-
-    case Expose:
-        if (!pWnd) return;
-	if (EVENT_Expose( pWnd, (XExposeEvent *)event )) {
-	    /* need to process ConfigureNotify first */
-	    XEvent new_event;
-
-	    /* attempt to find and process the ConfigureNotify event now */
-            if (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
-                                          ConfigureNotify, &new_event)) {
-                EVENT_ProcessEvent( &new_event );
-                if (!EVENT_Expose( pWnd, (XExposeEvent *)event ))
-            	    break;
-            }
-
-	    /* no luck at this time, defer Expose event for later */
-	    /* use "type" for an event counter, it is never rechecked */
-	    if (!pWnd->expose_event) {
-		pWnd->expose_event = malloc( sizeof(XExposeEvent) );
-		pWnd->expose_event[0] = *(XExposeEvent *)event;
-		pWnd->expose_event[0].type = 1;
-	    } else {
-		int i;
-
-		i = ++pWnd->expose_event[0].type;
-		pWnd->expose_event = realloc( pWnd->expose_event,
-					      i * sizeof(XExposeEvent) );
-		pWnd->expose_event[i-1] = *(XExposeEvent *)event;
-		FIXME(x11, "Try and combine Expose events? %d queued.\n", i);
-	    }
-	}
-	break;
-
-    case GraphicsExpose:
-        if (!pWnd) return;
-	EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
-        break;
-
-    case ConfigureNotify:
-        if (!pWnd) return;
-	EVENT_ConfigureNotify( pWnd, (XConfigureEvent*)event );
-	if (pWnd->expose_event) {
-	    /* process deferred Expose event(s) */
-	    int i;
-
-	    for (i=0; i<pWnd->expose_event[0].type; i++) {
-	        if(EVENT_Expose( pWnd, &pWnd->expose_event[i] ))
-		    ERR(x11, "Unprocessed expose event discarded\n");
-	    }
-	    free( pWnd->expose_event );
-	    pWnd->expose_event = NULL;
-	}
-	break;
-
-    case SelectionRequest:
-        if (!pWnd) return;
-	EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
-	break;
-
-    case SelectionNotify:
-        if (!pWnd) return;
-	EVENT_SelectionNotify( (XSelectionEvent *)event );
-	break;
-
-    case SelectionClear:
-        if (!pWnd) return;
-	EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
-	break;
-
-    case ClientMessage:
-        if (!pWnd) return;
-	EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
-	break;
-
-/*  case EnterNotify:
- *       EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
- *       break;
- */
-    case NoExpose:
-	break;
-
-    /* We get all these because of StructureNotifyMask. */
-    case UnmapNotify:
-    case CirculateNotify:
-    case CreateNotify:
-    case DestroyNotify:
-    case GravityNotify:
-    case ReparentNotify:
-	break;
-
-    case MapNotify:
-        if (!pWnd) return;
-	EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
-	break;
-
-    default:    
-	WARN(event, "Unprocessed event %s for hwnd %04x\n",
-	        event_names[event->type], pWnd? pWnd->hwndSelf : 0 );
-	break;
-    }
-}
-
-
-/***********************************************************************
- *           EVENT_RegisterWindow
- *
- * Associate an X window to a HWND.
- */
-void EVENT_RegisterWindow( WND *pWnd )
-{
-    if (wmProtocols == None)
-        wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
-    if (wmDeleteWindow == None)
-        wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
-    if( dndProtocol == None )
-	dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
-    if( dndSelection == None )
-	dndSelection = TSXInternAtom( display, "DndSelection" , False );
-
-    TSXSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
-
-    if (!winContext) winContext = TSXUniqueContext();
-    TSXSaveContext( display, pWnd->window, winContext, (char *)pWnd );
+  EVENT_GetDriver()->pDeleteIO(fd, io_type);
 }
 
 /***********************************************************************
- *           EVENT_DestroyWindow
- */
-void EVENT_DestroyWindow( WND *pWnd )
-{
-   XEvent xe;
-
-   if (pWnd->expose_event) {
-       free( pWnd->expose_event );
-       pWnd->expose_event = NULL;
-   }
-   TSXDeleteContext( display, pWnd->window, winContext );
-   TSXDestroyWindow( display, pWnd->window );
-   while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
-}
-
-
-/***********************************************************************
- *           IsUserIdle		(USER.333)
- *
- * Check if we have pending X events.
- */
-BOOL16 WINAPI IsUserIdle(void)
-{
-    struct timeval timeout = {0, 0};
-    fd_set check_set;
-
-    FD_ZERO(&check_set);
-    FD_SET(__event_x_connection, &check_set);
-    if( select(__event_x_connection + 1, &check_set, NULL, NULL, &timeout) > 0 )
-	return TRUE;
-    return FALSE;
-}
-
-
-/***********************************************************************
- *           EVENT_WaitNetEvent
+ * 		EVENT_WaitNetEvent
  *
  * Wait for a network event, optionally sleeping until one arrives.
  * Return TRUE if an event is pending, FALSE on timeout or error
  * (for instance lost connection with the server).
  */
-BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
+BOOL32 EVENT_WaitNetEvent(BOOL32 sleep, BOOL32 peek)
 {
-    XEvent event;
-    LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
-    int pending = TSXPending(display);
-
-    /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
-     * in this case, we fall through directly to the XNextEvent loop.
-     */
-
-    if ((maxWait != -1) && !pending)
-    {
-	int num_pending;
-        struct timeval timeout;
-	fd_set io_set[3];
-
-	memcpy( io_set, __event_io_set, sizeof(io_set) );
-
-	timeout.tv_usec = (maxWait % 1000) * 1000;
-	timeout.tv_sec = maxWait / 1000;
-
-#ifdef CONFIG_IPC
-	sigsetjmp(env_wait_x, 1);
-	stop_wait_op= CONT;
-	    
-	if (DDE_GetRemoteMessage()) {
-	    while(DDE_GetRemoteMessage())
-		;
-	    return TRUE;
-	}
-	stop_wait_op = STOP_WAIT_X;
-	/* The code up to the next "stop_wait_op = CONT" must be reentrant */
-	num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], 
-					      &io_set[EVENT_IO_WRITE], 
-					      &io_set[EVENT_IO_EXCEPT], &timeout );
-	if ( num_pending == 0 )
-        {
-	    stop_wait_op = CONT;
-            TIMER_ExpireTimers();
-	    return FALSE;
-	}
-        else stop_wait_op = CONT;
-#else  /* CONFIG_IPC */
-	num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ],
-					      &io_set[EVENT_IO_WRITE],
-					      &io_set[EVENT_IO_EXCEPT], &timeout );
-	if ( num_pending == 0)
-        {
-            /* Timeout or error */
-            TIMER_ExpireTimers();
-            return FALSE;
-        }
-#endif  /* CONFIG_IPC */
-
-	/*  Winsock asynchronous services */
-
-	if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) ) 
-	{
-	    num_pending--;
-	    if( num_pending )
-		WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
-	}
-	else /* no X events */
-	    return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
-    }
-    else if(!pending)
-    {				/* Wait for X11 input. */
-	fd_set set;
-
-	FD_ZERO(&set);
-	FD_SET(__event_x_connection, &set);
-	select(__event_x_connection + 1, &set, 0, 0, 0 );
-    }
-
-    /* Process current X event (and possibly others that occurred in the meantime) */
-
-    EnterCriticalSection(&X11DRV_CritSection);
-    while (XPending( display ))
-    {
-
-#ifdef CONFIG_IPC
-        if (DDE_GetRemoteMessage())
-        {
-            LeaveCriticalSection(&X11DRV_CritSection);
-            while(DDE_GetRemoteMessage()) ;
-            return TRUE;
-        }
-#endif  /* CONFIG_IPC */
-
-	XNextEvent( display, &event );
-
-        LeaveCriticalSection(&X11DRV_CritSection);
-        if( peek )
-        {
-	  WND*		pWnd;
-	  MESSAGEQUEUE* pQ;
-
-
-	  /* Check only for those events which can be processed
-	   * internally. */
-
-	  if( event.type == MotionNotify ||
-	      event.type == ButtonPress || event.type == ButtonRelease ||
-	      event.type == KeyPress || event.type == KeyRelease ||
-	      event.type == SelectionRequest || event.type == SelectionClear ||
-	      event.type == ClientMessage )
-	  {
-	       EVENT_ProcessEvent( &event );
-               continue;
-	  }
-
-          if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext,
-                            (char **)&pWnd ) || (event.type == NoExpose))
-              pWnd = NULL;
-
-	  if( pWnd )
-          {
-            if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
-            {
-              pQ->flags |= QUEUE_FLAG_XEVENT;
-              PostEvent(pQ->hTask);
-	      TSXPutBackEvent(display, &event);
-              break;
-	    }
-          }
-        }
-        else EVENT_ProcessEvent( &event );
-        EnterCriticalSection(&X11DRV_CritSection);
-    }
-    LeaveCriticalSection(&X11DRV_CritSection);
-    return TRUE;
+  return EVENT_GetDriver()->pWaitNetEvent(sleep, peek);
 }
 
-
 /***********************************************************************
- *           EVENT_Synchronize
+ *		EVENT_Synchronize
  *
  * Synchronize with the X server. Should not be used too often.
  */
-void EVENT_Synchronize()
+void EVENT_Synchronize(void)
 {
-    XEvent event;
-
-    /* Use of the X critical section is needed or we have a small
-     * race between XPending() and XNextEvent().
-     */
-    EnterCriticalSection( &X11DRV_CritSection );
-    XSync( display, False );
-    while (XPending( display ))
-    {
-	XNextEvent( display, &event );
-	/* unlock X critsection for EVENT_ProcessEvent() might switch tasks */
-	LeaveCriticalSection( &X11DRV_CritSection );
-	EVENT_ProcessEvent( &event );
-	EnterCriticalSection( &X11DRV_CritSection );
-    }    
-    LeaveCriticalSection( &X11DRV_CritSection );
+  EVENT_GetDriver()->pSynchronize();
 }
 
-/***********************************************************************
- *           EVENT_QueryZOrder
- *
- * Try to synchronize internal z-order with the window manager's.
- * Probably a futile endeavor.
+/**********************************************************************
+ *		EVENT_CheckFocus
  */
-static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB )
+BOOL32 EVENT_CheckFocus(void)
 {
-    /* return TRUE if we have at least two managed windows */
-
-    for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
-        if( (*pWndA)->flags & WIN_MANAGED &&
-            (*pWndA)->dwStyle & WS_VISIBLE ) break;
-    if( *pWndA )
-        for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
-            if( (*pWndB)->flags & WIN_MANAGED &&
-                (*pWndB)->dwStyle & WS_VISIBLE ) break;
-     return ((*pWndB) != NULL);
+  return EVENT_GetDriver()->pCheckFocus();
 }
 
-static Window __get_common_ancestor( Window A, Window B,
-                                     Window** children, unsigned* total )
-{
-    /* find the real root window */
-
-    Window      root, *childrenB;
-    unsigned    totalB;
-
-    do
-    {
-        if( *children ) TSXFree( *children );
-        TSXQueryTree( display, A, &root, &A, children, total );
-        TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
-        if( childrenB ) TSXFree( childrenB );
-    } while( A != B && A && B );
-    return ( A && B ) ? A : 0 ;
-}
-
-static Window __get_top_decoration( Window w, Window ancestor )
-{
-    Window*     children, root, prev = w, parent = w;
-    unsigned    total;
-
-    do
-    {
-        w = parent;
-        TSXQueryTree( display, w, &root, &parent, &children, &total );
-        if( children ) TSXFree( children );
-    } while( parent && parent != ancestor );
-    TRACE(event, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
-    return ( parent ) ? w : 0 ;
-}
-
-static unsigned __td_lookup( Window w, Window* list, unsigned max )
-{
-    unsigned    i;
-    for( i = 0; i < max; i++ ) if( list[i] == w ) break;
-    return i;
-}
-
-static BOOL32 EVENT_QueryZOrder( WND* pWndCheck )
-{
-    BOOL32      bRet = FALSE;
-    HWND32      hwndInsertAfter = HWND_TOP;
-    WND*        pWnd, *pWndZ = WIN_GetDesktop()->child;
-    Window      w, parent, *children = NULL;
-    unsigned    total, check, pos, best;
-
-    if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE;
-
-    parent = __get_common_ancestor( pWndZ->window, pWnd->window,
-                                      &children, &total );
-    if( parent && children )
-    {
-        w = __get_top_decoration( pWndCheck->window, parent );
-        if( w != children[total - 1] )
-        {
-            check = __td_lookup( w, children, total );
-            best = total;
-            for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
-            {
-                if( pWnd != pWndCheck )
-                {
-                    if( !(pWnd->flags & WIN_MANAGED) ||
-                        !(w = __get_top_decoration( pWnd->window, parent )) )
-                        continue;
-                    pos = __td_lookup( w, children, total );
-                    if( pos < best && pos > check )
-                    {
-                        best = pos;
-                        hwndInsertAfter = pWnd->hwndSelf;
-                    }
-                    if( check - best == 1 ) break;
-                }
-            }
-            WIN_UnlinkWindow( pWndCheck->hwndSelf );
-            WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
-        }
-    }
-    if( children ) TSXFree( children );
-    return bRet;
-}
-
-
 /***********************************************************************
- *           EVENT_XStateToKeyState
- *
- * Translate a X event state (Button1Mask, ShiftMask, etc...) to
- * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
+ *		EVENT_QueryPointer
  */
-static WORD EVENT_XStateToKeyState( int state )
+BOOL32 EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state)
 {
-    int kstate = 0;
-    
-    if (state & Button1Mask) kstate |= MK_LBUTTON;
-    if (state & Button2Mask) kstate |= MK_MBUTTON;
-    if (state & Button3Mask) kstate |= MK_RBUTTON;
-    if (state & ShiftMask)   kstate |= MK_SHIFT;
-    if (state & ControlMask) kstate |= MK_CONTROL;
-    return kstate;
-}
-
-/***********************************************************************
- *           EVENT_QueryPointer
- */
-BOOL32 EVENT_QueryPointer( DWORD *posX, DWORD *posY, DWORD *state )
-{
-    Window root, child;
-    int rootX, rootY, winX, winY;
-    unsigned int xstate;
-
-    if (!TSXQueryPointer( display, rootWindow, &root, &child,
-                          &rootX, &rootY, &winX, &winY, &xstate )) 
-        return FALSE;
-
-    *posX  = (DWORD)winX;
-    *posY  = (DWORD)winY;
-    *state = EVENT_XStateToKeyState( xstate );
-
-    return TRUE;
-}
-
-/***********************************************************************
- *           EVENT_Expose
- */
-static int EVENT_Expose( WND *pWnd, XExposeEvent *event )
-{
-    RECT32 rect;
-    int x, y;
-    unsigned int width, height;
-
-    /* When scrolling, many (fvwm2-based) window managers send the Expose
-     * event before sending the ConfigureNotify event, and we don't like
-     * that, so before processing the Expose event, we check whether the
-     * geometry has changed, and if so, we defer the Expose event until
-     * we get the ConfigureNotify event.  -Ove KÃ¥ven */
-    EVENT_GetGeometry( event->window, &x, &y, &width, &height );
-
-    if ( x != pWnd->rectWindow.left || y != pWnd->rectWindow.top ||
-         (width != pWnd->rectWindow.right - pWnd->rectWindow.left) ||
-         (height != pWnd->rectWindow.bottom - pWnd->rectWindow.top))
-        return 1; /* tell EVENT_ProcessEvent() to defer it */
-
-    /* Make position relative to client area instead of window */
-    rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
-    rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
-    rect.right  = rect.left + event->width;
-    rect.bottom = rect.top + event->height;
-
-    PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
-                        RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
-                        (event->count ? 0 : RDW_ERASENOW), 0 );
-    return 0;
+  return EVENT_GetDriver()->pQueryPointer(posX, posY, state);
 }
 
 
 /***********************************************************************
- *           EVENT_GraphicsExpose
- *
- * This is needed when scrolling area is partially obscured
- * by non-Wine X window.
- */
-static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
-{
-    RECT32 rect;
-
-    /* Make position relative to client area instead of window */
-    rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
-    rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
-    rect.right  = rect.left + event->width;
-    rect.bottom = rect.top + event->height;
-
-    PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
-                        RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
-                        (event->count ? 0 : RDW_ERASENOW), 0 );
-}
-
-
-/***********************************************************************
- *           EVENT_Key
- *
- * Handle a X key event
- */
-static void EVENT_Key( WND *pWnd, XKeyEvent *event )
-{
-    KEYBOARD_HandleEvent( pWnd, event );
-}
-
-
-/***********************************************************************
- *           EVENT_MotionNotify
- */
-static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event )
-{
-    int xOffset = pWnd? pWnd->rectWindow.left : 0;
-    int yOffset = pWnd? pWnd->rectWindow.top  : 0;
-
-    MOUSE_SendEvent( MOUSEEVENTF_MOVE, 
-                     xOffset + event->x, yOffset + event->y,
-                     EVENT_XStateToKeyState( event->state ), 
-                     event->time - MSG_WineStartTicks,
-                     pWnd? pWnd->hwndSelf : 0 );
-}
-
-
-/***********************************************************************
- *           EVENT_DummyMotionNotify
+ *		EVENT_DummyMotionNotify
  *
  * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
  */
 void EVENT_DummyMotionNotify(void)
 {
-    DWORD winX, winY, state;
-
-    if ( EVENT_QueryPointer( &winX, &winY, &state ) )
-    {
-        MOUSE_SendEvent( MOUSEEVENTF_MOVE, winX, winY, state,
-                         GetTickCount(), 0 );
-    }
+  EVENT_GetDriver()->pDummyMotionNotify();
 }
 
+/**********************************************************************
+ *		X11DRV_EVENT_Pending
+ */
+BOOL32 EVENT_Pending()
+{
+  return EVENT_GetDriver()->pPending();
+}
 
 /***********************************************************************
- *           EVENT_ButtonPress
- */
-static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event )
-{
-    static WORD statusCodes[NB_BUTTONS] = 
-        { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
-    int buttonNum = event->button - 1;
-
-    int xOffset = pWnd? pWnd->rectWindow.left : 0;
-    int yOffset = pWnd? pWnd->rectWindow.top  : 0;
-
-    if (buttonNum >= NB_BUTTONS) return;
-
-    MOUSE_SendEvent( statusCodes[buttonNum], 
-                     xOffset + event->x, yOffset + event->y,
-                     EVENT_XStateToKeyState( event->state ), 
-                     event->time - MSG_WineStartTicks,
-                     pWnd? pWnd->hwndSelf : 0 );
-}
-
-
-/***********************************************************************
- *           EVENT_ButtonRelease
- */
-static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event )
-{
-    static WORD statusCodes[NB_BUTTONS] = 
-        { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
-    int buttonNum = event->button - 1;
-
-    int xOffset = pWnd? pWnd->rectWindow.left : 0;
-    int yOffset = pWnd? pWnd->rectWindow.top  : 0;
-
-    if (buttonNum >= NB_BUTTONS) return;    
-
-    MOUSE_SendEvent( statusCodes[buttonNum], 
-                     xOffset + event->x, yOffset + event->y,
-                     EVENT_XStateToKeyState( event->state ), 
-                     event->time - MSG_WineStartTicks,
-                     pWnd? pWnd->hwndSelf : 0 );
-}
-
-
-/**********************************************************************
- *              EVENT_FocusIn
- */
-static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event )
-{
-    if (Options.managed) EVENT_QueryZOrder( pWnd );
-
-    if (event->detail != NotifyPointer)
-    { 
-	HWND32	hwnd = pWnd->hwndSelf;
-
-	if (hwnd != GetActiveWindow32()) 
-        {
-	    WINPOS_ChangeActiveWindow( hwnd, FALSE );
-	    KEYBOARD_UpdateState();
-        }
-	if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32()))
-            SetFocus32( hwnd );
-    }
-}
-
-
-/**********************************************************************
- *              EVENT_FocusOut
+ *		IsUserIdle	(USER.333)
  *
- * Note: only top-level override-redirect windows get FocusOut events.
+ * Check if we have pending X events.
  */
-static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
+BOOL16 WINAPI IsUserIdle(void)
 {
-    if (event->detail != NotifyPointer)
-    {
-	HWND32	hwnd = pWnd->hwndSelf;
-
-	if (hwnd == GetActiveWindow32()) 
-	    WINPOS_ChangeActiveWindow( 0, FALSE );
-	if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
-	    SetFocus32( 0 );
-    }
+  return EVENT_GetDriver()->pIsUserIdle();
 }
-
-/**********************************************************************
- *              EVENT_CheckFocus
- */
-BOOL32 EVENT_CheckFocus(void)
-{
-    WND*   pWnd;
-    Window xW;
-    int	   state;
-
-    TSXGetInputFocus(display, &xW, &state);
-    if( xW == None ||
-        TSXFindContext(display, xW, winContext, (char **)&pWnd) ) 
-        return FALSE;
-    return TRUE;
-}
-
-
-/**********************************************************************
- *              EVENT_GetGeometry
- *
- * 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,
-                               unsigned int *pwidth, unsigned int *pheight )
-{
-    Window root, parent, *children;
-    int xpos, ypos;
-    unsigned int width, height, border, depth, nb_children;
-
-    if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
-                       &border, &depth )) return;
-    if (win == rootWindow)
-    {
-        *px = *py = 0;
-        return;
-    }
-
-    for (;;)
-    {
-        if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
-            return;
-        TSXFree( children );
-        if (parent == rootWindow) break;
-        win = parent;
-        if (!TSXGetGeometry( display, win, &root, &xpos, &ypos,
-                           &width, &height, &border, &depth )) return;
-        *px += xpos;
-        *py += ypos;
-    }
-}
-
-
-/**********************************************************************
- *              EVENT_ConfigureNotify
- *
- * The ConfigureNotify event is only selected on top-level windows
- * when the -managed flag is used.
- */
-static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
-{
-    WINDOWPOS32 winpos;
-    RECT32 newWindowRect, newClientRect;
-    HRGN32 hrgnOldPos, hrgnNewPos;
-    Window above = event->above;
-    int x, y;
-    unsigned int width, height;
-
-    assert (pWnd->flags & WIN_MANAGED);
-
-    /* We don't rely on the event geometry info, because it is relative
-     * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
-     * if the window hasn't moved).
-     */
-    EVENT_GetGeometry( event->window, &x, &y, &width, &height );
-
-    /* Fill WINDOWPOS struct */
-    winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
-    winpos.hwnd = pWnd->hwndSelf;
-    winpos.x = x;
-    winpos.y = y;
-    winpos.cx = width;
-    winpos.cy = height;
-
-    /* Check for unchanged attributes */
-    if (winpos.x == pWnd->rectWindow.left && winpos.y == pWnd->rectWindow.top)
-        winpos.flags |= SWP_NOMOVE;
-    if ((winpos.cx == pWnd->rectWindow.right - pWnd->rectWindow.left) &&
-        (winpos.cy == pWnd->rectWindow.bottom - pWnd->rectWindow.top))
-        winpos.flags |= SWP_NOSIZE;
-    else
-    {
-        RECT32 rect = { 0, 0, pWnd->rectWindow.right - pWnd->rectWindow.left,
-                        pWnd->rectWindow.bottom - pWnd->rectWindow.top };
-        DCE_InvalidateDCE( pWnd, &rect );
-    }
-
-    /* Send WM_WINDOWPOSCHANGING */
-    SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
-
-    /* Calculate new position and size */
-    newWindowRect.left = x;
-    newWindowRect.right = x + width;
-    newWindowRect.top = y;
-    newWindowRect.bottom = y + height;
-
-    WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
-                           &pWnd->rectWindow, &pWnd->rectClient,
-                           &winpos, &newClientRect );
-
-    hrgnOldPos = CreateRectRgnIndirect32( &pWnd->rectWindow );
-    hrgnNewPos = CreateRectRgnIndirect32( &newWindowRect );
-    CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
-    DeleteObject32(hrgnOldPos);
-    DeleteObject32(hrgnNewPos);
- 
-    /* Set new size and position */
-    pWnd->rectWindow = newWindowRect;
-    pWnd->rectClient = newClientRect;
-    SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
-
-    if (!IsWindow32( winpos.hwnd )) return;
-    if( above == None )			/* absolute bottom */
-    {
-        WIN_UnlinkWindow( winpos.hwnd );
-        WIN_LinkWindow( winpos.hwnd, HWND_BOTTOM);
-    }
-    else EVENT_QueryZOrder( pWnd );	/* try to outsmart window manager */
-}
-
-
-/***********************************************************************
- *           EVENT_SelectionRequest
- */
-static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
-{
-    XSelectionEvent result;
-    Atom 	    rprop = None;
-    Window 	    request = event->requestor;
-
-    if(event->target == XA_STRING)
-    {
-	HANDLE16 hText;
-	LPSTR  text;
-	int    size,i,j;
-
-        rprop = event->property;
-
-	if(rprop == None) rprop = event->target;
-
-        if(event->selection!=XA_PRIMARY) rprop = None;
-        else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
-	else
-	{
-            /* open to make sure that clipboard is available */
-
-	    BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf );
-	    char* lpstr = 0;
-
-	    hText = GetClipboardData16(CF_TEXT);
-	    text = GlobalLock16(hText);
-	    size = GlobalSize16(hText);
-
-	    /* remove carriage returns */
-
-	    lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
-	    for(i=0,j=0; i < size && text[i]; i++ )
-	    {
-	       if( text[i] == '\r' && 
-		  (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
-	       lpstr[j++] = text[i];
-	    }
-	    lpstr[j]='\0';
-
-	    TSXChangeProperty(display, request, rprop, 
-			    XA_STRING, 8, PropModeReplace, 
-			    lpstr, j);
-	    HeapFree( GetProcessHeap(), 0, lpstr );
-
-	    /* close only if we opened before */
-
-	    if(couldOpen) CloseClipboard32();
-	}
-    }
-
-    if(rprop == None) 
-       TRACE(event,"Request for %s ignored\n", TSXGetAtomName(display,event->target));
-
-    result.type = SelectionNotify;
-    result.display = display;
-    result.requestor = request;
-    result.selection = event->selection;
-    result.property = rprop;
-    result.target = event->target;
-    result.time = event->time;
-    TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
-}
-
-
-/***********************************************************************
- *           EVENT_SelectionNotify
- */
-static void EVENT_SelectionNotify( XSelectionEvent *event )
-{
-    if (event->selection != XA_PRIMARY) return;
-
-    if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
-    else CLIPBOARD_ReadSelection( event->requestor, event->property );
-
-    TRACE(clipboard,"\tSelectionNotify done!\n");
-}
-
-
-/***********************************************************************
- *           EVENT_SelectionClear
- */
-static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
-{
-    if (event->selection != XA_PRIMARY) return;
-    CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf ); 
-}
-
-
-/**********************************************************************
- *           EVENT_DropFromOffix
- *
- * don't know if it still works (last Changlog is from 96/11/04)
- */
-static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event )
-{
-  unsigned long		data_length;
-  unsigned long		aux_long;
-  unsigned char*	p_data = NULL;
-  union {
-    Atom		atom_aux;
-    POINT32	pt_aux;
-    int		i;
-  }		u;
-  int			x, y;
-  BOOL16	        bAccept;
-  HGLOBAL16		hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
-  LPDRAGINFO            lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
-  SEGPTR		spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
-  Window		w_aux_root, w_aux_child;
-  WND*			pDropWnd;
-  
-  if( !lpDragInfo || !spDragInfo ) return;
-  
-  TSXQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child, 
-		   &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
-  
-  lpDragInfo->hScope = pWnd->hwndSelf;
-  lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
-  
-  /* find out drop point and drop window */
-  if( x < 0 || y < 0 ||
-      x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
-      y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
-    {   bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
-  else
-    {
-      bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
-      x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
-    }
-  pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
-  GlobalFree16( hDragInfo );
-  
-  if( bAccept )
-    {
-      TSXGetWindowProperty( display, DefaultRootWindow(display),
-			    dndSelection, 0, 65535, FALSE,
-			    AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
-			    &data_length, &aux_long, &p_data);
-      
-      if( !aux_long && p_data)	/* don't bother if > 64K */
-	{
-	  char *p = (char*) p_data;
-	  char *p_drop;
-	  
-	  aux_long = 0; 
-	  while( *p )	/* calculate buffer size */
-	    {
-	      p_drop = p;
-	      if((u.i = *p) != -1 ) 
-		u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
-	      if( u.i == -1 ) *p = -1;	/* mark as "bad" */
-	      else
-		{
-		  INT32 len = GetShortPathName32A( p, NULL, 0 );
-		  if (len) aux_long += len + 1;
-		  else *p = -1;
-		}
-	      p += strlen(p) + 1;
-	    }
-	  if( aux_long && aux_long < 65535 )
-	    {
-	      HDROP16                 hDrop;
-	      LPDROPFILESTRUCT16        lpDrop;
-	      
-	      aux_long += sizeof(DROPFILESTRUCT16) + 1; 
-	      hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
-	      lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop );
-	      
-	      if( lpDrop )
-		{
-		  lpDrop->wSize = sizeof(DROPFILESTRUCT16);
-		  lpDrop->ptMousePos.x = (INT16)x;
-		  lpDrop->ptMousePos.y = (INT16)y;
-		  lpDrop->fInNonClientArea = (BOOL16) 
-		    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
-		      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
-		      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
-		      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
-		  p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
-		  p = p_data;
-		  while(*p)
-		    {
-		      if( *p != -1 )	/* use only "good" entries */
-			{
-                          GetShortPathName32A( p, p_drop, 65535 );
-                          p_drop += strlen( p_drop ) + 1;
-			}
-		      p += strlen(p) + 1;
-		    }
-		  *p_drop = '\0';
-		  PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
-				 (WPARAM16)hDrop, 0L );
-		}
-	    }
-	}
-      if( p_data ) TSXFree(p_data);  
-      
-    } /* WS_EX_ACCEPTFILES */
-}
-
-/**********************************************************************
- *           EVENT_DropURLs
- *
- * drop items are separated by \n 
- * each item is prefixed by its mime type
- *
- * event->data.l[3], event->data.l[4] contains drop x,y position
- */
-static void EVENT_DropURLs( WND *pWnd, XClientMessageEvent *event )
-{
-  WND           *pDropWnd;
-  unsigned long	data_length;
-  unsigned long	aux_long, drop_len = 0;
-  unsigned char	*p_data = NULL; /* property data */
-  char		*p_drop = NULL;
-  char          *p, *next;
-  int		x, y, drop32 = FALSE ;
-  union {
-    Atom	atom_aux;
-    POINT32	pt_aux;
-    int         i;
-    Window      w_aux;
-  }		u; /* unused */
-  union {
-    HDROP16     h16;
-    HDROP32     h32;
-  } hDrop;
-
-  drop32 = pWnd->flags & WIN_ISWIN32;
-
-  if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
-    return;
-
-  TSXGetWindowProperty( display, DefaultRootWindow(display),
-			dndSelection, 0, 65535, FALSE,
-			AnyPropertyType, &u.atom_aux, &u.i,
-			&data_length, &aux_long, &p_data);
-  if (aux_long)
-    WARN(event,"property too large, truncated!\n");
-  TRACE(event,"urls=%s\n", p_data);
-
-  if( !aux_long && p_data) {	/* don't bother if > 64K */
-    /* calculate length */
-    p = p_data;
-    next = strchr(p, '\n');
-    while (p) {
-      if (next) *next=0;
-      if (strncmp(p,"file:",5) == 0 ) {
-	INT32 len = GetShortPathName32A( p+5, NULL, 0 );
-	if (len) drop_len += len + 1;
-      }
-      if (next) { 
-	*next = '\n'; 
-	p = next + 1;
-	next = strchr(p, '\n');
-      } else {
-	p = NULL;
-      }
-    }
-    
-    if( drop_len && drop_len < 65535 ) {
-      TSXQueryPointer( display, rootWindow, &u.w_aux, &u.w_aux, 
-		       &x, &y, &u.i, &u.i, &u.i);
-      pDropWnd = WIN_FindWndPtr( pWnd->hwndSelf );
-      
-      if (drop32) {
-	LPDROPFILESTRUCT32        lpDrop;
-	drop_len += sizeof(DROPFILESTRUCT32) + 1; 
-	hDrop.h32 = (HDROP32)GlobalAlloc32( GMEM_SHARE, drop_len );
-	lpDrop = (LPDROPFILESTRUCT32) GlobalLock32( hDrop.h32 );
-	
-	if( lpDrop ) {
-	  lpDrop->lSize = sizeof(DROPFILESTRUCT32);
-	  lpDrop->ptMousePos.x = (INT32)x;
-	  lpDrop->ptMousePos.y = (INT32)y;
-	  lpDrop->fInNonClientArea = (BOOL32) 
-	    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
-	      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
-	      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
-	      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
-	  lpDrop->fWideChar = FALSE;
-	  p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT32);
-	}
-      } else {
-	LPDROPFILESTRUCT16        lpDrop;
-	drop_len += sizeof(DROPFILESTRUCT16) + 1; 
-	hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len );
-	lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 );
-	
-	if( lpDrop ) {
-	  lpDrop->wSize = sizeof(DROPFILESTRUCT16);
-	  lpDrop->ptMousePos.x = (INT16)x;
-	  lpDrop->ptMousePos.y = (INT16)y;
-	  lpDrop->fInNonClientArea = (BOOL16) 
-	    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
-	      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
-	      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
-	      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
-	  p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
-	}
-      }
-      
-      /* create message content */
-      if (p_drop) {
-	p = p_data;
-	next = strchr(p, '\n');
-	while (p) {
-	  if (next) *next=0;
-	  if (strncmp(p,"file:",5) == 0 ) {
-	    INT32 len = GetShortPathName32A( p+5, p_drop, 65535 );
-	    if (len) {
-	      TRACE(event, "drop file %s as %s\n", p+5, p_drop);
-	      p_drop += len+1;
-	    } else {
-	      WARN(event, "can't convert file %s to dos name \n", p+5);
-	    }
-	  } else {
-	    WARN(event, "unknown mime type %s\n", p);
-	  }
-	  if (next) { 
-	    *next = '\n'; 
-	    p = next + 1;
-	    next = strchr(p, '\n');
-	  } else {
-	    p = NULL;
-	  }
-	  *p_drop = '\0';
-	}
-
-	if (drop32) {
-	  /* can not use PostMessage32A because it is currently based on 
-	   * PostMessage16 and WPARAM32 would be truncated to WPARAM16
-	   */
-	  GlobalUnlock32(hDrop.h32);
-	  SendMessage32A( pWnd->hwndSelf, WM_DROPFILES,
-			  (WPARAM32)hDrop.h32, 0L );
-	} else {
-	  GlobalUnlock16(hDrop.h16);
-	  PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
-			 (WPARAM16)hDrop.h16, 0L );
-	}
-      }
-    }
-    if( p_data ) TSXFree(p_data);  
-  }
-}
-
-/**********************************************************************
- *           EVENT_ClientMessage
- */
-static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
-{
-    if (event->message_type != None && event->format == 32) {
-      if ((event->message_type == wmProtocols) && 
-	  (((Atom) event->data.l[0]) == wmDeleteWindow))
-	SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
-      else if ( event->message_type == dndProtocol &&
-		(event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
-	EVENT_DropFromOffiX(pWnd, event);
-      else if ( event->message_type == dndProtocol &&
-		event->data.l[0] == DndURL )
-	EVENT_DropURLs(pWnd, event);
-      else {
-#if 0
-	/* enable this if you want to see the message */
-	unsigned char* p_data = NULL;
-	union {
-	  unsigned long	l;
-	  int            	i;
-	  Atom		atom;
-	} u; /* unused */
-	TSXGetWindowProperty( display, DefaultRootWindow(display),
-			      dndSelection, 0, 65535, FALSE,
-			      AnyPropertyType, &u.atom, &u.i,
-			      &u.l, &u.l, &p_data);
-	TRACE(event, "message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
-	      event->message_type, event->data.l[0], event->data.l[1], 
-	      event->data.l[2], event->data.l[3], event->data.l[4],
-	      p_data);
-#endif
-	TRACE(event, "unrecognized ClientMessage\n" );
-      }
-    }
-}
-
-/**********************************************************************
- *           EVENT_EnterNotify
- *
- * Install colormap when Wine window is focused in
- * self-managed mode with private colormap
- */
-/*
-  void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
-  {
-   if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
-     (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
-      TSXInstallColormap( display, COLOR_GetColormap() );
-  }
- */ 
-
-/**********************************************************************
- *		EVENT_MapNotify
- */
-void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
-{
-    HWND32 hwndFocus = GetFocus32();
-
-    if (hwndFocus && IsChild32( hWnd, hwndFocus ))
-      FOCUS_SetXFocus( (HWND32)hwndFocus );
-
-    return;
-}
-
diff --git a/windows/focus.c b/windows/focus.c
index 92c757a..5e64fe2 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -17,46 +17,11 @@
 static HWND32 hwndFocus = 0;
 
 /*****************************************************************
- *               FOCUS_SetXFocus
- *
- * Set the X focus.
- * Explicit colormap management seems to work only with OLVWM.
- */
-void FOCUS_SetXFocus( HWND32 hwnd )
-{
-    XWindowAttributes win_attr;
-    Window win;
-
-    /* Only mess with the X focus if there's */
-    /* no desktop window and no window manager. */
-    if ((rootWindow != DefaultRootWindow(display)) || Options.managed) return;
-
-    if (!hwnd)	/* If setting the focus to 0, uninstall the colormap */
-    {
-	if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
-	    TSXUninstallColormap( display, COLOR_GetColormap() );
-	return;
-    }
-
-      /* Set X focus and install colormap */
-
-    if (!(win = WIN_GetXWindow( hwnd ))) return;
-    if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
-        (win_attr.map_state != IsViewable))
-        return;  /* If window is not viewable, don't change anything */
-
-    TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
-    if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
-        TSXInstallColormap( display, COLOR_GetColormap() );
-
-    EVENT_Synchronize();
-}
-
-/*****************************************************************
  *	         FOCUS_SwitchFocus 
  */
 void FOCUS_SwitchFocus( HWND32 hFocusFrom, HWND32 hFocusTo )
 {
+    WND *pFocusTo = WIN_FindWndPtr( hFocusTo );
     hwndFocus = hFocusTo;
 
 #if 0
@@ -71,7 +36,8 @@
 
     /* According to API docs, the WM_SETFOCUS message is sent AFTER the window
        has received the keyboard focus. */
-    FOCUS_SetXFocus( hFocusTo );
+
+    pFocusTo->pDriver->pSetFocus(pFocusTo);
 
 #if 0
     SendMessage32A( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
diff --git a/windows/keyboard.c b/windows/keyboard.c
index a4eed11..85ea3b8 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -12,12 +12,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <X11/keysym.h>
-#include "ts_xlib.h"
-#include "ts_xresource.h"
-#include "ts_xutil.h"
-#include <X11/Xatom.h>
-
 #include "windows.h"
 #include "win.h"
 #include "gdi.h"
@@ -30,254 +24,16 @@
 #include "winerror.h"
 
 static LPKEYBD_EVENT_PROC DefKeybEventProc = NULL;
-static LPBYTE pKeyStateTable = NULL;
+LPBYTE pKeyStateTable = NULL;
 
-int min_keycode, max_keycode, keysyms_per_keycode;
-WORD keyc2vkey[256];
+extern KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver;
 
-static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
-static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
-
-/* Keyboard translation tables */
-static const int special_key[] =
-{
-    VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
-    0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
-    0, 0, 0, VK_ESCAPE                                          /* FF18 */
-};
-
-static const int cursor_key[] =
-{
-    VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
-                                       VK_NEXT, VK_END          /* FF50 */
-};
-
-static const int misc_key[] =
-{
-    VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
-    VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
-};
-
-static const int keypad_key[] =
-{
-    0, VK_NUMLOCK,                                        	/* FF7E */
-    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
-    0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
-    0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
-    VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
-				 VK_INSERT, VK_DELETE,          /* FF98 */
-    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
-    0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
-                               VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
-    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
-                            VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
-    VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
-};
-    
-static const int function_key[] =
-{
-    VK_F1, VK_F2,                                               /* FFBE */
-    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
-    VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
-};
-
-static const int modifier_key[] =
-{
-    VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
-    VK_MENU, VK_MENU, VK_MENU, VK_MENU                         /* FFE7 */
-};
-
-/* Returns the Windows virtual key code associated with the X event <e> */
-static WORD EVENT_event_to_vkey( XKeyEvent *e)
-{
-    KeySym keysym;
-
-    TSXLookupString(e, NULL, 0, &keysym, NULL);
-
-    if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask)) 
-        /* Only the Keypad keys 0-9 and . send different keysyms
-         * depending on the NumLock state */
-        return keypad_key[(keysym & 0xFF) - 0x7E];
-
-    return keyc2vkey[e->keycode];
-}
-
-/**********************************************************************
- *		KEYBOARD_Init
+/***********************************************************************
+ *           KEYBOARD_GetDriver
  */
-static void KEYBOARD_Init(void)
+KEYBOARD_DRIVER *KEYBOARD_GetDriver()
 {
-    int i;
-    KeySym *ksp;
-    XModifierKeymap *mmp;
-    KeySym keysym;
-    KeyCode *kcp;
-    XKeyEvent e2;
-    WORD vkey, OEMvkey;
-    int keyc;
-
-    TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
-    ksp = TSXGetKeyboardMapping(display, min_keycode,
-                              max_keycode + 1 - min_keycode, &keysyms_per_keycode);
-    /* We are only interested in keysyms_per_keycode.
-       There is no need to hold a local copy of the keysyms table */
-    TSXFree(ksp);
-    mmp = TSXGetModifierMapping(display);
-    kcp = mmp->modifiermap;
-    for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
-    {
-        int j;
-        
-        for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
-	    if (*kcp)
-            {
-		int k;
-                
-		for (k = 0; k < keysyms_per_keycode; k += 1)
-                    if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
-		    {
-                        AltGrMask = 1 << i;
-                        TRACE(key, "AltGrMask is %x\n", AltGrMask);
-		    }
-                    else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
-		    {
-                        NumLockMask = 1 << i;
-                        TRACE(key, "NumLockMask is %x\n", NumLockMask);
-		    }
-            }
-    }
-    TSXFreeModifiermap(mmp);
-
-    /* Now build two conversion arrays :
-     * keycode -> vkey + extended
-     * vkey + extended -> keycode */
-
-    e2.display = display;
-    e2.state = 0;
-
-    OEMvkey = VK_OEM_7; /* next is available.  */
-    for (keyc = min_keycode; keyc <= max_keycode; keyc++)
-    {
-        e2.keycode = (KeyCode)keyc;
-        TSXLookupString(&e2, NULL, 0, &keysym, NULL);
-        vkey = 0;
-        if (keysym)  /* otherwise, keycode not used */
-        {
-            if ((keysym >> 8) == 0xFF)         /* non-character key */
-            {
-                int key = keysym & 0xff;
-		
-                if (key >= 0x08 && key <= 0x1B)         /* special key */
-		    vkey = special_key[key - 0x08];
-                else if (key >= 0x50 && key <= 0x57)    /* cursor key */
-		    vkey = cursor_key[key - 0x50];
-                else if (key >= 0x60 && key <= 0x6B)    /* miscellaneous key */
-		    vkey = misc_key[key - 0x60];
-                else if (key >= 0x7E && key <= 0xB9)    /* keypad key */
-		    vkey = keypad_key[key - 0x7E];
-                else if (key >= 0xBE && key <= 0xCD)    /* function key */
-                {
-                    vkey = function_key[key - 0xBE];
-                    vkey |= 0x100; /* set extended bit */
-                }
-                else if (key >= 0xE1 && key <= 0xEA)    /* modifier key */
-		    vkey = modifier_key[key - 0xE1];
-                else if (key == 0xFF)                   /* DEL key */
-		    vkey = VK_DELETE;
-                /* extended must also be set for ALT_R, CTRL_R,
-                   INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
-                   keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
-                /* FIXME should we set extended bit for NumLock ? My
-                 * Windows does ... DF */
-                switch (keysym)
-                {
-                case XK_Control_R :
-                case XK_Alt_R :
-                case XK_Insert :
-                case XK_Delete :
-                case XK_Home :
-                case XK_End :
-                case XK_Prior :
-                case XK_Next :
-                case XK_Left :
-                case XK_Up :
-                case XK_Right :
-                case XK_Down :
-                case XK_KP_Divide :
-                case XK_KP_Enter :
-                    vkey |= 0x100;
-                }
-            }
-            for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
-            {
-                keysym = TSXLookupKeysym(&e2, i);
-                if ((keysym >= VK_0 && keysym <= VK_9)
-                    || (keysym >= VK_A && keysym <= VK_Z)
-                    || keysym == VK_SPACE)
-		    vkey = keysym;
-            }
-
-            for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
-            {
-                keysym = TSXLookupKeysym(&e2, i);
-		switch (keysym)
-		{
-		case ';':             vkey = VK_OEM_1; break;
-		case '/':             vkey = VK_OEM_2; break;
-		case '`':             vkey = VK_OEM_3; break;
-		case '[':             vkey = VK_OEM_4; break;
-		case '\\':            vkey = VK_OEM_5; break;
-		case ']':             vkey = VK_OEM_6; break;
-		case '\'':            vkey = VK_OEM_7; break;
-		case ',':             vkey = VK_OEM_COMMA; break;
-		case '.':             vkey = VK_OEM_PERIOD; break;
-		case '-':             vkey = VK_OEM_MINUS; break;
-		case '+':             vkey = VK_OEM_PLUS; break;
-		}
-	    }
-
-            if (!vkey)
-            {
-                /* Others keys: let's assign OEM virtual key codes in the allowed range,
-                 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
-                switch (++OEMvkey)
-                {
-                case 0xc1 : OEMvkey=0xdb; break;
-                case 0xe5 : OEMvkey=0xe9; break;
-                case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n");
-                }
-
-                vkey = OEMvkey;
-		  
-                if (TRACE_ON(keyboard))
-                {
-		    dbg_decl_str(keyboard, 1024);
-
-                    TRACE(keyboard, "OEM specific virtual key %X assigned "
-				 "to keycode %X:\n", OEMvkey, e2.keycode);
-                    for (i = 0; i < keysyms_per_keycode; i += 1)
-                    {
-                        char	*ksname;
-                        
-                        keysym = TSXLookupKeysym(&e2, i);
-                        ksname = TSXKeysymToString(keysym);
-                        if (!ksname)
-			    ksname = "NoSymbol";
-                        dsprintf(keyboard, "%lX (%s) ", keysym, ksname);
-                    }
-                    TRACE(keyboard, "(%s)\n", dbg_str(keyboard));
-                }
-            }
-        }
-        keyc2vkey[e2.keycode] = vkey;
-    } /* for */
-    /* Now store one keycode for each modifier. Used to simulate keypresses. */
-    kcControl = TSXKeysymToKeycode(display, XK_Control_L);
-    kcAlt = TSXKeysymToKeycode(display, XK_Alt_L);
-    if (!kcAlt) kcAlt = TSXKeysymToKeycode(display, XK_Meta_L);
-    kcShift = TSXKeysymToKeycode(display, XK_Shift_L);
-    kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock);
-    kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock);
+  return &X11DRV_KEYBOARD_Driver;
 }
 
 /***********************************************************************
@@ -285,13 +41,13 @@
  */
 WORD WINAPI KEYBOARD_Inquire(LPKBINFO kbInfo) 
 {
-    kbInfo->Begin_First_Range = 0;
-    kbInfo->End_First_Range = 0;
-    kbInfo->Begin_Second_Range = 0;
-    kbInfo->End_Second_Range = 0;
-    kbInfo->StateSize = 16; 
-
-    return sizeof(KBINFO);
+  kbInfo->Begin_First_Range = 0;
+  kbInfo->End_First_Range = 0;
+  kbInfo->Begin_Second_Range = 0;
+  kbInfo->End_Second_Range = 0;
+  kbInfo->StateSize = 16; 
+  
+  return sizeof(KBINFO);
 }
 
 /***********************************************************************
@@ -300,16 +56,16 @@
 VOID WINAPI KEYBOARD_Enable( LPKEYBD_EVENT_PROC lpKeybEventProc, 
                              LPBYTE lpKeyState )
 {
-    static BOOL32 initDone = FALSE;
-
-    DefKeybEventProc = lpKeybEventProc;
-    pKeyStateTable = lpKeyState;
-
-    /* all states to false */
-    memset( lpKeyState, 0, sizeof(lpKeyState) );
-
-    if (!initDone) KEYBOARD_Init();
-    initDone = TRUE;
+  static BOOL32 initDone = FALSE;
+  
+  DefKeybEventProc = lpKeybEventProc;
+  pKeyStateTable = lpKeyState;
+  
+  /* all states to false */
+  memset( lpKeyState, 0, sizeof(lpKeyState) );
+  
+  if (!initDone) KEYBOARD_GetDriver()->pInit();
+  initDone = TRUE;
 }
 
 /***********************************************************************
@@ -317,8 +73,8 @@
  */
 VOID WINAPI KEYBOARD_Disable(VOID)
 {
-    DefKeybEventProc = NULL;
-    pKeyStateTable = NULL;
+  DefKeybEventProc = NULL;
+  pKeyStateTable = NULL;
 }
 
 /***********************************************************************
@@ -327,239 +83,26 @@
 void KEYBOARD_SendEvent( BYTE bVk, BYTE bScan, DWORD dwFlags,
                          DWORD posX, DWORD posY, DWORD time )
 {
-    WINE_KEYBDEVENT wke;
-
-    if ( !DefKeybEventProc ) return;
-
-    TRACE( event, "(%d,%d,%04lX)\n", bVk, bScan, dwFlags );
-
-    wke.magic = WINE_KEYBDEVENT_MAGIC;
-    wke.posX  = posX;
-    wke.posY  = posY;
-    wke.time  = time;
-
-    DefKeybEventProc( bVk, bScan, dwFlags, (DWORD)&wke );
+  WINE_KEYBDEVENT wke;
+  
+  if ( !DefKeybEventProc ) return;
+  
+  TRACE( event, "(%d,%d,%04lX)\n", bVk, bScan, dwFlags );
+  
+  wke.magic = WINE_KEYBDEVENT_MAGIC;
+  wke.posX  = posX;
+  wke.posY  = posY;
+  wke.time  = time;
+  
+  DefKeybEventProc( bVk, bScan, dwFlags, (DWORD)&wke );
 }
 
-
-static BOOL32 NumState=FALSE, CapsState=FALSE;
-
-/**********************************************************************
- *		KEYBOARD_GenerateMsg
- *
- * Generate Down+Up messages when NumLock or CapsLock is pressed.
- *
- * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
- *
- */
-void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
-                           DWORD event_time )
-{
-  BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
-
-  if (*State) {
-    /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
-       don't treat it. It's from the same key press. Then the state goes to ON.
-       And from there, a 'release' event will switch off the toggle key. */
-    *State=FALSE;
-    TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]);
-  } else
-    {
-	if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */
-	  {
-	    if (Evtype!=KeyPress)
-	      {
-		TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n");
-	        KEYBOARD_SendEvent( vkey, 0, 0,
-                                    event_x, event_y, event_time );
-	        KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, 
-                                    event_x, event_y, event_time );
-		*State=FALSE;
-		pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */ 
-	      } 
-	  }
-	else /* it was OFF */
-	  if (Evtype==KeyPress)
-	    {
-	      TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n");
-	      KEYBOARD_SendEvent( vkey, 0, 0,
-                                  event_x, event_y, event_time );
-	      KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, 
-                                  event_x, event_y, event_time );
-	      *State=TRUE; /* Goes to intermediary state before going to ON */
-	      pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
-	    }
-    }
-}
-
-/***********************************************************************
- *           KEYBOARD_UpdateOneState
- *
- * Updates internal state for <vkey>, depending on key <state> under X
- *
- */
-void KEYBOARD_UpdateOneState ( int vkey, int state )
-{
-    /* Do something if internal table state != X state for keycode */
-    if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
-    {
-        TRACE(keyboard,"Adjusting state for vkey %#.2x. State before %#.2x \n",
-              vkey, pKeyStateTable[vkey]);
-
-        /* Fake key being pressed inside wine */
-	KEYBOARD_SendEvent( vkey, 0, state? 0 : KEYEVENTF_KEYUP, 
-                            0, 0, GetTickCount() );
-
-        TRACE(keyboard,"State after %#.2x \n",pKeyStateTable[vkey]);
-    }
-}
-
-/***********************************************************************
- *           KEYBOARD_UpdateState
- *
- * Update modifiers state (Ctrl, Alt, Shift)
- * when window is activated (called by EVENT_FocusIn in event.c)
- *
- * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
- * from wine to another application and back.
- * Toggle keys are handled in HandleEvent. (because XQueryKeymap says nothing
- *  about them)
- */
-void KEYBOARD_UpdateState ( void )
-{
-/* extract a bit from the char[32] bit suite */
-#define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0)
-
-    char keys_return[32];
-
-    TRACE(keyboard,"called\n");
-    if (!TSXQueryKeymap(display, keys_return)) {
-        ERR(keyboard,"Error getting keymap !");
-        return;
-    }
-
-    /* Adjust the ALT and CONTROL state if any has been changed outside wine */
-    KEYBOARD_UpdateOneState(VK_MENU, KeyState(kcAlt));
-    KEYBOARD_UpdateOneState(VK_CONTROL, KeyState(kcControl));
-    KEYBOARD_UpdateOneState(VK_SHIFT, KeyState(kcShift));
-#undef KeyState
-}
-
-/***********************************************************************
- *           KEYBOARD_HandleEvent
- *
- * Handle a X key event
- */
-void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
-{
-    char Str[24]; 
-    XComposeStatus cs; 
-    KeySym keysym;
-    WORD vkey = 0, bScan;
-    DWORD dwFlags;
-    static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
-    
-    int ascii_chars;
-
-    INT32 event_x = (pWnd? pWnd->rectWindow.left : 0) + event->x;
-    INT32 event_y = (pWnd? pWnd->rectWindow.top  : 0) + event->y;
-    DWORD event_time = event->time - MSG_WineStartTicks;
-
-    /* this allows support for dead keys */
-    if ((event->keycode >> 8) == 0x10)
-	event->keycode=(event->keycode & 0xff);
-
-    ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs);
-
-    TRACE(key, "EVENT_key : state = %X\n", event->state);
-    if (keysym == XK_Mode_switch)
-	{
-	TRACE(key, "Alt Gr key event received\n");
-	event->keycode = kcControl; /* Simulate Control */
-	KEYBOARD_HandleEvent( pWnd, event );
-
-	event->keycode = kcAlt; /* Simulate Alt */
-	force_extended = TRUE;
-	KEYBOARD_HandleEvent( pWnd, event );
-	force_extended = FALSE;
-	return;
-	}
-
-    Str[ascii_chars] = '\0';
-    if (TRACE_ON(key)){
-	char	*ksname;
-
-	ksname = TSXKeysymToString(keysym);
-	if (!ksname)
-	  ksname = "No Name";
-	TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", 
-		     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
-		     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
-    }
-
-    vkey = EVENT_event_to_vkey(event);
-    if (force_extended) vkey |= 0x100;
-
-    TRACE(key, "keycode 0x%x converted to vkey 0x%x\n",
-		    event->keycode, vkey);
-
-   if (vkey)
-   {
-    switch (vkey & 0xff)
-    {
-    case VK_NUMLOCK:    
-      KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
-                            event_time );
-      break;
-    case VK_CAPITAL:
-      TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
-      KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
-                            event_time ); 
-      TRACE(keyboard,"State after : %#.2x\n",pKeyStateTable[vkey]);
-      break;
-    default:
-        /* Adjust the NUMLOCK state if it has been changed outside wine */
-	if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
-	  { 
-	    TRACE(keyboard,"Adjusting NumLock state. \n");
-	    KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
-                                  event_time );
-	    KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
-                                  event_time );
-	  }
-        /* Adjust the CAPSLOCK state if it has been changed outside wine */
-	if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
-	  {
-              TRACE(keyboard,"Adjusting Caps Lock state.\n");
-	    KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
-                                  event_time );
-	    KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
-                                  event_time );
-	  }
-	/* Not Num nor Caps : end of intermediary states for both. */
-	NumState = FALSE;
-	CapsState = FALSE;
-
-	bScan = event->keycode - min_keycode; /* Windows starts from 0, X from
-                                                 min_keycode (8 usually) */
-	dwFlags = 0;
-	if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
-	if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
-	if ( force_extended )            dwFlags |= KEYEVENTF_WINE_FORCEEXTENDED;
-
-	KEYBOARD_SendEvent( vkey & 0xff, bScan, dwFlags, 
-                            event_x, event_y, event_time );
-    }
-   }
-}
-
-
 /**********************************************************************
  *           ScreenSwitchEnable      (KEYBOARD.100)
  */
 VOID WINAPI ScreenSwitchEnable(WORD unused)
 {
-    FIXME(keyboard,"(%04x): stub\n",unused);
+  FIXME(keyboard,"(%04x): stub\n",unused);
 }
 
 /**********************************************************************
@@ -567,9 +110,9 @@
  */
 DWORD WINAPI OemKeyScan(WORD wOemChar)
 {
-    TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar);
+  TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar);
 
-    return wOemChar;
+  return wOemChar;
 }
 
 /**********************************************************************
@@ -592,46 +135,7 @@
 
 WORD WINAPI VkKeyScan16(CHAR cChar)
 {
-	KeyCode keycode;
-	KeySym keysym;    	
-	int i,index;
-	int highbyte=0;
-
-	/* char->keysym (same for ANSI chars) */
-	keysym=(unsigned char) cChar;/* (!) cChar is signed */
-	if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
-	
-	keycode = TSXKeysymToKeycode(display, keysym);  /* keysym -> keycode */
-	if (!keycode)
-	{ /* It didn't work ... let's try with deadchar code. */
-	  keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
-	}
-
-	TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
-			 cChar,keysym,keysym,keycode);
-	
-	if (keycode)
-	  {
-	    for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
-	      if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
-	    switch (index) {
-	    case -1 :
-	      WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
-	    case 0 : break;
-	    case 1 : highbyte = 0x0100; break;
-	    case 2 : highbyte = 0X0600; break;
-	    default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index);
-	    }
-	    /*
-	      index : 0     adds 0x0000
-	      index : 1     adds 0x0100 (shift)
-	      index : ?     adds 0x0200 (ctrl)
-	      index : 2     adds 0x0600 (ctrl+alt)
-	      index : ?     adds 0x0700 (ctrl+alt+shift (used?))
-	     */
-	  }
-	TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
-	return keyc2vkey[keycode]+highbyte;   /* keycode -> (keyc2vkey) vkey */
+  return KEYBOARD_GetDriver()->pVkKeyScan(cChar);
 }
 
 /******************************************************************************
@@ -664,55 +168,16 @@
  */
 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
 {
-#define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
-
-	TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
-			 wCode,wMapType);
-	switch(wMapType) {
-		case 0:	{ /* vkey-code to scan-code */
-			/* let's do vkey -> keycode -> scan */
-			int keyc;
-			for (keyc=min_keycode; keyc<=max_keycode; keyc++)
-				if ((keyc2vkey[keyc] & 0xFF) == wCode)
-					returnMVK (keyc - min_keycode);
-		        return 0; }
-
-		case 1: /* scan-code to vkey-code */
-			/* let's do scan -> keycode -> vkey */
-
-			returnMVK (keyc2vkey[(wCode & 0xFF) + min_keycode]);
-
-		case 2: { /* vkey-code to unshifted ANSI code */
-			/* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
-		        /* My Windows returns 'A'. */
-			/* let's do vkey -> keycode -> (XLookupString) ansi char */
-			XKeyEvent e;
-			KeySym keysym;
-			char s[2];
-			e.display = display;
-			e.state = 0; /* unshifted */
-			e.keycode = MapVirtualKey16( wCode, 0);
-			if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
-			  returnMVK (*s);
-			
-			return 0;
-			}
-		default: /* reserved */
-			WARN(keyboard, "Unknown wMapType %d !\n",
-				wMapType);
-			return 0;	
-	}
-	return 0;
+  return KEYBOARD_GetDriver()->pMapVirtualKey(wCode,wMapType);
 }
 
-
 /****************************************************************************
  *	GetKBCodePage16   (KEYBOARD.132)
  */
 INT16 WINAPI GetKBCodePage16(void)
 {
-    TRACE(keyboard,"(void)\n");
-    return 850;
+  TRACE(keyboard,"(void)\n");
+  return 850;
 }
 
 /****************************************************************************
@@ -720,227 +185,32 @@
  */
 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
 {
-  /*	int i; */
-	
-        FIXME(keyboard,"(%ld,<ptr>,%d): stub\n",lParam,nSize);
-
- 	/*
-        lParam >>= 16;
-        lParam &= 0xff;
-
-		for (i = 0 ; i != KeyTableSize ; i++) 
-		if (KeyTable[i].scancode == lParam)  {
-			lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
-			return strlen(lpBuffer);
-		}
-		*/
-
-	*lpBuffer = 0;
-	return 0;
+  return KEYBOARD_GetDriver()->pGetKeyNameText(lParam, lpBuffer, nSize);
 }
 
 /****************************************************************************
  *	ToAscii   (KEYBOARD.4)
-
-The ToAscii function translates the specified virtual-key code and keyboard
-state to the corresponding Windows character or characters.
-
-If the specified key is a dead key, the return value is negative. Otherwise,
-it is one of the following values:
-Value	Meaning
-0	The specified virtual key has no translation for the current state of the keyboard.
-1	One Windows character was copied to the buffer.
-2	Two characters were copied to the buffer. This usually happens when a
-        dead-key character (accent or diacritic) stored in the keyboard layout cannot
-        be composed with the specified virtual key to form a single character.
-
-FIXME : should do the above (return 2 for non matching deadchar+char combinations)
-
+ *
+ * The ToAscii function translates the specified virtual-key code and keyboard
+ * state to the corresponding Windows character or characters.
+ *
+ * If the specified key is a dead key, the return value is negative. Otherwise,
+ * it is one of the following values:
+ * Value	Meaning
+ * 0	The specified virtual key has no translation for the current state of the keyboard.
+ * 1	One Windows character was copied to the buffer.
+ * 2	Two characters were copied to the buffer. This usually happens when a
+ *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
+ *      be composed with the specified virtual key to form a single character.
+ *
+ * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
+ *
  */
 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, 
                        LPVOID lpChar, UINT16 flags) 
 {
-    XKeyEvent e;
-    KeySym keysym;
-    static XComposeStatus cs;
-    INT32 ret;
-    int keyc;
-
-    if (scanCode==0) {
-        /* This happens when doing Alt+letter : a fake 'down arrow' key press
-           event is generated by windows. Just ignore it. */
-        TRACE(keyboard,"scanCode=0, doing nothing\n");
-        return 0;
-    }
-    e.display = display;
-    e.keycode = 0;
-    e.state = 0;
-    if (lpKeyState[VK_SHIFT] & 0x80)
-	e.state |= ShiftMask;
-    if (lpKeyState[VK_CAPITAL] & 0x01)
-	e.state |= LockMask;
-    if (lpKeyState[VK_CONTROL] & 0x80)
-    {
-	if (lpKeyState[VK_MENU] & 0x80)
-	    e.state |= AltGrMask;
-	else
-	    e.state |= ControlMask;
-    }
-    if (lpKeyState[VK_NUMLOCK] & 0x01)
-	e.state |= NumLockMask;
-    TRACE(key, "(%04X, %04X) : faked state = %X\n",
-		virtKey, scanCode, e.state);
-    /* We exit on the first keycode found, to speed up the thing. */
-    for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
-      { /* Find a keycode that could have generated this virtual key */
-          if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
-          { /* We filter the extended bit, we don't know it */
-              e.keycode = keyc; /* Store it temporarily */
-              if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) {
-                  e.keycode = 0; /* Wrong one (ex: because of the NumLock
-                         state), so set it to 0, we'll find another one */
-              }
-	  }
-      }
-
-    if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
-        e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
-          
-    if (virtKey==VK_DECIMAL)
-        e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
-
-    if (!e.keycode)
-      {
-	WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey);
-	return virtKey; /* whatever */
-      }
-    else TRACE(keyboard,"Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
-
-    ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
-    if (ret == 0)
-	{
-	BYTE dead_char = 0;
-
-	((char*)lpChar)[1] = '\0';
-	switch (keysym)
-	    {
-	/* symbolic ASCII is the same as defined in rfc1345 */
-#ifdef XK_dead_tilde
-	    case XK_dead_tilde :
-#endif
-	    case 0x1000FE7E : /* Xfree's XK_Dtilde */
-		dead_char = '~';	/* '? */
-		break;
-#ifdef XK_dead_acute
-	    case XK_dead_acute :
-#endif
-	    case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
-		dead_char = 0xb4;	/* '' */
-		break;
-#ifdef XK_dead_circumflex
-	    case XK_dead_circumflex :
-#endif
-	    case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
-		dead_char = '^';	/* '> */
-		break;
-#ifdef XK_dead_grave
-	    case XK_dead_grave :
-#endif
-	    case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
-		dead_char = '`';	/* '! */
-		break;
-#ifdef XK_dead_diaeresis
-	    case XK_dead_diaeresis :
-#endif
-	    case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
-		dead_char = 0xa8;	/* ': */
-		break;
-#ifdef XK_dead_cedilla
-	    case XK_dead_cedilla :
-	        dead_char = 0xb8;	/* ', */
-	        break;
-#endif
-#ifdef XK_dead_macron
-	    case XK_dead_macron :
-	        dead_char = '-';	/* 'm isn't defined on iso-8859-x */
-	        break;
-#endif
-#ifdef XK_dead_breve
-	    case XK_dead_breve :
-	        dead_char = 0xa2;	/* '( */
-	        break;
-#endif
-#ifdef XK_dead_abovedot
-	    case XK_dead_abovedot :
-	        dead_char = 0xff;	/* '. */
-	        break;
-#endif
-#ifdef XK_dead_abovering
-	    case XK_dead_abovering :
-	        dead_char = '0';	/* '0 isn't defined on iso-8859-x */
-	        break;
-#endif
-#ifdef XK_dead_doubleacute
-	    case XK_dead_doubleacute :
-	        dead_char = 0xbd;	/* '" */
-	        break;
-#endif
-#ifdef XK_dead_caron
-	    case XK_dead_caron :
-	        dead_char = 0xb7;	/* '< */
-	        break;
-#endif
-#ifdef XK_dead_ogonek
-	    case XK_dead_ogonek :
-	        dead_char = 0xb2;	/* '; */
-	        break;
-#endif
-/* FIXME: I don't know this three.
-	    case XK_dead_iota :
-	        dead_char = 'i';	 
-	        break;
-	    case XK_dead_voiced_sound :
-	        dead_char = 'v';
-	        break;
-	    case XK_dead_semivoiced_sound :
-	        dead_char = 's';
-	        break;
-*/
-	    }
-	if (dead_char)
-	    {
-	    *(char*)lpChar = dead_char;
-	    ret = -1;
-	    }
-	else
-	    {
-	    char	*ksname;
-
-	    ksname = TSXKeysymToString(keysym);
-	    if (!ksname)
-		ksname = "No Name";
-	    if ((keysym >> 8) != 0xff)
-		{
-		ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n",
-			keysym, ksname);
-		ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
-			virtKey, scanCode, e.keycode, e.state);
-		}
-	    }
-	}
-    else {  /* ret = 1 */
-        /* We have a special case to handle : Shift + arrow, shift + home, ...
-           X returns a char for it, but Windows doesn't. Let's eat it. */
-        if (!(lpKeyState[VK_NUMLOCK] & 0x01)  /* NumLock is off */
-            && (lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
-            && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
-        {
-            *(char*)lpChar = 0;
-            ret = 0;
-        }
-    }
-
-    TRACE(key, "ToAscii about to return %d with char %x\n",
-		ret, *(char*)lpChar);
-    return ret;
+    return KEYBOARD_GetDriver()->pToAscii(
+        virtKey, scanCode, lpKeyState, lpChar, flags
+    );
 }
+
diff --git a/windows/message.c b/windows/message.c
index f3b0c96..c7ad72d 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -4,6 +4,8 @@
  * Copyright 1993, 1994 Alexandre Julliard
  */
 
+#include "ts_xlib.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -449,7 +451,7 @@
 
     /* If the queue is empty, attempt to fill it */
     if (!sysMsgQueue->msgCount && THREAD_IsWin16( THREAD_Current() )
-                               && TSXPending(display))
+                               && EVENT_Pending())
         EVENT_WaitNetEvent( FALSE, FALSE );
 
     for (i = kbd_msg = 0; i < sysMsgQueue->msgCount; i++, pos++)
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 41efc2f..5d65d63 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -2048,9 +2048,10 @@
     else
     {  /* Grab the server only when moving top-level windows without desktop */
 	hdc = GetDC32( 0 );
-	if (rootWindow == DefaultRootWindow(display)) TSXGrabServer( display );
     }
 
+    wndPtr->pDriver->pPreSizeMove(wndPtr);
+
     if( iconic ) /* create a cursor for dragging */
     {
 	HICON16 hIcon = (wndPtr->class->hIcon) ? wndPtr->class->hIcon
@@ -2146,9 +2147,10 @@
     else
     {
 	ReleaseDC32( 0, hdc );
-	if (rootWindow == DefaultRootWindow(display)) TSXUngrabServer( display );
     }
 
+    wndPtr->pDriver->pPostSizeMove(wndPtr);
+
     if (HOOK_IsHooked( WH_CBT ))
     {
 	RECT16* pr = SEGPTR_NEW(RECT16);
diff --git a/windows/win.c b/windows/win.c
index c73ef1d..983aca5 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -31,6 +31,8 @@
 #include "winerror.h"
 #include "mdi.h"
 
+extern WND_DRIVER X11DRV_WND_Driver;
+
 /* Desktop window */
 static WND *pWndDesktop = NULL;
 
@@ -146,20 +148,6 @@
     }
 }
 
-
-/***********************************************************************
- *           WIN_GetXWindow
- *
- * Return the X window associated to a window.
- */
-Window WIN_GetXWindow( HWND32 hwnd )
-{
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
-    return wndPtr ? wndPtr->window : 0;
-}
-
-
 /***********************************************************************
  *           WIN_UnlinkWindow
  *
@@ -325,7 +313,7 @@
     if (!(wndPtr->dwStyle & WS_CHILD))
        if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
     if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
-    if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
+    wndPtr->pDriver->pDestroyWindow( wndPtr );
     DCE_FreeWindowDCE( wndPtr );    /* Always do this to catch orphaned DCs */ 
     WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
     wndPtr->hwndSelf = 0;
@@ -433,15 +421,15 @@
     pWndDesktop->wIDmenu           = 0;
     pWndDesktop->helpContext       = 0;
     pWndDesktop->flags             = 0;
-    pWndDesktop->window            = rootWindow;
     pWndDesktop->hSysMenu          = 0;
     pWndDesktop->userdata          = 0;
     pWndDesktop->pDriver           = &X11DRV_WND_Driver;
-    pWndDesktop->expose_event      = NULL;
-
     pWndDesktop->winproc = (WNDPROC16)class->winproc;
 
-    EVENT_RegisterWindow( pWndDesktop );
+    /* FIXME: How do we know if it should be Unicode or not */
+    if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
+      return FALSE;
+    
     SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
     pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
     return TRUE;
@@ -648,7 +636,8 @@
     wndPtr->rectWindow.bottom = cs->y + cs->cy;
     wndPtr->rectClient        = wndPtr->rectWindow;
 
-    (*wndPtr->pDriver->pCreateWindow)(wndPtr, classPtr, cs, unicode);
+    if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
+       return FALSE;
 
     /* Set the window menu */
 
@@ -924,7 +913,7 @@
     WIN_CheckFocus(pWnd);
 
     if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
-    if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd ); 
+    if( !pWnd->window ) CLIPBOARD_GetDriver()->pResetOwner( pWnd ); 
   
     SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
 
@@ -986,7 +975,7 @@
 	    if( !IsWindow32(hwnd) ) return TRUE;
 	}
 
-    if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */
+    if( wndPtr->window ) CLIPBOARD_GetDriver()->pResetOwner( wndPtr ); /* before the window is unmapped */
 
       /* Hide the window */
 
diff --git a/windows/winpos.c b/windows/winpos.c
index de2e46e..fcb9a39 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -6,9 +6,6 @@
  */
 
 #include <string.h>
-#include "ts_xlib.h"
-#include "ts_xutil.h"
-#include <X11/Xatom.h>
 #include "sysmetrics.h"
 #include "heap.h"
 #include "module.h"
@@ -1435,35 +1432,6 @@
     }
 }
 
-
-/***********************************************************************
- *           WINPOS_ForceXWindowRaise
- *
- * Raise a window on top of the X stacking order, while preserving 
- * the correct Windows Z order.
- */
-static void WINPOS_ForceXWindowRaise( WND* pWnd )
-{
-    XWindowChanges winChanges;
-    WND *wndPrev;
-
-    /* Raise all windows up to pWnd according to their Z order.
-     * (it would be easier with sibling-related Below but it doesn't
-     * work very well with SGI mwm for instance)
-     */
-    winChanges.stack_mode = Above;
-    while (pWnd)
-    {
-        if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0,
-                                                CWStackMode, &winChanges );
-        wndPrev = WIN_GetDesktop()->child;
-        if (wndPrev == pWnd) break;
-        while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
-        pWnd = wndPrev;
-    }
-}
-
-
 /*******************************************************************
  *	   WINPOS_SetActiveWindow
  *
@@ -1620,9 +1588,8 @@
 			       hwndActive
 	    );
 
-    if( !hwndPrevActive && wndPtr && 
-	 wndPtr->window && !(wndPtr->flags & WIN_MANAGED) )
-	WINPOS_ForceXWindowRaise(wndPtr);
+    if( !hwndPrevActive && wndPtr )
+        (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
 
     /* if active wnd is minimized redraw icon title */
     if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
@@ -2057,104 +2024,6 @@
  return uFlags;
 }
 
-
-/***********************************************************************
- *           WINPOS_FindDeskTopXWindow
- *
- * Find the actual X window which needs be restacked.
- * Used by WINPOS_SetXWindowPos().
- */
-static Window WINPOS_FindDeskTopXWindow( WND *wndPtr )
-{
-    if (!(wndPtr->flags & WIN_MANAGED))
-        return wndPtr->window;
-    else
-    {
-        Window window, root, parent, *children;
-        int nchildren;
-        window = wndPtr->window;
-        for (;;)
-        {
-            TSXQueryTree( display, window, &root, &parent,
-                        &children, &nchildren );
-            TSXFree( children );
-            if (parent == root)
-                return window;
-            window = parent;
-        }
-    }
-}
-
-/***********************************************************************
- *           WINPOS_SetXWindowPos
- *
- * SetWindowPos() for an X window. Used by the real SetWindowPos().
- */
-static void WINPOS_SetXWindowPos( const WINDOWPOS32 *winpos )
-{
-    XWindowChanges winChanges;
-    int changeMask = 0;
-    WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
-
-    if (!(winpos->flags & SWP_NOSIZE))
-    {
-        winChanges.width     = winpos->cx;
-        winChanges.height    = winpos->cy;
-        changeMask |= CWWidth | CWHeight;
-
-        /* Tweak dialog window size hints */
-
-        if ((wndPtr->flags & WIN_MANAGED) &&
-            (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
-        {
-            XSizeHints *size_hints = TSXAllocSizeHints();
-
-            if (size_hints)
-            {
-                long supplied_return;
-
-                TSXGetWMSizeHints( display, wndPtr->window, size_hints,
-                                 &supplied_return, XA_WM_NORMAL_HINTS);
-                size_hints->min_width = size_hints->max_width = winpos->cx;
-                size_hints->min_height = size_hints->max_height = winpos->cy;
-                TSXSetWMSizeHints( display, wndPtr->window, size_hints,
-                                 XA_WM_NORMAL_HINTS );
-                TSXFree(size_hints);
-            }
-        }
-    }
-    if (!(winpos->flags & SWP_NOMOVE))
-    {
-        winChanges.x = winpos->x;
-        winChanges.y = winpos->y;
-        changeMask |= CWX | CWY;
-    }
-    if (!(winpos->flags & SWP_NOZORDER))
-    {
-	winChanges.stack_mode = Below;
-	changeMask |= CWStackMode;
-
-        if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
-        else if (winpos->hwndInsertAfter != HWND_BOTTOM)
-        {
-            WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
-	    Window stack[2];
-
-	    stack[0] = WINPOS_FindDeskTopXWindow( insertPtr );
-	    stack[1] = WINPOS_FindDeskTopXWindow( wndPtr );
-
-	    /* for stupid window managers (i.e. all of them) */
-
-	    TSXRestackWindows(display, stack, 2); 
-	    changeMask &= ~CWStackMode;
-	}
-    }
-    if (!changeMask) return;
-
-    TSXReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges );
-}
-
-
 /***********************************************************************
  *           SetWindowPos   (USER.232)
  */
@@ -2364,7 +2233,7 @@
 
 	if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
 	{
-              WINPOS_SetXWindowPos( &winpos );
+              wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
 	      winpos.hwndInsertAfter = tempInsertAfter;
 	}
 	else  uFlags |= SMC_SETXPOS;
@@ -2459,12 +2328,12 @@
         {
 	    HWND32 focus, curr;
 
+	    wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
 	    if( uFlags & SMC_SETXPOS )
 	    {
-              WINPOS_SetXWindowPos( &winpos );
               winpos.hwndInsertAfter = tempInsertAfter;
 	    }
-            TSXMapWindow( display, wndPtr->window );
+
             if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
 
 	    /* If focus was set to an unmapped window, reset X focus now */
@@ -2488,19 +2357,18 @@
     }
     else if (flags & SWP_HIDEWINDOW)
     {
+        wndPtr->dwStyle &= ~WS_VISIBLE;
+
         if (wndPtr->window)
         {
-           if (wndPtr->dwStyle & WS_VISIBLE) TSXUnmapWindow( display, wndPtr->window );
-           wndPtr->dwStyle &= ~WS_VISIBLE;
-           if( uFlags & SMC_SETXPOS )
-           {
-               WINPOS_SetXWindowPos( &winpos );
-               winpos.hwndInsertAfter = tempInsertAfter;
-           }
+	    wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
+	    if( uFlags & SMC_SETXPOS )
+	    {
+              winpos.hwndInsertAfter = tempInsertAfter;
+	    }
         }
         else
         {
-            wndPtr->dwStyle &= ~WS_VISIBLE;
             if (!(flags & SWP_NOREDRAW))
                 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
                                     0, RDW_INVALIDATE | RDW_ALLCHILDREN |
diff --git a/windows/x11drv/Makefile.in b/windows/x11drv/Makefile.in
index 89eb67b..ebf0d61 100644
--- a/windows/x11drv/Makefile.in
+++ b/windows/x11drv/Makefile.in
@@ -6,7 +6,12 @@
 MODULE    = x11drv
 
 C_SRCS = \
-	init.c
+	clipboard.c \
+	event.c \
+	init.c \
+	keyboard.c \
+	mouse.c \
+	wnd.c
 
 all: $(MODULE).o
 
diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c
new file mode 100644
index 0000000..39c1f47
--- /dev/null
+++ b/windows/x11drv/clipboard.c
@@ -0,0 +1,299 @@
+/*
+ * X11 windows driver
+ *
+ * Copyright 1994 Martin Ayotte
+ *	     1996 Alex Korobka
+ */
+
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+
+#include <X11/Xatom.h>
+#include "ts_xlib.h"
+
+#include "windows.h"
+#include "wintypes.h"
+
+#include "clipboard.h"
+#include "debug.h"
+#include "message.h"
+#include "win.h"
+#include "x11drv.h"
+
+extern HWND32 hWndClipOwner;
+extern HWND32 hWndClipWindow;
+extern CLIPFORMAT ClipFormats[];
+
+static Bool   selectionWait = False;
+static Bool   selectionAcquired = False;
+static Window selectionWindow = None;
+static Window selectionPrevWindow = None;
+
+/**************************************************************************
+ * 		X11DRV_CLIPBOARD_CheckSelection	[Internal]
+ *
+ * Prevent X selection from being lost when a top level window is
+ * destroyed.
+ */
+static void X11DRV_CLIPBOARD_CheckSelection(WND* pWnd)
+{
+    TRACE(clipboard,"\tchecking %08x\n", (unsigned)pWnd->window);
+
+    if( selectionAcquired && selectionWindow != None &&
+        pWnd->window == selectionWindow )
+    {
+	selectionPrevWindow = selectionWindow;
+	selectionWindow = None;
+
+	if( pWnd->next ) 
+	    selectionWindow = pWnd->next->window;
+	else if( pWnd->parent )
+             if( pWnd->parent->child != pWnd ) 
+                 selectionWindow = pWnd->parent->child->window;
+
+	TRACE(clipboard,"\tswitching selection from %08x to %08x\n", 
+                    (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
+
+	if( selectionWindow != None )
+	{
+	    TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
+	    if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
+		selectionWindow = None;
+	}
+    }
+}
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ReadSelection
+ *
+ * Called from the SelectionNotify event handler. 
+ */
+void X11DRV_CLIPBOARD_ReadSelection(Window w,Atom prop)
+{
+    HANDLE32 	 hText = 0;
+    LPCLIPFORMAT lpFormat = ClipFormats; 
+
+    TRACE(clipboard,"ReadSelection callback\n");
+
+    if(prop != None)
+    {
+	Atom		atype=AnyPropertyType;
+	int		aformat;
+	unsigned long 	nitems,remain;
+	unsigned char*	val=NULL;
+
+        TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop));
+
+        /* TODO: Properties longer than 64K */
+
+	if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
+	    &atype, &aformat, &nitems, &remain, &val) != Success)
+	    WARN(clipboard, "\tcouldn't read property\n");
+	else
+	{
+           TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n",
+		             TSXGetAtomName(display,atype),aformat,nitems,val);
+
+	   if(atype == XA_STRING && aformat == 8)
+	   {
+	      int 	i,inlcount = 0;
+	      char*	lpstr;
+
+	      TRACE(clipboard,"\tselection is '%s'\n",val);
+
+	      for(i=0; i <= nitems; i++)
+		  if( val[i] == '\n' ) inlcount++;
+
+	      if( nitems )
+	      {
+	        hText=GlobalAlloc32(GMEM_MOVEABLE, nitems + inlcount + 1);
+	        if( (lpstr = (char*)GlobalLock32(hText)) )
+	          for(i=0,inlcount=0; i <= nitems; i++)
+	          {
+	  	     if( val[i] == '\n' ) lpstr[inlcount++]='\r';
+		     lpstr[inlcount++]=val[i];
+		  }
+	        else hText = 0;
+	      }
+	   }
+	   TSXFree(val);
+	}
+   }
+
+   /* delete previous CF_TEXT and CF_OEMTEXT data */
+
+   if( hText )
+   {
+     lpFormat = &ClipFormats[CF_TEXT-1];
+     if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) 
+         CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
+     lpFormat = &ClipFormats[CF_OEMTEXT-1];
+     if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)  
+         CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
+
+     lpFormat->wDataPresent = 1;
+     lpFormat->hData32 = hText;
+     lpFormat->hData16 = 0;
+   }
+
+   selectionWait=False;
+}
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ReleaseSelection
+ *
+ * Wine might have lost XA_PRIMARY selection because of
+ * EmptyClipboard() or other client. 
+ */
+void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd)
+{
+    /* w is the window that lost selection,
+     * 
+     * selectionPrevWindow is nonzero if CheckSelection() was called. 
+     */
+
+    TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n", 
+	  (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
+
+    if( selectionAcquired )
+    {
+	if( w == selectionWindow || selectionPrevWindow == None)
+	{
+	    /* alright, we really lost it */
+
+	    selectionAcquired = False;
+	    selectionWindow = None; 
+
+	    /* but we'll keep existing data for internal use */
+	}
+	else if( w == selectionPrevWindow )
+	{
+	    w = TSXGetSelectionOwner(display, XA_PRIMARY);
+	    if( w == None )
+		TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
+	}
+    }
+
+    selectionPrevWindow = None;
+}
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_EmptyClipboard
+ */
+void X11DRV_CLIPBOARD_EmptyClipboard()
+{
+  if(selectionAcquired)
+    {
+      selectionAcquired	= False;
+      selectionPrevWindow 	= selectionWindow;
+      selectionWindow 	= None;
+      
+      TRACE(clipboard, "\tgiving up selection (spw = %08x)\n", 
+	    (unsigned)selectionPrevWindow);
+      
+      TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
+    }
+}
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_SetClipboardData
+ */
+void X11DRV_CLIPBOARD_SetClipboardData(UINT32 wFormat)
+{
+    Window       owner;
+
+    /* Acquire X selection if text format */
+
+    if( !selectionAcquired && 
+	(wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
+    {
+	owner = X11DRV_WND_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() );
+
+	TSXSetSelectionOwner(display,XA_PRIMARY, owner, CurrentTime);
+	if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
+	{
+	    selectionAcquired = True;
+	    selectionWindow = owner;
+
+	    TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n", 
+						(unsigned) owner);
+	}
+    }
+}
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_RequestSelection
+ */
+BOOL32 X11DRV_CLIPBOARD_RequestSelection()
+{
+    HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32();
+
+    if( selectionAcquired )
+      return TRUE;
+
+    if( !hWnd ) return FALSE;
+
+    TRACE(clipboard,"Requesting selection...\n");
+
+  /* request data type XA_STRING, later
+   * CLIPBOARD_ReadSelection() will be invoked 
+   * from the SelectionNotify event handler */
+
+    TSXConvertSelection(display,XA_PRIMARY,XA_STRING,
+                      TSXInternAtom(display,"PRIMARY_TEXT",False),
+                      X11DRV_WND_GetXWindow(hWnd),CurrentTime);
+
+  /* wait until SelectionNotify is processed 
+   *
+   * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the 
+   *	    CLIPBOARD_CheckSelection() ). 
+   */
+
+    selectionWait=True;
+    while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE );
+
+  /* we treat Unix text as CF_OEMTEXT */
+    TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n", 
+		      ClipFormats[CF_OEMTEXT-1].wDataPresent);
+
+    return (BOOL32)ClipFormats[CF_OEMTEXT-1].wDataPresent;
+}
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ResetOwner
+ *
+ * Called from DestroyWindow().
+ */
+void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd)
+{
+    LPCLIPFORMAT lpFormat = ClipFormats;
+
+    TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n", 
+				hWndClipOwner, (unsigned)selectionWindow);
+
+    if( pWnd->hwndSelf == hWndClipOwner)
+    {
+	SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
+
+	/* check if all formats were rendered */
+
+	while(lpFormat)
+	{
+	    if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
+	    {
+		TRACE(clipboard,"\tdata missing for clipboard format %i\n", 
+				   lpFormat->wFormatID); 
+		lpFormat->wDataPresent = 0;
+	    }
+	    lpFormat = lpFormat->NextFormat;
+	}
+	hWndClipOwner = 0;
+    }
+
+    /* now try to salvage current selection from being destroyed by X */
+
+    if( pWnd->window ) X11DRV_CLIPBOARD_CheckSelection(pWnd);
+}
+
+#endif /* !defined(X_DISPLAY_MISSING) */
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
new file mode 100644
index 0000000..e301647
--- /dev/null
+++ b/windows/x11drv/event.c
@@ -0,0 +1,1388 @@
+/*
+ * X11 windows driver
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include "ts_xlib.h"
+#include "ts_xresource.h"
+#include "ts_xutil.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "windows.h"
+#include "winnt.h"
+#include "gdi.h"
+#include "heap.h"
+#include "queue.h"
+#include "win.h"
+#include "class.h"
+#include "dce.h"
+#include "message.h"
+#include "module.h"
+#include "options.h"
+#include "queue.h"
+#include "winpos.h"
+#include "drive.h"
+#include "shell.h"
+#include "keyboard.h"
+#include "mouse.h"
+#include "debug.h"
+#include "dde_proc.h"
+#include "winsock.h"
+#include "mouse.h"
+#include "x11drv.h"
+
+/* X context to associate a hwnd to an X window */
+extern XContext winContext;
+
+extern Atom wmProtocols;
+extern Atom wmDeleteWindow;
+extern Atom dndProtocol;
+extern Atom dndSelection;
+
+#define NB_BUTTONS      3     /* Windows can handle 3 buttons */
+
+#define DndNotDnd       -1    /* OffiX drag&drop */
+#define DndUnknown      0
+#define DndRawData      1
+#define DndFile         2
+#define DndFiles        3
+#define DndText         4
+#define DndDir          5
+#define DndLink         6
+#define DndExe          7
+
+#define DndEND          8
+
+#define DndURL          128   /* KDE drag&drop */
+
+/* EVENT_WaitNetEvent() master fd sets */
+
+static fd_set __event_io_set[3];
+static int    __event_max_fd = 0;
+static int    __event_x_connection = 0;
+
+static const char * const event_names[] =
+{
+  "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
+  "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
+  "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
+  "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
+  "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
+  "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
+  "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
+  "ClientMessage", "MappingNotify"
+};
+
+static void EVENT_ProcessEvent( XEvent *event );
+
+  /* Event handlers */
+static void EVENT_Key( WND *pWnd, XKeyEvent *event );
+static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event );
+static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event );
+static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event );
+static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event );
+static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event );
+static int  EVENT_Expose( WND *pWnd, XExposeEvent *event );
+static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
+static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event );
+static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
+static void EVENT_SelectionNotify( XSelectionEvent *event);
+static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
+static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
+static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event );
+
+/* Usable only with OLVWM - compile option perhaps?
+static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
+*/
+
+static void EVENT_GetGeometry( Window win, int *px, int *py,
+                               unsigned int *pwidth, unsigned int *pheight );
+
+
+/***********************************************************************
+ *           EVENT_Init
+ *
+ * Initialize network IO.
+ */
+BOOL32 X11DRV_EVENT_Init(void)
+{
+  int  i;
+  for( i = 0; i < 3; i++ )
+    FD_ZERO( __event_io_set + i );
+  
+  __event_max_fd = __event_x_connection = ConnectionNumber(display);
+  FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] );
+  __event_max_fd++;
+  return TRUE;
+}
+
+/***********************************************************************
+ *		X11DRV_EVENT_AddIO 
+ */
+void X11DRV_EVENT_AddIO( int fd, unsigned io_type )
+{
+  FD_SET( fd, &__event_io_set[io_type] );
+  if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
+}
+
+/***********************************************************************
+ *		X11DRV_EVENT_DeleteIO 
+ */
+void X11DRV_EVENT_DeleteIO( int fd, unsigned io_type )
+{
+  FD_CLR( fd, &__event_io_set[io_type] );
+}
+
+/***********************************************************************
+ *		X11DRV_EVENT_IsUserIdle 
+ */
+BOOL16 WINAPI X11DRV_EVENT_IsUserIdle(void)
+{
+  struct timeval timeout = {0, 0};
+  fd_set check_set;
+  
+  FD_ZERO(&check_set);
+  FD_SET(__event_x_connection, &check_set);
+  if( select(__event_x_connection + 1, &check_set, NULL, NULL, &timeout) > 0 )
+    return TRUE;
+  return FALSE;
+}
+
+/***********************************************************************
+ *           X11DRV_EVENT_WaitNetEvent
+ *
+ * Wait for a network event, optionally sleeping until one arrives.
+ * Return TRUE if an event is pending, FALSE on timeout or error
+ * (for instance lost connection with the server).
+ */
+
+BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
+{
+  XEvent event;
+  LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
+  int pending = TSXPending(display);
+  
+  /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
+   * in this case, we fall through directly to the XNextEvent loop.
+   */
+  
+  if ((maxWait != -1) && !pending)
+    {
+      int num_pending;
+      struct timeval timeout;
+      fd_set io_set[3];
+      
+      memcpy( io_set, __event_io_set, sizeof(io_set) );
+      
+      timeout.tv_usec = (maxWait % 1000) * 1000;
+      timeout.tv_sec = maxWait / 1000;
+      
+#ifdef CONFIG_IPC
+      sigsetjmp(env_wait_x, 1);
+      stop_wait_op= CONT;
+      
+      if (DDE_GetRemoteMessage()) {
+	while(DDE_GetRemoteMessage())
+	  ;
+	return TRUE;
+      }
+      stop_wait_op = STOP_WAIT_X;
+      /* The code up to the next "stop_wait_op = CONT" must be reentrant */
+      num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], 
+			    &io_set[EVENT_IO_WRITE], 
+			    &io_set[EVENT_IO_EXCEPT], &timeout );
+      if ( num_pending == 0 )
+        {
+	  stop_wait_op = CONT;
+	  TIMER_ExpireTimers();
+	  return FALSE;
+	}
+      else stop_wait_op = CONT;
+#else  /* CONFIG_IPC */
+      num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ],
+			    &io_set[EVENT_IO_WRITE],
+			    &io_set[EVENT_IO_EXCEPT], &timeout );
+      if ( num_pending == 0)
+        {
+	  /* Timeout or error */
+	  TIMER_ExpireTimers();
+	  return FALSE;
+        }
+#endif  /* CONFIG_IPC */
+      
+      /*  Winsock asynchronous services */
+      
+      if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) ) 
+	{
+	  num_pending--;
+	  if( num_pending )
+	    WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
+	}
+      else /* no X events */
+	return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
+    }
+  else if(!pending)
+    {				/* Wait for X11 input. */
+      fd_set set;
+      
+      FD_ZERO(&set);
+      FD_SET(__event_x_connection, &set);
+      select(__event_x_connection + 1, &set, 0, 0, 0 );
+    }
+  
+  /* Process current X event (and possibly others that occurred in the meantime) */
+  
+  EnterCriticalSection(&X11DRV_CritSection);
+  while (XPending( display ))
+    {
+      
+#ifdef CONFIG_IPC
+      if (DDE_GetRemoteMessage())
+        {
+	  LeaveCriticalSection(&X11DRV_CritSection);
+	  while(DDE_GetRemoteMessage()) ;
+	  return TRUE;
+        }
+#endif  /* CONFIG_IPC */
+      
+      XNextEvent( display, &event );
+      
+      LeaveCriticalSection(&X11DRV_CritSection);
+      if( peek )
+        {
+	  WND*		pWnd;
+	  MESSAGEQUEUE* pQ;
+	  
+
+	  /* Check only for those events which can be processed
+	   * internally. */
+
+	  if( event.type == MotionNotify ||
+	      event.type == ButtonPress || event.type == ButtonRelease ||
+	      event.type == KeyPress || event.type == KeyRelease ||
+	      event.type == SelectionRequest || event.type == SelectionClear ||
+	      event.type == ClientMessage )
+	    {
+	      EVENT_ProcessEvent( &event );
+	      continue;
+	    }
+	  
+          if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext,
+			      (char **)&pWnd ) || (event.type == NoExpose))
+	    pWnd = NULL;
+	  
+	  if( pWnd )
+	    {
+	      if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
+		{
+		  pQ->flags |= QUEUE_FLAG_XEVENT;
+		  PostEvent(pQ->hTask);
+		  TSXPutBackEvent(display, &event);
+		  break;
+		}
+	    }
+        }
+      else EVENT_ProcessEvent( &event );
+      EnterCriticalSection(&X11DRV_CritSection);
+    }
+  LeaveCriticalSection(&X11DRV_CritSection);
+  return TRUE;
+}
+
+/***********************************************************************
+ *           EVENT_Synchronize
+ *
+ * Synchronize with the X server. Should not be used too often.
+ */
+void X11DRV_EVENT_Synchronize()
+{
+  XEvent event;
+  
+  /* Use of the X critical section is needed or we have a small
+   * race between XPending() and XNextEvent().
+   */
+  EnterCriticalSection( &X11DRV_CritSection );
+  XSync( display, False );
+  while (XPending( display ))
+    {
+      XNextEvent( display, &event );
+      /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */
+      LeaveCriticalSection( &X11DRV_CritSection );
+      EVENT_ProcessEvent( &event );
+      EnterCriticalSection( &X11DRV_CritSection );
+    }    
+  LeaveCriticalSection( &X11DRV_CritSection );
+}
+
+/***********************************************************************
+ *           EVENT_ProcessEvent
+ *
+ * Process an X event.
+ */
+static void EVENT_ProcessEvent( XEvent *event )
+{
+  WND *pWnd;
+    
+  if ( TSXFindContext( display, event->xany.window, winContext,
+		       (char **)&pWnd ) != 0) {
+    if ( event->type == ClientMessage) {
+      /* query window (drag&drop event contains only drag window) */
+      Window   	root, child;
+      int      	root_x, root_y, child_x, child_y;
+      unsigned	u;
+      TSXQueryPointer( display, rootWindow, &root, &child,
+		       &root_x, &root_y, &child_x, &child_y, &u);
+      if (TSXFindContext( display, child, winContext, (char **)&pWnd ) != 0)
+	return;
+    } else {
+      pWnd = NULL;  /* Not for a registered window */
+    }
+  }
+  
+  TRACE(event, "Got event %s for hwnd %04x\n",
+	event_names[event->type], pWnd? pWnd->hwndSelf : 0 );
+  
+  switch(event->type)
+    {
+    case KeyPress:
+    case KeyRelease:
+      EVENT_Key( pWnd, (XKeyEvent*)event );
+      break;
+      
+    case ButtonPress:
+      EVENT_ButtonPress( pWnd, (XButtonEvent*)event );
+      break;
+      
+    case ButtonRelease:
+      EVENT_ButtonRelease( pWnd, (XButtonEvent*)event );
+      break;
+      
+    case MotionNotify:
+      /* Wine between two fast machines across the overloaded campus
+	 ethernet gets very boged down in MotionEvents. The following
+	 simply finds the last motion event in the queue and drops
+	 the rest. On a good link events are servered before they build
+	 up so this doesn't take place. On a slow link this may cause
+	 problems if the event order is important. I'm not yet seen
+	 of any problems. Jon 7/6/96.
+      */
+      while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
+				      MotionNotify, event));    
+      EVENT_MotionNotify( pWnd, (XMotionEvent*)event );
+      break;
+      
+    case FocusIn:
+      if (!pWnd) return;
+      EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event );
+      break;
+      
+    case FocusOut:
+      if (!pWnd) return;
+      EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event );
+      break;
+      
+    case Expose:
+      if (!pWnd) return;
+      if (EVENT_Expose( pWnd, (XExposeEvent *)event )) {
+	/* need to process ConfigureNotify first */
+	XEvent new_event;
+	
+	/* attempt to find and process the ConfigureNotify event now */
+	if (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
+				     ConfigureNotify, &new_event)) {
+	  EVENT_ProcessEvent( &new_event );
+	  if (!EVENT_Expose( pWnd, (XExposeEvent *)event ))
+	    break;
+	}
+	
+	/* no luck at this time, defer Expose event for later */
+	/* use "type" for an event counter, it is never rechecked */
+	if (!pWnd->expose_event) {
+	  pWnd->expose_event = malloc( sizeof(XExposeEvent) );
+	  pWnd->expose_event[0] = *(XExposeEvent *)event;
+	  pWnd->expose_event[0].type = 1;
+	} else {
+	  int i;
+	  
+	  i = ++pWnd->expose_event[0].type;
+	  pWnd->expose_event = realloc( pWnd->expose_event,
+					i * sizeof(XExposeEvent) );
+	  pWnd->expose_event[i-1] = *(XExposeEvent *)event;
+	  FIXME(x11, "Try and combine Expose events? %d queued.\n", i);
+	}
+      }
+      break;
+      
+    case GraphicsExpose:
+      if (!pWnd) return;
+      EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
+      break;
+      
+    case ConfigureNotify:
+      if (!pWnd) return;
+      EVENT_ConfigureNotify( pWnd, (XConfigureEvent*)event );
+      if (pWnd->expose_event) {
+	/* process deferred Expose event(s) */
+	int i;
+	
+	for (i=0; i<pWnd->expose_event[0].type; i++) {
+	  if(EVENT_Expose( pWnd, &pWnd->expose_event[i] ))
+	    ERR(x11, "Unprocessed expose event discarded\n");
+	}
+	free( pWnd->expose_event );
+	pWnd->expose_event = NULL;
+      }
+      break;
+
+    case SelectionRequest:
+      if (!pWnd) return;
+      EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
+      break;
+
+    case SelectionNotify:
+      if (!pWnd) return;
+      EVENT_SelectionNotify( (XSelectionEvent *)event );
+      break;
+
+    case SelectionClear:
+      if (!pWnd) return;
+      EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
+      break;
+      
+    case ClientMessage:
+      if (!pWnd) return;
+      EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
+      break;
+
+#if 0
+    case EnterNotify:
+      EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
+      break;
+#endif
+
+    case NoExpose:
+      break;
+      
+      /* We get all these because of StructureNotifyMask. */
+    case UnmapNotify:
+    case CirculateNotify:
+    case CreateNotify:
+    case DestroyNotify:
+    case GravityNotify:
+    case ReparentNotify:
+      break;
+      
+    case MapNotify:
+      if (!pWnd) return;
+      EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
+      break;
+      
+    default:    
+      WARN(event, "Unprocessed event %s for hwnd %04x\n",
+	   event_names[event->type], pWnd? pWnd->hwndSelf : 0 );
+      break;
+    }
+}
+
+/***********************************************************************
+ *           EVENT_QueryZOrder
+ *
+ * Try to synchronize internal z-order with the window manager's.
+ * Probably a futile endeavor.
+ */
+static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB )
+{
+  /* return TRUE if we have at least two managed windows */
+  
+  for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
+    if( (*pWndA)->flags & WIN_MANAGED &&
+	(*pWndA)->dwStyle & WS_VISIBLE ) break;
+  if( *pWndA )
+    for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
+      if( (*pWndB)->flags & WIN_MANAGED &&
+	  (*pWndB)->dwStyle & WS_VISIBLE ) break;
+  return ((*pWndB) != NULL);
+}
+
+static Window __get_common_ancestor( Window A, Window B,
+                                     Window** children, unsigned* total )
+{
+  /* find the real root window */
+  
+  Window      root, *childrenB;
+  unsigned    totalB;
+  
+  do
+    {
+      if( *children ) TSXFree( *children );
+      TSXQueryTree( display, A, &root, &A, children, total );
+      TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
+      if( childrenB ) TSXFree( childrenB );
+    } while( A != B && A && B );
+  return ( A && B ) ? A : 0 ;
+}
+
+static Window __get_top_decoration( Window w, Window ancestor )
+{
+  Window*     children, root, prev = w, parent = w;
+  unsigned    total;
+  
+  do
+    {
+      w = parent;
+      TSXQueryTree( display, w, &root, &parent, &children, &total );
+      if( children ) TSXFree( children );
+    } while( parent && parent != ancestor );
+  TRACE(event, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
+  return ( parent ) ? w : 0 ;
+}
+
+static unsigned __td_lookup( Window w, Window* list, unsigned max )
+{
+  unsigned    i;
+  for( i = 0; i < max; i++ ) if( list[i] == w ) break;
+  return i;
+}
+
+static BOOL32 EVENT_QueryZOrder( WND* pWndCheck )
+{
+  BOOL32      bRet = FALSE;
+  HWND32      hwndInsertAfter = HWND_TOP;
+  WND*        pWnd, *pWndZ = WIN_GetDesktop()->child;
+  Window      w, parent, *children = NULL;
+  unsigned    total, check, pos, best;
+  
+  if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE;
+  
+  parent = __get_common_ancestor( pWndZ->window, pWnd->window,
+				  &children, &total );
+  if( parent && children )
+    {
+      w = __get_top_decoration( pWndCheck->window, parent );
+      if( w != children[total - 1] )
+        {
+	  check = __td_lookup( w, children, total );
+	  best = total;
+	  for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
+            {
+	      if( pWnd != pWndCheck )
+                {
+		  if( !(pWnd->flags & WIN_MANAGED) ||
+		      !(w = __get_top_decoration( pWnd->window, parent )) )
+		    continue;
+		  pos = __td_lookup( w, children, total );
+		  if( pos < best && pos > check )
+                    {
+		      best = pos;
+		      hwndInsertAfter = pWnd->hwndSelf;
+                    }
+		  if( check - best == 1 ) break;
+                }
+            }
+	  WIN_UnlinkWindow( pWndCheck->hwndSelf );
+	  WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
+        }
+    }
+  if( children ) TSXFree( children );
+  return bRet;
+}
+
+
+/***********************************************************************
+ *           EVENT_XStateToKeyState
+ *
+ * Translate a X event state (Button1Mask, ShiftMask, etc...) to
+ * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
+ */
+static WORD EVENT_XStateToKeyState( int state )
+{
+  int kstate = 0;
+  
+  if (state & Button1Mask) kstate |= MK_LBUTTON;
+  if (state & Button2Mask) kstate |= MK_MBUTTON;
+  if (state & Button3Mask) kstate |= MK_RBUTTON;
+  if (state & ShiftMask)   kstate |= MK_SHIFT;
+  if (state & ControlMask) kstate |= MK_CONTROL;
+  return kstate;
+}
+
+/***********************************************************************
+ *           X11DRV_EVENT_QueryPointer
+ */
+BOOL32 X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state)
+{
+  Window root, child;
+  int rootX, rootY, winX, winY;
+  unsigned int xstate;
+  
+  if (!TSXQueryPointer( display, rootWindow, &root, &child,
+			&rootX, &rootY, &winX, &winY, &xstate )) 
+    return FALSE;
+  
+  if(posX)
+    *posX  = (DWORD)winX;
+  if(posY)
+    *posY  = (DWORD)winY;
+  if(state)
+    *state = EVENT_XStateToKeyState( xstate );
+  
+  return TRUE;
+}
+
+/***********************************************************************
+ *           EVENT_Expose
+ */
+static int EVENT_Expose( WND *pWnd, XExposeEvent *event )
+{
+  RECT32 rect;
+  int x, y;
+  unsigned int width, height;
+  
+  /* When scrolling, many (fvwm2-based) window managers send the Expose
+   * event before sending the ConfigureNotify event, and we don't like
+   * that, so before processing the Expose event, we check whether the
+   * geometry has changed, and if so, we defer the Expose event until
+   * we get the ConfigureNotify event.  -Ove KÃ¥ven */
+  EVENT_GetGeometry( event->window, &x, &y, &width, &height );
+  
+  if ( x != pWnd->rectWindow.left || y != pWnd->rectWindow.top ||
+       (width != pWnd->rectWindow.right - pWnd->rectWindow.left) ||
+       (height != pWnd->rectWindow.bottom - pWnd->rectWindow.top))
+    return 1; /* tell EVENT_ProcessEvent() to defer it */
+
+  /* Make position relative to client area instead of window */
+  rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
+  rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
+  rect.right  = rect.left + event->width;
+  rect.bottom = rect.top + event->height;
+  
+  PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
+		      RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
+		      (event->count ? 0 : RDW_ERASENOW), 0 );
+  return 0;
+}
+
+
+/***********************************************************************
+ *           EVENT_GraphicsExpose
+ *
+ * This is needed when scrolling area is partially obscured
+ * by non-Wine X window.
+ */
+static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
+{
+  RECT32 rect;
+  
+  /* Make position relative to client area instead of window */
+  rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
+  rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
+  rect.right  = rect.left + event->width;
+  rect.bottom = rect.top + event->height;
+  
+  PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
+		      RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
+		      (event->count ? 0 : RDW_ERASENOW), 0 );
+}
+
+
+/***********************************************************************
+ *           EVENT_Key
+ *
+ * Handle a X key event
+ */
+static void EVENT_Key( WND *pWnd, XKeyEvent *event )
+{
+  KEYBOARD_HandleEvent( pWnd, event );
+}
+
+
+/***********************************************************************
+ *           EVENT_MotionNotify
+ */
+static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event )
+{
+  int xOffset = pWnd? pWnd->rectWindow.left : 0;
+  int yOffset = pWnd? pWnd->rectWindow.top  : 0;
+
+  MOUSE_SendEvent( MOUSEEVENTF_MOVE, 
+		   xOffset + event->x, yOffset + event->y,
+		   EVENT_XStateToKeyState( event->state ), 
+		   event->time - MSG_WineStartTicks,
+		   pWnd? pWnd->hwndSelf : 0 );
+}
+
+
+/***********************************************************************
+ *           X11DRV_EVENT_DummyMotionNotify
+ *
+ * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
+ */
+void X11DRV_EVENT_DummyMotionNotify(void)
+{
+  DWORD winX, winY, state;
+  
+  if ( EVENT_QueryPointer( &winX, &winY, &state ) )
+    {
+      MOUSE_SendEvent( MOUSEEVENTF_MOVE, winX, winY, state,
+		       GetTickCount(), 0 );
+    }
+}
+
+
+/***********************************************************************
+ *           EVENT_ButtonPress
+ */
+static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event )
+{
+  static WORD statusCodes[NB_BUTTONS] = 
+  { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
+  int buttonNum = event->button - 1;
+  
+  int xOffset = pWnd? pWnd->rectWindow.left : 0;
+  int yOffset = pWnd? pWnd->rectWindow.top  : 0;
+  
+  if (buttonNum >= NB_BUTTONS) return;
+  
+  MOUSE_SendEvent( statusCodes[buttonNum], 
+		   xOffset + event->x, yOffset + event->y,
+		   EVENT_XStateToKeyState( event->state ), 
+		   event->time - MSG_WineStartTicks,
+		   pWnd? pWnd->hwndSelf : 0 );
+}
+
+
+/***********************************************************************
+ *           EVENT_ButtonRelease
+ */
+static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event )
+{
+  static WORD statusCodes[NB_BUTTONS] = 
+  { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
+  int buttonNum = event->button - 1;
+  
+  int xOffset = pWnd? pWnd->rectWindow.left : 0;
+  int yOffset = pWnd? pWnd->rectWindow.top  : 0;
+  
+  if (buttonNum >= NB_BUTTONS) return;    
+  
+  MOUSE_SendEvent( statusCodes[buttonNum], 
+		   xOffset + event->x, yOffset + event->y,
+		   EVENT_XStateToKeyState( event->state ), 
+		   event->time - MSG_WineStartTicks,
+		   pWnd? pWnd->hwndSelf : 0 );
+}
+
+
+/**********************************************************************
+ *              EVENT_FocusIn
+ */
+static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event )
+{
+  if (Options.managed) EVENT_QueryZOrder( pWnd );
+  
+  if (event->detail != NotifyPointer)
+    { 
+      HWND32	hwnd = pWnd->hwndSelf;
+
+      if (hwnd != GetActiveWindow32()) 
+        {
+	  WINPOS_ChangeActiveWindow( hwnd, FALSE );
+	  KEYBOARD_UpdateState();
+        }
+      if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32()))
+            SetFocus32( hwnd );
+    }
+}
+
+
+/**********************************************************************
+ *              EVENT_FocusOut
+ *
+ * Note: only top-level override-redirect windows get FocusOut events.
+ */
+static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
+{
+  if (event->detail != NotifyPointer)
+    {
+      HWND32	hwnd = pWnd->hwndSelf;
+      
+      if (hwnd == GetActiveWindow32()) 
+	WINPOS_ChangeActiveWindow( 0, FALSE );
+      if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
+	SetFocus32( 0 );
+    }
+}
+
+/**********************************************************************
+ *              X11DRV_EVENT_CheckFocus
+ */
+BOOL32 X11DRV_EVENT_CheckFocus(void)
+{
+  WND*   pWnd;
+  Window xW;
+  int	   state;
+  
+  TSXGetInputFocus(display, &xW, &state);
+    if( xW == None ||
+        TSXFindContext(display, xW, winContext, (char **)&pWnd) ) 
+      return FALSE;
+    return TRUE;
+}
+
+/**********************************************************************
+ *              EVENT_GetGeometry
+ *
+ * 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,
+                               unsigned int *pwidth, unsigned int *pheight )
+{
+  Window root, parent, *children;
+  int xpos, ypos;
+  unsigned int width, height, border, depth, nb_children;
+  
+  if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
+                       &border, &depth )) return;
+  if (win == rootWindow)
+    {
+      *px = *py = 0;
+      return;
+    }
+  
+  for (;;)
+    {
+      if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
+	return;
+      TSXFree( children );
+      if (parent == rootWindow) break;
+      win = parent;
+      if (!TSXGetGeometry( display, win, &root, &xpos, &ypos,
+                           &width, &height, &border, &depth )) return;
+      *px += xpos;
+      *py += ypos;
+    }
+}
+
+
+/**********************************************************************
+ *              EVENT_ConfigureNotify
+ *
+ * The ConfigureNotify event is only selected on top-level windows
+ * when the -managed flag is used.
+ */
+static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
+{
+  WINDOWPOS32 winpos;
+  RECT32 newWindowRect, newClientRect;
+  HRGN32 hrgnOldPos, hrgnNewPos;
+  Window above = event->above;
+  int x, y;
+  unsigned int width, height;
+  
+  assert (pWnd->flags & WIN_MANAGED);
+  
+  /* We don't rely on the event geometry info, because it is relative
+   * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
+   * if the window hasn't moved).
+   */
+  EVENT_GetGeometry( event->window, &x, &y, &width, &height );
+    
+  /* Fill WINDOWPOS struct */
+  winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
+  winpos.hwnd = pWnd->hwndSelf;
+  winpos.x = x;
+  winpos.y = y;
+  winpos.cx = width;
+  winpos.cy = height;
+    
+  /* Check for unchanged attributes */
+  if (winpos.x == pWnd->rectWindow.left && winpos.y == pWnd->rectWindow.top)
+    winpos.flags |= SWP_NOMOVE;
+  if ((winpos.cx == pWnd->rectWindow.right - pWnd->rectWindow.left) &&
+      (winpos.cy == pWnd->rectWindow.bottom - pWnd->rectWindow.top))
+    winpos.flags |= SWP_NOSIZE;
+  else
+    {
+      RECT32 rect = { 0, 0, pWnd->rectWindow.right - pWnd->rectWindow.left,
+		      pWnd->rectWindow.bottom - pWnd->rectWindow.top };
+      DCE_InvalidateDCE( pWnd, &rect );
+    }
+  
+  /* Send WM_WINDOWPOSCHANGING */
+  SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
+  
+  /* Calculate new position and size */
+  newWindowRect.left = x;
+  newWindowRect.right = x + width;
+  newWindowRect.top = y;
+  newWindowRect.bottom = y + height;
+
+  WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
+			 &pWnd->rectWindow, &pWnd->rectClient,
+			 &winpos, &newClientRect );
+  
+  hrgnOldPos = CreateRectRgnIndirect32( &pWnd->rectWindow );
+  hrgnNewPos = CreateRectRgnIndirect32( &newWindowRect );
+  CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
+  DeleteObject32(hrgnOldPos);
+  DeleteObject32(hrgnNewPos);
+  
+  /* Set new size and position */
+  pWnd->rectWindow = newWindowRect;
+  pWnd->rectClient = newClientRect;
+  SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
+  
+  if (!IsWindow32( winpos.hwnd )) return;
+  if( above == None )			/* absolute bottom */
+    {
+      WIN_UnlinkWindow( winpos.hwnd );
+      WIN_LinkWindow( winpos.hwnd, HWND_BOTTOM);
+    }
+  else EVENT_QueryZOrder( pWnd );	/* try to outsmart window manager */
+}
+
+
+/***********************************************************************
+ *           EVENT_SelectionRequest
+ */
+static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
+{
+  XSelectionEvent result;
+  Atom 	    rprop = None;
+  Window 	    request = event->requestor;
+
+  if(event->target == XA_STRING)
+    {
+      HANDLE16 hText;
+      LPSTR  text;
+      int    size,i,j;
+      
+      rprop = event->property;
+      
+      if(rprop == None) rprop = event->target;
+      
+      if(event->selection!=XA_PRIMARY) rprop = None;
+      else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
+      else
+	{
+	  /* open to make sure that clipboard is available */
+
+	  BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf );
+	  char* lpstr = 0;
+	  
+	  hText = GetClipboardData16(CF_TEXT);
+	  text = GlobalLock16(hText);
+	  size = GlobalSize16(hText);
+	  
+	  /* remove carriage returns */
+	  
+	  lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
+	  for(i=0,j=0; i < size && text[i]; i++ )
+	    {
+	      if( text[i] == '\r' && 
+		  (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
+	      lpstr[j++] = text[i];
+	    }
+	  lpstr[j]='\0';
+	  
+	  TSXChangeProperty(display, request, rprop, 
+			    XA_STRING, 8, PropModeReplace, 
+			    lpstr, j);
+	  HeapFree( GetProcessHeap(), 0, lpstr );
+	  
+	  /* close only if we opened before */
+	  
+	  if(couldOpen) CloseClipboard32();
+	}
+    }
+  
+  if(rprop == None) 
+    TRACE(event,"Request for %s ignored\n", TSXGetAtomName(display,event->target));
+  
+  result.type = SelectionNotify;
+  result.display = display;
+  result.requestor = request;
+  result.selection = event->selection;
+  result.property = rprop;
+  result.target = event->target;
+  result.time = event->time;
+  TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
+}
+
+
+/***********************************************************************
+ *           EVENT_SelectionNotify
+ */
+static void EVENT_SelectionNotify( XSelectionEvent *event )
+{
+  if (event->selection != XA_PRIMARY) return;
+  
+  if (event->target != XA_STRING) X11DRV_CLIPBOARD_ReadSelection( 0, None );
+  else X11DRV_CLIPBOARD_ReadSelection( event->requestor, event->property );
+  
+  TRACE(clipboard,"\tSelectionNotify done!\n");
+}
+
+
+/***********************************************************************
+ *           EVENT_SelectionClear
+ */
+static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
+{
+  if (event->selection != XA_PRIMARY) return;
+  X11DRV_CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf ); 
+}
+
+
+/**********************************************************************
+ *           EVENT_DropFromOffix
+ *
+ * don't know if it still works (last Changlog is from 96/11/04)
+ */
+static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event )
+{
+  unsigned long		data_length;
+  unsigned long		aux_long;
+  unsigned char*	p_data = NULL;
+  union {
+    Atom		atom_aux;
+    POINT32	pt_aux;
+    int		i;
+  }		u;
+  int			x, y;
+  BOOL16	        bAccept;
+  HGLOBAL16		hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
+  LPDRAGINFO            lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
+  SEGPTR		spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
+  Window		w_aux_root, w_aux_child;
+  WND*			pDropWnd;
+  
+  if( !lpDragInfo || !spDragInfo ) return;
+  
+  TSXQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child, 
+		   &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
+  
+  lpDragInfo->hScope = pWnd->hwndSelf;
+  lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
+  
+  /* find out drop point and drop window */
+  if( x < 0 || y < 0 ||
+      x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
+      y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
+    {   bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
+  else
+    {
+      bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
+      x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
+    }
+  pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
+  GlobalFree16( hDragInfo );
+  
+  if( bAccept )
+    {
+      TSXGetWindowProperty( display, DefaultRootWindow(display),
+			    dndSelection, 0, 65535, FALSE,
+			    AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
+			    &data_length, &aux_long, &p_data);
+      
+      if( !aux_long && p_data)	/* don't bother if > 64K */
+	{
+	  char *p = (char*) p_data;
+	  char *p_drop;
+	  
+	  aux_long = 0; 
+	  while( *p )	/* calculate buffer size */
+	    {
+	      p_drop = p;
+	      if((u.i = *p) != -1 ) 
+		u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
+	      if( u.i == -1 ) *p = -1;	/* mark as "bad" */
+	      else
+		{
+		  INT32 len = GetShortPathName32A( p, NULL, 0 );
+		  if (len) aux_long += len + 1;
+		  else *p = -1;
+		}
+	      p += strlen(p) + 1;
+	    }
+	  if( aux_long && aux_long < 65535 )
+	    {
+	      HDROP16                 hDrop;
+	      LPDROPFILESTRUCT16        lpDrop;
+	      
+	      aux_long += sizeof(DROPFILESTRUCT16) + 1; 
+	      hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
+	      lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop );
+	      
+	      if( lpDrop )
+		{
+		  lpDrop->wSize = sizeof(DROPFILESTRUCT16);
+		  lpDrop->ptMousePos.x = (INT16)x;
+		  lpDrop->ptMousePos.y = (INT16)y;
+		  lpDrop->fInNonClientArea = (BOOL16) 
+		    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
+		      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
+		      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
+		      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
+		  p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
+		  p = p_data;
+		  while(*p)
+		    {
+		      if( *p != -1 )	/* use only "good" entries */
+			{
+                          GetShortPathName32A( p, p_drop, 65535 );
+                          p_drop += strlen( p_drop ) + 1;
+			}
+		      p += strlen(p) + 1;
+		    }
+		  *p_drop = '\0';
+		  PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
+				 (WPARAM16)hDrop, 0L );
+		}
+	    }
+	}
+      if( p_data ) TSXFree(p_data);  
+      
+    } /* WS_EX_ACCEPTFILES */
+}
+
+/**********************************************************************
+ *           EVENT_DropURLs
+ *
+ * drop items are separated by \n 
+ * each item is prefixed by its mime type
+ *
+ * event->data.l[3], event->data.l[4] contains drop x,y position
+ */
+static void EVENT_DropURLs( WND *pWnd, XClientMessageEvent *event )
+{
+  WND           *pDropWnd;
+  unsigned long	data_length;
+  unsigned long	aux_long, drop_len = 0;
+  unsigned char	*p_data = NULL; /* property data */
+  char		*p_drop = NULL;
+  char          *p, *next;
+  int		x, y, drop32 = FALSE ;
+  union {
+    Atom	atom_aux;
+    POINT32	pt_aux;
+    int         i;
+    Window      w_aux;
+  }		u; /* unused */
+  union {
+    HDROP16     h16;
+    HDROP32     h32;
+  } hDrop;
+
+  drop32 = pWnd->flags & WIN_ISWIN32;
+
+  if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
+    return;
+
+  TSXGetWindowProperty( display, DefaultRootWindow(display),
+			dndSelection, 0, 65535, FALSE,
+			AnyPropertyType, &u.atom_aux, &u.i,
+			&data_length, &aux_long, &p_data);
+  if (aux_long)
+    WARN(event,"property too large, truncated!\n");
+  TRACE(event,"urls=%s\n", p_data);
+
+  if( !aux_long && p_data) {	/* don't bother if > 64K */
+    /* calculate length */
+    p = p_data;
+    next = strchr(p, '\n');
+    while (p) {
+      if (next) *next=0;
+      if (strncmp(p,"file:",5) == 0 ) {
+	INT32 len = GetShortPathName32A( p+5, NULL, 0 );
+	if (len) drop_len += len + 1;
+      }
+      if (next) { 
+	*next = '\n'; 
+	p = next + 1;
+	next = strchr(p, '\n');
+      } else {
+	p = NULL;
+      }
+    }
+    
+    if( drop_len && drop_len < 65535 ) {
+      TSXQueryPointer( display, rootWindow, &u.w_aux, &u.w_aux, 
+		       &x, &y, &u.i, &u.i, &u.i);
+      pDropWnd = WIN_FindWndPtr( pWnd->hwndSelf );
+      
+      if (drop32) {
+	LPDROPFILESTRUCT32        lpDrop;
+	drop_len += sizeof(DROPFILESTRUCT32) + 1; 
+	hDrop.h32 = (HDROP32)GlobalAlloc32( GMEM_SHARE, drop_len );
+	lpDrop = (LPDROPFILESTRUCT32) GlobalLock32( hDrop.h32 );
+	
+	if( lpDrop ) {
+	  lpDrop->lSize = sizeof(DROPFILESTRUCT32);
+	  lpDrop->ptMousePos.x = (INT32)x;
+	  lpDrop->ptMousePos.y = (INT32)y;
+	  lpDrop->fInNonClientArea = (BOOL32) 
+	    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
+	      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
+	      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
+	      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
+	  lpDrop->fWideChar = FALSE;
+	  p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT32);
+	}
+      } else {
+	LPDROPFILESTRUCT16        lpDrop;
+	drop_len += sizeof(DROPFILESTRUCT16) + 1; 
+	hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len );
+	lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 );
+	
+	if( lpDrop ) {
+	  lpDrop->wSize = sizeof(DROPFILESTRUCT16);
+	  lpDrop->ptMousePos.x = (INT16)x;
+	  lpDrop->ptMousePos.y = (INT16)y;
+	  lpDrop->fInNonClientArea = (BOOL16) 
+	    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
+	      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
+	      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
+	      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
+	  p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
+	}
+      }
+      
+      /* create message content */
+      if (p_drop) {
+	p = p_data;
+	next = strchr(p, '\n');
+	while (p) {
+	  if (next) *next=0;
+	  if (strncmp(p,"file:",5) == 0 ) {
+	    INT32 len = GetShortPathName32A( p+5, p_drop, 65535 );
+	    if (len) {
+	      TRACE(event, "drop file %s as %s\n", p+5, p_drop);
+	      p_drop += len+1;
+	    } else {
+	      WARN(event, "can't convert file %s to dos name \n", p+5);
+	    }
+	  } else {
+	    WARN(event, "unknown mime type %s\n", p);
+	  }
+	  if (next) { 
+	    *next = '\n'; 
+	    p = next + 1;
+	    next = strchr(p, '\n');
+	  } else {
+	    p = NULL;
+	  }
+	  *p_drop = '\0';
+	}
+
+	if (drop32) {
+	  /* can not use PostMessage32A because it is currently based on 
+	   * PostMessage16 and WPARAM32 would be truncated to WPARAM16
+	   */
+	  GlobalUnlock32(hDrop.h32);
+	  SendMessage32A( pWnd->hwndSelf, WM_DROPFILES,
+			  (WPARAM32)hDrop.h32, 0L );
+	} else {
+	  GlobalUnlock16(hDrop.h16);
+	  PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
+			 (WPARAM16)hDrop.h16, 0L );
+	}
+      }
+    }
+    if( p_data ) TSXFree(p_data);  
+  }
+}
+
+/**********************************************************************
+ *           EVENT_ClientMessage
+ */
+static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
+{
+  if (event->message_type != None && event->format == 32) {
+    if ((event->message_type == wmProtocols) && 
+	(((Atom) event->data.l[0]) == wmDeleteWindow))
+      SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
+    else if ( event->message_type == dndProtocol &&
+	      (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
+      EVENT_DropFromOffiX(pWnd, event);
+    else if ( event->message_type == dndProtocol &&
+	      event->data.l[0] == DndURL )
+      EVENT_DropURLs(pWnd, event);
+    else {
+#if 0
+      /* enable this if you want to see the message */
+      unsigned char* p_data = NULL;
+      union {
+	unsigned long	l;
+	int            	i;
+	Atom		atom;
+      } u; /* unused */
+      TSXGetWindowProperty( display, DefaultRootWindow(display),
+			    dndSelection, 0, 65535, FALSE,
+			    AnyPropertyType, &u.atom, &u.i,
+			    &u.l, &u.l, &p_data);
+      TRACE(event, "message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
+	    event->message_type, event->data.l[0], event->data.l[1], 
+	    event->data.l[2], event->data.l[3], event->data.l[4],
+	    p_data);
+#endif
+      TRACE(event, "unrecognized ClientMessage\n" );
+    }
+  }
+}
+
+/**********************************************************************
+ *           EVENT_EnterNotify
+ *
+ * Install colormap when Wine window is focused in
+ * self-managed mode with private colormap
+ */
+#if 0
+void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
+{
+  if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
+      (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
+    TSXInstallColormap( display, COLOR_GetColormap() );
+}
+#endif
+
+/**********************************************************************
+ *		EVENT_MapNotify
+ */
+void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
+{
+  HWND32 hwndFocus = GetFocus32();
+  
+  if (hwndFocus && IsChild32( hWnd, hwndFocus ))
+    X11DRV_WND_SetFocus( WIN_FindWndPtr( hwndFocus ) );
+  
+  return;
+}
+
+/**********************************************************************
+ *		X11DRV_EVENT_Pending
+ */
+BOOL32 X11DRV_EVENT_Pending()
+{
+  return TSXPending(display);
+}
+
+#endif /* !defined(X_DISPLAY_MISSING) */
+
+
+
diff --git a/windows/x11drv/init.c b/windows/x11drv/init.c
index 70a0822..cdae2aa 100644
--- a/windows/x11drv/init.c
+++ b/windows/x11drv/init.c
@@ -1,139 +1,70 @@
 /*
- * X11 windows driver
+ * X11 driver
  *
- * Copyright 1993, 1994 Alexandre Julliard
  * Copyright 1998 Patrik Stridvall
  */
 
-#include <string.h>
-#include <X11/Xatom.h>
-#include "ts_xlib.h"
-#include "color.h"
-#include "display.h"
-#include "dce.h"
-#include "options.h"
-#include "message.h"
-#include "win.h"
-#include "windows.h"
-#include "x11drv.h"
+#include "config.h"
 
-static BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode);
-static WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent);
+#ifndef X_DISPLAY_MISSING
+
+#include "x11drv.h"
 
 WND_DRIVER X11DRV_WND_Driver =
 {
-    X11DRV_WND_CreateWindow,
-    X11DRV_WND_SetParent
+  X11DRV_WND_CreateDesktopWindow,
+  X11DRV_WND_CreateWindow,
+  X11DRV_WND_DestroyWindow,
+  X11DRV_WND_SetParent,
+  X11DRV_WND_ForceWindowRaise,
+  X11DRV_WND_SetWindowPos,
+  X11DRV_WND_SetText,
+  X11DRV_WND_SetFocus,
+  X11DRV_WND_PreSizeMove,
+  X11DRV_WND_PostSizeMove
 };
 
-extern Cursor DISPLAY_XCursor;  /* Current X cursor */
-
-/**********************************************************************
- *		X11DRV_WND_CreateWindow	[Internal]
- */
-static BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode)
+CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver =
 {
-  /* Create the X window (only for top-level windows, and then only */
-  /* when there's no desktop window) */
-  
-  if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
-    {
-      XSetWindowAttributes win_attr;
-      
-      if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
-			      (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
-        {
-	  win_attr.event_mask = ExposureMask | KeyPressMask |
-	    KeyReleaseMask | PointerMotionMask |
-	    ButtonPressMask | ButtonReleaseMask |
-	    FocusChangeMask | StructureNotifyMask;
-	  win_attr.override_redirect = FALSE;
-	  wndPtr->flags |= WIN_MANAGED;
-	}
-      else
-        {
-	  win_attr.event_mask = ExposureMask | KeyPressMask |
-	    KeyReleaseMask | PointerMotionMask |
-	    ButtonPressMask | ButtonReleaseMask |
-	    FocusChangeMask;
-	  win_attr.override_redirect = TRUE;
-	}
-      win_attr.colormap      = COLOR_GetColormap();
-      win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
-      win_attr.save_under    = ((classPtr->style & CS_SAVEBITS) != 0);
-      win_attr.cursor        = DISPLAY_XCursor;
-      wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y,
-                                        cs->cx, cs->cy, 0, CopyFromParent,
-                                        InputOutput, CopyFromParent,
-                                        CWEventMask | CWOverrideRedirect |
-                                        CWColormap | CWCursor | CWSaveUnder |
-                                        CWBackingStore, &win_attr );
+  X11DRV_CLIPBOARD_EmptyClipboard,
+  X11DRV_CLIPBOARD_SetClipboardData,
+  X11DRV_CLIPBOARD_RequestSelection,
+  X11DRV_CLIPBOARD_ResetOwner
+};
 
-      if ((wndPtr->flags & WIN_MANAGED) &&
-	  (cs->dwExStyle & WS_EX_DLGMODALFRAME))
-        {
-	  XSizeHints* size_hints = TSXAllocSizeHints();
-	  
-	  if (size_hints)
-            {
-	      size_hints->min_width = size_hints->max_width = cs->cx;
-	      size_hints->min_height = size_hints->max_height = cs->cy;
-                size_hints->flags = (PSize | PMinSize | PMaxSize);
-                TSXSetWMSizeHints( display, wndPtr->window, size_hints,
-				   XA_WM_NORMAL_HINTS );
-                TSXFree(size_hints);
-            }
-        }
-      
-      if (cs->hwndParent)  /* Get window owner */
-	{
-	  Window win = WIN_GetXWindow( cs->hwndParent );
-	  if (win) TSXSetTransientForHint( display, wndPtr->window, win );
-	}
-      EVENT_RegisterWindow( wndPtr );
-    }
-  return TRUE;
-}
-
-/*****************************************************************
- *		X11DRV_WND_SetParent	[Internal]
- */
-static WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
+KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver =
 {
-    if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) )
-    {
-	WND* pWndPrev = wndPtr->parent;
+  X11DRV_KEYBOARD_Init,
+  X11DRV_KEYBOARD_VkKeyScan,
+  X11DRV_KEYBOARD_MapVirtualKey,
+  X11DRV_KEYBOARD_GetKeyNameText,
+  X11DRV_KEYBOARD_ToAscii
+};
 
-	if( pWndParent != pWndPrev )
-	{
-	    BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf);
+EVENT_DRIVER X11DRV_EVENT_Driver = 
+{
+  X11DRV_EVENT_Init,
+  X11DRV_EVENT_AddIO,
+  X11DRV_EVENT_DeleteIO,
+  X11DRV_EVENT_WaitNetEvent,
+  X11DRV_EVENT_Synchronize,
+  X11DRV_EVENT_CheckFocus,
+  X11DRV_EVENT_QueryPointer,
+  X11DRV_EVENT_DummyMotionNotify,
+  X11DRV_EVENT_Pending,
+  X11DRV_EVENT_IsUserIdle
+};
 
-	    if ( wndPtr->window )
-	    {
-		/* Toplevel window needs to be reparented.  Used by Tk 8.0 */
+#if 0 
+MOUSE_DRIVER X11DRV_MOUSE_Driver =
+{
+};
+#endif
 
-		TSXDestroyWindow( display, wndPtr->window );
-		wndPtr->window = None;
-	    }
-	    else if( bFixupDCE )
-		DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
+#endif /* !defined(X_DISPLAY_MISSING) */
 
-	    WIN_UnlinkWindow(wndPtr->hwndSelf);
-	    wndPtr->parent = pWndParent;
 
-	    /* FIXME: Create an X counterpart for reparented top-level windows
-	     * when not in the desktop mode. */
-     
-	    if ( pWndParent != WIN_GetDesktop() ) wndPtr->dwStyle |= WS_CHILD;
-	    WIN_LinkWindow(wndPtr->hwndSelf, HWND_BOTTOM);
 
-	    if( bFixupDCE )
-	    {
-	        DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
-		UpdateWindow32(wndPtr->hwndSelf);
-	    }
-	}
-	return pWndPrev;
-    } /* failure */
-    return 0;
-}
+
+
+
diff --git a/windows/x11drv/keyboard.c b/windows/x11drv/keyboard.c
new file mode 100644
index 0000000..a28a107
--- /dev/null
+++ b/windows/x11drv/keyboard.c
@@ -0,0 +1,815 @@
+/*
+ * X11 windows driver
+ *
+ * Copyright 1993 Bob Amstadt
+ * Copyright 1996 Albrecht Kleine 
+ * Copyright 1997 David Faure
+ * Copyright 1998 Morten Welinder
+ * Copyright 1998 Ulrich Weigand
+ */
+
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include "ts_xlib.h"
+#include "ts_xresource.h"
+#include "ts_xutil.h"
+
+#include "debug.h"
+#include "message.h"
+#include "wintypes.h"
+#include "x11drv.h"
+
+extern LPBYTE pKeyStateTable;
+
+int min_keycode, max_keycode, keysyms_per_keycode;
+WORD keyc2vkey[256];
+
+static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
+static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
+
+/* Keyboard translation tables */
+static const int special_key[] =
+{
+    VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
+    0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
+    0, 0, 0, VK_ESCAPE                                          /* FF18 */
+};
+
+static const int cursor_key[] =
+{
+    VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
+                                       VK_NEXT, VK_END          /* FF50 */
+};
+
+static const int misc_key[] =
+{
+    VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
+    VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
+};
+
+static const int keypad_key[] =
+{
+    0, VK_NUMLOCK,                                        	/* FF7E */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
+    0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
+    0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
+    VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
+				 VK_INSERT, VK_DELETE,          /* FF98 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
+    0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
+                               VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
+    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
+                            VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
+    VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
+};
+    
+static const int function_key[] =
+{
+    VK_F1, VK_F2,                                               /* FFBE */
+    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
+    VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
+};
+
+static const int modifier_key[] =
+{
+    VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
+    VK_MENU, VK_MENU, VK_MENU, VK_MENU                         /* FFE7 */
+};
+
+/* Returns the Windows virtual key code associated with the X event <e> */
+static WORD EVENT_event_to_vkey( XKeyEvent *e)
+{
+    KeySym keysym;
+
+    TSXLookupString(e, NULL, 0, &keysym, NULL);
+
+    if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask)) 
+        /* Only the Keypad keys 0-9 and . send different keysyms
+         * depending on the NumLock state */
+        return keypad_key[(keysym & 0xFF) - 0x7E];
+
+    return keyc2vkey[e->keycode];
+}
+
+static BOOL32 NumState=FALSE, CapsState=FALSE;
+
+/**********************************************************************
+ *		KEYBOARD_GenerateMsg
+ *
+ * Generate Down+Up messages when NumLock or CapsLock is pressed.
+ *
+ * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
+ *
+ */
+void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
+                           DWORD event_time )
+{
+  BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
+
+  if (*State) {
+    /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
+       don't treat it. It's from the same key press. Then the state goes to ON.
+       And from there, a 'release' event will switch off the toggle key. */
+    *State=FALSE;
+    TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]);
+  } else
+    {
+	if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */
+	  {
+	    if (Evtype!=KeyPress)
+	      {
+		TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n");
+	        KEYBOARD_SendEvent( vkey, 0, 0,
+                                    event_x, event_y, event_time );
+	        KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, 
+                                    event_x, event_y, event_time );
+		*State=FALSE;
+		pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */ 
+	      } 
+	  }
+	else /* it was OFF */
+	  if (Evtype==KeyPress)
+	    {
+	      TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n");
+	      KEYBOARD_SendEvent( vkey, 0, 0,
+                                  event_x, event_y, event_time );
+	      KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, 
+                                  event_x, event_y, event_time );
+	      *State=TRUE; /* Goes to intermediary state before going to ON */
+	      pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
+	    }
+    }
+}
+
+/***********************************************************************
+ *           KEYBOARD_UpdateOneState
+ *
+ * Updates internal state for <vkey>, depending on key <state> under X
+ *
+ */
+void KEYBOARD_UpdateOneState ( int vkey, int state )
+{
+    /* Do something if internal table state != X state for keycode */
+    if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
+    {
+        TRACE(keyboard,"Adjusting state for vkey %#.2x. State before %#.2x \n",
+              vkey, pKeyStateTable[vkey]);
+
+        /* Fake key being pressed inside wine */
+	KEYBOARD_SendEvent( vkey, 0, state? 0 : KEYEVENTF_KEYUP, 
+                            0, 0, GetTickCount() );
+
+        TRACE(keyboard,"State after %#.2x \n",pKeyStateTable[vkey]);
+    }
+}
+
+/***********************************************************************
+ *           KEYBOARD_UpdateState
+ *
+ * Update modifiers state (Ctrl, Alt, Shift)
+ * when window is activated (called by EVENT_FocusIn in event.c)
+ *
+ * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
+ * from wine to another application and back.
+ * Toggle keys are handled in HandleEvent. (because XQueryKeymap says nothing
+ *  about them)
+ */
+void KEYBOARD_UpdateState ( void )
+{
+/* extract a bit from the char[32] bit suite */
+#define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0)
+
+    char keys_return[32];
+
+    TRACE(keyboard,"called\n");
+    if (!TSXQueryKeymap(display, keys_return)) {
+        ERR(keyboard,"Error getting keymap !");
+        return;
+    }
+
+    /* Adjust the ALT and CONTROL state if any has been changed outside wine */
+    KEYBOARD_UpdateOneState(VK_MENU, KeyState(kcAlt));
+    KEYBOARD_UpdateOneState(VK_CONTROL, KeyState(kcControl));
+    KEYBOARD_UpdateOneState(VK_SHIFT, KeyState(kcShift));
+#undef KeyState
+}
+
+/***********************************************************************
+ *           KEYBOARD_HandleEvent
+ *
+ * Handle a X key event
+ */
+void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
+{
+    char Str[24]; 
+    XComposeStatus cs; 
+    KeySym keysym;
+    WORD vkey = 0, bScan;
+    DWORD dwFlags;
+    static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
+    
+    int ascii_chars;
+
+    INT32 event_x = (pWnd? pWnd->rectWindow.left : 0) + event->x;
+    INT32 event_y = (pWnd? pWnd->rectWindow.top  : 0) + event->y;
+    DWORD event_time = event->time - MSG_WineStartTicks;
+
+    /* this allows support for dead keys */
+    if ((event->keycode >> 8) == 0x10)
+	event->keycode=(event->keycode & 0xff);
+
+    ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs);
+
+    TRACE(key, "EVENT_key : state = %X\n", event->state);
+    if (keysym == XK_Mode_switch)
+	{
+	TRACE(key, "Alt Gr key event received\n");
+	event->keycode = kcControl; /* Simulate Control */
+	KEYBOARD_HandleEvent( pWnd, event );
+
+	event->keycode = kcAlt; /* Simulate Alt */
+	force_extended = TRUE;
+	KEYBOARD_HandleEvent( pWnd, event );
+	force_extended = FALSE;
+	return;
+	}
+
+    Str[ascii_chars] = '\0';
+    if (TRACE_ON(key)){
+	char	*ksname;
+
+	ksname = TSXKeysymToString(keysym);
+	if (!ksname)
+	  ksname = "No Name";
+	TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", 
+		     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
+		     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
+    }
+
+    vkey = EVENT_event_to_vkey(event);
+    if (force_extended) vkey |= 0x100;
+
+    TRACE(key, "keycode 0x%x converted to vkey 0x%x\n",
+		    event->keycode, vkey);
+
+   if (vkey)
+   {
+    switch (vkey & 0xff)
+    {
+    case VK_NUMLOCK:    
+      KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
+                            event_time );
+      break;
+    case VK_CAPITAL:
+      TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
+      KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
+                            event_time ); 
+      TRACE(keyboard,"State after : %#.2x\n",pKeyStateTable[vkey]);
+      break;
+    default:
+        /* Adjust the NUMLOCK state if it has been changed outside wine */
+	if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
+	  { 
+	    TRACE(keyboard,"Adjusting NumLock state. \n");
+	    KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
+                                  event_time );
+	    KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
+                                  event_time );
+	  }
+        /* Adjust the CAPSLOCK state if it has been changed outside wine */
+	if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
+	  {
+              TRACE(keyboard,"Adjusting Caps Lock state.\n");
+	    KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
+                                  event_time );
+	    KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
+                                  event_time );
+	  }
+	/* Not Num nor Caps : end of intermediary states for both. */
+	NumState = FALSE;
+	CapsState = FALSE;
+
+	bScan = event->keycode - min_keycode; /* Windows starts from 0, X from
+                                                 min_keycode (8 usually) */
+	dwFlags = 0;
+	if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
+	if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
+	if ( force_extended )            dwFlags |= KEYEVENTF_WINE_FORCEEXTENDED;
+
+	KEYBOARD_SendEvent( vkey & 0xff, bScan, dwFlags, 
+                            event_x, event_y, event_time );
+    }
+   }
+}
+
+/**********************************************************************
+ *		X11DRV_KEYBOARD_Init
+ */
+void X11DRV_KEYBOARD_Init(void)
+{
+    int i;
+    KeySym *ksp;
+    XModifierKeymap *mmp;
+    KeySym keysym;
+    KeyCode *kcp;
+    XKeyEvent e2;
+    WORD vkey, OEMvkey;
+    int keyc;
+
+    TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
+    ksp = TSXGetKeyboardMapping(display, min_keycode,
+                              max_keycode + 1 - min_keycode, &keysyms_per_keycode);
+    /* We are only interested in keysyms_per_keycode.
+       There is no need to hold a local copy of the keysyms table */
+    TSXFree(ksp);
+    mmp = TSXGetModifierMapping(display);
+    kcp = mmp->modifiermap;
+    for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
+    {
+        int j;
+        
+        for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
+	    if (*kcp)
+            {
+		int k;
+                
+		for (k = 0; k < keysyms_per_keycode; k += 1)
+                    if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
+		    {
+                        AltGrMask = 1 << i;
+                        TRACE(key, "AltGrMask is %x\n", AltGrMask);
+		    }
+                    else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
+		    {
+                        NumLockMask = 1 << i;
+                        TRACE(key, "NumLockMask is %x\n", NumLockMask);
+		    }
+            }
+    }
+    TSXFreeModifiermap(mmp);
+
+    /* Now build two conversion arrays :
+     * keycode -> vkey + extended
+     * vkey + extended -> keycode */
+
+    e2.display = display;
+    e2.state = 0;
+
+    OEMvkey = VK_OEM_7; /* next is available.  */
+    for (keyc = min_keycode; keyc <= max_keycode; keyc++)
+    {
+        e2.keycode = (KeyCode)keyc;
+        TSXLookupString(&e2, NULL, 0, &keysym, NULL);
+        vkey = 0;
+        if (keysym)  /* otherwise, keycode not used */
+        {
+            if ((keysym >> 8) == 0xFF)         /* non-character key */
+            {
+                int key = keysym & 0xff;
+		
+                if (key >= 0x08 && key <= 0x1B)         /* special key */
+		    vkey = special_key[key - 0x08];
+                else if (key >= 0x50 && key <= 0x57)    /* cursor key */
+		    vkey = cursor_key[key - 0x50];
+                else if (key >= 0x60 && key <= 0x6B)    /* miscellaneous key */
+		    vkey = misc_key[key - 0x60];
+                else if (key >= 0x7E && key <= 0xB9)    /* keypad key */
+		    vkey = keypad_key[key - 0x7E];
+                else if (key >= 0xBE && key <= 0xCD)    /* function key */
+                {
+                    vkey = function_key[key - 0xBE];
+                    vkey |= 0x100; /* set extended bit */
+                }
+                else if (key >= 0xE1 && key <= 0xEA)    /* modifier key */
+		    vkey = modifier_key[key - 0xE1];
+                else if (key == 0xFF)                   /* DEL key */
+		    vkey = VK_DELETE;
+                /* extended must also be set for ALT_R, CTRL_R,
+                   INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
+                   keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
+                /* FIXME should we set extended bit for NumLock ? My
+                 * Windows does ... DF */
+                switch (keysym)
+                {
+                case XK_Control_R :
+                case XK_Alt_R :
+                case XK_Insert :
+                case XK_Delete :
+                case XK_Home :
+                case XK_End :
+                case XK_Prior :
+                case XK_Next :
+                case XK_Left :
+                case XK_Up :
+                case XK_Right :
+                case XK_Down :
+                case XK_KP_Divide :
+                case XK_KP_Enter :
+                    vkey |= 0x100;
+                }
+            }
+            for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
+            {
+                keysym = TSXLookupKeysym(&e2, i);
+                if ((keysym >= VK_0 && keysym <= VK_9)
+                    || (keysym >= VK_A && keysym <= VK_Z)
+                    || keysym == VK_SPACE)
+		    vkey = keysym;
+            }
+
+            for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
+            {
+                keysym = TSXLookupKeysym(&e2, i);
+		switch (keysym)
+		{
+		case ';':             vkey = VK_OEM_1; break;
+		case '/':             vkey = VK_OEM_2; break;
+		case '`':             vkey = VK_OEM_3; break;
+		case '[':             vkey = VK_OEM_4; break;
+		case '\\':            vkey = VK_OEM_5; break;
+		case ']':             vkey = VK_OEM_6; break;
+		case '\'':            vkey = VK_OEM_7; break;
+		case ',':             vkey = VK_OEM_COMMA; break;
+		case '.':             vkey = VK_OEM_PERIOD; break;
+		case '-':             vkey = VK_OEM_MINUS; break;
+		case '+':             vkey = VK_OEM_PLUS; break;
+		}
+	    }
+
+            if (!vkey)
+            {
+                /* Others keys: let's assign OEM virtual key codes in the allowed range,
+                 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
+                switch (++OEMvkey)
+                {
+                case 0xc1 : OEMvkey=0xdb; break;
+                case 0xe5 : OEMvkey=0xe9; break;
+                case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n");
+                }
+
+                vkey = OEMvkey;
+		  
+                if (TRACE_ON(keyboard))
+                {
+		    dbg_decl_str(keyboard, 1024);
+
+                    TRACE(keyboard, "OEM specific virtual key %X assigned "
+				 "to keycode %X:\n", OEMvkey, e2.keycode);
+                    for (i = 0; i < keysyms_per_keycode; i += 1)
+                    {
+                        char	*ksname;
+                        
+                        keysym = TSXLookupKeysym(&e2, i);
+                        ksname = TSXKeysymToString(keysym);
+                        if (!ksname)
+			    ksname = "NoSymbol";
+                        dsprintf(keyboard, "%lX (%s) ", keysym, ksname);
+                    }
+                    TRACE(keyboard, "(%s)\n", dbg_str(keyboard));
+                }
+            }
+        }
+        keyc2vkey[e2.keycode] = vkey;
+    } /* for */
+    /* Now store one keycode for each modifier. Used to simulate keypresses. */
+    kcControl = TSXKeysymToKeycode(display, XK_Control_L);
+    kcAlt = TSXKeysymToKeycode(display, XK_Alt_L);
+    if (!kcAlt) kcAlt = TSXKeysymToKeycode(display, XK_Meta_L);
+    kcShift = TSXKeysymToKeycode(display, XK_Shift_L);
+    kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock);
+    kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock);
+}
+
+/***********************************************************************
+ *		X11DRV_KEYBOARD_VkKeyScan
+ */
+WORD X11DRV_KEYBOARD_VkKeyScan(CHAR cChar)
+{
+	KeyCode keycode;
+	KeySym keysym;    	
+	int i,index;
+	int highbyte=0;
+
+	/* char->keysym (same for ANSI chars) */
+	keysym=(unsigned char) cChar;/* (!) cChar is signed */
+	if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
+	
+	keycode = TSXKeysymToKeycode(display, keysym);  /* keysym -> keycode */
+	if (!keycode)
+	{ /* It didn't work ... let's try with deadchar code. */
+	  keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
+	}
+
+	TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
+			 cChar,keysym,keysym,keycode);
+	
+	if (keycode)
+	  {
+	    for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
+	      if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
+	    switch (index) {
+	    case -1 :
+	      WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
+	    case 0 : break;
+	    case 1 : highbyte = 0x0100; break;
+	    case 2 : highbyte = 0X0600; break;
+	    default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index);
+	    }
+	    /*
+	      index : 0     adds 0x0000
+	      index : 1     adds 0x0100 (shift)
+	      index : ?     adds 0x0200 (ctrl)
+	      index : 2     adds 0x0600 (ctrl+alt)
+	      index : ?     adds 0x0700 (ctrl+alt+shift (used?))
+	     */
+	  }
+	TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
+	return keyc2vkey[keycode]+highbyte;   /* keycode -> (keyc2vkey) vkey */
+}
+
+/***********************************************************************
+ *		X11DRV_KEYBOARD_MapVirtualKey
+ */
+UINT16 X11DRV_KEYBOARD_MapVirtualKey(UINT16 wCode, UINT16 wMapType)
+{
+#define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
+
+	TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
+			 wCode,wMapType);
+	switch(wMapType) {
+		case 0:	{ /* vkey-code to scan-code */
+			/* let's do vkey -> keycode -> scan */
+			int keyc;
+			for (keyc=min_keycode; keyc<=max_keycode; keyc++)
+				if ((keyc2vkey[keyc] & 0xFF) == wCode)
+					returnMVK (keyc - min_keycode);
+		        return 0; }
+
+		case 1: /* scan-code to vkey-code */
+			/* let's do scan -> keycode -> vkey */
+
+			returnMVK (keyc2vkey[(wCode & 0xFF) + min_keycode]);
+
+		case 2: { /* vkey-code to unshifted ANSI code */
+			/* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
+		        /* My Windows returns 'A'. */
+			/* let's do vkey -> keycode -> (XLookupString) ansi char */
+			XKeyEvent e;
+			KeySym keysym;
+			char s[2];
+			e.display = display;
+			e.state = 0; /* unshifted */
+			e.keycode = MapVirtualKey16( wCode, 0);
+			if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
+			  returnMVK (*s);
+			
+			return 0;
+			}
+		default: /* reserved */
+			WARN(keyboard, "Unknown wMapType %d !\n",
+				wMapType);
+			return 0;	
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *		X11DRV_KEYBOARD_GetKeyNameText
+ */
+INT16 X11DRV_KEYBOARD_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT16 nSize)
+{
+#if 0
+  int i;
+#endif
+	
+  FIXME(keyboard,"(%ld,<ptr>,%d): stub\n",lParam,nSize);
+
+#if 0
+  lParam >>= 16;
+  lParam &= 0xff;
+  
+  for (i = 0 ; i != KeyTableSize ; i++) 
+    if (KeyTable[i].scancode == lParam)  {
+      lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
+      return strlen(lpBuffer);
+    }
+#endif
+
+  *lpBuffer = 0;
+  return 0;
+}
+
+/***********************************************************************
+ *		X11DRV_KEYBOARD_ToAscii
+ *
+ * The ToAscii function translates the specified virtual-key code and keyboard
+ * state to the corresponding Windows character or characters.
+ *
+ * If the specified key is a dead key, the return value is negative. Otherwise,
+ * it is one of the following values:
+ * Value	Meaning
+ * 0	The specified virtual key has no translation for the current state of the keyboard.
+ * 1	One Windows character was copied to the buffer.
+ * 2	Two characters were copied to the buffer. This usually happens when a
+ *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
+ *      be composed with the specified virtual key to form a single character.
+ *
+ * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
+ *
+ */
+INT16 X11DRV_KEYBOARD_ToAscii(
+    UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, 
+    LPVOID lpChar, UINT16 flags)
+{
+    XKeyEvent e;
+    KeySym keysym;
+    static XComposeStatus cs;
+    INT32 ret;
+    int keyc;
+
+    if (scanCode==0) {
+        /* This happens when doing Alt+letter : a fake 'down arrow' key press
+           event is generated by windows. Just ignore it. */
+        TRACE(keyboard,"scanCode=0, doing nothing\n");
+        return 0;
+    }
+    e.display = display;
+    e.keycode = 0;
+    e.state = 0;
+    if (lpKeyState[VK_SHIFT] & 0x80)
+	e.state |= ShiftMask;
+    if (lpKeyState[VK_CAPITAL] & 0x01)
+	e.state |= LockMask;
+    if (lpKeyState[VK_CONTROL] & 0x80)
+    {
+	if (lpKeyState[VK_MENU] & 0x80)
+	    e.state |= AltGrMask;
+	else
+	    e.state |= ControlMask;
+    }
+    if (lpKeyState[VK_NUMLOCK] & 0x01)
+	e.state |= NumLockMask;
+    TRACE(key, "(%04X, %04X) : faked state = %X\n",
+		virtKey, scanCode, e.state);
+    /* We exit on the first keycode found, to speed up the thing. */
+    for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
+      { /* Find a keycode that could have generated this virtual key */
+          if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
+          { /* We filter the extended bit, we don't know it */
+              e.keycode = keyc; /* Store it temporarily */
+              if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) {
+                  e.keycode = 0; /* Wrong one (ex: because of the NumLock
+                         state), so set it to 0, we'll find another one */
+              }
+	  }
+      }
+
+    if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
+        e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
+          
+    if (virtKey==VK_DECIMAL)
+        e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
+
+    if (!e.keycode)
+      {
+	WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey);
+	return virtKey; /* whatever */
+      }
+    else TRACE(keyboard,"Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
+
+    ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
+    if (ret == 0)
+	{
+	BYTE dead_char = 0;
+
+	((char*)lpChar)[1] = '\0';
+	switch (keysym)
+	    {
+	/* symbolic ASCII is the same as defined in rfc1345 */
+#ifdef XK_dead_tilde
+	    case XK_dead_tilde :
+#endif
+	    case 0x1000FE7E : /* Xfree's XK_Dtilde */
+		dead_char = '~';	/* '? */
+		break;
+#ifdef XK_dead_acute
+	    case XK_dead_acute :
+#endif
+	    case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
+		dead_char = 0xb4;	/* '' */
+		break;
+#ifdef XK_dead_circumflex
+	    case XK_dead_circumflex :
+#endif
+	    case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
+		dead_char = '^';	/* '> */
+		break;
+#ifdef XK_dead_grave
+	    case XK_dead_grave :
+#endif
+	    case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
+		dead_char = '`';	/* '! */
+		break;
+#ifdef XK_dead_diaeresis
+	    case XK_dead_diaeresis :
+#endif
+	    case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
+		dead_char = 0xa8;	/* ': */
+		break;
+#ifdef XK_dead_cedilla
+	    case XK_dead_cedilla :
+	        dead_char = 0xb8;	/* ', */
+	        break;
+#endif
+#ifdef XK_dead_macron
+	    case XK_dead_macron :
+	        dead_char = '-';	/* 'm isn't defined on iso-8859-x */
+	        break;
+#endif
+#ifdef XK_dead_breve
+	    case XK_dead_breve :
+	        dead_char = 0xa2;	/* '( */
+	        break;
+#endif
+#ifdef XK_dead_abovedot
+	    case XK_dead_abovedot :
+	        dead_char = 0xff;	/* '. */
+	        break;
+#endif
+#ifdef XK_dead_abovering
+	    case XK_dead_abovering :
+	        dead_char = '0';	/* '0 isn't defined on iso-8859-x */
+	        break;
+#endif
+#ifdef XK_dead_doubleacute
+	    case XK_dead_doubleacute :
+	        dead_char = 0xbd;	/* '" */
+	        break;
+#endif
+#ifdef XK_dead_caron
+	    case XK_dead_caron :
+	        dead_char = 0xb7;	/* '< */
+	        break;
+#endif
+#ifdef XK_dead_ogonek
+	    case XK_dead_ogonek :
+	        dead_char = 0xb2;	/* '; */
+	        break;
+#endif
+/* FIXME: I don't know this three.
+	    case XK_dead_iota :
+	        dead_char = 'i';	 
+	        break;
+	    case XK_dead_voiced_sound :
+	        dead_char = 'v';
+	        break;
+	    case XK_dead_semivoiced_sound :
+	        dead_char = 's';
+	        break;
+*/
+	    }
+	if (dead_char)
+	    {
+	    *(char*)lpChar = dead_char;
+	    ret = -1;
+	    }
+	else
+	    {
+	    char	*ksname;
+
+	    ksname = TSXKeysymToString(keysym);
+	    if (!ksname)
+		ksname = "No Name";
+	    if ((keysym >> 8) != 0xff)
+		{
+		ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n",
+			keysym, ksname);
+		ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
+			virtKey, scanCode, e.keycode, e.state);
+		}
+	    }
+	}
+    else {  /* ret = 1 */
+        /* We have a special case to handle : Shift + arrow, shift + home, ...
+           X returns a char for it, but Windows doesn't. Let's eat it. */
+        if (!(lpKeyState[VK_NUMLOCK] & 0x01)  /* NumLock is off */
+            && (lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
+            && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
+        {
+            *(char*)lpChar = 0;
+            ret = 0;
+        }
+    }
+
+    TRACE(key, "ToAscii about to return %d with char %x\n",
+		ret, *(char*)lpChar);
+    return ret;
+}
+
+#endif /* !defined(X_DISPLAY_MISSING) */
+
+
diff --git a/windows/x11drv/mouse.c b/windows/x11drv/mouse.c
new file mode 100644
index 0000000..ed87b98
--- /dev/null
+++ b/windows/x11drv/mouse.c
@@ -0,0 +1,13 @@
+/*
+ * X11 windows driver
+ *
+ * Copyright 1998 Patrik Stridvall
+ */
+
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+
+#include "x11drv.h"
+
+#endif /* !defined(X_DISPLAY_MISSING) */
diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c
new file mode 100644
index 0000000..019886a
--- /dev/null
+++ b/windows/x11drv/wnd.c
@@ -0,0 +1,431 @@
+/*
+ * X11 windows driver
+ *
+ * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
+ *                             1993 David Metcalfe
+ *                       1995, 1996 Alex Korobka
+ */
+
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+
+#include <X11/Xatom.h>
+#include "ts_xlib.h"
+#include "ts_xutil.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "color.h"
+#include "display.h"
+#include "dce.h"
+#include "options.h"
+#include "message.h"
+#include "win.h"
+#include "windows.h"
+#include "x11drv.h"
+
+/**********************************************************************/
+
+extern Cursor DISPLAY_XCursor;  /* Current X cursor */
+
+/**********************************************************************/
+
+/* X context to associate a hwnd to an X window */
+XContext winContext = 0;
+
+Atom wmProtocols = None;
+Atom wmDeleteWindow = None;
+Atom dndProtocol = None;
+Atom dndSelection = None;
+
+/***********************************************************************
+ *           X11DRV_WND_GetXWindow
+ *
+ * Return the X window associated to a window.
+ */
+Window X11DRV_WND_GetXWindow(HWND32 hwnd)
+{
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
+    return wndPtr ? wndPtr->window : 0;
+}
+
+/***********************************************************************
+ *		X11DRV_WND_RegisterWindow
+ *
+ * Associate an X window to a HWND.
+ */
+static void X11DRV_WND_RegisterWindow(WND *pWnd)
+{
+  TSXSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
+  
+  if (!winContext) winContext = TSXUniqueContext();
+  TSXSaveContext( display, pWnd->window, winContext, (char *)pWnd );
+}
+
+/**********************************************************************
+ *		X11DRV_WND_CreateDesktopWindow
+ */
+BOOL32 X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL32 bUnicode)
+{
+    if (wmProtocols == None)
+        wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
+    if (wmDeleteWindow == None)
+        wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
+    if( dndProtocol == None )
+	dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
+    if( dndSelection == None )
+	dndSelection = TSXInternAtom( display, "DndSelection" , False );
+
+    wndPtr->window = rootWindow;
+    wndPtr->expose_event = NULL;
+    X11DRV_WND_RegisterWindow( wndPtr );
+
+    return TRUE;
+}
+
+/**********************************************************************
+ *		X11DRV_WND_CreateWindow
+ */
+BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode)
+{
+  /* Create the X window (only for top-level windows, and then only */
+  /* when there's no desktop window) */
+  
+  if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
+    {
+      XSetWindowAttributes win_attr;
+      
+      if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
+			      (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
+        {
+	  win_attr.event_mask = ExposureMask | KeyPressMask |
+	    KeyReleaseMask | PointerMotionMask |
+	    ButtonPressMask | ButtonReleaseMask |
+	    FocusChangeMask | StructureNotifyMask;
+	  win_attr.override_redirect = FALSE;
+	  wndPtr->flags |= WIN_MANAGED;
+	}
+      else
+        {
+	  win_attr.event_mask = ExposureMask | KeyPressMask |
+	    KeyReleaseMask | PointerMotionMask |
+	    ButtonPressMask | ButtonReleaseMask |
+	    FocusChangeMask;
+	  win_attr.override_redirect = TRUE;
+	}
+      win_attr.colormap      = COLOR_GetColormap();
+      win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
+      win_attr.save_under    = ((classPtr->style & CS_SAVEBITS) != 0);
+      win_attr.cursor        = DISPLAY_XCursor;
+      wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y,
+                                        cs->cx, cs->cy, 0, CopyFromParent,
+                                        InputOutput, CopyFromParent,
+                                        CWEventMask | CWOverrideRedirect |
+                                        CWColormap | CWCursor | CWSaveUnder |
+                                        CWBackingStore, &win_attr );
+     
+      if(!wndPtr->window)
+	return FALSE;
+
+      if ((wndPtr->flags & WIN_MANAGED) &&
+	  (cs->dwExStyle & WS_EX_DLGMODALFRAME))
+        {
+	  XSizeHints* size_hints = TSXAllocSizeHints();
+	  
+	  if (size_hints)
+            {
+	      size_hints->min_width = size_hints->max_width = cs->cx;
+	      size_hints->min_height = size_hints->max_height = cs->cy;
+                size_hints->flags = (PSize | PMinSize | PMaxSize);
+                TSXSetWMSizeHints( display, wndPtr->window, size_hints,
+				   XA_WM_NORMAL_HINTS );
+                TSXFree(size_hints);
+            }
+        }
+      
+      if (cs->hwndParent)  /* Get window owner */
+	{
+	  Window win = X11DRV_WND_GetXWindow( cs->hwndParent );
+	  if (win) TSXSetTransientForHint( display, wndPtr->window, win );
+	}
+      X11DRV_WND_RegisterWindow( wndPtr );
+    }
+  return TRUE;
+}
+
+/***********************************************************************
+ *		X11DRV_WND_DestroyWindow
+ */
+BOOL32 X11DRV_WND_DestroyWindow(WND *pWnd)
+{
+   if (pWnd->expose_event) 
+     {
+       free( pWnd->expose_event );
+       pWnd->expose_event = NULL;
+     }
+
+   if (pWnd->window)
+     {
+       XEvent xe;
+       TSXDeleteContext( display, pWnd->window, winContext );
+       TSXDestroyWindow( display, pWnd->window );
+       while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
+       pWnd->window = None;
+     }
+
+   return TRUE;
+}
+
+/*****************************************************************
+ *		X11DRV_WND_SetParent
+ */
+WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
+{
+    if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) )
+    {
+	WND* pWndPrev = wndPtr->parent;
+
+	if( pWndParent != pWndPrev )
+	{
+	    BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf);
+
+	    if ( wndPtr->window )
+	    {
+		/* Toplevel window needs to be reparented.  Used by Tk 8.0 */
+
+		TSXDestroyWindow( display, wndPtr->window );
+		wndPtr->window = None;
+	    }
+	    else if( bFixupDCE )
+		DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
+
+	    WIN_UnlinkWindow(wndPtr->hwndSelf);
+	    wndPtr->parent = pWndParent;
+
+	    /* FIXME: Create an X counterpart for reparented top-level windows
+	     * when not in the desktop mode. */
+     
+	    if ( pWndParent != WIN_GetDesktop() ) wndPtr->dwStyle |= WS_CHILD;
+	    WIN_LinkWindow(wndPtr->hwndSelf, HWND_BOTTOM);
+
+	    if( bFixupDCE )
+	    {
+	        DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
+		UpdateWindow32(wndPtr->hwndSelf);
+	    }
+	}
+	return pWndPrev;
+    } /* failure */
+    return 0;
+}
+
+/***********************************************************************
+ *		X11DRV_WND_ForceWindowRaise
+ *
+ * Raise a window on top of the X stacking order, while preserving 
+ * the correct Windows Z order.
+ */
+void X11DRV_WND_ForceWindowRaise(WND *pWnd)
+{
+  XWindowChanges winChanges;
+  WND *wndPrev;
+  
+  if( !pWnd || !pWnd->window || (pWnd->flags & WIN_MANAGED) )
+    return;
+  
+  /* Raise all windows up to pWnd according to their Z order.
+   * (it would be easier with sibling-related Below but it doesn't
+   * work very well with SGI mwm for instance)
+   */
+  winChanges.stack_mode = Above;
+  while (pWnd)
+    {
+      if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0,
+                                                CWStackMode, &winChanges );
+      wndPrev = WIN_GetDesktop()->child;
+      if (wndPrev == pWnd) break;
+      while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next;
+      pWnd = wndPrev;
+    }
+}
+
+/***********************************************************************
+ *		X11DRV_WND_FindDesktopXWindow	[Internal]
+ *
+ * Find the actual X window which needs be restacked.
+ * Used by X11DRV_SetWindowPos().
+ */
+static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
+{
+  if (!(wndPtr->flags & WIN_MANAGED))
+    return wndPtr->window;
+  else
+    {
+      Window window, root, parent, *children;
+      int nchildren;
+      window = wndPtr->window;
+      for (;;)
+        {
+	  TSXQueryTree( display, window, &root, &parent,
+                        &children, &nchildren );
+	  TSXFree( children );
+	  if (parent == root)
+	    return window;
+	  window = parent;
+        }
+    }
+}
+
+/***********************************************************************
+ *           WINPOS_SetXWindowPos
+ *
+ * SetWindowPos() for an X window. Used by the real SetWindowPos().
+ */
+void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS)
+{
+  XWindowChanges winChanges;
+  int changeMask = 0;
+  WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
+  
+  if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
+    {
+      if(wndPtr && wndPtr->window) TSXUnmapWindow( display, wndPtr->window );
+    }
+
+  if(bSMC_SETXPOS)
+    {
+      if ( !(winpos->flags & SWP_NOSIZE))
+	{
+	  winChanges.width     = winpos->cx;
+	  winChanges.height    = winpos->cy;
+	  changeMask |= CWWidth | CWHeight;
+	  
+	  /* Tweak dialog window size hints */
+	  
+	  if ((winposPtr->flags & WIN_MANAGED) &&
+	      (winposPtr->dwExStyle & WS_EX_DLGMODALFRAME))
+	    {
+	      XSizeHints *size_hints = TSXAllocSizeHints();
+	      
+	      if (size_hints)
+		{
+		  long supplied_return;
+		  
+		  TSXGetWMSizeHints( display, winposPtr->window, size_hints,
+				     &supplied_return, XA_WM_NORMAL_HINTS);
+		  size_hints->min_width = size_hints->max_width = winpos->cx;
+		  size_hints->min_height = size_hints->max_height = winpos->cy;
+		  TSXSetWMSizeHints( display, winposPtr->window, size_hints,
+				     XA_WM_NORMAL_HINTS );
+		  TSXFree(size_hints);
+		}
+	    }
+	}
+      if (!(winpos->flags & SWP_NOMOVE))
+	{
+	  winChanges.x = winpos->x;
+	  winChanges.y = winpos->y;
+	  changeMask |= CWX | CWY;
+	}
+      if (!(winpos->flags & SWP_NOZORDER))
+	{
+	  winChanges.stack_mode = Below;
+	  changeMask |= CWStackMode;
+	  
+	  if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
+	  else if (winpos->hwndInsertAfter != HWND_BOTTOM)
+	    {
+	      WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
+	      Window stack[2];
+	      
+	      stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
+	      stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
+	      
+	      /* for stupid window managers (i.e. all of them) */
+	      
+	      TSXRestackWindows(display, stack, 2); 
+	      changeMask &= ~CWStackMode;
+	    }
+	}
+      if (changeMask)
+	{
+	  TSXReconfigureWMWindow( display, winposPtr->window, 0, changeMask, &winChanges );
+	}
+    }
+
+  if ( winpos->flags & SWP_SHOWWINDOW )
+    {
+      if(wndPtr && wndPtr->window) TSXMapWindow( display, wndPtr->window );
+    }
+}
+
+/*****************************************************************
+ *		X11DRV_WND_SetText
+ */
+void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
+{   
+  if (!wndPtr->window)
+    return;
+
+  TSXStoreName( display, wndPtr->window, text );
+  TSXSetIconName( display, wndPtr->window, text );
+}
+
+/*****************************************************************
+ *		X11DRV_WND_SetFocus
+ *
+ * Set the X focus.
+ * Explicit colormap management seems to work only with OLVWM.
+ */
+void X11DRV_WND_SetFocus(WND *wndPtr)
+{
+  HWND32 hwnd =  wndPtr->hwndSelf;
+  XWindowAttributes win_attr;
+  
+  /* Only mess with the X focus if there's */
+  /* no desktop window and no window manager. */
+  if ((rootWindow != DefaultRootWindow(display)) || Options.managed) return;
+  
+  if (!hwnd)	/* If setting the focus to 0, uninstall the colormap */
+    {
+      if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
+	TSXUninstallColormap( display, COLOR_GetColormap() );
+      return;
+    }
+  
+  /* Set X focus and install colormap */
+  
+  if (!wndPtr->window) return;
+  
+  if (!TSXGetWindowAttributes( display, wndPtr->window, &win_attr ) ||
+      (win_attr.map_state != IsViewable))
+    return;  /* If window is not viewable, don't change anything */
+  
+  TSXSetInputFocus( display,wndPtr->window, RevertToParent, CurrentTime );
+  if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
+    TSXInstallColormap( display, COLOR_GetColormap() );
+  
+  EVENT_Synchronize();
+}
+
+/*****************************************************************
+ *		X11DRV_WND_PreSizeMove
+ */
+void X11DRV_WND_PreSizeMove(WND *wndPtr)
+{
+  if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
+    TSXGrabServer( display );
+}
+
+/*****************************************************************
+ *		 X11DRV_WND_PostSizeMove
+ */
+void X11DRV_WND_PostSizeMove(WND *wndPtr)
+{
+  if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
+    TSXUngrabServer( display );
+}
+
+#endif /* !defined(X_DISPLAY_MISSING) */