Use a table of handlers to dispatch X events and get rid of the
special casing for DGA and tablet events.
Unify the declarations of all the event handlers.

diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c
index 7797c9b..8532f28 100644
--- a/dlls/x11drv/clipboard.c
+++ b/dlls/x11drv/clipboard.c
@@ -2940,18 +2940,19 @@
 /***********************************************************************
  *           X11DRV_SelectionRequest
  */
-void X11DRV_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event )
+void X11DRV_SelectionRequest( HWND hWnd, XEvent *event )
 {
     if (!hWnd) return;
-    X11DRV_HandleSelectionRequest( hWnd, event, FALSE );
+    X11DRV_HandleSelectionRequest( hWnd, &event->xselectionrequest, FALSE );
 }
 
 
 /***********************************************************************
  *           X11DRV_SelectionClear
  */
-void X11DRV_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
+void X11DRV_SelectionClear( HWND hWnd, XEvent *xev )
 {
+    XSelectionClearEvent *event = &xev->xselectionclear;
     if (!hWnd) return;
     if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
         X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd, event->time );
diff --git a/dlls/x11drv/dga2.c b/dlls/x11drv/dga2.c
index ea4132b..e72b496 100644
--- a/dlls/x11drv/dga2.c
+++ b/dlls/x11drv/dga2.c
@@ -42,8 +42,8 @@
 
 LPDDHALMODEINFO xf86dga2_modes;
 unsigned xf86dga2_mode_count;
+HWND DGAhwnd = 0;
 static XDGAMode* modes;
-static int dga_event, dga_error;
 
 static void convert_mode(XDGAMode *mode, LPDDHALMODEINFO info)
 {
@@ -66,9 +66,58 @@
     return 1;
 }
 
+static void X11DRV_DGAKeyPressEvent( HWND hwnd, XEvent *xev )
+{
+    /* Fill a XKeyEvent to send to EVENT_Key */
+    XDGAKeyEvent *event = (XDGAKeyEvent *)xev;
+    XEvent ke;
+
+    ke.xkey.type = KeyPress;
+    ke.xkey.serial = event->serial;
+    ke.xkey.send_event = FALSE;
+    ke.xkey.display = event->display;
+    ke.xkey.window = 0;
+    ke.xkey.root = 0;
+    ke.xkey.subwindow = 0;
+    ke.xkey.time = event->time;
+    ke.xkey.x = -1;
+    ke.xkey.y = -1;
+    ke.xkey.x_root = -1;
+    ke.xkey.y_root = -1;
+    ke.xkey.state = event->state;
+    ke.xkey.keycode = event->keycode;
+    ke.xkey.same_screen = TRUE;
+    X11DRV_KeyEvent( 0, &ke );
+}
+
+static void X11DRV_DGAKeyReleaseEvent( HWND hwnd, XEvent *xev )
+{
+    /* Fill a XKeyEvent to send to EVENT_Key */
+    XDGAKeyEvent *event = (XDGAKeyEvent *)xev;
+    XEvent ke;
+
+    ke.xkey.type = KeyRelease;
+    ke.xkey.serial = event->serial;
+    ke.xkey.send_event = FALSE;
+    ke.xkey.display = event->display;
+    ke.xkey.window = 0;
+    ke.xkey.root = 0;
+    ke.xkey.subwindow = 0;
+    ke.xkey.time = event->time;
+    ke.xkey.x = -1;
+    ke.xkey.y = -1;
+    ke.xkey.x_root = -1;
+    ke.xkey.y_root = -1;
+    ke.xkey.state = event->state;
+    ke.xkey.keycode = event->keycode;
+    ke.xkey.same_screen = TRUE;
+    X11DRV_KeyEvent( 0, &ke );
+}
+
+
 void X11DRV_XF86DGA2_Init(void)
 {
-  int nmodes, major, minor, i;
+  int nmodes, major, minor, i, event_base, error_base;
   Bool ok;
 
   TRACE("\n");
@@ -81,7 +130,7 @@
   if (!usedga) return;
 
   wine_tsx11_lock();
-  ok = XDGAQueryExtension(gdi_display, &dga_event, &dga_error);
+  ok = XDGAQueryExtension(gdi_display, &event_base, &error_base);
   if (ok)
   {
       X11DRV_expect_error(gdi_display, DGA2ErrorHandler, NULL);
@@ -121,6 +170,13 @@
   for (i=0; i<nmodes; i++)
     convert_mode(&modes[i], &xf86dga2_modes[i+1]);
 
+  /* register event handlers */
+  X11DRV_register_event_handler( event_base + MotionNotify, X11DRV_DGAMotionEvent );
+  X11DRV_register_event_handler( event_base + ButtonPress, X11DRV_DGAButtonPressEvent );
+  X11DRV_register_event_handler( event_base + ButtonRelease, X11DRV_DGAButtonReleaseEvent );
+  X11DRV_register_event_handler( event_base + KeyPress, X11DRV_DGAKeyPressEvent );
+  X11DRV_register_event_handler( event_base + KeyRelease, X11DRV_DGAKeyReleaseEvent );
+
   TRACE("Enabling XF86DGA2 mode\n");
 }
 
@@ -160,8 +216,7 @@
 			  KeyPressMask|KeyReleaseMask|
 			  ButtonPressMask|ButtonReleaseMask|
 			  PointerMotionMask);
-	X11DRV_EVENT_SetDGAStatus((HWND)ddlocal->hWnd, dga_event);
-	X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
+        DGAhwnd = (HWND)ddlocal->hWnd;
       }
       dga_dev = new_dev;
       vram = dga_dev->mode.bytesPerScanline * dga_dev->mode.imageHeight;
@@ -184,8 +239,7 @@
     X11DRV_DDHAL_SwitchMode(0, NULL, NULL);
     XDGASetMode(display, DefaultScreen(display), 0);
     VirtualFree(dga_dev->data, 0, MEM_RELEASE);
-    X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_ABSOLUTE);
-    X11DRV_EVENT_SetDGAStatus(0, -1);
+    DGAhwnd = 0;
     XFree(dga_dev);
     XDGACloseFramebuffer(display, DefaultScreen(display));
     dga_dev = NULL;
diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c
index 9da9b1b..b8fe9ed 100644
--- a/dlls/x11drv/event.c
+++ b/dlls/x11drv/event.c
@@ -66,64 +66,171 @@
 
 #define DndURL          128   /* KDE drag&drop */
 
-static const char * const event_names[] =
+  /* Event handlers */
+static void EVENT_FocusIn( HWND hwnd, XEvent *event );
+static void EVENT_FocusOut( HWND hwnd, XEvent *event );
+static void EVENT_PropertyNotify( HWND hwnd, XEvent *event );
+static void EVENT_ClientMessage( HWND hwnd, XEvent *event );
+
+struct event_handler
 {
-  "", "", "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"
+    int                  type;    /* event type */
+    x11drv_event_handler handler; /* corresponding handler function */
 };
 
+#define MAX_EVENT_HANDLERS 64
 
-static void EVENT_ProcessEvent( XEvent *event );
+static struct event_handler handlers[MAX_EVENT_HANDLERS] =
+{
+    /* list must be sorted by event type */
+    { KeyPress,         X11DRV_KeyEvent },
+    { KeyRelease,       X11DRV_KeyEvent },
+    { ButtonPress,      X11DRV_ButtonPress },
+    { ButtonRelease,    X11DRV_ButtonRelease },
+    { MotionNotify,     X11DRV_MotionNotify },
+    { EnterNotify,      X11DRV_EnterNotify },
+    /* LeaveNotify */
+    { FocusIn,          EVENT_FocusIn },
+    { FocusOut,         EVENT_FocusOut },
+    { KeymapNotify,     X11DRV_KeymapNotify },
+    { Expose,           X11DRV_Expose },
+    /* GraphicsExpose */
+    /* NoExpose */
+    /* VisibilityNotify */
+    /* CreateNotify */
+    /* DestroyNotify */
+    { UnmapNotify,      X11DRV_UnmapNotify },
+    { MapNotify,        X11DRV_MapNotify },
+    /* MapRequest */
+    /* ReparentNotify */
+    { ConfigureNotify,  X11DRV_ConfigureNotify },
+    /* ConfigureRequest */
+    /* GravityNotify */
+    /* ResizeRequest */
+    /* CirculateNotify */
+    /* CirculateRequest */
+    { PropertyNotify,   EVENT_PropertyNotify },
+    { SelectionClear,   X11DRV_SelectionClear },
+    { SelectionRequest, X11DRV_SelectionRequest },
+    /* SelectionNotify */
+    /* ColormapNotify */
+    { ClientMessage,    EVENT_ClientMessage },
+    { MappingNotify,    X11DRV_MappingNotify },
+};
 
-  /* Event handlers */
-static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
-static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
-static void EVENT_PropertyNotify( XPropertyEvent *event );
-static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
+static int nb_event_handlers = 18;  /* change this if you add handlers above */
 
-#ifdef HAVE_LIBXXF86DGA2
-static int DGAMotionEventType;
-static int DGAButtonPressEventType;
-static int DGAButtonReleaseEventType;
-static int DGAKeyPressEventType;
-static int DGAKeyReleaseEventType;
 
