📄 windows.c
字号:
sizeof (RAWINPUTHEADER)); if (dwSize < sizeof (RAWINPUT)) return; /* unexpected packet? */ lpb = (LPBYTE) alloca(dwSize); if (lpb == NULL) return; if (pGetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &dwSize, sizeof (RAWINPUTHEADER)) != dwSize) return; queue_from_rawinput((RAWINPUT *) lpb);} /* wminput_handler */static LRESULT CALLBACK RawWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam){ if (Msg == WM_INPUT) wminput_handler(wParam, lParam); else if (Msg == WM_DESTROY) return(0); return pDefWindowProcA(hWnd, Msg, wParam, lParam);} /* RawWndProc */static int init_event_queue(void){ HINSTANCE hInstance = pGetModuleHandleA(NULL); WNDCLASSEX wce; RAWINPUTDEVICE rid; ZeroMemory(input_events, sizeof (input_events)); input_events_read = input_events_write = 0; ZeroMemory(&wce, sizeof (wce)); wce.cbSize = sizeof(WNDCLASSEX); wce.lpfnWndProc = RawWndProc; wce.lpszClassName = class_name; wce.hInstance = hInstance; class_atom = pRegisterClassExA(&wce); if (class_atom == 0) return(0); raw_hwnd = pCreateWindowExA(0, class_name, win_name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, hInstance, NULL); if (raw_hwnd == NULL) return(0); pInitializeCriticalSection(&mutex); ZeroMemory(&rid, sizeof (rid)); rid.usUsagePage = 1; /* GenericDesktop page */ rid.usUsage = 2; /* GeneralDestop Mouse usage. */ rid.dwFlags = RIDEV_INPUTSINK; rid.hwndTarget = raw_hwnd; if (!pRegisterRawInputDevices(&rid, 1, sizeof (rid))) { pDeleteCriticalSection(&mutex); return(0); } /* if */ return(1);} /* init_event_queue */static void cleanup_window(void){ if (raw_hwnd) { MSG Msg; pDestroyWindow(raw_hwnd); while (pPeekMessageA(&Msg, raw_hwnd, 0, 0, PM_REMOVE)) { pTranslateMessage(&Msg); pDispatchMessageA(&Msg); } /* while */ raw_hwnd = 0; } /* if */ if (class_atom) { pUnregisterClassA(class_name, pGetModuleHandleA(NULL)); class_atom = 0; } /* if */} /* cleanup_window */static int accept_device(const RAWINPUTDEVICELIST *dev){ const char rdp_ident[] = "\\??\\Root#RDP_MOU#0000#"; char *buf = NULL; UINT ct = 0; if (dev->dwType != RIM_TYPEMOUSE) return(0); /* keyboard or some other fruity thing. */ if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, NULL, &ct) < 0) return(0); /* ct == is chars, not bytes, but we used the ASCII version. */ buf = (char *) alloca(ct); if (buf == NULL) return(0); if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, buf, &ct) < 0) return(0); /* * Apparently there's a fake "RDP" device...I guess this is * "Remote Desktop Protocol" for controlling the system pointer * remotely via Windows Remote Desktop, but that's just a guess. * At any rate, we don't want that device, so skip it if detected. * * Idea for this found here: * http://link.mywwwserver.com/~jstookey/arcade/rawmouse/raw_mouse.c */ /* avoiding memcmp here so we don't get a C runtime dependency... */ if (ct >= sizeof (rdp_ident) - 1) { int i; for (i = 0; i < sizeof (rdp_ident) - 1; i++) { if (buf[i] != rdp_ident[i]) break; } /* for */ if (i == sizeof (rdp_ident) - 1) return(0); /* this is an RDP thing. Skip this device. */ } /* if */ return(1); /* we want this device. */} /* accept_device *//* !!! FIXME: this code sucks. */static void get_device_product_name(char *name, size_t namesize, const RAWINPUTDEVICELIST *dev){ const char regkeyroot[] = "System\\CurrentControlSet\\Enum\\"; const char default_device_name[] = "Unidentified input device"; DWORD outsize = namesize; DWORD regtype = REG_SZ; char *buf = NULL; char *ptr = NULL; char *keyname = NULL; UINT i = 0; UINT ct = 0; LONG rc = 0; HKEY hkey; *name = '\0'; /* really insane default. */ if (sizeof (default_device_name) >= namesize) return; /* in case we can't stumble upon something better... */ CopyMemory(name, default_device_name, sizeof (default_device_name)); if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, NULL, &ct) < 0) return; /* ct == is chars, not bytes, but we used the ASCII version. */ buf = (char *) alloca(ct+1); keyname = (char *) alloca(ct + sizeof (regkeyroot)); if ((buf == NULL) || (keyname == NULL)) return; if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, buf, &ct) < 0) return; /* * This string tap dancing gets us a registry keyname in this form: * SYSTEM\CurrentControlSet\Enum\BUSTYPE\DEVICECLASS\DEVICEID * (those are my best-guess for the actual elements, but the format * appears to be sound.) */ ct -= 4; buf += 4; /* skip the "\\??\\" on the front of the string. */ for (i = 0, ptr = buf; i < ct; i++, ptr++) /* convert '#' to '\\' ... */ { if (*ptr == '#') *ptr = '\\'; else if (*ptr == '{') /* hit the GUID part of the string. */ break; } /* for */ *ptr = '\0'; CopyMemory(keyname, regkeyroot, sizeof (regkeyroot) - 1); CopyMemory(keyname + (sizeof (regkeyroot) - 1), buf, i + 1); rc = pRegOpenKeyExA(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey); if (rc != ERROR_SUCCESS) return; rc = pRegQueryValueExA(hkey, "DeviceDesc", NULL, ®type, name, &outsize); pRegCloseKey(hkey); if (rc != ERROR_SUCCESS) { /* msdn says failure may mangle the buffer, so default it again. */ CopyMemory(name, default_device_name, sizeof (default_device_name)); return; } /* if */ name[namesize-1] = '\0'; /* just in case. */} /* get_device_product_name */static void init_mouse(const RAWINPUTDEVICELIST *dev){ MouseStruct *mouse = &mice[available_mice]; if (accept_device(dev)) { ZeroMemory(mouse, sizeof (MouseStruct)); get_device_product_name(mouse->name, sizeof (mouse->name), dev); mouse->handle = dev->hDevice; available_mice++; /* we're good. */ } /* if */} /* init_mouse */static int windows_wminput_init(void){ RAWINPUTDEVICELIST *devlist = NULL; UINT ct = 0; UINT i; available_mice = 0; if (!find_api_symbols()) /* only supported on WinXP and later. */ return(0); pGetRawInputDeviceList(NULL, &ct, sizeof (RAWINPUTDEVICELIST)); if (ct == 0) /* no devices. */ return(0); devlist = (PRAWINPUTDEVICELIST) alloca(sizeof (RAWINPUTDEVICELIST) * ct); pGetRawInputDeviceList(devlist, &ct, sizeof (RAWINPUTDEVICELIST)); for (i = 0; i < ct; i++) init_mouse(&devlist[i]); if (!init_event_queue()) { cleanup_window(); available_mice = 0; } /* if */ return(available_mice);} /* windows_wminput_init */static void windows_wminput_quit(void){ /* unregister WM_INPUT devices... */ RAWINPUTDEVICE rid; ZeroMemory(&rid, sizeof (rid)); rid.usUsagePage = 1; /* GenericDesktop page */ rid.usUsage = 2; /* GeneralDestop Mouse usage. */ rid.dwFlags |= RIDEV_REMOVE; pRegisterRawInputDevices(&rid, 1, sizeof (rid)); cleanup_window(); available_mice = 0; pDeleteCriticalSection(&mutex);} /* windows_wminput_quit */static const char *windows_wminput_name(unsigned int index){ if (index < available_mice) return(mice[index].name); return(NULL);} /* windows_wminput_name *//* * Windows doesn't send a WM_INPUT event when you unplug a mouse, * so we try to do a basic query by device handle here; if the * query fails, we assume the device has vanished and generate a * disconnect. */static int check_for_disconnects(ManyMouseEvent *ev){ /* * (i) is static so we iterate through all mice round-robin and check * one mouse per call to ManyMouse_PollEvent(). This makes this test O(1). */ static unsigned int i = 0; MouseStruct *mouse = NULL; if (++i >= available_mice) /* check first in case of redetect */ i = 0; mouse = &mice[i]; if (mouse->handle != NULL) /* not NULL == still plugged in. */ { UINT size = 0; UINT rc = pGetRawInputDeviceInfoA(mouse->handle, RIDI_DEVICEINFO, NULL, &size); if (rc == (UINT) -1) /* failed...probably unplugged... */ { mouse->handle = NULL; ev->type = MANYMOUSE_EVENT_DISCONNECT; ev->device = i; return(1); } /* if */ } /* if */ return(0); /* no disconnect event this time. */} /* check_for_disconnects */static int windows_wminput_poll(ManyMouseEvent *ev){ MSG Msg; /* run the queue for WM_INPUT messages, etc ... */ int found = 0; /* ...favor existing events in the queue... */ pEnterCriticalSection(&mutex); if (input_events_read != input_events_write) /* no events if equal. */ { CopyMemory(ev, &input_events[input_events_read], sizeof (*ev)); input_events_read = ((input_events_read + 1) % MAX_EVENTS); found = 1; } /* if */ pLeaveCriticalSection(&mutex); if (!found) { /* pump Windows for new hardware events... */ while (pPeekMessageA(&Msg, raw_hwnd, 0, 0, PM_REMOVE)) { pTranslateMessage(&Msg); pDispatchMessageA(&Msg); } /* while */ /* In case something new came in, give it to the app... */ pEnterCriticalSection(&mutex); if (input_events_read != input_events_write) /* no events if equal. */ { CopyMemory(ev, &input_events[input_events_read], sizeof (*ev)); input_events_read = ((input_events_read + 1) % MAX_EVENTS); found = 1; } /* if */ pLeaveCriticalSection(&mutex); } /* if */ /* * Check for disconnects if queue is totally empty and Windows didn't * report anything new at this time. This ensures that we don't send a * disconnect event through ManyMouse and then later give a valid * event to the app for a device that is now missing. */ if (!found) found = check_for_disconnects(ev); return(found);} /* windows_wminput_poll */#elsestatic int windows_wminput_init(void) { return(-1); }static void windows_wminput_quit(void) {}static const char *windows_wminput_name(unsigned int index) { return(0); }static int windows_wminput_poll(ManyMouseEvent *event) { return(0); }#endif /* ifdef WINDOWS blocker */ManyMouseDriver ManyMouseDriver_windows ={ windows_wminput_init, windows_wminput_quit, windows_wminput_name, windows_wminput_poll};/* end of windows_wminput.c ... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -