diff src/video/win32/SDL_win32mouse.c @ 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 c121d94672cb
children 0e2b65f32298
line wrap: on
line diff
--- 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: */