-static BOOL DGAUsed = FALSE;
-static HWND DGAhwnd = 0;
-#endif
+/* return the name of an X event */
+static const char *dbgstr_event( int type )
+{
+    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 used for the current input method */
-static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
-static BOOL in_transition = FALSE; /* This is not used as for today */
+    if (type >= KeyPress && type <= MappingNotify) return event_names[type - KeyPress];
+    return wine_dbg_sprintf( "Extension event %d", type );
+}
+
+
+/***********************************************************************
+ *           find_handler
+ *
+ * Find the handler for a given event type. Caller must hold the x11 lock.
+ */
+static inline x11drv_event_handler find_handler( int type )
+{
+    int min = 0, max = nb_event_handlers - 1;
+
+    while (min <= max)
+    {
+        int pos = (min + max) / 2;
+        if (handlers[pos].type == type) return handlers[pos].handler;
+        if (handlers[pos].type > type) max = pos - 1;
+        else min = pos + 1;
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           X11DRV_register_event_handler
+ *
+ * Register a handler for a given event type.
+ * If already registered, overwrite the previous handler.
+ */
+void X11DRV_register_event_handler( int type, x11drv_event_handler handler )
+{
+    int min, max;
+
+    wine_tsx11_lock();
+    min = 0;
+    max = nb_event_handlers - 1;
+    while (min <= max)
+    {
+        int pos = (min + max) / 2;
+        if (handlers[pos].type == type)
+        {
+            handlers[pos].handler = handler;
+            goto done;
+        }
+        if (handlers[pos].type > type) max = pos - 1;
+        else min = pos + 1;
+    }
+    /* insert it between max and min */
+    memmove( &handlers[min+1], &handlers[min], (nb_event_handlers - min) * sizeof(handlers[0]) );
+    handlers[min].type = type;
+    handlers[min].handler = handler;
+    nb_event_handlers++;
+    assert( nb_event_handlers <= MAX_EVENT_HANDLERS );
+done:
+    wine_tsx11_unlock();
+    TRACE("registered handler %p for event %d count %d\n", handler, type, nb_event_handlers );
+}
 
 
 /***********************************************************************
  *           process_events
  */
-static int process_events( struct x11drv_thread_data *data )
+static int process_events( Display *display )
 {
     XEvent event;
-    int count = 0;
+    HWND hwnd;
+    int count;
+    x11drv_event_handler handler;
 
     wine_tsx11_lock();
-    while ( XPending( data->display ) )
+    for (count = 0; XPending(display); count++)
     {
-        Bool ignore;
+        XNextEvent( display, &event );
+        if (XFilterEvent( &event, None )) continue;  /* filtered, ignore it */
 
-        XNextEvent( data->display, &event );
-        ignore = XFilterEvent( &event, None );
+        if (!(handler = find_handler( event.type )))
+        {
+            TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
+            continue;  /* no handler, ignore it */
+        }
+
+        if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0)
+            hwnd = 0;  /* not for a registered window */
+        if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow();
+
         wine_tsx11_unlock();
-        if (!ignore) EVENT_ProcessEvent( &event );
-        count++;
+        TRACE( "%s for hwnd/window %p/%lx\n",
+               dbgstr_event( event.type ), hwnd, event.xany.window );
+        handler( hwnd, &event );
         wine_tsx11_lock();
     }
     wine_tsx11_unlock();
+    if (count) TRACE( "processed %d events\n", count );
     return count;
 }
 
@@ -154,12 +261,12 @@
     wine_tsx11_unlock();
 
     data->process_event_count++;
-    if (process_events( data )) ret = count;
+    if (process_events( data->display )) ret = count;
     else
     {
         ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
                                         timeout, flags & MWMO_ALERTABLE );
-        if (ret == count) process_events( data );
+        if (ret == count) process_events( data->display );
     }
     data->process_event_count--;
     return ret;
@@ -200,193 +307,6 @@
 
 }
 
-/***********************************************************************
- *           EVENT_ProcessEvent
- *
- * Process an X event.
- */
-static void EVENT_ProcessEvent( XEvent *event )
-{
-  HWND hWnd;
-  Display *display = event->xany.display;
-
-  TRACE( "called.\n" );
-
-  switch (event->type)
-  {
-    case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
-	 FIXME("Got SelectionNotify - must not happen!\n");
-	 /* fall through */
-
-      /* We get all these because of StructureNotifyMask.
-         This check is placed here to avoid getting error messages below,
-         as X might send some of these even for windows that have already
-         been deleted ... */
-    case CirculateNotify:
-    case CreateNotify:
-    case DestroyNotify:
-    case GravityNotify:
-    case ReparentNotify:
-      return;
-  }
-
-#ifdef HAVE_LIBXXF86DGA2
-  if (DGAUsed) {
-    if (event->type == DGAMotionEventType) {
-      TRACE("DGAMotionEvent received.\n");
-      X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
-      return;
-    }
-    if (event->type == DGAButtonPressEventType) {
-      TRACE("DGAButtonPressEvent received.\n");
-      X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
-      return;
-    }
-    if (event->type == DGAButtonReleaseEventType) {
-      TRACE("DGAButtonReleaseEvent received.\n");
-      X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
-      return;
-    }
-    if ((event->type == DGAKeyPressEventType) ||
-	(event->type == DGAKeyReleaseEventType)) {
-      /* Fill a XKeyEvent to send to EVENT_Key */
-      XKeyEvent ke;
-      XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
-
-      TRACE("DGAKeyPress/ReleaseEvent received.\n");
-
-      if (evt->type == DGAKeyReleaseEventType)
-	ke.type = KeyRelease;
-      else
-	ke.type = KeyPress;
-      ke.serial = evt->serial;
-      ke.send_event = FALSE;
-      ke.display = evt->display;
-      ke.window = 0;
-      ke.root = 0;
-      ke.subwindow = 0;
-      ke.time = evt->time;
-      ke.x = -1;
-      ke.y = -1;
-      ke.x_root = -1;
-      ke.y_root = -1;
-      ke.state = evt->state;
-      ke.keycode = evt->keycode;
-      ke.same_screen = TRUE;
-      X11DRV_KeyEvent( 0, &ke );
-      return;
-    }
-  }
-#endif
-
-  wine_tsx11_lock();
-  if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
-      hWnd = 0;  /* Not for a registered window */
-  wine_tsx11_unlock();
-  if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
-
-  if (!hWnd && event->type != PropertyNotify &&
-      event->type != MappingNotify && event->type != KeymapNotify)
-      WARN( "Got event %s for unknown Window %08lx\n",
-            event_names[event->type], event->xany.window );
-  else if (event->type <= MappingNotify)
-      TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
-            event_names[event->type], hWnd, event->xany.window, GetFocus() );
-  else
-      TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
-            hWnd, event->xany.window, GetFocus() );
-
-  if (X11DRV_ProcessTabletEvent(hWnd, event))
-  {
-        TRACE("Return: filtered by tablet\n");
-        return;
-  }
-
-  switch(event->type)
-    {
-    case KeyPress:
-    case KeyRelease:
-      /* FIXME: should generate a motion event if event point is different from current pos */
-      X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
-      break;
-
-    case ButtonPress:
-      X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
-      break;
-
-    case ButtonRelease:
-      X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
-      break;
-
-    case MotionNotify:
-      X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
-      break;
-
-    case EnterNotify:
-      X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
-      break;
-
-    case FocusIn:
-      EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
-      break;
-
-    case FocusOut:
-      EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
-      break;
-
-    case Expose:
-      X11DRV_Expose( hWnd, &event->xexpose );
-      break;
-
-    case ConfigureNotify:
-      if (!hWnd) return;
-      X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
-      break;
-
-    case SelectionRequest:
-      X11DRV_SelectionRequest( hWnd, (XSelectionRequestEvent *)event );
-      break;
-
-    case SelectionClear:
-      X11DRV_SelectionClear( hWnd, (XSelectionClearEvent*) event );
-      break;
-
-    case PropertyNotify:
-      EVENT_PropertyNotify( (XPropertyEvent *)event );
-      break;
-
-    case ClientMessage:
-      if (!hWnd) return;
-      EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
-      break;
-
-    case NoExpose:
-      break;
-
-    case MapNotify:
-      X11DRV_MapNotify( hWnd, (XMapEvent *)event );
-      break;
-
-    case UnmapNotify:
-      X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
-      break;
-
-    case KeymapNotify:
-      X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
-      break;
-
-    case MappingNotify:
-      X11DRV_MappingNotify( (XMappingEvent *) event );
-      break;
-
-    default:
-      WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
-      break;
-    }
-    TRACE( "returns.\n" );
-}
-
-
 /*******************************************************************
  *         can_activate_window
  *
@@ -500,8 +420,9 @@
 /**********************************************************************
  *              EVENT_FocusIn
  */
