zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_windowsevents.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #if SDL_VIDEO_DRIVER_WINDOWS
24 
25 #include "SDL_windowsvideo.h"
26 #include "SDL_windowsshape.h"
27 #include "SDL_syswm.h"
28 #include "SDL_vkeys.h"
29 #include "../../events/SDL_events_c.h"
30 #include "../../events/SDL_touch_c.h"
31 #include "../../events/scancodes_windows.h"
32 
33 /* Dropfile support */
34 #include <shellapi.h>
35 
36 /* For GET_X_LPARAM, GET_Y_LPARAM. */
37 #include <windowsx.h>
38 
39 /* #define WMMSG_DEBUG */
40 #ifdef WMMSG_DEBUG
41 #include <stdio.h>
42 #include "wmmsg.h"
43 #endif
44 
45 /* Masks for processing the windows KEYDOWN and KEYUP messages */
46 #define REPEATED_KEYMASK (1<<30)
47 #define EXTENDED_KEYMASK (1<<24)
48 
49 #define VK_ENTER 10 /* Keypad Enter ... no VKEY defined? */
50 #ifndef VK_OEM_NEC_EQUAL
51 #define VK_OEM_NEC_EQUAL 0x92
52 #endif
53 
54 /* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
55 #ifndef WM_XBUTTONDOWN
56 #define WM_XBUTTONDOWN 0x020B
57 #endif
58 #ifndef WM_XBUTTONUP
59 #define WM_XBUTTONUP 0x020C
60 #endif
61 #ifndef GET_XBUTTON_WPARAM
62 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
63 #endif
64 #ifndef WM_INPUT
65 #define WM_INPUT 0x00ff
66 #endif
67 #ifndef WM_TOUCH
68 #define WM_TOUCH 0x0240
69 #endif
70 
71 static SDL_Scancode
72 WindowsScanCodeToSDLScanCode( LPARAM lParam, WPARAM wParam )
73 {
75  char bIsExtended;
76  int nScanCode = ( lParam >> 16 ) & 0xFF;
77 
78  /* 0x45 here to work around both pause and numlock sharing the same scancode, so use the VK key to tell them apart */
79  if ( nScanCode == 0 || nScanCode == 0x45 )
80  {
81  switch( wParam )
82  {
83  case VK_CLEAR: return SDL_SCANCODE_CLEAR;
84  case VK_MODECHANGE: return SDL_SCANCODE_MODE;
85  case VK_SELECT: return SDL_SCANCODE_SELECT;
86  case VK_EXECUTE: return SDL_SCANCODE_EXECUTE;
87  case VK_HELP: return SDL_SCANCODE_HELP;
88  case VK_PAUSE: return SDL_SCANCODE_PAUSE;
89  case VK_NUMLOCK: return SDL_SCANCODE_NUMLOCKCLEAR;
90 
91  case VK_F13: return SDL_SCANCODE_F13;
92  case VK_F14: return SDL_SCANCODE_F14;
93  case VK_F15: return SDL_SCANCODE_F15;
94  case VK_F16: return SDL_SCANCODE_F16;
95  case VK_F17: return SDL_SCANCODE_F17;
96  case VK_F18: return SDL_SCANCODE_F18;
97  case VK_F19: return SDL_SCANCODE_F19;
98  case VK_F20: return SDL_SCANCODE_F20;
99  case VK_F21: return SDL_SCANCODE_F21;
100  case VK_F22: return SDL_SCANCODE_F22;
101  case VK_F23: return SDL_SCANCODE_F23;
102  case VK_F24: return SDL_SCANCODE_F24;
103 
104  case VK_OEM_NEC_EQUAL: return SDL_SCANCODE_KP_EQUALS;
105  case VK_BROWSER_BACK: return SDL_SCANCODE_AC_BACK;
106  case VK_BROWSER_FORWARD: return SDL_SCANCODE_AC_FORWARD;
107  case VK_BROWSER_REFRESH: return SDL_SCANCODE_AC_REFRESH;
108  case VK_BROWSER_STOP: return SDL_SCANCODE_AC_STOP;
109  case VK_BROWSER_SEARCH: return SDL_SCANCODE_AC_SEARCH;
110  case VK_BROWSER_FAVORITES: return SDL_SCANCODE_AC_BOOKMARKS;
111  case VK_BROWSER_HOME: return SDL_SCANCODE_AC_HOME;
112  case VK_VOLUME_MUTE: return SDL_SCANCODE_AUDIOMUTE;
113  case VK_VOLUME_DOWN: return SDL_SCANCODE_VOLUMEDOWN;
114  case VK_VOLUME_UP: return SDL_SCANCODE_VOLUMEUP;
115 
116  case VK_MEDIA_NEXT_TRACK: return SDL_SCANCODE_AUDIONEXT;
117  case VK_MEDIA_PREV_TRACK: return SDL_SCANCODE_AUDIOPREV;
118  case VK_MEDIA_STOP: return SDL_SCANCODE_AUDIOSTOP;
119  case VK_MEDIA_PLAY_PAUSE: return SDL_SCANCODE_AUDIOPLAY;
120  case VK_LAUNCH_MAIL: return SDL_SCANCODE_MAIL;
121  case VK_LAUNCH_MEDIA_SELECT: return SDL_SCANCODE_MEDIASELECT;
122 
124 
125  case VK_ATTN: return SDL_SCANCODE_SYSREQ;
126  case VK_CRSEL: return SDL_SCANCODE_CRSEL;
127  case VK_EXSEL: return SDL_SCANCODE_EXSEL;
128  case VK_OEM_CLEAR: return SDL_SCANCODE_CLEAR;
129 
130  case VK_LAUNCH_APP1: return SDL_SCANCODE_APP1;
131  case VK_LAUNCH_APP2: return SDL_SCANCODE_APP2;
132 
133  default: return SDL_SCANCODE_UNKNOWN;
134  }
135  }
136 
137  if ( nScanCode > 127 )
138  return SDL_SCANCODE_UNKNOWN;
139 
140  code = windows_scancode_table[nScanCode];
141 
142  bIsExtended = ( lParam & ( 1 << 24 ) ) != 0;
143  if ( !bIsExtended )
144  {
145  switch ( code )
146  {
147  case SDL_SCANCODE_HOME:
148  return SDL_SCANCODE_KP_7;
149  case SDL_SCANCODE_UP:
150  return SDL_SCANCODE_KP_8;
151  case SDL_SCANCODE_PAGEUP:
152  return SDL_SCANCODE_KP_9;
153  case SDL_SCANCODE_LEFT:
154  return SDL_SCANCODE_KP_4;
155  case SDL_SCANCODE_RIGHT:
156  return SDL_SCANCODE_KP_6;
157  case SDL_SCANCODE_END:
158  return SDL_SCANCODE_KP_1;
159  case SDL_SCANCODE_DOWN:
160  return SDL_SCANCODE_KP_2;
162  return SDL_SCANCODE_KP_3;
163  case SDL_SCANCODE_INSERT:
164  return SDL_SCANCODE_KP_0;
165  case SDL_SCANCODE_DELETE:
166  return SDL_SCANCODE_KP_PERIOD;
169  default:
170  break;
171  }
172  }
173  else
174  {
175  switch ( code )
176  {
177  case SDL_SCANCODE_RETURN:
178  return SDL_SCANCODE_KP_ENTER;
179  case SDL_SCANCODE_LALT:
180  return SDL_SCANCODE_RALT;
181  case SDL_SCANCODE_LCTRL:
182  return SDL_SCANCODE_RCTRL;
183  case SDL_SCANCODE_SLASH:
184  return SDL_SCANCODE_KP_DIVIDE;
186  return SDL_SCANCODE_KP_PLUS;
187  default:
188  break;
189  }
190  }
191 
192  return code;
193 }
194 
195 
196 void
197 WIN_CheckWParamMouseButton( SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button )
198 {
199  if ( bwParamMousePressed && !bSDLMousePressed )
200  {
201  SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
202  }
203  else if ( !bwParamMousePressed && bSDLMousePressed )
204  {
205  SDL_SendMouseButton(data->window, 0, SDL_RELEASED, button);
206  }
207 }
208 
209 /*
210 * Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
211 * so this funciton reconciles our view of the world with the current buttons reported by windows
212 */
213 void
214 WIN_CheckWParamMouseButtons( WPARAM wParam, SDL_WindowData *data )
215 {
216  if ( wParam != data->mouse_button_flags )
217  {
218  Uint32 mouseFlags = SDL_GetMouseState( NULL, NULL );
219  WIN_CheckWParamMouseButton( (wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
220  WIN_CheckWParamMouseButton( (wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
221  WIN_CheckWParamMouseButton( (wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
222  WIN_CheckWParamMouseButton( (wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
223  WIN_CheckWParamMouseButton( (wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
224  data->mouse_button_flags = wParam;
225  }
226 }
227 
228 
229 void
230 WIN_CheckRawMouseButtons( ULONG rawButtons, SDL_WindowData *data )
231 {
232  if ( rawButtons != data->mouse_button_flags )
233  {
234  Uint32 mouseFlags = SDL_GetMouseState( NULL, NULL );
235  if ( (rawButtons & RI_MOUSE_BUTTON_1_DOWN) )
236  WIN_CheckWParamMouseButton( (rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
237  if ( (rawButtons & RI_MOUSE_BUTTON_1_UP) )
238  WIN_CheckWParamMouseButton( !(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
239  if ( (rawButtons & RI_MOUSE_BUTTON_2_DOWN) )
240  WIN_CheckWParamMouseButton( (rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
241  if ( (rawButtons & RI_MOUSE_BUTTON_2_UP) )
242  WIN_CheckWParamMouseButton( !(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
243  if ( (rawButtons & RI_MOUSE_BUTTON_3_DOWN) )
244  WIN_CheckWParamMouseButton( (rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
245  if ( (rawButtons & RI_MOUSE_BUTTON_3_UP) )
246  WIN_CheckWParamMouseButton( !(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
247  if ( (rawButtons & RI_MOUSE_BUTTON_4_DOWN) )
248  WIN_CheckWParamMouseButton( (rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
249  if ( (rawButtons & RI_MOUSE_BUTTON_4_UP) )
250  WIN_CheckWParamMouseButton( !(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
251  if ( (rawButtons & RI_MOUSE_BUTTON_5_DOWN) )
252  WIN_CheckWParamMouseButton( (rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
253  if ( (rawButtons & RI_MOUSE_BUTTON_5_UP) )
254  WIN_CheckWParamMouseButton( !(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
255  data->mouse_button_flags = rawButtons;
256  }
257 }
258 
260 WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
261 {
262  if (codepoint <= 0x7F) {
263  text[0] = (char) codepoint;
264  text[1] = '\0';
265  } else if (codepoint <= 0x7FF) {
266  text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
267  text[1] = 0x80 | (char) (codepoint & 0x3F);
268  text[2] = '\0';
269  } else if (codepoint <= 0xFFFF) {
270  text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
271  text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
272  text[2] = 0x80 | (char) (codepoint & 0x3F);
273  text[3] = '\0';
274  } else if (codepoint <= 0x10FFFF) {
275  text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
276  text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
277  text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
278  text[3] = 0x80 | (char) (codepoint & 0x3F);
279  text[4] = '\0';
280  } else {
281  return SDL_FALSE;
282  }
283  return SDL_TRUE;
284 }
285 
286 LRESULT CALLBACK
287 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
288 {
290  LRESULT returnCode = -1;
291 
292  /* Send a SDL_SYSWMEVENT if the application wants them */
294  SDL_SysWMmsg wmmsg;
295 
296  SDL_VERSION(&wmmsg.version);
298  wmmsg.msg.win.hwnd = hwnd;
299  wmmsg.msg.win.msg = msg;
300  wmmsg.msg.win.wParam = wParam;
301  wmmsg.msg.win.lParam = lParam;
302  SDL_SendSysWMEvent(&wmmsg);
303  }
304 
305  /* Get the window data for the window */
306  data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
307  if (!data) {
308  return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
309  }
310 
311 #ifdef WMMSG_DEBUG
312  {
313  FILE *log = fopen("wmmsg.txt", "a");
314  fprintf(log, "Received windows message: %p ", hwnd);
315  if (msg > MAX_WMMSG) {
316  fprintf(log, "%d", msg);
317  } else {
318  fprintf(log, "%s", wmtab[msg]);
319  }
320  fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
321  fclose(log);
322  }
323 #endif
324 
325  if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
326  return 0;
327 
328  switch (msg) {
329 
330  case WM_SHOWWINDOW:
331  {
332  if (wParam) {
334  } else {
336  }
337  }
338  break;
339 
340  case WM_ACTIVATE:
341  {
342  BOOL minimized;
343 
344  minimized = HIWORD(wParam);
345  if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
346  Uint32 mouseFlags;
347  SHORT keyState;
348 
352  if (IsZoomed(hwnd)) {
355  }
356  if (SDL_GetKeyboardFocus() != data->window) {
358  }
359  /* mouse buttons may have changed state here, we need
360  to resync them, but we will get a WM_MOUSEMOVE right away which will fix
361  things up if in non raw mode also
362  */
363  mouseFlags = SDL_GetMouseState( NULL, NULL );
364 
365  keyState = GetAsyncKeyState( VK_LBUTTON );
366  WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
367  keyState = GetAsyncKeyState( VK_RBUTTON );
368  WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
369  keyState = GetAsyncKeyState( VK_MBUTTON );
370  WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
371  keyState = GetAsyncKeyState( VK_XBUTTON1 );
372  WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
373  keyState = GetAsyncKeyState( VK_XBUTTON2 );
374  WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
375  data->mouse_button_flags = 0;
376 
377  if(SDL_GetMouse()->relative_mode) {
378  LONG cx, cy;
379  RECT rect;
380  GetWindowRect(hwnd, &rect);
381 
382  cx = (rect.left + rect.right) / 2;
383  cy = (rect.top + rect.bottom) / 2;
384 
385  /* Make an absurdly small clip rect */
386  rect.left = cx-1;
387  rect.right = cx+1;
388  rect.top = cy-1;
389  rect.bottom = cy+1;
390 
391  ClipCursor(&rect);
392  }
393 
394  /*
395  * FIXME: Update keyboard state
396  */
398  } else {
399  if (SDL_GetKeyboardFocus() == data->window) {
401  }
402  if (minimized) {
405  }
406  }
407  }
408  returnCode = 0;
409  break;
410 
411  case WM_MOUSEMOVE:
412  if( !SDL_GetMouse()->relative_mode )
413  SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
414  /* don't break here, fall through to check the wParam like the button presses */
415  case WM_LBUTTONUP:
416  case WM_RBUTTONUP:
417  case WM_MBUTTONUP:
418  case WM_XBUTTONUP:
419  case WM_LBUTTONDOWN:
420  case WM_RBUTTONDOWN:
421  case WM_MBUTTONDOWN:
422  case WM_XBUTTONDOWN:
423  if( !SDL_GetMouse()->relative_mode )
424  WIN_CheckWParamMouseButtons( wParam, data );
425  break;
426 
427  case WM_INPUT:
428  {
429  HRAWINPUT hRawInput = (HRAWINPUT)lParam;
430  RAWINPUT inp;
431  UINT size = sizeof(inp);
432 
434  break;
435 
436  GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
437 
438  /* Mouse data */
439  if(inp.header.dwType == RIM_TYPEMOUSE)
440  {
441  RAWMOUSE* mouse = &inp.data.mouse;
442 
443  if((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE)
444  {
445  SDL_SendMouseMotion(data->window, 0, 1, (int)mouse->lLastX, (int)mouse->lLastY);
446  }
447  else
448  {
449  /* synthesize relative moves from the abs position */
450  static SDL_Point initialMousePoint;
451  if ( initialMousePoint.x == 0 && initialMousePoint.y == 0 )
452  {
453  initialMousePoint.x = mouse->lLastX;
454  initialMousePoint.y = mouse->lLastY;
455  }
456 
457  SDL_SendMouseMotion(data->window, 0, 1, (int)(mouse->lLastX-initialMousePoint.x), (int)(mouse->lLastY-initialMousePoint.y) );
458 
459  initialMousePoint.x = mouse->lLastX;
460  initialMousePoint.y = mouse->lLastY;
461  }
462  WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
463  }
464  break;
465  }
466 
467  case WM_MOUSEWHEEL:
468  {
469  /* FIXME: This may need to accumulate deltas up to WHEEL_DELTA */
470  short motion = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
471 
472  SDL_SendMouseWheel(data->window, 0, 0, motion);
473  break;
474  }
475 
476 #ifdef WM_MOUSELEAVE
477  case WM_MOUSELEAVE:
478  if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode) {
479  POINT cursorPos;
480  GetCursorPos(&cursorPos);
481  ScreenToClient(hwnd, &cursorPos);
482  SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
484  }
485  returnCode = 0;
486  break;
487 #endif /* WM_MOUSELEAVE */
488 
489  case WM_KEYDOWN:
490  case WM_SYSKEYDOWN:
491  {
492  SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
493  if ( code != SDL_SCANCODE_UNKNOWN ) {
495  }
496  }
497  if (msg == WM_KEYDOWN) {
498  BYTE keyboardState[256];
499  char text[5];
500  UINT32 utf32 = 0;
501 
502  GetKeyboardState(keyboardState);
503  if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) {
504  WORD repitition;
505  for (repitition = lParam & 0xffff; repitition > 0; repitition--) {
506  WIN_ConvertUTF32toUTF8(utf32, text);
507  SDL_SendKeyboardText(text);
508  }
509  }
510  }
511  returnCode = 0;
512  break;
513 
514  case WM_SYSKEYUP:
515  case WM_KEYUP:
516  {
517  SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
518  if ( code != SDL_SCANCODE_UNKNOWN ) {
519  if (code == SDL_SCANCODE_PRINTSCREEN &&
522  }
524  }
525  }
526  returnCode = 0;
527  break;
528 
529  case WM_UNICHAR:
530  {
531  if (wParam == UNICODE_NOCHAR) {
532  returnCode = 1;
533  break;
534  }
535  }
536  /* no break */
537  case WM_CHAR:
538  {
539  char text[5];
540 
541  WIN_ConvertUTF32toUTF8(wParam, text);
542  SDL_SendKeyboardText(text);
543  }
544  returnCode = 0;
545  break;
546 
547 #ifdef WM_INPUTLANGCHANGE
548  case WM_INPUTLANGCHANGE:
549  {
551  }
552  returnCode = 1;
553  break;
554 #endif /* WM_INPUTLANGCHANGE */
555 
556 #ifdef WM_GETMINMAXINFO
557  case WM_GETMINMAXINFO:
558  {
559  MINMAXINFO *info;
560  RECT size;
561  int x, y;
562  int w, h;
563  int min_w, min_h;
564  int max_w, max_h;
565  int style;
566  BOOL menu;
567  BOOL constrain_max_size;
568 
569  /* If we allow resizing, let the resize happen naturally */
570  if (SDL_IsShapedWindow(data->window))
572 
573  /* Get the current position of our window */
574  GetWindowRect(hwnd, &size);
575  x = size.left;
576  y = size.top;
577 
578  /* Calculate current size of our window */
579  SDL_GetWindowSize(data->window, &w, &h);
580  SDL_GetWindowMinimumSize(data->window, &min_w, &min_h);
581  SDL_GetWindowMaximumSize(data->window, &max_w, &max_h);
582 
583  /* Store in min_w and min_h difference between current size and minimal
584  size so we don't need to call AdjustWindowRectEx twice */
585  min_w -= w;
586  min_h -= h;
587  if (max_w && max_h) {
588  max_w -= w;
589  max_h -= h;
590  constrain_max_size = TRUE;
591  } else {
592  constrain_max_size = FALSE;
593  }
594 
595  size.top = 0;
596  size.left = 0;
597  size.bottom = h;
598  size.right = w;
599 
600  style = GetWindowLong(hwnd, GWL_STYLE);
601  /* DJM - according to the docs for GetMenu(), the
602  return value is undefined if hwnd is a child window.
603  Aparently it's too difficult for MS to check
604  inside their function, so I have to do it here.
605  */
606  menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
607  AdjustWindowRectEx(&size, style, menu, 0);
608  w = size.right - size.left;
609  h = size.bottom - size.top;
610 
611  /* Fix our size to the current size */
612  info = (MINMAXINFO *) lParam;
614  info->ptMinTrackSize.x = w + min_w;
615  info->ptMinTrackSize.y = h + min_h;
616  if (constrain_max_size) {
617  info->ptMaxTrackSize.x = w + max_w;
618  info->ptMaxTrackSize.y = h + max_h;
619  }
620  } else {
621  info->ptMaxSize.x = w;
622  info->ptMaxSize.y = h;
623  info->ptMaxPosition.x = x;
624  info->ptMaxPosition.y = y;
625  info->ptMinTrackSize.x = w;
626  info->ptMinTrackSize.y = h;
627  info->ptMaxTrackSize.x = w;
628  info->ptMaxTrackSize.y = h;
629  }
630  }
631  returnCode = 0;
632  break;
633 #endif /* WM_GETMINMAXINFO */
634 
635  case WM_WINDOWPOSCHANGED:
636  {
637  RECT rect;
638  int x, y;
639  int w, h;
640  Uint32 window_flags;
641 
642  if (!GetClientRect(hwnd, &rect) ||
643  (rect.right == rect.left && rect.bottom == rect.top)) {
644  break;
645  }
646  ClientToScreen(hwnd, (LPPOINT) & rect);
647  ClientToScreen(hwnd, (LPPOINT) & rect + 1);
648 
649  window_flags = SDL_GetWindowFlags(data->window);
650  if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
651  (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
652  ClipCursor(&rect);
653  }
654 
655  x = rect.left;
656  y = rect.top;
658 
659  w = rect.right - rect.left;
660  h = rect.bottom - rect.top;
662  h);
663  }
664  break;
665 
666  case WM_SETCURSOR:
667  {
668  Uint16 hittest;
669 
670  hittest = LOWORD(lParam);
671  if (hittest == HTCLIENT) {
672  SetCursor(SDL_cursor);
673  returnCode = TRUE;
674  }
675  }
676  break;
677 
678  /* We were occluded, refresh our display */
679  case WM_PAINT:
680  {
681  RECT rect;
682  if (GetUpdateRect(hwnd, &rect, FALSE)) {
683  ValidateRect(hwnd, NULL);
685  0, 0);
686  }
687  }
688  returnCode = 0;
689  break;
690 
691  /* We'll do our own drawing, prevent flicker */
692  case WM_ERASEBKGND:
693  {
694  }
695  return (1);
696 
697 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
698  case WM_SYSCOMMAND:
699  {
700  /* Don't start the screensaver or blank the monitor in fullscreen apps */
701  if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
702  (wParam & 0xFFF0) == SC_MONITORPOWER) {
703  if (SDL_GetVideoDevice()->suspend_screensaver) {
704  return (0);
705  }
706  }
707  }
708  break;
709 #endif /* System has screensaver support */
710 
711  case WM_CLOSE:
712  {
714  }
715  returnCode = 0;
716  break;
717 
718  case WM_TOUCH:
719  {
720  UINT i, num_inputs = LOWORD(wParam);
721  PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
722  if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
723  RECT rect;
724  float x, y;
725 
726  if (!GetClientRect(hwnd, &rect) ||
727  (rect.right == rect.left && rect.bottom == rect.top)) {
728  if (inputs) {
729  SDL_stack_free(inputs);
730  }
731  break;
732  }
733  ClientToScreen(hwnd, (LPPOINT) & rect);
734  ClientToScreen(hwnd, (LPPOINT) & rect + 1);
735  rect.top *= 100;
736  rect.left *= 100;
737  rect.bottom *= 100;
738  rect.right *= 100;
739 
740  for (i = 0; i < num_inputs; ++i) {
741  PTOUCHINPUT input = &inputs[i];
742 
743  const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
744  if (!SDL_GetTouch(touchId)) {
745  if (SDL_AddTouch(touchId, "") < 0) {
746  continue;
747  }
748  }
749 
750  /* Get the normalized coordinates for the window */
751  x = (float)(input->x - rect.left)/(rect.right - rect.left);
752  y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
753 
754  if (input->dwFlags & TOUCHEVENTF_DOWN) {
755  SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
756  }
757  if (input->dwFlags & TOUCHEVENTF_MOVE) {
758  SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
759  }
760  if (input->dwFlags & TOUCHEVENTF_UP) {
761  SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
762  }
763  }
764  }
765  SDL_stack_free(inputs);
766 
767  data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
768  return 0;
769  }
770  break;
771 
772  case WM_DROPFILES:
773  {
774  UINT i;
775  HDROP drop = (HDROP) wParam;
776  UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
777  for (i = 0; i < count; ++i) {
778  UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
779  LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
780  if (buffer) {
781  if (DragQueryFile(drop, i, buffer, size)) {
782  char *file = WIN_StringToUTF8(buffer);
783  SDL_SendDropFile(file);
784  SDL_free(file);
785  }
786  SDL_stack_free(buffer);
787  }
788  }
789  DragFinish(drop);
790  return 0;
791  }
792  break;
793  }
794 
795  /* If there's a window proc, assume it's going to handle messages */
796  if (data->wndproc) {
797  return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
798  } else if (returnCode >= 0) {
799  return returnCode;
800  } else {
801  return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
802  }
803 }
804 
805 void
807 {
808  const Uint8 *keystate;
809  MSG msg;
810  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
811  DispatchMessage(&msg);
812  }
813 
814  /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one.
815  You won't get a KEYUP until both are released, and that keyup will only be for the second
816  key you released. Take heroic measures and check the keystate as of the last handled event,
817  and if we think a key is pressed when Windows doesn't, unstick it in SDL's state. */
818  keystate = SDL_GetKeyboardState(NULL);
819  if ((keystate[SDL_SCANCODE_LSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
821  }
822  if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
824  }
825 }
826 
827 static int app_registered = 0;
828 LPTSTR SDL_Appname = NULL;
829 Uint32 SDL_Appstyle = 0;
830 HINSTANCE SDL_Instance = NULL;
831 
832 /* Register the class for this application */
833 int
834 SDL_RegisterApp(char *name, Uint32 style, void *hInst)
835 {
836  WNDCLASS class;
837 
838  /* Only do this once... */
839  if (app_registered) {
840  ++app_registered;
841  return (0);
842  }
843  if (!name && !SDL_Appname) {
844  name = "SDL_app";
845 #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
846  SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
847 #endif
848  SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
849  }
850 
851  if (name) {
852  SDL_Appname = WIN_UTF8ToString(name);
853  SDL_Appstyle = style;
854  SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
855  }
856 
857  /* Register the application class */
858  class.hCursor = NULL;
859  class.hIcon =
860  LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
861  LR_DEFAULTCOLOR);
862  class.lpszMenuName = NULL;
863  class.lpszClassName = SDL_Appname;
864  class.hbrBackground = NULL;
865  class.hInstance = SDL_Instance;
866  class.style = SDL_Appstyle;
867  class.lpfnWndProc = WIN_WindowProc;
868  class.cbWndExtra = 0;
869  class.cbClsExtra = 0;
870  if (!RegisterClass(&class)) {
871  return SDL_SetError("Couldn't register application class");
872  }
873 
874  app_registered = 1;
875  return 0;
876 }
877 
878 /* Unregisters the windowclass registered in SDL_RegisterApp above. */
879 void
880 SDL_UnregisterApp()
881 {
882  WNDCLASS class;
883 
884  /* SDL_RegisterApp might not have been called before */
885  if (!app_registered) {
886  return;
887  }
888  --app_registered;
889  if (app_registered == 0) {
890  /* Check for any registered window classes. */
891  if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
892  UnregisterClass(SDL_Appname, SDL_Instance);
893  }
894  SDL_free(SDL_Appname);
895  SDL_Appname = NULL;
896  }
897 }
898 
899 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
900 
901 /* vi: set ts=4 sw=4 expandtab: */
SDL_version version
Definition: SDL_syswm.h:114
HINSTANCE SDL_Instance
DECLSPEC void SDLCALL SDL_GetWindowMaximumSize(SDL_Window *window, int *w, int *h)
Get the maximum size of a window&#39;s client area.
Definition: SDL_video.c:1710
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:42
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:62
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:611
int Win32_ResizeWindowShape(SDL_Window *window)
DECLSPEC void SDLCALL SDL_GetWindowMinimumSize(SDL_Window *window, int *w, int *h)
Get the minimum size of a window&#39;s client area.
Definition: SDL_video.c:1674
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
#define SDL_BUTTON_RMASK
Definition: SDL_mouse.h:211
#define NULL
Definition: ftobjs.h:61
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:227
SDL_bool
Definition: SDL_stdinc.h:116
#define SDL_BUTTON_X2MASK
Definition: SDL_mouse.h:213
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
DECLSPEC SDL_Window *SDLCALL SDL_GetMouseFocus(void)
Get the window which currently has mouse focus.
Definition: SDL_mouse.c:68
#define SDL_BUTTON_RIGHT
Definition: SDL_mouse.h:206
EGLSurface EGLint x
Definition: eglext.h:293
The structure that defines a point.
Definition: SDL_rect.h:47
DECLSPEC void SDLCALL SDL_free(void *mem)
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:213
#define SDL_ENABLE
Definition: SDL_events.h:688
FILE * file
Definition: visualinfo.c:88
LPTSTR SDL_Appname
DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys)
Get a snapshot of the current state of the keyboard.
Definition: SDL_keyboard.c:832
EGLImageKHR EGLint * name
Definition: eglext.h:284
DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h)
Get the size of a window&#39;s client area.
Definition: SDL_video.c:1638
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
SDL_Window * window
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:207
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:93
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
#define SDL_FORCE_INLINE
Definition: begin_code.h:141
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:624
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:650
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:275
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
int x
Definition: SDL_rect.h:49
DECLSPEC Uint32 SDLCALL SDL_GetMouseState(int *x, int *y)
Retrieve the current state of the mouse.
Definition: SDL_mouse.c:382
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
DECLSPEC SDL_bool SDLCALL SDL_IsShapedWindow(const SDL_Window *window)
Return whether the given window is a shaped window.
Definition: SDL_shape.c:57
#define SDL_GetEventState(type)
Definition: SDL_events.h:701
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:178
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:204
int y
Definition: SDL_rect.h:50
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define _THIS
struct SDL_VideoData * videodata
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:784
GLint GLsizei count
Definition: gl2ext.h:1011
SDL_bool relative_mode
Definition: SDL_mouse_c.h:68
#define SDL_BUTTON_X1MASK
Definition: SDL_mouse.h:212
union SDL_SysWMmsg::@77 msg
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:41
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
#define SDL_BUTTON_LMASK
Definition: SDL_mouse.h:209
#define SDL_BUTTON_MIDDLE
Definition: SDL_mouse.h:205
DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window *window)
Get the window flags.
Definition: SDL_video.c:1409
int SDL_AddTouch(SDL_TouchID touchID, const char *name)
Definition: SDL_touch.c:130
#define FALSE
Definition: ftobjs.h:57
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:115
Definition: inftrees.h:24
EGLSurface EGLint EGLint y
Definition: eglext.h:293
void WIN_UpdateKeymap(void)
GLenum GLenum GLenum input
Definition: glew.h:12631
void WIN_PumpEvents(_THIS)
static const SDL_Scancode windows_scancode_table[]
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
int SDL_SendDropFile(const char *file)
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, int x, int y)
Definition: SDL_mouse.c:332
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:548
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:226
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:137
#define VK_OEM_102
Definition: SDL_vkeys.h:74
DECLSPEC SDL_Window *SDLCALL SDL_GetKeyboardFocus(void)
Get the window which currently has keyboard focus.
Definition: SDL_keyboard.c:603
char * wmtab[]
Definition: wmmsg.h:4
#define SDL_PRESSED
Definition: SDL_events.h:50
int i
Definition: pngrutil.c:1377
void WIN_CheckClipboardUpdate(struct SDL_VideoData *data)
#define SDL_BUTTON_X2
Definition: SDL_mouse.h:208
HCURSOR SDL_cursor
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_BUTTON_MMASK
Definition: SDL_mouse.h:210
#define MAX_WMMSG
Definition: wmmsg.h:2
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:73
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:276
SDL_Scancode
The SDL keyboard scancode representation.
Definition: SDL_scancode.h:43
#define TRUE
Definition: ftobjs.h:53
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata)
Uint32 SDL_Appstyle
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC
GLsizei size
Definition: gl2ext.h:1467