changeset 2710:44e49d3fa6cf

Final merge of Google Summer of Code 2008 work... Many-mouse and tablet support by Szymon Wilczek, mentored by Ryan C. Gordon Everything concerning the project is noted on the wiki: http://wilku.ravenlord.ws/doku.php?id=start
author Sam Lantinga <slouken@libsdl.org>
date Mon, 25 Aug 2008 06:33:00 +0000
parents fd3f0f1147e7
children 62e7af9b2b67
files configure.in include/SDL_events.h include/SDL_keysym.h include/SDL_mouse.h src/SDL_compat.c src/events/SDL_mouse.c src/events/SDL_mouse_c.h src/video/cocoa/SDL_cocoamouse.m src/video/cocoa/SDL_cocoawindow.m src/video/win32/SDL_win32events.c src/video/win32/SDL_win32mouse.c src/video/win32/SDL_win32video.c src/video/win32/SDL_win32window.c src/video/x11/SDL_x11dyn.h src/video/x11/SDL_x11events.c src/video/x11/SDL_x11mouse.c src/video/x11/SDL_x11sym.h src/video/x11/SDL_x11video.c src/video/x11/SDL_x11video.h src/video/x11/SDL_x11window.c test/testalpha.c test/testgl.c
diffstat 22 files changed, 806 insertions(+), 268 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Mon Aug 25 05:30:28 2008 +0000
+++ b/configure.in	Mon Aug 25 06:33:00 2008 +0000
@@ -1033,6 +1033,9 @@
             SOURCES="$SOURCES $srcdir/src/video/Xext/XmuStdCmap/*.c"
             EXTRA_CFLAGS="$EXTRA_CFLAGS $X_CFLAGS"
 
+echo "FIXME: Need to get dynamic loading of XInput working"
+	    enable_x11_shared=no
+
             if test x$enable_x11_shared = xmaybe; then
                 enable_x11_shared=$x11_symbols_private
             fi
@@ -1055,7 +1058,7 @@
                 AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT, "$x11ext_lib")
             else
                 enable_x11_shared=no
-                EXTRA_LDFLAGS="$EXTRA_LDFLAGS $X_LIBS -lX11 -lXext"
+                EXTRA_LDFLAGS="$EXTRA_LDFLAGS $X_LIBS -lX11 -lXext -lXi"
             fi
             have_video=yes
 
--- a/include/SDL_events.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/include/SDL_events.h	Mon Aug 25 06:33:00 2008 +0000
@@ -72,9 +72,11 @@
     SDL_JOYBUTTONUP,            /**< Joystick button released */
     SDL_QUIT,                   /**< User-requested quit */
     SDL_SYSWMEVENT,             /**< System specific event */
+    SDL_PROXIMITYIN,            /**< Proximity In event */
+    SDL_PROXIMITYOUT,           /**< Proximity Out event */
     SDL_EVENT_RESERVED1,        /**< Reserved for future use... */
-    SDL_EVENT_RESERVED2,        /**< Reserved for future use... */
-    SDL_EVENT_RESERVED3,        /**< Reserved for future use... */
+    SDL_EVENT_RESERVED2,
+    SDL_EVENT_RESERVED3,
     /* Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use */
     SDL_USEREVENT = 24,
     /* This last event is only for bounding internal arrays
@@ -112,7 +114,9 @@
         SDL_EVENTMASK(SDL_JOYHATMOTION) |
         SDL_EVENTMASK(SDL_JOYBUTTONDOWN) | SDL_EVENTMASK(SDL_JOYBUTTONUP),
     SDL_QUITMASK = SDL_EVENTMASK(SDL_QUIT),
-    SDL_SYSWMEVENTMASK = SDL_EVENTMASK(SDL_SYSWMEVENT)
+    SDL_SYSWMEVENTMASK = SDL_EVENTMASK(SDL_SYSWMEVENT),
+    SDL_PROXIMITYINMASK = SDL_EVENTMASK(SDL_PROXIMITYIN),
+    SDL_PROXIMITYOUTMASK = SDL_EVENTMASK(SDL_PROXIMITYOUT)
 } SDL_EventMask;
 #define SDL_ALLEVENTS		0xFFFFFFFF
 
@@ -170,6 +174,13 @@
     Uint8 state;            /**< The current button state */
     int x;                  /**< X coordinate, relative to window */
     int y;                  /**< Y coordinate, relative to window */
+    int z;                  /**< Z coordinate, for future use */
+    int pressure;           /**< Pressure reported by tablets */
+    int pressure_max;       /**< Maximum value of the pressure reported by the device */
+    int pressure_min;       /**< Minimum value of the pressure reported by the device */
+    int rotation;           /**< For future use */
+    int tilt;               /**< For future use */
+    int cursor;             /**< The cursor being used in the event */
     int xrel;               /**< The relative motion in the X direction */
     int yrel;               /**< The relative motion in the Y direction */
     SDL_WindowID windowID;  /**< The window with mouse focus, if any */
@@ -316,6 +327,15 @@
     int h;
 } SDL_ResizeEvent;
 
+typedef struct SDL_ProximityEvent
+{
+    Uint8 type;
+    Uint8 which;
+    int cursor;
+    int x;
+    int y;
+} SDL_ProximityEvent;
+
 /**
  * \union SDL_Event
  *
@@ -337,6 +357,7 @@
     SDL_QuitEvent quit;             /**< Quit request event data */
     SDL_UserEvent user;             /**< Custom event data */
     SDL_SysWMEvent syswm;           /**< System dependent window event data */
+    SDL_ProximityEvent proximity;   /**< Proximity In or Out event */
 
     /* Temporarily here for backwards compatibility */
     SDL_ActiveEvent active;
--- a/include/SDL_keysym.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/include/SDL_keysym.h	Mon Aug 25 06:33:00 2008 +0000
@@ -242,7 +242,7 @@
     SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),
     SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),
     SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),
-    SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP),
+    SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP)
 };
 
 /**
--- a/include/SDL_mouse.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/include/SDL_mouse.h	Mon Aug 25 06:33:00 2008 +0000
@@ -72,7 +72,7 @@
  *
  * \brief Get the window which currently has focus for the currently selected mouse.
  */
-extern DECLSPEC SDL_WindowID SDLCALL SDL_GetMouseFocusWindow(void);
+extern DECLSPEC SDL_WindowID SDLCALL SDL_GetMouseFocusWindow(int index);
 
 /**
  * \fn int SDL_SetRelativeMouseMode(SDL_bool enabled)
@@ -92,7 +92,8 @@
  *
  * \sa SDL_GetRelativeMouseMode()
  */
-extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled);
+extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(int index,
+                                                     SDL_bool enabled);
 
 /**
  * \fn SDL_bool SDL_GetRelativeMouseMode()
@@ -101,7 +102,7 @@
  *
  * \sa SDL_SetRelativeMouseMode()
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void);
+extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(int index);
 
 /**
  * \fn Uint8 SDL_GetMouseState(int *x, int *y)
@@ -113,7 +114,7 @@
  * mouse cursor position relative to the focus window for the currently
  * selected mouse.  You can pass NULL for either x or y.
  */
-extern DECLSPEC Uint8 SDLCALL SDL_GetMouseState(int *x, int *y);
+extern DECLSPEC Uint8 SDLCALL SDL_GetMouseState(int index, int *x, int *y);
 
 /**
  * \fn Uint8 SDL_GetRelativeMouseState(int *x, int *y)
@@ -124,7 +125,8 @@
  * be tested using the SDL_BUTTON(X) macros, and x and y are set to the
  * mouse deltas since the last call to SDL_GetRelativeMouseState().
  */
-extern DECLSPEC Uint8 SDLCALL SDL_GetRelativeMouseState(int *x, int *y);
+extern DECLSPEC Uint8 SDLCALL SDL_GetRelativeMouseState(int index, int *x,
+                                                        int *y);
 
 /**
  * \fn void SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
@@ -203,6 +205,16 @@
    Button 2:	Middle mouse button
    Button 3:	Right mouse button
  */
+
+/* FIXME: Where do these functions go in this header?
+          Also, add doxygen documentation for these...
+*/
+extern DECLSPEC char *SDLCALL SDL_GetMouseName(int index);
+
+extern DECLSPEC int SDLCALL SDL_GetCursorsNumber(int index);
+
+extern DECLSPEC int SDLCALL SDL_GetCurrentCursor(int index);
+
 #define SDL_BUTTON(X)		(1 << ((X)-1))
 #define SDL_BUTTON_LEFT		1
 #define SDL_BUTTON_MIDDLE	2
--- a/src/SDL_compat.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/SDL_compat.c	Mon Aug 25 06:33:00 2008 +0000
@@ -256,7 +256,7 @@
             }
 
             selected = SDL_SelectMouse(event->wheel.which);
-            SDL_GetMouseState(&x, &y);
+            SDL_GetMouseState(selected, &x, &y);
             SDL_SelectMouse(selected);
 
             if (event->wheel.y > 0) {
--- a/src/events/SDL_mouse.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/events/SDL_mouse.c	Mon Aug 25 06:33:00 2008 +0000
@@ -28,9 +28,13 @@
 #include "default_cursor.h"
 
 
-static int SDL_num_mice;
-static int SDL_current_mouse;
-static SDL_Mouse **SDL_mice;
+static int SDL_num_mice = 0;
+static int SDL_current_mouse = -1;
+static SDL_Mouse **SDL_mice = NULL;
+static int *SDL_IdIndex = NULL;
+static int SDL_highestId = -1;
+static int last_x, last_y;      /* the last reported x and y coordinates by the system cursor */
+int x_max, y_max;               /* current window width and height */
 
 
 /* Public functions */
@@ -50,10 +54,44 @@
 }
 
 int
-SDL_AddMouse(const SDL_Mouse * mouse, int index)
+SDL_SetMouseIndexId(int id, int index)
+{
+    if (id < 0) {
+        SDL_SetError("Invalid Mouse ID");
+        return -1;
+    }
+    if (id > SDL_highestId) {
+        int *indexes;
+        indexes = (int *) SDL_realloc(SDL_IdIndex, (id + 1) * sizeof(int));
+        if (!indexes) {
+            SDL_OutOfMemory();
+            return -1;
+        }
+        SDL_IdIndex = indexes;
+        SDL_IdIndex[id] = index;
+        SDL_highestId = id;
+    } else {
+        SDL_IdIndex[id] = index;
+    }
+    return 1;
+}
+
+SDL_Mouse *
+SDL_GetMouseByID(int id)
+{
+    if (id < 0 || id > SDL_highestId) {
+        return NULL;
+    }
+    return SDL_GetMouse(SDL_IdIndex[id]);
+}
+
+int
+SDL_AddMouse(const SDL_Mouse * mouse, int index, char *name, int pressure_max,
+             int pressure_min, int ends)
 {
     SDL_Mouse **mice;
     int selected_mouse;
+    int length;
 
     /* Add the mouse to the list of mice */
     if (index < 0 || index >= SDL_num_mice || SDL_mice[index]) {
@@ -75,7 +113,13 @@
     }
     *SDL_mice[index] = *mouse;
 
-    /* Create the default cursor for the mouse */
+    /* we're setting the mouse properties */
+    length = 0;
+    length = SDL_strlen(name);
+    SDL_mice[index]->name = SDL_malloc((length + 1) * sizeof(char));
+    SDL_strlcpy(SDL_mice[index]->name, name, length);
+    SDL_mice[index]->pressure_max = pressure_max;
+    SDL_mice[index]->pressure_min = pressure_min;
     SDL_mice[index]->cursor_shown = SDL_TRUE;
     selected_mouse = SDL_SelectMouse(index);
     SDL_mice[index]->cur_cursor = NULL;
@@ -83,6 +127,14 @@
         SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH,
                          DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
     SDL_SetCursor(SDL_mice[index]->def_cursor);
+    /* we're assuming that all mice are in the computer sensing zone */
+    SDL_mice[index]->proximity = SDL_TRUE;
+    /* we're assuming that all mice are working in the absolute position mode
+       thanx to that, the users that don't want to use many mice don't have to
+       worry about anything */
+    SDL_mice[index]->relative_mode = SDL_FALSE;
+    SDL_mice[index]->current_end = 0;
+    SDL_mice[index]->total_ends = ends;
     SDL_SelectMouse(selected_mouse);
 
     return index;
@@ -98,6 +150,7 @@
     }
 
     mouse->def_cursor = NULL;
+    SDL_free(mouse->name);
     while (mouse->cursors) {
         SDL_FreeCursor(mouse->cursors);
     }
@@ -155,9 +208,9 @@
 }
 
 SDL_WindowID
-SDL_GetMouseFocusWindow()
+SDL_GetMouseFocusWindow(int index)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+    SDL_Mouse *mouse = SDL_GetMouse(index);
 
     if (!mouse) {
         return 0;
@@ -177,9 +230,9 @@
 }
 
 int
-SDL_SetRelativeMouseMode(SDL_bool enabled)
+SDL_SetRelativeMouseMode(int index, SDL_bool enabled)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+    SDL_Mouse *mouse = SDL_GetMouse(index);
 
     if (!mouse) {
         return -1;
@@ -205,9 +258,9 @@
 }
 
 SDL_bool
-SDL_GetRelativeMouseMode()
+SDL_GetRelativeMouseMode(int index)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+    SDL_Mouse *mouse = SDL_GetMouse(index);
 
     if (!mouse) {
         return SDL_FALSE;
@@ -216,9 +269,9 @@
 }
 
 Uint8
-SDL_GetMouseState(int *x, int *y)
+SDL_GetMouseState(int index, int *x, int *y)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+    SDL_Mouse *mouse = SDL_GetMouse(index);
 
     if (!mouse) {
         if (x) {
@@ -240,9 +293,9 @@
 }
 
 Uint8
-SDL_GetRelativeMouseState(int *x, int *y)
+SDL_GetRelativeMouseState(int index, int *x, int *y)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+    SDL_Mouse *mouse = SDL_GetMouse(index);
 
     if (!mouse) {
         if (x) {
@@ -266,16 +319,18 @@
 }
 
 void
-SDL_SetMouseFocus(int index, SDL_WindowID windowID)
+SDL_SetMouseFocus(int id, SDL_WindowID windowID)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(index);
-    int i;
+    SDL_Mouse *mouse = SDL_GetMouseByID(id);
+    int i, index;
     SDL_bool focus;
 
     if (!mouse || (mouse->focus == windowID)) {
         return;
     }
 
+    index = SDL_IdIndex[id];
+
     /* See if the current window has lost focus */
     if (mouse->focus) {
         focus = SDL_FALSE;
@@ -315,28 +370,62 @@
 }
 
 int
-SDL_SendMouseMotion(int index, int relative, int x, int y)
+SDL_SendProximity(int id, int x, int y, int type)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(index);
+    SDL_Mouse *mouse = SDL_GetMouseByID(id);
+    int posted = 0;
+    last_x = x;
+    last_y = y;
+    if (SDL_ProcessEvents[type] == SDL_ENABLE) {
+        SDL_Event event;
+        event.proximity.which = (Uint8) index;
+        event.proximity.x = x;
+        event.proximity.y = y;
+        event.proximity.cursor = mouse->current_end;
+        event.proximity.type = type;
+        posted = (SDL_PushEvent(&event) > 0);
+        if (type == SDL_PROXIMITYIN) {
+            mouse->proximity = SDL_TRUE;
+        } else {
+            mouse->proximity = SDL_FALSE;
+        }
+    }
+    return posted;
+}
+
+int
+SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure)
+{
+    SDL_Mouse *mouse = SDL_GetMouseByID(id);
     int posted;
     int xrel;
     int yrel;
 
+    /* while using the relative mode and many windows, we have to be sure,
+       that the pointers find themselves inside the windows */
+    if (x > x_max) {
+        x = x_max;
+    }
+    if (y > y_max) {
+        y = y_max;
+    }
+
     if (!mouse || mouse->flush_motion) {
         return 0;
     }
 
-    if (relative) {
-        /* Push the cursor around */
-        xrel = x;
-        yrel = y;
-        x = (mouse->x + xrel);
-        y = (mouse->y + yrel);
-    } else {
-        xrel = x - mouse->x;
-        yrel = y - mouse->y;
+    /* if the mouse is out of proximity we don't to want to have any motion from it */
+    if (mouse->proximity == SDL_FALSE) {
+        last_x = x;
+        last_y = y;
+        return 0;
     }
 
+    /* the relative motion is calculated regarding the system cursor last position */
+
+    xrel = x - last_x;
+    yrel = y - last_y;
+
     /* Drop events that don't change state */
     if (!xrel && !yrel) {
 #if 0
@@ -345,13 +434,29 @@
         return 0;
     }
 
-    /* Update internal mouse state */
-    if (!mouse->relative_mode) {
+    /* Update internal mouse coordinates */
+    if (mouse->relative_mode == SDL_FALSE) {
         mouse->x = x;
         mouse->y = y;
+    } else {
+        if (mouse->x + xrel > x_max) {
+            mouse->x = x_max;
+        } else if (mouse->x + xrel < 0) {
+            mouse->x = 0;
+        } else {
+            mouse->x += xrel;
+        }
+        if (mouse->y + yrel > y_max) {
+            mouse->y = y_max;
+        } else if (mouse->y + yrel < 0) {
+            mouse->y = 0;
+        } else {
+            mouse->y += yrel;
+        }
     }
     mouse->xdelta += xrel;
     mouse->ydelta += yrel;
+    mouse->pressure = pressure;
 
     /* Move the mouse cursor, if needed */
     if (mouse->cursor_shown && !mouse->relative_mode &&
@@ -361,25 +466,32 @@
 
     /* Post the event, if desired */
     posted = 0;
-    if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE) {
+    if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE &&
+        mouse->proximity == SDL_TRUE) {
         SDL_Event event;
         event.motion.type = SDL_MOUSEMOTION;
         event.motion.which = (Uint8) index;
         event.motion.state = mouse->buttonstate;
         event.motion.x = mouse->x;
         event.motion.y = mouse->y;
+        event.motion.pressure = mouse->pressure;
         event.motion.xrel = xrel;
         event.motion.yrel = yrel;
         event.motion.windowID = mouse->focus;
+        event.motion.pressure_max = mouse->pressure_max;
+        event.motion.pressure_min = mouse->pressure_min;
+        event.motion.cursor = mouse->current_end;
         posted = (SDL_PushEvent(&event) > 0);
     }
+    last_x = x;
+    last_y = y;
     return posted;
 }
 
 int
-SDL_SendMouseButton(int index, Uint8 state, Uint8 button)
+SDL_SendMouseButton(int id, Uint8 state, Uint8 button)
 {
-    SDL_Mouse *mouse = SDL_GetMouse(index);
+    SDL_Mouse *mouse = SDL_GetMouseByID(id);
     int posted;
     Uint8 type;
 
@@ -398,10 +510,6 @@
         mouse->buttonstate |= SDL_BUTTON(button);
         break;
     case SDL_RELEASED:
-        if (!(mouse->buttonstate & SDL_BUTTON(button))) {
-            /* Ignore this event, no state change */
-            return 0;
-        }
         type = SDL_MOUSEBUTTONUP;
         mouse->buttonstate &= ~SDL_BUTTON(button);
         break;
@@ -463,7 +571,7 @@
         mouse->WarpMouse(mouse, windowID, x, y);
     } else {
         SDL_SetMouseFocus(SDL_current_mouse, windowID);
-        SDL_SendMouseMotion(SDL_current_mouse, 0, x, y);
+        SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0);
     }
 }
 
@@ -649,4 +757,53 @@
     return shown;
 }
 
+char *
+SDL_GetMouseName(int index)
+{
+    SDL_Mouse *mouse = SDL_GetMouse(index);
+    if (!mouse) {
+        return NULL;
+    }
+    return mouse->name;
+}
+
+void
+SDL_UpdateCoordinates(int x, int y)
+{
+    x_max = x;
+    y_max = y;
+}
+
+void
+SDL_ChangeEnd(int id, int end)
+{
+    SDL_Mouse *mouse = SDL_GetMouseByID(id);
+
+    if (mouse) {
+        mouse->current_end = end;
+    }
+}
+
+int
+SDL_GetCursorsNumber(int index)
+{
+    SDL_Mouse *mouse = SDL_GetMouse(index);
+
+    if (!mouse) {
+        return -1;
+    }
+    return mouse->total_ends;
+}
+
+int
+SDL_GetCurrentCursor(int index)
+{
+    SDL_Mouse *mouse = SDL_GetMouse(index);
+
+    if (!mouse) {
+        return -1;
+    }
+    return mouse->current_end;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/events/SDL_mouse_c.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/events/SDL_mouse_c.h	Mon Aug 25 06:33:00 2008 +0000
@@ -29,9 +29,7 @@
 struct SDL_Cursor
 {
     SDL_Mouse *mouse;
-
     SDL_Cursor *next;
-
     void *driverdata;
 };
 
@@ -56,14 +54,27 @@
     /* Free the mouse when it's time */
     void (*FreeMouse) (SDL_Mouse * mouse);
 
+    /* data common for tablets */
+    int pressure;
+    int pressure_max;
+    int pressure_min;
+    int tilt;                   /* for future use */
+    int rotation;               /* for future use */
+    int total_ends;
+    int current_end;
+
     /* Data common to all mice */
     SDL_WindowID focus;
+    int which;
     int x;
     int y;
+    int z;                      /* for future use */
     int xdelta;
     int ydelta;
+    char *name;
     Uint8 buttonstate;
     SDL_bool relative_mode;
+    SDL_bool proximity;
     SDL_bool flush_motion;
 
     SDL_Cursor *cursors;
@@ -74,17 +85,23 @@
     void *driverdata;
 };
 
-
 /* Initialize the mouse subsystem */
 extern int SDL_MouseInit(void);
 
 /* Get the mouse at an index */
 extern SDL_Mouse *SDL_GetMouse(int index);
 
+/* Assign an id to a mouse at an index */
+extern int SDL_SetMouseIndexId(int id, int index);
+
+/* Get the mouse by id */
+extern SDL_Mouse *SDL_GetMouseByID(int id);
+
 /* Add a mouse, possibly reattaching at a particular index (or -1),
    returning the index of the mouse, or -1 if there was an error.
  */
-extern int SDL_AddMouse(const SDL_Mouse * mouse, int index);
+extern int SDL_AddMouse(const SDL_Mouse * mouse, int index, char *name,
+                        int pressure_max, int pressure_min, int ends);
 
 /* Remove a mouse at an index, clearing the slot for later */
 extern void SDL_DelMouse(int index);
@@ -93,20 +110,24 @@
 extern void SDL_ResetMouse(int index);
 
 /* Set the mouse focus window */
-extern void SDL_SetMouseFocus(int index, SDL_WindowID windowID);
+extern void SDL_SetMouseFocus(int id, SDL_WindowID windowID);
 
 /* Send a mouse motion event for a mouse at an index */
-extern int SDL_SendMouseMotion(int index, int relative, int x, int y);
+extern int SDL_SendMouseMotion(int id, int relative, int x, int y, int z);
 
 /* Send a mouse button event for a mouse at an index */
-extern int SDL_SendMouseButton(int index, Uint8 state, Uint8 button);
+extern int SDL_SendMouseButton(int id, Uint8 state, Uint8 button);
 
 /* Send a mouse wheel event for a mouse at an index */
-extern int SDL_SendMouseWheel(int index, int x, int y);
+extern int SDL_SendMouseWheel(int id, int x, int y);
 
 /* Shutdown the mouse subsystem */
 extern void SDL_MouseQuit(void);
 
+/* FIXME: Where do these functions go in this header? */
+extern void SDL_UpdateCoordinates(int x, int y);
+extern void SDL_ChangeEnd(int id, int end);
+
 #endif /* _SDL_mouse_c_h */
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/cocoa/SDL_cocoamouse.m	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/cocoa/SDL_cocoamouse.m	Mon Aug 25 06:33:00 2008 +0000
@@ -32,7 +32,8 @@
     SDL_Mouse mouse;
 
     SDL_zero(mouse);
-    data->mouse = SDL_AddMouse(&mouse, -1);
+    data->mouse = SDL_AddMouse(&mouse, -1, "Mouse", 0, 0, 1);
+    SDL_SetMouseIndexId(data->mouse, data->mouse);
 }
 
 void
--- a/src/video/cocoa/SDL_cocoawindow.m	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/cocoa/SDL_cocoawindow.m	Mon Aug 25 06:33:00 2008 +0000
@@ -250,7 +250,7 @@
         if (mouse->focus != _data->windowID) {
             SDL_SetMouseFocus(index, _data->windowID);
         }
-        SDL_SendMouseMotion(index, 0, (int)point.x, (int)point.y);
+        SDL_SendMouseMotion(index, 0, (int)point.x, (int)point.y, 0);
     }
 }
 
--- a/src/video/win32/SDL_win32events.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/win32/SDL_win32events.c	Mon Aug 25 06:33:00 2008 +0000
@@ -19,6 +19,12 @@
     Sam Lantinga
     slouken@libsdl.org
 */
+
+#if (_WIN32_WINNT < 0x0501)
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
 #include "SDL_config.h"
 
 #include "SDL_win32video.h"
@@ -26,6 +32,11 @@
 #include "SDL_vkeys.h"
 #include "../../events/SDL_events_c.h"
 
+#include <wintab.h>
+#define PACKETDATA ( PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_CURSOR)
+#define PACKETMODE 0
+#include <pktdef.h>
+
 /*#define WMMSG_DEBUG*/
 #ifdef WMMSG_DEBUG
 #include <stdio.h>
@@ -49,6 +60,12 @@
 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
 #endif
 
+extern HCTX *g_hCtx;
+extern HANDLE *mice;
+extern int total_mice;
+extern int tablet;
+int pressure = 0;               /* the pressure reported by the tablet */
+
 static WPARAM
 RemapVKEY(WPARAM wParam, LPARAM lParam)
 {
@@ -84,6 +101,8 @@
 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     SDL_WindowData *data;
+    RAWINPUT *raw;
+    PACKET packet;
 
     /* Send a SDL_SYSWMEVENT if the application wants them */
     if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
@@ -114,10 +133,40 @@
         fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
         fclose(log);
     }
+
 #endif
 
     switch (msg) {
 
+    case WT_PACKET:
+        {
+            /* if we receive such data we need to update the pressure */
+            if (WTPacket((HCTX) lParam, wParam, &packet)) {
+                SDL_ChangeEnd(tablet, (int) packet.pkCursor);
+                pressure = (int) packet.pkNormalPressure;
+            }
+        }
+        break;
+
+    case WT_PROXIMITY:
+        {
+            /* checking where the proximity message showed up */
+            int h_context = LOWORD(lParam);
+            LPPOINT point;
+            GetCursorPos(&point);
+            ScreenToClient(hwnd, &point);
+
+            /* are we in proximity or out of proximity */
+            if (h_context == 0) {
+                SDL_SendProximity(tablet, (int) (&point->x),
+                                  (int) (&point->y), SDL_PROXIMITYOUT);
+            } else {
+                SDL_SendProximity(tablet, (int) (&point->x),
+                                  (int) (&point->y), SDL_PROXIMITYIN);
+            }
+        }
+        break;
+
     case WM_SHOWWINDOW:
         {
             if (wParam) {
@@ -161,48 +210,72 @@
                                         SDL_WINDOWEVENT_MINIMIZED, 0, 0);
                 }
             }
-            return (0);
         }
-        break;
-
-    case WM_MOUSEMOVE:
-        {
-            int index;
-            SDL_Mouse *mouse;
-            int x, y;
+        return (0);
 
-            index = data->videodata->mouse;
-            mouse = SDL_GetMouse(index);
+    case WM_INPUT:             /* mouse events */
+        {
+            LPBYTE lpb;
+            int w, h;
+            const RAWINPUTHEADER *header;
+            int index;
+            int i;
+            int size = 0;
+            const RAWMOUSE *raw_mouse = NULL;
+            LPPOINT point;
+            USHORT flags;
 
-            if (mouse->focus != data->windowID) {
-                TRACKMOUSEEVENT tme;
-
-                tme.cbSize = sizeof(tme);
-                tme.dwFlags = TME_LEAVE;
-                tme.hwndTrack = hwnd;
-                TrackMouseEvent(&tme);
+            /* we're collecting data from the mouse */
+            GetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &size,
+                            sizeof(RAWINPUTHEADER));
+            lpb = SDL_malloc(size * sizeof(LPBYTE));
+            GetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &size,
+                            sizeof(RAWINPUTHEADER));
+            raw = (RAWINPUT *) lpb;
+            header = &raw->header;
+            flags = raw->data.mouse.usButtonFlags;
 
-                SDL_SetMouseFocus(index, data->windowID);
+            /* we're checking which mouse generated the event */
+            for (i = 0; i < total_mice; ++i) {
+                if (mice[i] == header->hDevice) {
+                    index = i;
+                    break;
+                }
             }
+            GetCursorPos(&point);
+            ScreenToClient(hwnd, &point);
+            SDL_GetWindowSize(data->windowID, &w, &h);
+            SDL_UpdateCoordinates(w, h);        /* we're updating the current window size */
 
-            /* mouse has moved within the window */
-            x = LOWORD(lParam);
-            y = HIWORD(lParam);
-            if (mouse->relative_mode) {
-                int w, h;
-                POINT center;
-                SDL_GetWindowSize(data->windowID, &w, &h);
-                center.x = (w / 2);
-                center.y = (h / 2);
-                x -= center.x;
-                y -= center.y;
-                if (x || y) {
-                    ClientToScreen(hwnd, &center);
-                    SetCursorPos(center.x, center.y);
-                    SDL_SendMouseMotion(index, 1, x, y);
+            /* if the message was sent by a tablet we have to send also pressure */
+            if (i == tablet) {
+                SDL_SendMouseMotion(index, 0, (int) (&point->x),
+                                    (int) (&point->y), pressure);
+            } else {
+                SDL_SendMouseMotion(index, 0, (int) (&point->x),
+                                    (int) (&point->y), 0);
+            }
+            /* we're sending mouse buttons messages to check up if sth changed */
+            if (flags & RI_MOUSE_BUTTON_1_DOWN) {
+                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_LEFT);
+            } else if (flags & RI_MOUSE_BUTTON_1_UP) {
+                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_LEFT);
+            }
+            if (flags & RI_MOUSE_BUTTON_2_DOWN) {
+                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_MIDDLE);
+            } else if (flags & RI_MOUSE_BUTTON_2_UP) {
+                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_MIDDLE);
+            }
+            if (flags & RI_MOUSE_BUTTON_3_DOWN) {
+                SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_RIGHT);
+            } else if (flags & RI_MOUSE_BUTTON_3_UP) {
+                SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_RIGHT);
+            }
+            if (flags & RI_MOUSE_WHEEL) {
+                if (raw->data.mouse.usButtonData != 0) {
+                    SDL_SendMouseWheel(index, 0,
+                                       raw->data.mouse.usButtonData);
                 }
-            } else {
-                SDL_SendMouseMotion(index, 0, x, y);
             }
         }
         return (0);
@@ -221,117 +294,6 @@
         }
         return (0);
 
-    case WM_LBUTTONDOWN:
-    case WM_LBUTTONUP:
-    case WM_MBUTTONDOWN:
-    case WM_MBUTTONUP:
-    case WM_RBUTTONDOWN:
-    case WM_RBUTTONUP:
-    case WM_XBUTTONDOWN:
-    case WM_XBUTTONUP:
-        {
-            int xbuttonval = 0;
-            int index;
-            SDL_Mouse *mouse;
-            Uint8 button, state;
-
-            /* DJM:
-               We want the SDL window to take focus so that
-               it acts like a normal windows "component"
-               (e.g. gains keyboard focus on a mouse click).
-             */
-            SetFocus(hwnd);
-
-            index = data->videodata->mouse;
-            mouse = SDL_GetMouse(index);
-
-            /* Figure out which button to use */
-            switch (msg) {
-            case WM_LBUTTONDOWN:
-                button = SDL_BUTTON_LEFT;
-                state = SDL_PRESSED;
-                break;
-            case WM_LBUTTONUP:
-                button = SDL_BUTTON_LEFT;
-                state = SDL_RELEASED;
-                break;
-            case WM_MBUTTONDOWN:
-                button = SDL_BUTTON_MIDDLE;
-                state = SDL_PRESSED;
-                break;
-            case WM_MBUTTONUP:
-                button = SDL_BUTTON_MIDDLE;
-                state = SDL_RELEASED;
-                break;
-            case WM_RBUTTONDOWN:
-                button = SDL_BUTTON_RIGHT;
-                state = SDL_PRESSED;
-                break;
-            case WM_RBUTTONUP:
-                button = SDL_BUTTON_RIGHT;
-                state = SDL_RELEASED;
-                break;
-            case WM_XBUTTONDOWN:
-                xbuttonval = GET_XBUTTON_WPARAM(wParam);
-                button = SDL_BUTTON_X1 + xbuttonval - 1;
-                state = SDL_PRESSED;
-                break;
-            case WM_XBUTTONUP:
-                xbuttonval = GET_XBUTTON_WPARAM(wParam);
-                button = SDL_BUTTON_X1 + xbuttonval - 1;
-                state = SDL_RELEASED;
-                break;
-            default:
-                /* Eh? Unknown button? */
-                return (0);
-            }
-            if (state == SDL_PRESSED) {
-                /* Grab mouse so we get up events */
-                if (++data->mouse_pressed > 0) {
-                    SetCapture(hwnd);
-                }
-            } else {
-                /* Release mouse after all up events */
-                if (--data->mouse_pressed <= 0) {
-                    ReleaseCapture();
-                    data->mouse_pressed = 0;
-                }
-            }
-
-            if (!mouse->relative_mode) {
-                int x, y;
-                x = LOWORD(lParam);
-                y = HIWORD(lParam);
-                SDL_SendMouseMotion(index, 0, x, y);
-            }
-            SDL_SendMouseButton(index, state, button);
-
-            /*
-             * MSDN says:
-             *  "Unlike the WM_LBUTTONUP, WM_MBUTTONUP, and WM_RBUTTONUP
-             *   messages, an application should return TRUE from [an
-             *   XBUTTON message] if it processes it. Doing so will allow
-             *   software that simulates this message on Microsoft Windows
-             *   systems earlier than Windows 2000 to determine whether
-             *   the window procedure processed the message or called
-             *   DefWindowProc to process it.
-             */
-            if (xbuttonval > 0) {
-                return (TRUE);
-            }
-        }
-        return (0);
-
-    case WM_MOUSEWHEEL:
-        {
-            int index;
-            int motion = (short) HIWORD(wParam);
-
-            index = data->videodata->mouse;
-            SDL_SendMouseWheel(index, 0, motion);
-        }
-        return (0);
-
     case WM_SYSKEYDOWN:
     case WM_KEYDOWN:
         {
@@ -426,6 +388,7 @@
                     wParam = VK_ENTER;
                 break;
             }
+
             /* Windows only reports keyup for print screen */
             if (wParam == VK_SNAPSHOT
                 && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
@@ -499,11 +462,9 @@
                inside their function, so I have to do it here.
              */
             style = GetWindowLong(hwnd, GWL_STYLE);
-            AdjustWindowRect(&size,
-                             style,
-                             style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) !=
-                             NULL);
-
+            AdjustWindowRect(&size, style,
+                             style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd)
+                             != NULL);
             w = size.right - size.left;
             h = size.bottom - size.top;
 
@@ -661,8 +622,9 @@
 
     /* Register the application class */
     class.hCursor = NULL;
-    class.hIcon = LoadImage(SDL_Instance, SDL_Appname,
-                            IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
+    class.hIcon =
+        LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
+                  LR_DEFAULTCOLOR);
     class.lpszMenuName = NULL;
     class.lpszClassName = SDL_Appname;
     class.hbrBackground = NULL;
@@ -707,11 +669,8 @@
 {
     TCHAR buffer[1024];
     char *message;
-
-    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
-                  NULL,
-                  GetLastError(), 0, buffer, SDL_arraysize(buffer), NULL);
-
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
+                  buffer, SDL_arraysize(buffer), NULL);
     message = WIN_StringToUTF8(buffer);
     SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ":" : "", message);
     SDL_free(message);
--- a/src/video/win32/SDL_win32mouse.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/win32/SDL_win32mouse.c	Mon Aug 25 06:33:00 2008 +0000
@@ -19,20 +19,179 @@
     Sam Lantinga
     slouken@libsdl.org
 */
+
+/* we need to define it, so that raw input is included*/
+
+#if (_WIN32_WINNT < 0x0501)
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
 #include "SDL_config.h"
 
 #include "SDL_win32video.h"
 
 #include "../../events/SDL_mouse_c.h"
 
