Mercurial > sdl-ios-xcode
comparison src/video/win32/SDL_win32events.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 | 3202e4826c57 |
children | 62e7af9b2b67 |
comparison
equal
deleted
inserted
replaced
2709:fd3f0f1147e7 | 2710:44e49d3fa6cf |
---|---|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | 18 |
19 Sam Lantinga | 19 Sam Lantinga |
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 */ | 21 */ |
22 | |
23 #if (_WIN32_WINNT < 0x0501) | |
24 #undef _WIN32_WINNT | |
25 #define _WIN32_WINNT 0x0501 | |
26 #endif | |
27 | |
22 #include "SDL_config.h" | 28 #include "SDL_config.h" |
23 | 29 |
24 #include "SDL_win32video.h" | 30 #include "SDL_win32video.h" |
25 #include "SDL_syswm.h" | 31 #include "SDL_syswm.h" |
26 #include "SDL_vkeys.h" | 32 #include "SDL_vkeys.h" |
27 #include "../../events/SDL_events_c.h" | 33 #include "../../events/SDL_events_c.h" |
34 | |
35 #include <wintab.h> | |
36 #define PACKETDATA ( PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_CURSOR) | |
37 #define PACKETMODE 0 | |
38 #include <pktdef.h> | |
28 | 39 |
29 /*#define WMMSG_DEBUG*/ | 40 /*#define WMMSG_DEBUG*/ |
30 #ifdef WMMSG_DEBUG | 41 #ifdef WMMSG_DEBUG |
31 #include <stdio.h> | 42 #include <stdio.h> |
32 #include "wmmsg.h" | 43 #include "wmmsg.h" |
47 #endif | 58 #endif |
48 #ifndef GET_XBUTTON_WPARAM | 59 #ifndef GET_XBUTTON_WPARAM |
49 #define GET_XBUTTON_WPARAM(w) (HIWORD(w)) | 60 #define GET_XBUTTON_WPARAM(w) (HIWORD(w)) |
50 #endif | 61 #endif |
51 | 62 |
63 extern HCTX *g_hCtx; | |
64 extern HANDLE *mice; | |
65 extern int total_mice; | |
66 extern int tablet; | |
67 int pressure = 0; /* the pressure reported by the tablet */ | |
68 | |
52 static WPARAM | 69 static WPARAM |
53 RemapVKEY(WPARAM wParam, LPARAM lParam) | 70 RemapVKEY(WPARAM wParam, LPARAM lParam) |
54 { | 71 { |
55 int i; | 72 int i; |
56 BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF); | 73 BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF); |
82 | 99 |
83 LRESULT CALLBACK | 100 LRESULT CALLBACK |
84 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | 101 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) |
85 { | 102 { |
86 SDL_WindowData *data; | 103 SDL_WindowData *data; |
104 RAWINPUT *raw; | |
105 PACKET packet; | |
87 | 106 |
88 /* Send a SDL_SYSWMEVENT if the application wants them */ | 107 /* Send a SDL_SYSWMEVENT if the application wants them */ |
89 if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { | 108 if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { |
90 SDL_SysWMmsg wmmsg; | 109 SDL_SysWMmsg wmmsg; |
91 | 110 |
112 fprintf(log, "%s", wmtab[msg]); | 131 fprintf(log, "%s", wmtab[msg]); |
113 } | 132 } |
114 fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam); | 133 fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam); |
115 fclose(log); | 134 fclose(log); |
116 } | 135 } |
136 | |
117 #endif | 137 #endif |
118 | 138 |
119 switch (msg) { | 139 switch (msg) { |
140 | |
141 case WT_PACKET: | |
142 { | |
143 /* if we receive such data we need to update the pressure */ | |
144 if (WTPacket((HCTX) lParam, wParam, &packet)) { | |
145 SDL_ChangeEnd(tablet, (int) packet.pkCursor); | |
146 pressure = (int) packet.pkNormalPressure; | |
147 } | |
148 } | |
149 break; | |
150 | |
151 case WT_PROXIMITY: | |
152 { | |
153 /* checking where the proximity message showed up */ | |
154 int h_context = LOWORD(lParam); | |
155 LPPOINT point; | |
156 GetCursorPos(&point); | |
157 ScreenToClient(hwnd, &point); | |
158 | |
159 /* are we in proximity or out of proximity */ | |
160 if (h_context == 0) { | |
161 SDL_SendProximity(tablet, (int) (&point->x), | |
162 (int) (&point->y), SDL_PROXIMITYOUT); | |
163 } else { | |
164 SDL_SendProximity(tablet, (int) (&point->x), | |
165 (int) (&point->y), SDL_PROXIMITYIN); | |
166 } | |
167 } | |
168 break; | |
120 | 169 |
121 case WM_SHOWWINDOW: | 170 case WM_SHOWWINDOW: |
122 { | 171 { |
123 if (wParam) { | 172 if (wParam) { |
124 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, | 173 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, |
159 if (minimized) { | 208 if (minimized) { |
160 SDL_SendWindowEvent(data->windowID, | 209 SDL_SendWindowEvent(data->windowID, |
161 SDL_WINDOWEVENT_MINIMIZED, 0, 0); | 210 SDL_WINDOWEVENT_MINIMIZED, 0, 0); |
162 } | 211 } |
163 } | 212 } |
164 return (0); | 213 } |
165 } | 214 return (0); |
166 break; | 215 |
167 | 216 case WM_INPUT: /* mouse events */ |
168 case WM_MOUSEMOVE: | 217 { |
218 LPBYTE lpb; | |
219 int w, h; | |
220 const RAWINPUTHEADER *header; | |
221 int index; | |
222 int i; | |
223 int size = 0; | |
224 const RAWMOUSE *raw_mouse = NULL; | |
225 LPPOINT point; | |
226 USHORT flags; | |
227 | |
228 /* we're collecting data from the mouse */ | |
229 GetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &size, | |
230 sizeof(RAWINPUTHEADER)); | |
231 lpb = SDL_malloc(size * sizeof(LPBYTE)); | |
232 GetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &size, | |
233 sizeof(RAWINPUTHEADER)); | |
234 raw = (RAWINPUT *) lpb; | |
235 header = &raw->header; | |
236 flags = raw->data.mouse.usButtonFlags; | |
237 | |
238 /* we're checking which mouse generated the event */ | |
239 for (i = 0; i < total_mice; ++i) { | |
240 if (mice[i] == header->hDevice) { | |
241 index = i; | |
242 break; | |
243 } | |
244 } | |
245 GetCursorPos(&point); | |
246 ScreenToClient(hwnd, &point); | |
247 SDL_GetWindowSize(data->windowID, &w, &h); | |
248 SDL_UpdateCoordinates(w, h); /* we're updating the current window size */ | |
249 | |
250 /* if the message was sent by a tablet we have to send also pressure */ | |
251 if (i == tablet) { | |
252 SDL_SendMouseMotion(index, 0, (int) (&point->x), | |
253 (int) (&point->y), pressure); | |
254 } else { | |
255 SDL_SendMouseMotion(index, 0, (int) (&point->x), | |
256 (int) (&point->y), 0); | |
257 } | |
258 /* we're sending mouse buttons messages to check up if sth changed */ | |
259 if (flags & RI_MOUSE_BUTTON_1_DOWN) { | |
260 SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_LEFT); | |
261 } else if (flags & RI_MOUSE_BUTTON_1_UP) { | |
262 SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_LEFT); | |
263 } | |
264 if (flags & RI_MOUSE_BUTTON_2_DOWN) { | |
265 SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_MIDDLE); | |
266 } else if (flags & RI_MOUSE_BUTTON_2_UP) { | |
267 SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_MIDDLE); | |
268 } | |
269 if (flags & RI_MOUSE_BUTTON_3_DOWN) { | |
270 SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_RIGHT); | |
271 } else if (flags & RI_MOUSE_BUTTON_3_UP) { | |
272 SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_RIGHT); | |
273 } | |
274 if (flags & RI_MOUSE_WHEEL) { | |
275 if (raw->data.mouse.usButtonData != 0) { | |
276 SDL_SendMouseWheel(index, 0, | |
277 raw->data.mouse.usButtonData); | |
278 } | |
279 } | |
280 } | |
281 return (0); | |
282 | |
283 case WM_MOUSELEAVE: | |
169 { | 284 { |
170 int index; | 285 int index; |
171 SDL_Mouse *mouse; | 286 SDL_Mouse *mouse; |
172 int x, y; | |
173 | 287 |
174 index = data->videodata->mouse; | 288 index = data->videodata->mouse; |
175 mouse = SDL_GetMouse(index); | 289 mouse = SDL_GetMouse(index); |
176 | 290 |
177 if (mouse->focus != data->windowID) { | |
178 TRACKMOUSEEVENT tme; | |
179 | |
180 tme.cbSize = sizeof(tme); | |
181 tme.dwFlags = TME_LEAVE; | |
182 tme.hwndTrack = hwnd; | |
183 TrackMouseEvent(&tme); | |
184 | |
185 SDL_SetMouseFocus(index, data->windowID); | |
186 } | |
187 | |
188 /* mouse has moved within the window */ | |
189 x = LOWORD(lParam); | |
190 y = HIWORD(lParam); | |
191 if (mouse->relative_mode) { | |
192 int w, h; | |
193 POINT center; | |
194 SDL_GetWindowSize(data->windowID, &w, &h); | |
195 center.x = (w / 2); | |
196 center.y = (h / 2); | |
197 x -= center.x; | |
198 y -= center.y; | |
199 if (x || y) { | |
200 ClientToScreen(hwnd, ¢er); | |
201 SetCursorPos(center.x, center.y); | |
202 SDL_SendMouseMotion(index, 1, x, y); | |
203 } | |
204 } else { | |
205 SDL_SendMouseMotion(index, 0, x, y); | |
206 } | |
207 } | |
208 return (0); | |
209 | |
210 case WM_MOUSELEAVE: | |
211 { | |
212 int index; | |
213 SDL_Mouse *mouse; | |
214 | |
215 index = data->videodata->mouse; | |
216 mouse = SDL_GetMouse(index); | |
217 | |
218 if (mouse->focus == data->windowID) { | 291 if (mouse->focus == data->windowID) { |
219 SDL_SetMouseFocus(index, 0); | 292 SDL_SetMouseFocus(index, 0); |
220 } | 293 } |
221 } | |
222 return (0); | |
223 | |
224 case WM_LBUTTONDOWN: | |
225 case WM_LBUTTONUP: | |
226 case WM_MBUTTONDOWN: | |
227 case WM_MBUTTONUP: | |
228 case WM_RBUTTONDOWN: | |
229 case WM_RBUTTONUP: | |
230 case WM_XBUTTONDOWN: | |
231 case WM_XBUTTONUP: | |
232 { | |
233 int xbuttonval = 0; | |
234 int index; | |
235 SDL_Mouse *mouse; | |
236 Uint8 button, state; | |
237 | |
238 /* DJM: | |
239 We want the SDL window to take focus so that | |
240 it acts like a normal windows "component" | |
241 (e.g. gains keyboard focus on a mouse click). | |
242 */ | |
243 SetFocus(hwnd); | |
244 | |
245 index = data->videodata->mouse; | |
246 mouse = SDL_GetMouse(index); | |
247 | |
248 /* Figure out which button to use */ | |
249 switch (msg) { | |
250 case WM_LBUTTONDOWN: | |
251 button = SDL_BUTTON_LEFT; | |
252 state = SDL_PRESSED; | |
253 break; | |
254 case WM_LBUTTONUP: | |
255 button = SDL_BUTTON_LEFT; | |
256 state = SDL_RELEASED; | |
257 break; | |
258 case WM_MBUTTONDOWN: | |
259 button = SDL_BUTTON_MIDDLE; | |
260 state = SDL_PRESSED; | |
261 break; | |
262 case WM_MBUTTONUP: | |
263 button = SDL_BUTTON_MIDDLE; | |
264 state = SDL_RELEASED; | |
265 break; | |
266 case WM_RBUTTONDOWN: | |
267 button = SDL_BUTTON_RIGHT; | |
268 state = SDL_PRESSED; | |
269 break; | |
270 case WM_RBUTTONUP: | |
271 button = SDL_BUTTON_RIGHT; | |
272 state = SDL_RELEASED; | |
273 break; | |
274 case WM_XBUTTONDOWN: | |
275 xbuttonval = GET_XBUTTON_WPARAM(wParam); | |
276 button = SDL_BUTTON_X1 + xbuttonval - 1; | |
277 state = SDL_PRESSED; | |
278 break; | |
279 case WM_XBUTTONUP: | |
280 xbuttonval = GET_XBUTTON_WPARAM(wParam); | |
281 button = SDL_BUTTON_X1 + xbuttonval - 1; | |
282 state = SDL_RELEASED; | |
283 break; | |
284 default: | |
285 /* Eh? Unknown button? */ | |
286 return (0); | |
287 } | |
288 if (state == SDL_PRESSED) { | |
289 /* Grab mouse so we get up events */ | |
290 if (++data->mouse_pressed > 0) { | |
291 SetCapture(hwnd); | |
292 } | |
293 } else { | |
294 /* Release mouse after all up events */ | |
295 if (--data->mouse_pressed <= 0) { | |
296 ReleaseCapture(); | |
297 data->mouse_pressed = 0; | |
298 } | |
299 } | |
300 | |
301 if (!mouse->relative_mode) { | |
302 int x, y; | |
303 x = LOWORD(lParam); | |
304 y = HIWORD(lParam); | |
305 SDL_SendMouseMotion(index, 0, x, y); | |
306 } | |
307 SDL_SendMouseButton(index, state, button); | |
308 | |
309 /* | |
310 * MSDN says: | |
311 * "Unlike the WM_LBUTTONUP, WM_MBUTTONUP, and WM_RBUTTONUP | |
312 * messages, an application should return TRUE from [an | |
313 * XBUTTON message] if it processes it. Doing so will allow | |
314 * software that simulates this message on Microsoft Windows | |
315 * systems earlier than Windows 2000 to determine whether | |
316 * the window procedure processed the message or called | |
317 * DefWindowProc to process it. | |
318 */ | |
319 if (xbuttonval > 0) { | |
320 return (TRUE); | |
321 } | |
322 } | |
323 return (0); | |
324 | |
325 case WM_MOUSEWHEEL: | |
326 { | |
327 int index; | |
328 int motion = (short) HIWORD(wParam); | |
329 | |
330 index = data->videodata->mouse; | |
331 SDL_SendMouseWheel(index, 0, motion); | |
332 } | 294 } |
333 return (0); | 295 return (0); |
334 | 296 |
335 case WM_SYSKEYDOWN: | 297 case WM_SYSKEYDOWN: |
336 case WM_KEYDOWN: | 298 case WM_KEYDOWN: |
424 case VK_RETURN: | 386 case VK_RETURN: |
425 if (lParam & EXTENDED_KEYMASK) | 387 if (lParam & EXTENDED_KEYMASK) |
426 wParam = VK_ENTER; | 388 wParam = VK_ENTER; |
427 break; | 389 break; |
428 } | 390 } |
391 | |
429 /* Windows only reports keyup for print screen */ | 392 /* Windows only reports keyup for print screen */ |
430 if (wParam == VK_SNAPSHOT | 393 if (wParam == VK_SNAPSHOT |
431 && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] == | 394 && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] == |
432 SDL_RELEASED) { | 395 SDL_RELEASED) { |
433 SDL_SendKeyboardKey(index, SDL_PRESSED, | 396 SDL_SendKeyboardKey(index, SDL_PRESSED, |
497 return value is undefined if hwnd is a child window. | 460 return value is undefined if hwnd is a child window. |
498 Aparently it's too difficult for MS to check | 461 Aparently it's too difficult for MS to check |
499 inside their function, so I have to do it here. | 462 inside their function, so I have to do it here. |
500 */ | 463 */ |
501 style = GetWindowLong(hwnd, GWL_STYLE); | 464 style = GetWindowLong(hwnd, GWL_STYLE); |
502 AdjustWindowRect(&size, | 465 AdjustWindowRect(&size, style, |
503 style, | 466 style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) |
504 style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) != | 467 != NULL); |
505 NULL); | |
506 | |
507 w = size.right - size.left; | 468 w = size.right - size.left; |
508 h = size.bottom - size.top; | 469 h = size.bottom - size.top; |
509 | 470 |
510 /* Fix our size to the current size */ | 471 /* Fix our size to the current size */ |
511 info = (MINMAXINFO *) lParam; | 472 info = (MINMAXINFO *) lParam; |
659 SDL_Instance = hInst ? hInst : GetModuleHandle(NULL); | 620 SDL_Instance = hInst ? hInst : GetModuleHandle(NULL); |
660 } | 621 } |
661 | 622 |
662 /* Register the application class */ | 623 /* Register the application class */ |
663 class.hCursor = NULL; | 624 class.hCursor = NULL; |
664 class.hIcon = LoadImage(SDL_Instance, SDL_Appname, | 625 class.hIcon = |
665 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); | 626 LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0, |
627 LR_DEFAULTCOLOR); | |
666 class.lpszMenuName = NULL; | 628 class.lpszMenuName = NULL; |
667 class.lpszClassName = SDL_Appname; | 629 class.lpszClassName = SDL_Appname; |
668 class.hbrBackground = NULL; | 630 class.hbrBackground = NULL; |
669 class.hInstance = SDL_Instance; | 631 class.hInstance = SDL_Instance; |
670 class.style = SDL_Appstyle; | 632 class.style = SDL_Appstyle; |
705 void | 667 void |
706 WIN_SetError(const char *prefix) | 668 WIN_SetError(const char *prefix) |
707 { | 669 { |
708 TCHAR buffer[1024]; | 670 TCHAR buffer[1024]; |
709 char *message; | 671 char *message; |
710 | 672 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, |
711 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, | 673 buffer, SDL_arraysize(buffer), NULL); |
712 NULL, | |
713 GetLastError(), 0, buffer, SDL_arraysize(buffer), NULL); | |
714 | |
715 message = WIN_StringToUTF8(buffer); | 674 message = WIN_StringToUTF8(buffer); |
716 SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ":" : "", message); | 675 SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ":" : "", message); |
717 SDL_free(message); | 676 SDL_free(message); |
718 } | 677 } |
719 | 678 |