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, &center);
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