+#include <wintab.h>
+
+#define PACKETDATA ( PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_CURSOR)
+#define PACKETMODE 0
+#include <pktdef.h>
+extern HANDLE *mice;
+extern int total_mice;
+extern int tablet;
+
 void
 WIN_InitMouse(_THIS)
 {
+    int index = 0;
+    RAWINPUTDEVICELIST *deviceList = NULL;
+    int devCount = 0;
+    int i;
+    int tmp = 0;
+    char *buffer = NULL;
+    char *tab = "wacom";        /* since windows does't give us handles to tablets, we have to detect a tablet by it's name */
+    const char *rdp = "rdp_mou";
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
-    SDL_Mouse mouse;
+
+    /* we're checking for the number of rawinput devices */
+    if (GetRawInputDeviceList(NULL, &devCount, sizeof(RAWINPUTDEVICELIST))) {
+        return;
+    }
+
+    deviceList = SDL_malloc(sizeof(RAWINPUTDEVICELIST) * devCount);
+
+    /* we're getting the raw input device list */
+    GetRawInputDeviceList(deviceList, &devCount, sizeof(RAWINPUTDEVICELIST));
+    mice = SDL_malloc(devCount * sizeof(HANDLE));
+
+    /* we're getting the details of the devices */
+    for (i = 0; i < devCount; ++i) {
+        int is_rdp = 0;
+        int j;
+        int k;
+        char *default_device_name = "Pointing device xx";
+        const char *reg_key_root = "System\\CurrentControlSet\\Enum\\";
+        char *device_name = SDL_malloc(256 * sizeof(char));
+        char *key_name = NULL;
+        char *tmp_name = NULL;
+        LONG rc = 0;
+        HKEY hkey;
+        DWORD regtype = REG_SZ;
+        DWORD out = 256 * sizeof(char);
+        SDL_Mouse mouse;
+        int l;
+        if (deviceList[i].dwType != RIM_TYPEMOUSE) {    /* if a device isn't a mouse type we don't want it */
+            continue;
+        }
+        if (GetRawInputDeviceInfoA
+            (deviceList[i].hDevice, RIDI_DEVICENAME, NULL, &tmp) < 0) {
+            continue;
+        }
+        buffer = SDL_malloc((tmp + 1) * sizeof(char));
+        key_name = SDL_malloc(tmp + sizeof(reg_key_root) * sizeof(char));
+
+        /* we're getting the device registry path and polishing it to get it's name,
+           surely there must be an easier way, but we haven't found it yet */
+        if (GetRawInputDeviceInfoA
+            (deviceList[i].hDevice, RIDI_DEVICENAME, buffer, &tmp) < 0) {
+            continue;
+        }
+        buffer += 4;
+        tmp -= 4;
+        tmp_name = buffer;
+        for (j = 0; j < tmp; ++j) {
+            if (*tmp_name == '#') {
+                *tmp_name = '\\';
+            }
 
-    SDL_zero(mouse);
-    data->mouse = SDL_AddMouse(&mouse, -1);
+            else if (*tmp_name == '{') {
+                break;
+            }
+            ++tmp_name;
+        }
+        *tmp_name = '\0';
+        SDL_memcpy(key_name, reg_key_root, SDL_strlen(reg_key_root));
+        SDL_memcpy(key_name + (SDL_strlen(reg_key_root)), buffer, j + 1);
+        l = SDL_strlen(key_name);
+        is_rdp = 0;
+        if (l >= 7) {
+            for (j = 0; j < l - 7; ++j) {
+                for (k = 0; k < 7; ++k) {
+                    if (rdp[k] !=
+                        SDL_tolower((unsigned char) key_name[j + k])) {
+                        break;
+                    }
+                }
+                if (k == 7) {
+                    is_rdp = 1;
+                    break;
+                }
+            }
+        }
+        if (is_rdp == 1) {
+            SDL_free(buffer);
+            SDL_free(key_name);
+            SDL_free(device_name);
+            is_rdp = 0;
+            continue;
+        }
+
+        /* we're opening the registry key to get the mouse name */
+        rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_name, 0, KEY_READ, &hkey);
+        if (rc != ERROR_SUCCESS) {
+            SDL_memcpy(device_name, default_device_name,
+                       SDL_strlen(default_device_name));
+        }
+        rc = RegQueryValueExA(hkey, "DeviceDesc", NULL, &regtype, device_name,
+                              &out);
+        RegCloseKey(hkey);
+        if (rc != ERROR_SUCCESS) {
+            SDL_memcpy(device_name, default_device_name,
+                       SDL_strlen(default_device_name));
+        }
+
+        /* we're saving the handle to the device */
+        mice[index] = deviceList[i].hDevice;
+        SDL_zero(mouse);
+        SDL_SetMouseIndexId(index, index);
+        l = SDL_strlen(device_name);
+
+        /* we're checking if the device isn't by any chance a tablet */
+        if (tablet == -1) {
+            for (j = 0; j < l - 5; ++j) {
+                for (k = 0; k < 5; ++k) {
+                    if (tab[k] !=
+                        SDL_tolower((unsigned char) device_name[j + k])) {
+                        break;
+                    }
+                }
+                if (k == 5) {
+                    tablet = index;
+                    break;
+                }
+            }
+        }
+
+        /* if it's a tablet, let's read it's maximum and minimum pressure */
+        if (tablet == index) {
+            AXIS pressure;
+            int cursors;
+            WTInfo(WTI_DEVICES, DVC_NPRESSURE, &pressure);
+            WTInfo(WTI_DEVICES, DVC_NCSRTYPES, &cursors);
+            data->mouse =
+                SDL_AddMouse(&mouse, index, device_name, pressure.axMax,
+                             pressure.axMin, cursors);
+        } else {
+            data->mouse = SDL_AddMouse(&mouse, index, device_name, 0, 0, 1);
+        }
+        ++index;
+        SDL_free(buffer);
+        SDL_free(key_name);
+    }
+    total_mice = index;
+    SDL_free(deviceList);
 }
 
 void
@@ -40,7 +199,8 @@
 {
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
 
-    SDL_DelMouse(data->mouse);
+    /* let's delete all of the mice */
+    SDL_MouseQuit();
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/win32/SDL_win32video.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/win32/SDL_win32video.c	Mon Aug 25 06:33:00 2008 +0000
@@ -31,10 +31,17 @@
 #include "SDL_d3drender.h"
 #include "SDL_gdirender.h"
 
+#include <wintab.h>
+
 /* Initialization/Query functions */
 static int WIN_VideoInit(_THIS);
 static void WIN_VideoQuit(_THIS);
 
+int total_mice = 0;             /* total mouse count */
+HANDLE *mice = NULL;            /* the handles to the detected mice */
+HCTX *g_hCtx = NULL;            /* handles to tablet contexts */
+int tablet = -1;                /* we're assuming that there is no tablet */
+
 /* WIN32 driver bootstrap functions */
 
 static int
@@ -140,8 +147,7 @@
 }
 
 VideoBootStrap WIN32_bootstrap = {
-    "win32", "SDL Win32/64 video driver",
-    WIN_Available, WIN_CreateDevice
+    "win32", "SDL Win32/64 video driver", WIN_Available, WIN_CreateDevice
 };
 
 
@@ -157,6 +163,7 @@
     GDI_AddRenderDriver(_this);
 #endif
 
+    g_hCtx = SDL_malloc(sizeof(HCTX));
     WIN_InitKeyboard(_this);
     WIN_InitMouse(_this);
 
@@ -169,6 +176,7 @@
     WIN_QuitModes(_this);
     WIN_QuitKeyboard(_this);
     WIN_QuitMouse(_this);
+    SDL_free(g_hCtx);
 }
 
 /* vim: set ts=4 sw=4 expandtab: */
--- a/src/video/win32/SDL_win32window.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/win32/SDL_win32window.c	Mon Aug 25 06:33:00 2008 +0000
@@ -19,6 +19,14 @@
     Sam Lantinga
     slouken@libsdl.org
 */
+
+/* we need to define it, so that raw input is included */
+
+#if (_WIN32_WINNT < 0x0501)
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
 #include "SDL_config.h"
 
 #include "../SDL_sysvideo.h"
@@ -29,6 +37,15 @@
 /* This is included after SDL_win32video.h, which includes windows.h */
 #include "SDL_syswm.h"
 
+#include <wintab.h>
+
+/* we're telling wintab that we want to receive movement, button events and pressure information in packets */
+#define PACKETDATA ( PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_CURSOR)
+#define PACKETMODE 0
+#include <pktdef.h>
+
+extern HCTX *g_hCtx;            /* the table of tablet event contexts, each windows has to have it's own tablet context */
+int highestId = 0;              /* the highest id of the tablet context */
 
 static int
 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
@@ -132,6 +149,9 @@
 int
 WIN_CreateWindow(_THIS, SDL_Window * window)
 {
+    RAWINPUTDEVICE Rid;
+    AXIS TabX, TabY;
+    LOGCONTEXT lc;
     HWND hwnd;
     HWND top;
     RECT rect;
@@ -180,13 +200,53 @@
     hwnd =
         CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
                      SDL_Instance, NULL);
-    WIN_PumpEvents(_this);
-
     if (!hwnd) {
         WIN_SetError("Couldn't create window");
         return -1;
     }
 
+    /* we're configuring the tablet data. See Wintab reference for more info */
+    if (WTInfo(WTI_DEFSYSCTX, 0, &lc) != 0) {
+        lc.lcPktData = PACKETDATA;
+        lc.lcPktMode = PACKETMODE;
+        lc.lcOptions |= CXO_MESSAGES;
+        lc.lcOptions |= CXO_SYSTEM;
+        lc.lcMoveMask = PACKETDATA;
+        lc.lcBtnDnMask = lc.lcBtnUpMask = PACKETDATA;
+        WTInfo(WTI_DEVICES, DVC_X, &TabX);
+        WTInfo(WTI_DEVICES, DVC_Y, &TabY);
+        lc.lcInOrgX = 0;
+        lc.lcInOrgY = 0;
+        lc.lcInExtX = TabX.axMax;
+        lc.lcInExtY = TabY.axMax;
+        lc.lcOutOrgX = 0;
+        lc.lcOutOrgY = 0;
+        lc.lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
+        lc.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);
+        if (window->id > highestId) {
+            HCTX *tmp_hctx;
+            highestId = window->id;
+            tmp_hctx =
+                (HCTX *) SDL_realloc(g_hCtx, (highestId + 1) * sizeof(HCTX));
+            if (!tmp_hctx) {
+                SDL_OutOfMemory();
+                DestroyWindow(hwnd);
+                return -1;
+            }
+            g_hCtx = tmp_hctx;
+        }
+        g_hCtx[window->id] = WTOpen(hwnd, &lc, TRUE);
+    }
+
+    /* we're telling the window, we want it to report raw input events from mice */
+    Rid.usUsagePage = 0x01;
+    Rid.usUsage = 0x02;
+    Rid.dwFlags = RIDEV_INPUTSINK;
+    Rid.hwndTarget = hwnd;
+    RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
+
+    WIN_PumpEvents(_this);
+
     if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
         DestroyWindow(hwnd);
         return -1;
@@ -389,6 +449,7 @@
 #endif
         ReleaseDC(data->hwnd, data->hdc);
         if (data->created) {
+            WTClose(g_hCtx[window->id]);
             DestroyWindow(data->hwnd);
         }
         SDL_free(data);
--- a/src/video/x11/SDL_x11dyn.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11dyn.h	Mon Aug 25 06:33:00 2008 +0000
@@ -29,7 +29,7 @@
 #include <X11/Xatom.h>
 #include <X11/Xlibint.h>
 #include <X11/Xproto.h>
-
+//#include <X11/extensions/XInput.h>
 #include "../Xext/extensions/Xext.h"
 #include "../Xext/extensions/extutil.h"
 
--- a/src/video/x11/SDL_x11events.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11events.c	Mon Aug 25 06:33:00 2008 +0000
@@ -29,6 +29,12 @@
 #include "SDL_x11video.h"
 #include "../../events/SDL_events_c.h"
 
+extern int motion;              /* the motion event id defined by an XInput function */
+extern int button_pressed;      /* the button_pressed event id defined by an XInput function */
+extern int button_released;     /* the button_released event id defined by an XInput function */
+extern int proximity_in;        /* the proximity in event defined by an XInput function */
+extern int proximity_out;       /* the proximity out event defined by an XInput function */
+
 static void
 X11_DispatchEvent(_THIS)
 {
@@ -91,9 +97,10 @@
 #endif
             if ((xevent.xcrossing.mode != NotifyGrab) &&
                 (xevent.xcrossing.mode != NotifyUngrab)) {
-                SDL_SetMouseFocus(videodata->mouse, data->windowID);
-                SDL_SendMouseMotion(videodata->mouse, 0, xevent.xcrossing.x,
-                                    xevent.xcrossing.y);
+                XDeviceMotionEvent *move = (XDeviceMotionEvent *) & xevent;
+                SDL_SetMouseFocus(move->deviceid, data->windowID);
+                SDL_SendMouseMotion(move->deviceid, 0, move->x,
+                                    move->y, move->axis_data[2]);
             }
         }
         break;
@@ -111,9 +118,8 @@
             if ((xevent.xcrossing.mode != NotifyGrab) &&
                 (xevent.xcrossing.mode != NotifyUngrab) &&
                 (xevent.xcrossing.detail != NotifyInferior)) {
-                SDL_SendMouseMotion(videodata->mouse, 0,
-                                    xevent.xcrossing.x, xevent.xcrossing.y);
-                SDL_SetMouseFocus(videodata->mouse, 0);
+                XDeviceMotionEvent *move = (XDeviceMotionEvent *) & xevent;
+                SDL_SetMouseFocus(move->deviceid, 0);
             }
         }
         break;
@@ -166,30 +172,6 @@
         }
         break;
 
-        /* Mouse motion? */
-    case MotionNotify:{
-#ifdef DEBUG_MOTION
-            printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
-#endif
-            SDL_SendMouseMotion(videodata->mouse, 0, xevent.xmotion.x,
-                                xevent.xmotion.y);
-        }
-        break;
-
-        /* Mouse button press? */
-    case ButtonPress:{
-            SDL_SendMouseButton(videodata->mouse, SDL_PRESSED,
-                                xevent.xbutton.button);
-        }
-        break;
-
-        /* Mouse button release? */
-    case ButtonRelease:{
-            SDL_SendMouseButton(videodata->mouse, SDL_RELEASED,
-                                xevent.xbutton.button);
-        }
-        break;
-
         /* Key press? */
     case KeyPress:{
             KeyCode keycode = xevent.xkey.keycode;
@@ -301,8 +283,44 @@
         break;
 
     default:{
+            if (xevent.type == motion) {        /* MotionNotify */
+#ifdef DEBUG_MOTION
+                printf("X11 motion: %d,%d\n", xevent.xmotion.x,
+                       xevent.xmotion.y);
+#endif
+                XWindowAttributes attrib;
+                XGetWindowAttributes(videodata->display,
+                                     ((XAnyEvent *) & xevent)->window,
+                                     &attrib);
+                SDL_UpdateCoordinates(attrib.width, attrib.height);
+                XDeviceMotionEvent *move = (XDeviceMotionEvent *) & xevent;
+                SDL_SendMouseMotion(move->deviceid, 0, move->x,
+                                    move->y, move->axis_data[2]);
+            } else if (xevent.type == button_pressed) { /* ButtonPress */
+                XDeviceButtonPressedEvent *pressed =
+                    (XDeviceButtonPressedEvent *) & xevent;
+                SDL_SendMouseButton(pressed->deviceid, SDL_PRESSED,
+                                    pressed->button);
+            } else if (xevent.type == button_released) {        /* ButtonRelease */
+                XDeviceButtonReleasedEvent *released =
+                    (XDeviceButtonReleasedEvent *) & xevent;
+                SDL_SendMouseButton(released->deviceid, SDL_RELEASED,
+                                    released->button);
+            } else if (xevent.type == proximity_in) {
+                XProximityNotifyEvent *proximity =
+                    (XProximityNotifyEvent *) & xevent;
+                SDL_SendProximity(proximity->deviceid, proximity->x,
+                                  proximity->y, SDL_PROXIMITYIN);
+            } else if (xevent.type == proximity_out) {
+                XProximityNotifyEvent *proximity =
+                    (XProximityNotifyEvent *) & xevent;
+                SDL_SendProximity(proximity->deviceid, proximity->x,
+                                  proximity->y, SDL_PROXIMITYOUT);
+            }
 #ifdef DEBUG_XEVENTS
-            printf("Unhandled event %d\n", xevent.type);
+            else {
+                printf("Unhandled event %d\n", xevent.type);
+            }
 #endif
         }
         break;
--- a/src/video/x11/SDL_x11mouse.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11mouse.c	Mon Aug 25 06:33:00 2008 +0000
@@ -28,11 +28,70 @@
 void
 X11_InitMouse(_THIS)
 {
+    extern XDevice **SDL_XDevices;
+    XDevice **newDevices;
+    int i, j, index = 0, numOfDevices;
+    extern int SDL_NumOfXDevices;
+    XDeviceInfo *DevList;
+    XAnyClassPtr deviceClass;
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
-    SDL_Mouse mouse;
+
+    /* we're getting the list of input devices */
+    DevList = XListInputDevices(data->display, &numOfDevices);
+    SDL_XDevices = (XDevice **) SDL_malloc(sizeof(XDevice));
+
+    /* we're aquiring valuators:mices, tablets, etc. */
+    for (i = 0; i < numOfDevices; ++i) {
+        /* if it's the core pointer or core keyborard we don't want it */
+        if ((DevList[i].use != IsXPointer && DevList[i].use != IsXKeyboard)) {
+            /* we have to check all of the device classes */
+            deviceClass = DevList[i].inputclassinfo;
+            for (j = 0; j < DevList[i].num_classes; ++j) {
+                if (deviceClass->class == ValuatorClass) {      /* bingo ;) */
+                    XValuatorInfo *valInfo;
+                    SDL_Mouse mouse;
 
-    SDL_zero(mouse);
-    data->mouse = SDL_AddMouse(&mouse, -1);
+                    newDevices =
+                        (XDevice **) SDL_realloc(SDL_XDevices,
+                                                 (index +
+                                                  1) * sizeof(*newDevices));
+                    if (!newDevices) {
+                        SDL_OutOfMemory();
+                        return;
+                    }
+                    SDL_XDevices = newDevices;
+                    SDL_XDevices[index] =
+                        XOpenDevice(data->display, DevList[i].id);
+                    SDL_zero(mouse);
+
+                    /* the id of the device differs from its index
+                     * so we're assigning the index of a device to it's id */
+                    SDL_SetMouseIndexId(DevList[i].id, index);
+                    /* lets get the device parameters */
+                    valInfo = (XValuatorInfo *) deviceClass;
+                    /* if the device reports pressure, lets check it parameteres */
+                    if (valInfo->num_axes > 2) {
+                        data->mouse =
+                            SDL_AddMouse(&mouse, index++, DevList[i].name,
+                                         valInfo->axes[2].max_value,
+                                         valInfo->axes[2].min_value, 1);
+                    } else {
+                        data->mouse =
+                            SDL_AddMouse(&mouse, index++, DevList[i].name, 0,
+                                         0, 1);
+                    }
+                    break;
+                }
+                /* if it's not class we're interested in, lets go further */
+                deviceClass =
+                    (XAnyClassPtr) ((char *) deviceClass +
+                                    deviceClass->length);
+            }
+        }
+    }
+    XFreeDeviceList(DevList);
+
+    SDL_NumOfXDevices = index;
 }
 
 void
@@ -40,7 +99,8 @@
 {
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
 
-    SDL_DelMouse(data->mouse);
+    /* let's delete all of the mice */
+    SDL_MouseQuit();
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/x11/SDL_x11sym.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11sym.h	Mon Aug 25 06:33:00 2008 +0000
@@ -144,6 +144,11 @@
 SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return)
 SDL_X11_SYM(XExtensionErrorHandler,XSetExtensionErrorHandler,(XExtensionErrorHandler a),(a),return)
 
+/*SDL_X11_SYM(XDeviceInfo* , XListInputDevices, (Display* a, int* b), (a,b),return)
+SDL_X11_SYM(void, XFreeDeviceList, (XDeviceInfo* a), (a),)
+SDL_X11_SYM(int, XSelectExtensionEvent,(Display* a, Window b, XEventClass* c, int d),(a,b,c,d),return)
+SDL_X11_SYM(XDevice* ,XOpenDevice,(Display* a, XID b), (a,b),return)*/
+
 #if NeedWidePrototypes
 SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return)
 #else
--- a/src/video/x11/SDL_x11video.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11video.c	Mon Aug 25 06:33:00 2008 +0000
@@ -27,8 +27,14 @@
 #include "../SDL_pixels_c.h"
 
 #include "SDL_x11video.h"
-//#include "SDL_d3drender.h"
-//#include "SDL_gdirender.h"
+
+XDevice **SDL_XDevices;
+int SDL_NumOfXDevices;
+XEventClass SDL_XEvents[256];
+int SDL_NumOfXEvents;
+
+int motion, button_pressed, button_released;    /* the definitions of the mice events */
+int proximity_in, proximity_out;
 
 /* Initialization/Query functions */
 static int X11_VideoInit(_THIS);
@@ -97,7 +103,6 @@
 X11_DeleteDevice(SDL_VideoDevice * device)
 {
     SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
-
     if (data->display) {
         XCloseDisplay(data->display);
     }
@@ -212,6 +217,8 @@
 int
 X11_VideoInit(_THIS)
 {
+    int i, index = 0, event_code;
+    XEventClass xEvent;
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
 
     /* Get the window class name, usually the name of the application */
@@ -241,6 +248,42 @@
     }
     X11_InitMouse(_this);
 
+    /* we're generating the table of events that should be recognized */
+    for (i = 0; i < SDL_NumOfXDevices; ++i) {
+        /* button events */
+        DeviceButtonPress(SDL_XDevices[i], event_code, xEvent);
+        if (xEvent) {
+            SDL_XEvents[index++] = xEvent;
+            button_pressed = event_code;
+        }
+        DeviceButtonRelease(SDL_XDevices[i], event_code, xEvent);
+        if (xEvent) {
+            SDL_XEvents[index++] = xEvent;
+            button_released = event_code;
+        }
+
+        /* proximity events */
+        ProximityIn(SDL_XDevices[i], event_code, xEvent);
+        if (xEvent) {
+            SDL_XEvents[index++] = xEvent;
+            proximity_in = event_code;
+        }
+        ProximityOut(SDL_XDevices[i], event_code, xEvent);
+        if (xEvent) {
+            SDL_XEvents[index++] = xEvent;
+            proximity_out = event_code;
+        }
+
+        /* motion events */
+        DeviceMotionNotify(SDL_XDevices[i], event_code, xEvent);
+        if (xEvent) {
+            SDL_XEvents[index++] = xEvent;
+            motion = event_code;
+        }
+
+    }
+    SDL_NumOfXEvents = index;
+
     return 0;
 }
 
@@ -263,6 +306,7 @@
     X11_QuitModes(_this);
     X11_QuitKeyboard(_this);
     X11_QuitMouse(_this);
+    free(SDL_XDevices);
 }
 
 /* vim: set ts=4 sw=4 expandtab: */
--- a/src/video/x11/SDL_x11video.h	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11video.h	Mon Aug 25 06:33:00 2008 +0000
@@ -29,6 +29,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
+#include <X11/extensions/XInput.h>
 
 #if SDL_VIDEO_DRIVER_X11_XINERAMA
 #include "../Xext/extensions/Xinerama.h"
@@ -68,7 +69,7 @@
     int numwindows;
     SDL_WindowData **windowlist;
     int windowlistlength;
-    int mouse;
+    int *mouse;
     int keyboard;
     Atom WM_DELETE_WINDOW;
     SDL_scancode key_layout[256];
--- a/src/video/x11/SDL_x11window.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/src/video/x11/SDL_x11window.c	Mon Aug 25 06:33:00 2008 +0000
@@ -153,6 +153,8 @@
     XSizeHints *sizehints;
     XWMHints *wmhints;
     XClassHint *classhints;
+    extern XEventClass SDL_XEvents[];
+    extern int SDL_NumOfXEvents;
 
 #if SDL_VIDEO_DRIVER_X11_XINERAMA
 /* FIXME
@@ -481,6 +483,7 @@
         Uint32 fevent = 0;
         pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
                       XNFilterEvents, &fevent, NULL);
+        XMapWindow(data->display, w);
         XSelectInput(data->display, w,
                      (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
                       ExposureMask | ButtonPressMask | ButtonReleaseMask |
@@ -489,6 +492,7 @@
                       KeymapStateMask | fevent));
     }
 #else
+    XMapWindow(data->display, w);
     XSelectInput(data->display, w,
                  (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
                   ExposureMask | ButtonPressMask | ButtonReleaseMask |
@@ -497,6 +501,9 @@
                   KeymapStateMask));
 #endif
 
+    /* we're informing the display what extension events we want to receive from it */
+    XSelectExtensionEvent(data->display, w, SDL_XEvents, SDL_NumOfXEvents);
+
     return 0;
 }
 
--- a/test/testalpha.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/test/testalpha.c	Mon Aug 25 06:33:00 2008 +0000
@@ -273,7 +273,7 @@
     if (light != NULL) {
         int x, y;
 
-        SDL_GetMouseState(&x, &y);
+        SDL_GetMouseState(0, &x, &y);
         FlashLight(screen, light, x, y);
     }
 
--- a/test/testgl.c	Mon Aug 25 05:30:28 2008 +0000
+++ b/test/testgl.c	Mon Aug 25 06:33:00 2008 +0000
@@ -270,7 +270,7 @@
     }
 
     /* Move the image around */
-    SDL_GetMouseState(&x, &y);
+    SDL_GetMouseState(0, &x, &y);
     x -= w / 2;
     y -= h / 2;