-static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
+static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
 {
+    XFocusChangeEvent *event = &xev->xfocus;
     XIC xic;
 
     if (!hwnd) return;
@@ -535,8 +456,9 @@
  *
  * Note: only top-level windows get FocusOut events.
  */
-static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
+static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
 {
+    XFocusChangeEvent *event = &xev->xfocus;
     HWND hwnd_tmp;
     Window focus_win;
     int revert;
@@ -591,8 +513,9 @@
  *   We use this to release resources like Pixmaps when a selection
  *   client no longer needs them.
  */
-static void EVENT_PropertyNotify( XPropertyEvent *event )
+static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
 {
+  XPropertyEvent *event = &xev->xproperty;
   /* Check if we have any resources to free */
   TRACE("Received PropertyNotify event: \n");
 
@@ -916,8 +839,12 @@
 /**********************************************************************
  *           EVENT_ClientMessage
  */
-static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
+static void EVENT_ClientMessage( HWND hWnd, XEvent *xev )
 {
+    XClientMessageEvent *event = &xev->xclient;
+
+    if (!hWnd) return;
+
   if (event->message_type != None && event->format == 32) {
     if (event->message_type == x11drv_atom(WM_PROTOCOLS))
         handle_wm_protocols_message( hWnd, event );
@@ -964,39 +891,3 @@
     }
   }
 }
-
-
-/**********************************************************************
- *              X11DRV_EVENT_SetInputMethod
- */
-INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
-{
-  INPUT_TYPE prev = current_input_type;
-
-  /* Flag not used yet */
-  in_transition = FALSE;
-  current_input_type = type;
-
-  return prev;
-}
-
-#ifdef HAVE_LIBXXF86DGA2
-/**********************************************************************
- *              X11DRV_EVENT_SetDGAStatus
- */
-void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
-{
-  if (event_base < 0) {
-    DGAUsed = FALSE;
-    DGAhwnd = 0;
-  } else {
-    DGAUsed = TRUE;
-    DGAhwnd = hwnd;
-    DGAMotionEventType = event_base + MotionNotify;
-    DGAButtonPressEventType = event_base + ButtonPress;
-    DGAButtonReleaseEventType = event_base + ButtonRelease;
-    DGAKeyPressEventType = event_base + KeyPress;
-    DGAKeyReleaseEventType = event_base + KeyRelease;
-  }
-}
-#endif
diff --git a/dlls/x11drv/keyboard.c b/dlls/x11drv/keyboard.c
index ef0241f..5b0fd78 100644
--- a/dlls/x11drv/keyboard.c
+++ b/dlls/x11drv/keyboard.c
@@ -1097,7 +1097,7 @@
  * from wine to another application and back.
  * Toggle keys are handled in HandleEvent.
  */
-void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event )
+void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
 {
     int i, j, alt, control, shift;
     DWORD time = GetCurrentTime();
@@ -1105,10 +1105,10 @@
     alt = control = shift = 0;
     for (i = 0; i < 32; i++)
     {
-        if (!event->key_vector[i]) continue;
+        if (!event->xkeymap.key_vector[i]) continue;
         for (j = 0; j < 8; j++)
         {
-            if (!(event->key_vector[i] & (1<<j))) continue;
+            if (!(event->xkeymap.key_vector[i] & (1<<j))) continue;
             switch(keyc2vkey[(i * 8) + j] & 0xff)
             {
             case VK_MENU:    alt = 1; break;
@@ -1127,8 +1127,9 @@
  *
  * Handle a X key event
  */
-void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event )
+void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
 {
+    XKeyEvent *event = &xev->xkey;
     char Str[24];
     KeySym keysym = 0;
     WORD vkey = 0, bScan;
@@ -1705,12 +1706,12 @@
 /***********************************************************************
  *           X11DRV_MappingNotify
  */
-void X11DRV_MappingNotify( XMappingEvent *event )
+void X11DRV_MappingNotify( HWND dummy, XEvent *event )
 {
     HWND hwnd;
 
     wine_tsx11_lock();
-    XRefreshKeyboardMapping(event);
+    XRefreshKeyboardMapping(&event->xmapping);
     wine_tsx11_unlock();
     X11DRV_InitKeyboard( pKeyStateTable );
 
diff --git a/dlls/x11drv/mouse.c b/dlls/x11drv/mouse.c
index e1b0da9..6697364 100644
--- a/dlls/x11drv/mouse.c
+++ b/dlls/x11drv/mouse.c
@@ -536,8 +536,9 @@
 /***********************************************************************
  *           X11DRV_ButtonPress
  */
-void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event )
+void X11DRV_ButtonPress( HWND hwnd, XEvent *xev )
 {
+    XButtonEvent *event = &xev->xbutton;
     int buttonNum = event->button - 1;
     WORD wData = 0;
     POINT pt;
@@ -566,8 +567,9 @@
 /***********************************************************************
  *           X11DRV_ButtonRelease
  */
-void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event )
+void X11DRV_ButtonRelease( HWND hwnd, XEvent *xev )
 {
+    XButtonEvent *event = &xev->xbutton;
     int buttonNum = event->button - 1;
     POINT pt;
 
@@ -585,8 +587,9 @@
 /***********************************************************************
  *           X11DRV_MotionNotify
  */
-void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event )
+void X11DRV_MotionNotify( HWND hwnd, XEvent *xev )
 {
+    XMotionEvent *event = &xev->xmotion;
     POINT pt;
 
     TRACE("hwnd %p, event->is_hint %d\n", hwnd, event->is_hint);
@@ -604,8 +607,9 @@
 /***********************************************************************
  *           X11DRV_EnterNotify
  */
-void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event )
+void X11DRV_EnterNotify( HWND hwnd, XEvent *xev )
 {
+    XCrossingEvent *event = &xev->xcrossing;
     POINT pt;
 
     TRACE("hwnd %p, event->detail %d\n", hwnd, event->detail);
@@ -623,36 +627,43 @@
 
 
 #ifdef HAVE_LIBXXF86DGA2
+
+extern HWND DGAhwnd;
+
 /**********************************************************************
  *              X11DRV_DGAMotionEvent
  */
-void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event )
+void X11DRV_DGAMotionEvent( HWND hwnd, XEvent *xev )
 {
+    XDGAMotionEvent *event = (XDGAMotionEvent *)xev;
     update_key_state( event->state );
-    send_mouse_event( hwnd, MOUSEEVENTF_MOVE, event->dx, event->dy, 0, event->time );
+    send_mouse_event( DGAhwnd, MOUSEEVENTF_MOVE, event->dx, event->dy, 0, event->time );
 }
 
 /**********************************************************************
  *              X11DRV_DGAButtonPressEvent
  */
-void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event )
+void X11DRV_DGAButtonPressEvent( HWND hwnd, XEvent *xev )
 {
+    XDGAButtonEvent *event = (XDGAButtonEvent *)xev;
     int buttonNum = event->button - 1;
 
     if (buttonNum >= NB_BUTTONS) return;
     update_key_state( event->state );
-    send_mouse_event( hwnd, button_down_flags[buttonNum], 0, 0, 0, event->time );
+    send_mouse_event( DGAhwnd, button_down_flags[buttonNum], 0, 0, 0, event->time );
 }
 
 /**********************************************************************
  *              X11DRV_DGAButtonReleaseEvent
  */
-void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event )
+void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XEvent *xev )
 {
+    XDGAButtonEvent *event = (XDGAButtonEvent *)xev;
     int buttonNum = event->button - 1;
 
     if (buttonNum >= NB_BUTTONS) return;
     update_key_state( event->state );
-    send_mouse_event( hwnd, button_up_flags[buttonNum], 0, 0, 0, event->time );
+    send_mouse_event( DGAhwnd, button_up_flags[buttonNum], 0, 0, 0, event->time );
 }
+
 #endif /* HAVE_LIBXXF86DGA2 */
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index faaed71..a66bf8c 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -138,8 +138,9 @@
 /***********************************************************************
  *           X11DRV_Expose
  */
-void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
+void X11DRV_Expose( HWND hwnd, XEvent *xev )
 {
+    XExposeEvent *event = &xev->xexpose;
     RECT rect;
     struct x11drv_win_data *data;
     int flags = RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN;
@@ -1196,7 +1197,7 @@
 /**********************************************************************
  *		X11DRV_MapNotify
  */
-void X11DRV_MapNotify( HWND hwnd, XMapEvent *event )
+void X11DRV_MapNotify( HWND hwnd, XEvent *event )
 {
     struct x11drv_win_data *data;
     HWND hwndFocus = GetFocus();
@@ -1216,9 +1217,9 @@
 
         /* FIXME: hack */
         wine_tsx11_lock();
-        XGetGeometry( event->display, data->whole_window, &root, &x, &y, &width, &height,
+        XGetGeometry( event->xmap.display, data->whole_window, &root, &x, &y, &width, &height,
                         &border, &depth );
-        XTranslateCoordinates( event->display, data->whole_window, root, 0, 0, &x, &y, &top );
+        XTranslateCoordinates( event->xmap.display, data->whole_window, root, 0, 0, &x, &y, &top );
         wine_tsx11_unlock();
         rect.left   = x;
         rect.top    = y;
@@ -1244,7 +1245,7 @@
 /**********************************************************************
  *              X11DRV_UnmapNotify
  */
-void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event )
+void X11DRV_UnmapNotify( HWND hwnd, XEvent *event )
 {
     struct x11drv_win_data *data;
     WND *win;
@@ -1416,14 +1417,16 @@
 /***********************************************************************
  *		X11DRV_ConfigureNotify
  */
-void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
+void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
 {
+    XConfigureEvent *event = &xev->xconfigure;
     HWND oldInsertAfter;
     struct x11drv_win_data *data;
     RECT rect;
     WINDOWPOS winpos;
     int x = event->x, y = event->y;
 
+    if (!hwnd) return;
     if (!(data = X11DRV_get_win_data( hwnd ))) return;
 
     /* Get geometry */
diff --git a/dlls/x11drv/wintab.c b/dlls/x11drv/wintab.c
index 9502e7a..920648a 100644
--- a/dlls/x11drv/wintab.c
+++ b/dlls/x11drv/wintab.c
@@ -219,13 +219,13 @@
 #include <X11/Xlib.h>
 #include <X11/extensions/XInput.h>
 
-static int           motion_type = -1;
-static int           button_press_type = -1;
-static int           button_release_type = -1;
-static int           key_press_type = -1;
-static int           key_release_type = -1;
-static int           proximity_in_type = -1;
-static int           proximity_out_type = -1;
+static int           motion_type;
+static int           button_press_type;
+static int           button_release_type;
+static int           key_press_type;
+static int           key_release_type;
+static int           proximity_in_type;
+static int           proximity_out_type;
 
 static HWND          hwndTabletDefault;
 static WTPACKET      gMsgPacket;
@@ -588,107 +588,90 @@
     button_state[deviceid] = rc;
 }
 
-int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event)
+static void motion_event( HWND hwnd, XEvent *event )
 {
+    XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
+    LPWTI_CURSORS_INFO cursor = &gSysCursor[motion->deviceid];
+
     memset(&gMsgPacket,0,sizeof(WTPACKET));
 
-    if(event->type ==  motion_type)
-    {
-        XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
-        LPWTI_CURSORS_INFO cursor = &gSysCursor[motion->deviceid];
+    TRACE("Received tablet motion event (%p)\n",hwnd);
 
-        TRACE_(event)("Received tablet motion event (%p)\n",hwnd);
-        TRACE("Received tablet motion event (%p)\n",hwnd);
-        /* Set cursor to inverted if cursor is the eraser */
-        gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
-        gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
-        gMsgPacket.pkSerialNumber = gSerial++;
-        gMsgPacket.pkCursor = motion->deviceid;
-        gMsgPacket.pkX = motion->axis_data[0];
-        gMsgPacket.pkY = motion->axis_data[1];
-        gMsgPacket.pkOrientation.orAzimuth =
-                    figure_deg(motion->axis_data[3],motion->axis_data[4]);
-        gMsgPacket.pkOrientation.orAltitude = 
-                    (1000 - 15 * max
-                        (abs(motion->axis_data[3]),
-                        abs(motion->axis_data[4]))
-                        )*(gMsgPacket.pkStatus & TPS_INVERT?-1:1);
-        gMsgPacket.pkNormalPressure = motion->axis_data[2];
-        gMsgPacket.pkButtons = get_button_state(motion->deviceid);
-        SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
-    }
-    else if ((event->type == button_press_type)||(event->type ==
-              button_release_type))
-    {
-        XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
-        LPWTI_CURSORS_INFO cursor = &gSysCursor[button->deviceid];
+    /* Set cursor to inverted if cursor is the eraser */
+    gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
+    gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(motion->time);
+    gMsgPacket.pkSerialNumber = gSerial++;
+    gMsgPacket.pkCursor = motion->deviceid;
+    gMsgPacket.pkX = motion->axis_data[0];
+    gMsgPacket.pkY = motion->axis_data[1];
+    gMsgPacket.pkOrientation.orAzimuth = figure_deg(motion->axis_data[3],motion->axis_data[4]);
+    gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max
+                                            (abs(motion->axis_data[3]),
+                                             abs(motion->axis_data[4])))
+                                           * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
+    gMsgPacket.pkNormalPressure = motion->axis_data[2];
+    gMsgPacket.pkButtons = get_button_state(motion->deviceid);
+    SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
+}
 
-        TRACE_(event)("Received tablet button event\n");
-        TRACE("Received tablet button %s event\n", (event->type ==
-                                button_press_type)?"press":"release");
+static void button_event( HWND hwnd, XEvent *event )
+{
+    XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
+    LPWTI_CURSORS_INFO cursor = &gSysCursor[button->deviceid];
 
-        /* Set cursor to inverted if cursor is the eraser */
-        gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
-        set_button_state(button->deviceid);
-        gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
-        gMsgPacket.pkSerialNumber = gSerial++;
-        gMsgPacket.pkCursor = button->deviceid;
-        gMsgPacket.pkX = button->axis_data[0];
-        gMsgPacket.pkY = button->axis_data[1];
-        gMsgPacket.pkOrientation.orAzimuth =
-                    figure_deg(button->axis_data[3],button->axis_data[4]);
-        gMsgPacket.pkOrientation.orAltitude =
-                    (1000 - 15 * max
-                        (abs(button->axis_data[3]),
-                        abs(button->axis_data[4]))
-                        )*(gMsgPacket.pkStatus & TPS_INVERT?-1:1);
-        gMsgPacket.pkNormalPressure = button->axis_data[2];
-        gMsgPacket.pkButtons = get_button_state(button->deviceid);
-        SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
-  }
-    else if (event->type == key_press_type)
-    {
-        TRACE_(event)("Received tablet key press event\n");
+    memset(&gMsgPacket,0,sizeof(WTPACKET));
+
+    TRACE("Received tablet button %s event\n", (event->type == button_press_type)?"press":"release");
+
+    /* Set cursor to inverted if cursor is the eraser */
+    gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
+    set_button_state(button->deviceid);
+    gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(button->time);
+    gMsgPacket.pkSerialNumber = gSerial++;
+    gMsgPacket.pkCursor = button->deviceid;
+    gMsgPacket.pkX = button->axis_data[0];
+    gMsgPacket.pkY = button->axis_data[1];
+    gMsgPacket.pkOrientation.orAzimuth = figure_deg(button->axis_data[3],button->axis_data[4]);
+    gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(button->axis_data[3]),
+                                                            abs(button->axis_data[4])))
+                                           * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
+    gMsgPacket.pkNormalPressure = button->axis_data[2];
+    gMsgPacket.pkButtons = get_button_state(button->deviceid);
+    SendMessageW(hwndTabletDefault,WT_PACKET,0,(LPARAM)hwnd);
+}
+
+static void key_event( HWND hwnd, XEvent *event )
+{
+    if (event->type == key_press_type)
         FIXME("Received tablet key press event\n");
-    }
-    else if (event->type == key_release_type)
-    {
-        TRACE_(event)("Received tablet key release event\n");
-        FIXME("Received tablet key release event\n");
-    }
-    else if ((event->type == proximity_in_type) ||
-             (event->type == proximity_out_type))
-    {
-        XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
-        LPWTI_CURSORS_INFO cursor = &gSysCursor[proximity->deviceid];
-
-        TRACE_(event)("Received tablet proximity event\n");
-        TRACE("Received tablet proximity event\n");
-        /* Set cursor to inverted if cursor is the eraser */
-        gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
-        gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
-        gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
-        gMsgPacket.pkSerialNumber = gSerial++;
-        gMsgPacket.pkCursor = proximity->deviceid;
-        gMsgPacket.pkX = proximity->axis_data[0];
-        gMsgPacket.pkY = proximity->axis_data[1];
-        gMsgPacket.pkOrientation.orAzimuth =
-                    figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
-        gMsgPacket.pkOrientation.orAltitude =
-                    (1000 - 15 * max
-                        (abs(proximity->axis_data[3]),
-                        abs(proximity->axis_data[4]))
-                        )*(gMsgPacket.pkStatus & TPS_INVERT?-1:1);
-        gMsgPacket.pkNormalPressure = proximity->axis_data[2];
-        gMsgPacket.pkButtons = get_button_state(proximity->deviceid);
-
-        SendMessageW(hwndTabletDefault, WT_PROXIMITY,
-                     (event->type==proximity_out_type)?0:1, (LPARAM)hwnd);
-    }
     else
-        return 0;
+        FIXME("Received tablet key release event\n");
+}
 
-    return 1;
+static void proximity_event( HWND hwnd, XEvent *event )
+{
+    XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) event;
+    LPWTI_CURSORS_INFO cursor = &gSysCursor[proximity->deviceid];
+
+    memset(&gMsgPacket,0,sizeof(WTPACKET));
+
+    TRACE("Received tablet proximity event\n");
+    /* Set cursor to inverted if cursor is the eraser */
+    gMsgPacket.pkStatus = (cursor->TYPE == 0xc85a ?TPS_INVERT:0);
+    gMsgPacket.pkStatus |= (event->type==proximity_out_type)?TPS_PROXIMITY:0;
+    gMsgPacket.pkTime = EVENT_x11_time_to_win32_time(proximity->time);
+    gMsgPacket.pkSerialNumber = gSerial++;
+    gMsgPacket.pkCursor = proximity->deviceid;
+    gMsgPacket.pkX = proximity->axis_data[0];
+    gMsgPacket.pkY = proximity->axis_data[1];
+    gMsgPacket.pkOrientation.orAzimuth = figure_deg(proximity->axis_data[3],proximity->axis_data[4]);
+    gMsgPacket.pkOrientation.orAltitude = ((1000 - 15 * max(abs(proximity->axis_data[3]),
+                                                            abs(proximity->axis_data[4])))
+                                           * (gMsgPacket.pkStatus & TPS_INVERT?-1:1));
+    gMsgPacket.pkNormalPressure = proximity->axis_data[2];
+    gMsgPacket.pkButtons = get_button_state(proximity->deviceid);
+
+    SendMessageW(hwndTabletDefault, WT_PROXIMITY, (event->type == proximity_in_type), (LPARAM)hwnd);
 }
 
 int X11DRV_AttachEventQueueToTablet(HWND hOwner)
@@ -700,7 +683,6 @@
     XDeviceInfo     *devices;
     XDeviceInfo     *target = NULL;
     XDevice         *the_device;
-    XInputClassInfo *ip;
     XEventClass     event_list[7];
     Window          win = X11DRV_get_whole_window( hOwner );
 
@@ -731,43 +713,29 @@
 
         if (the_device->num_classes > 0)
         {
-            for (ip = the_device->classes, loop=0; loop < target->num_classes;
-                 ip++, loop++)
-            {
-                switch(ip->input_class)
-                {
-                    case KeyClass:
-                        DeviceKeyPress(the_device, key_press_type,
-                                       event_list[event_number]);
-                        event_number++;
-                        DeviceKeyRelease(the_device, key_release_type,
-                                          event_list[event_number]);
-                        event_number++;
-                        break;
-                    case ButtonClass:
-                        DeviceButtonPress(the_device, button_press_type,
-                                       event_list[event_number]);
-                        event_number++;
-                        DeviceButtonRelease(the_device, button_release_type,
-                                            event_list[event_number]);
-                        event_number++;
-                        break;
-                    case ValuatorClass:
-                        DeviceMotionNotify(the_device, motion_type,
-                                           event_list[event_number]);
-                        event_number++;
-                        ProximityIn(the_device, proximity_in_type,
-                                 event_list[event_number]);
-                        event_number++;
-                        ProximityOut(the_device, proximity_out_type,
-                                     event_list[event_number]);
-                        event_number++;
-                        break;
-                    default:
-                        ERR("unknown class\n");
-                        break;
-                }
-            }
+            DeviceKeyPress(the_device, key_press_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+            DeviceKeyRelease(the_device, key_release_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+            DeviceButtonPress(the_device, button_press_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+            DeviceButtonRelease(the_device, button_release_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+            DeviceMotionNotify(the_device, motion_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+            ProximityIn(the_device, proximity_in_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+            ProximityOut(the_device, proximity_out_type, event_list[event_number]);
+            if (event_list[event_number]) event_number++;
+
+            if (key_press_type) X11DRV_register_event_handler( key_press_type, key_event );
+            if (key_release_type) X11DRV_register_event_handler( key_release_type, key_event );
+            if (button_press_type) X11DRV_register_event_handler( button_press_type, button_event );
+            if (button_release_type) X11DRV_register_event_handler( button_release_type, button_event );
+            if (motion_type) X11DRV_register_event_handler( motion_type, motion_event );
+            if (proximity_in_type) X11DRV_register_event_handler( proximity_in_type, proximity_event );
+            if (proximity_out_type) X11DRV_register_event_handler( proximity_out_type, proximity_event );
+
             if (pXSelectExtensionEvent(data->display, win, event_list, event_number))
             {
                 ERR( "error selecting extended events\n");
@@ -1201,11 +1169,6 @@
 
 #else /* HAVE_X11_EXTENSIONS_XINPUT_H */
 
-int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event)
-{
-    return 0;
-}
-
 /***********************************************************************
  *		AttachEventQueueToTablet (X11DRV.@)
  */
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index 65a368c..db19661 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -456,36 +456,28 @@
 
 /* X11 event driver */
 
-typedef enum {
-  X11DRV_INPUT_RELATIVE,
-  X11DRV_INPUT_ABSOLUTE
-} INPUT_TYPE;
-extern INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type);
+typedef void (*x11drv_event_handler)( HWND hwnd, XEvent *event );
 
-extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
-extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
-extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
-extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
-extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
-extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
-extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
-extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
-extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
-extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
-extern void X11DRV_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event );
-extern void X11DRV_SelectionClear( HWND hWnd, XSelectionClearEvent *event );
-extern void X11DRV_MappingNotify( XMappingEvent *event );
+extern void X11DRV_register_event_handler( int type, x11drv_event_handler handler );
 
-#ifdef HAVE_LIBXXF86DGA2
-void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base) ;
-
-extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
-extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
-extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
-#endif
+extern void X11DRV_ButtonPress( HWND hwnd, XEvent *event );
+extern void X11DRV_ButtonRelease( HWND hwnd, XEvent *event );
+extern void X11DRV_MotionNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_EnterNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_KeyEvent( HWND hwnd, XEvent *event );
+extern void X11DRV_KeymapNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_Expose( HWND hwnd, XEvent *event );
+extern void X11DRV_MapNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_UnmapNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_ConfigureNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_SelectionRequest( HWND hWnd, XEvent *event );
+extern void X11DRV_SelectionClear( HWND hWnd, XEvent *event );
+extern void X11DRV_MappingNotify( HWND hWnd, XEvent *event );
+extern void X11DRV_DGAMotionEvent( HWND hwnd, XEvent *event );
+extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XEvent *event );
+extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XEvent *event );
 
 extern DWORD EVENT_x11_time_to_win32_time(Time time);
-extern int X11DRV_ProcessTabletEvent(HWND hwnd, XEvent *event);
 
 /* x11drv private window data */
 struct x11drv_win_data