SDL  2.0
SDL_windowsevents.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_WINDOWS
24 
25 #include "SDL_windowsvideo.h"
26 #include "SDL_windowsshape.h"
27 #include "SDL_system.h"
28 #include "SDL_syswm.h"
29 #include "SDL_timer.h"
30 #include "SDL_vkeys.h"
31 #include "SDL_hints.h"
32 #include "../../events/SDL_events_c.h"
33 #include "../../events/SDL_touch_c.h"
34 #include "../../events/scancodes_windows.h"
35 #include "SDL_hints.h"
36 
37 /* Dropfile support */
38 #include <shellapi.h>
39 
40 /* For GET_X_LPARAM, GET_Y_LPARAM. */
41 #include <windowsx.h>
42 
43 /* #define WMMSG_DEBUG */
44 #ifdef WMMSG_DEBUG
45 #include <stdio.h>
46 #include "wmmsg.h"
47 #endif
48 
49 /* Masks for processing the windows KEYDOWN and KEYUP messages */
50 #define REPEATED_KEYMASK (1<<30)
51 #define EXTENDED_KEYMASK (1<<24)
52 
53 #define VK_ENTER 10 /* Keypad Enter ... no VKEY defined? */
54 #ifndef VK_OEM_NEC_EQUAL
55 #define VK_OEM_NEC_EQUAL 0x92
56 #endif
57 
58 /* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
59 #ifndef WM_XBUTTONDOWN
60 #define WM_XBUTTONDOWN 0x020B
61 #endif
62 #ifndef WM_XBUTTONUP
63 #define WM_XBUTTONUP 0x020C
64 #endif
65 #ifndef GET_XBUTTON_WPARAM
66 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
67 #endif
68 #ifndef WM_INPUT
69 #define WM_INPUT 0x00ff
70 #endif
71 #ifndef WM_TOUCH
72 #define WM_TOUCH 0x0240
73 #endif
74 #ifndef WM_MOUSEHWHEEL
75 #define WM_MOUSEHWHEEL 0x020E
76 #endif
77 #ifndef WM_POINTERUPDATE
78 #define WM_POINTERUPDATE 0x0245
79 #endif
80 #ifndef WM_UNICHAR
81 #define WM_UNICHAR 0x0109
82 #endif
83 
84 static SDL_Scancode
85 VKeytoScancodeFallback(WPARAM vkey)
86 {
87  switch (vkey) {
88  case VK_LEFT: return SDL_SCANCODE_LEFT;
89  case VK_UP: return SDL_SCANCODE_UP;
90  case VK_RIGHT: return SDL_SCANCODE_RIGHT;
91  case VK_DOWN: return SDL_SCANCODE_DOWN;
92 
93  default: return SDL_SCANCODE_UNKNOWN;
94  }
95 }
96 
97 static SDL_Scancode
98 VKeytoScancode(WPARAM vkey)
99 {
100  switch (vkey) {
101  case VK_MODECHANGE: return SDL_SCANCODE_MODE;
102  case VK_SELECT: return SDL_SCANCODE_SELECT;
103  case VK_EXECUTE: return SDL_SCANCODE_EXECUTE;
104  case VK_HELP: return SDL_SCANCODE_HELP;
105  case VK_PAUSE: return SDL_SCANCODE_PAUSE;
106  case VK_NUMLOCK: return SDL_SCANCODE_NUMLOCKCLEAR;
107 
108  case VK_F13: return SDL_SCANCODE_F13;
109  case VK_F14: return SDL_SCANCODE_F14;
110  case VK_F15: return SDL_SCANCODE_F15;
111  case VK_F16: return SDL_SCANCODE_F16;
112  case VK_F17: return SDL_SCANCODE_F17;
113  case VK_F18: return SDL_SCANCODE_F18;
114  case VK_F19: return SDL_SCANCODE_F19;
115  case VK_F20: return SDL_SCANCODE_F20;
116  case VK_F21: return SDL_SCANCODE_F21;
117  case VK_F22: return SDL_SCANCODE_F22;
118  case VK_F23: return SDL_SCANCODE_F23;
119  case VK_F24: return SDL_SCANCODE_F24;
120 
121  case VK_OEM_NEC_EQUAL: return SDL_SCANCODE_KP_EQUALS;
122  case VK_BROWSER_BACK: return SDL_SCANCODE_AC_BACK;
123  case VK_BROWSER_FORWARD: return SDL_SCANCODE_AC_FORWARD;
124  case VK_BROWSER_REFRESH: return SDL_SCANCODE_AC_REFRESH;
125  case VK_BROWSER_STOP: return SDL_SCANCODE_AC_STOP;
126  case VK_BROWSER_SEARCH: return SDL_SCANCODE_AC_SEARCH;
127  case VK_BROWSER_FAVORITES: return SDL_SCANCODE_AC_BOOKMARKS;
128  case VK_BROWSER_HOME: return SDL_SCANCODE_AC_HOME;
129  case VK_VOLUME_MUTE: return SDL_SCANCODE_AUDIOMUTE;
130  case VK_VOLUME_DOWN: return SDL_SCANCODE_VOLUMEDOWN;
131  case VK_VOLUME_UP: return SDL_SCANCODE_VOLUMEUP;
132 
133  case VK_MEDIA_NEXT_TRACK: return SDL_SCANCODE_AUDIONEXT;
134  case VK_MEDIA_PREV_TRACK: return SDL_SCANCODE_AUDIOPREV;
135  case VK_MEDIA_STOP: return SDL_SCANCODE_AUDIOSTOP;
136  case VK_MEDIA_PLAY_PAUSE: return SDL_SCANCODE_AUDIOPLAY;
137  case VK_LAUNCH_MAIL: return SDL_SCANCODE_MAIL;
138  case VK_LAUNCH_MEDIA_SELECT: return SDL_SCANCODE_MEDIASELECT;
139 
141 
142  case VK_ATTN: return SDL_SCANCODE_SYSREQ;
143  case VK_CRSEL: return SDL_SCANCODE_CRSEL;
144  case VK_EXSEL: return SDL_SCANCODE_EXSEL;
145  case VK_OEM_CLEAR: return SDL_SCANCODE_CLEAR;
146 
147  case VK_LAUNCH_APP1: return SDL_SCANCODE_APP1;
148  case VK_LAUNCH_APP2: return SDL_SCANCODE_APP2;
149 
150  default: return SDL_SCANCODE_UNKNOWN;
151  }
152 }
153 
154 static SDL_Scancode
155 WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
156 {
157  SDL_Scancode code;
158  int nScanCode = (lParam >> 16) & 0xFF;
159  SDL_bool bIsExtended = (lParam & (1 << 24)) != 0;
160 
161  code = VKeytoScancode(wParam);
162 
163  if (code == SDL_SCANCODE_UNKNOWN && nScanCode <= 127) {
164  code = windows_scancode_table[nScanCode];
165 
166  if (bIsExtended) {
167  switch (code) {
168  case SDL_SCANCODE_RETURN:
169  code = SDL_SCANCODE_KP_ENTER;
170  break;
171  case SDL_SCANCODE_LALT:
172  code = SDL_SCANCODE_RALT;
173  break;
174  case SDL_SCANCODE_LCTRL:
175  code = SDL_SCANCODE_RCTRL;
176  break;
177  case SDL_SCANCODE_SLASH:
178  code = SDL_SCANCODE_KP_DIVIDE;
179  break;
181  code = SDL_SCANCODE_KP_PLUS;
182  break;
183  default:
184  break;
185  }
186  } else {
187  switch (code) {
188  case SDL_SCANCODE_HOME:
189  code = SDL_SCANCODE_KP_7;
190  break;
191  case SDL_SCANCODE_UP:
192  code = SDL_SCANCODE_KP_8;
193  break;
194  case SDL_SCANCODE_PAGEUP:
195  code = SDL_SCANCODE_KP_9;
196  break;
197  case SDL_SCANCODE_LEFT:
198  code = SDL_SCANCODE_KP_4;
199  break;
200  case SDL_SCANCODE_RIGHT:
201  code = SDL_SCANCODE_KP_6;
202  break;
203  case SDL_SCANCODE_END:
204  code = SDL_SCANCODE_KP_1;
205  break;
206  case SDL_SCANCODE_DOWN:
207  code = SDL_SCANCODE_KP_2;
208  break;
210  code = SDL_SCANCODE_KP_3;
211  break;
212  case SDL_SCANCODE_INSERT:
213  code = SDL_SCANCODE_KP_0;
214  break;
215  case SDL_SCANCODE_DELETE:
216  code = SDL_SCANCODE_KP_PERIOD;
217  break;
220  break;
221  default:
222  break;
223  }
224  }
225  }
226 
227  /* The on-screen keyboard can generate VK_LEFT and VK_RIGHT events without a scancode
228  * value set, however we cannot simply map these in VKeytoScancode() or we will be
229  * incorrectly handling the arrow keys on the number pad when NumLock is disabled
230  * (which also generate VK_LEFT, VK_RIGHT, etc in that scenario). Instead, we'll only
231  * map them if none of the above special number pad mappings applied. */
232  if (code == SDL_SCANCODE_UNKNOWN) {
233  code = VKeytoScancodeFallback(wParam);
234  }
235 
236  return code;
237 }
238 
239 static SDL_bool
240 WIN_ShouldIgnoreFocusClick()
241 {
243 }
244 
245 static void
246 WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, Uint32 mouseFlags, SDL_bool bSwapButtons, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID)
247 {
248  if (bSwapButtons) {
249  if (button == SDL_BUTTON_LEFT) {
251  }
252  else if (button == SDL_BUTTON_RIGHT) {
254  }
255  }
256 
257  if (data->focus_click_pending & SDL_BUTTON(button)) {
258  /* Ignore the button click for activation */
259  if (!bwParamMousePressed) {
260  data->focus_click_pending &= ~SDL_BUTTON(button);
261  WIN_UpdateClipCursor(data->window);
262  }
263  if (WIN_ShouldIgnoreFocusClick()) {
264  return;
265  }
266  }
267 
268  if (bwParamMousePressed && !(mouseFlags & SDL_BUTTON(button))) {
269  SDL_SendMouseButton(data->window, mouseID, SDL_PRESSED, button);
270  } else if (!bwParamMousePressed && (mouseFlags & SDL_BUTTON(button))) {
271  SDL_SendMouseButton(data->window, mouseID, SDL_RELEASED, button);
272  }
273 }
274 
275 /*
276 * Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
277 * so this function reconciles our view of the world with the current buttons reported by windows
278 */
279 static void
280 WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID)
281 {
282  if (wParam != data->mouse_button_flags) {
283  Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
284 
285  /* WM_LBUTTONDOWN and friends handle button swapping for us. No need to check SM_SWAPBUTTON here. */
286  WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_LEFT, mouseID);
287  WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_MIDDLE, mouseID);
288  WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), mouseFlags, SDL_FALSE, data, SDL_BUTTON_RIGHT, mouseID);
289  WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X1, mouseID);
290  WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), mouseFlags, SDL_FALSE, data, SDL_BUTTON_X2, mouseID);
291 
292  data->mouse_button_flags = wParam;
293  }
294 }
295 
296 static void
297 WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data)
298 {
299  if (rawButtons != data->mouse_button_flags) {
300  Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
301  SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
302  if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
303  WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0);
304  if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
305  WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0);
306  if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
307  WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0);
308  if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
309  WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0);
310  if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
311  WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0);
312  if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
313  WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0);
314  if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
315  WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0);
316  if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
317  WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0);
318  if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
319  WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0);
320  if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
321  WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0);
322  data->mouse_button_flags = rawButtons;
323  }
324 }
325 
326 static void
327 WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
328 {
329  Uint32 mouseFlags;
330  SHORT keyState;
331  SDL_bool swapButtons;
332 
333  /* mouse buttons may have changed state here, we need to resync them,
334  but we will get a WM_MOUSEMOVE right away which will fix things up if in non raw mode also
335  */
336  mouseFlags = SDL_GetMouseState(NULL, NULL);
337  swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
338 
339  keyState = GetAsyncKeyState(VK_LBUTTON);
340  if (!(keyState & 0x8000)) {
341  WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0);
342  }
343  keyState = GetAsyncKeyState(VK_RBUTTON);
344  if (!(keyState & 0x8000)) {
345  WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0);
346  }
347  keyState = GetAsyncKeyState(VK_MBUTTON);
348  if (!(keyState & 0x8000)) {
349  WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0);
350  }
351  keyState = GetAsyncKeyState(VK_XBUTTON1);
352  if (!(keyState & 0x8000)) {
353  WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0);
354  }
355  keyState = GetAsyncKeyState(VK_XBUTTON2);
356  if (!(keyState & 0x8000)) {
357  WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0);
358  }
359  data->mouse_button_flags = 0;
360 }
361 
362 static BOOL
363 WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
364 {
365  if (codepoint <= 0x7F) {
366  text[0] = (char) codepoint;
367  text[1] = '\0';
368  } else if (codepoint <= 0x7FF) {
369  text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
370  text[1] = 0x80 | (char) (codepoint & 0x3F);
371  text[2] = '\0';
372  } else if (codepoint <= 0xFFFF) {
373  text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
374  text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
375  text[2] = 0x80 | (char) (codepoint & 0x3F);
376  text[3] = '\0';
377  } else if (codepoint <= 0x10FFFF) {
378  text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
379  text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
380  text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
381  text[3] = 0x80 | (char) (codepoint & 0x3F);
382  text[4] = '\0';
383  } else {
384  return SDL_FALSE;
385  }
386  return SDL_TRUE;
387 }
388 
389 static SDL_bool
390 ShouldGenerateWindowCloseOnAltF4(void)
391 {
393 }
394 
395 /* Win10 "Fall Creators Update" introduced the bug that SetCursorPos() (as used by SDL_WarpMouseInWindow())
396  doesn't reliably generate WM_MOUSEMOVE events anymore (see #3931) which breaks relative mouse mode via warping.
397  This is used to implement a workaround.. */
398 static SDL_bool isWin10FCUorNewer = SDL_FALSE;
399 
400 /* We want to generate mouse events from mouse and pen, and touch events from touchscreens */
401 #define MI_WP_SIGNATURE 0xFF515700
402 #define MI_WP_SIGNATURE_MASK 0xFFFFFF00
403 #define IsTouchEvent(dw) ((dw) & MI_WP_SIGNATURE_MASK) == MI_WP_SIGNATURE
404 
405 typedef enum
406 {
407  SDL_MOUSE_EVENT_SOURCE_UNKNOWN,
408  SDL_MOUSE_EVENT_SOURCE_MOUSE,
409  SDL_MOUSE_EVENT_SOURCE_TOUCH,
410  SDL_MOUSE_EVENT_SOURCE_PEN,
411 } SDL_MOUSE_EVENT_SOURCE;
412 
413 static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource()
414 {
415  LPARAM extrainfo = GetMessageExtraInfo();
416  /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */
417  /* Versions below Vista will set the low 7 bits to the Mouse ID and don't use bit 7:
418  Check bits 8-32 for the signature (which will indicate a Tablet PC Pen or Touch Device).
419  Only check bit 7 when Vista and up(Cleared=Pen, Set=Touch(which we need to filter out)),
420  when the signature is set. The Mouse ID will be zero for an actual mouse. */
421  if (IsTouchEvent(extrainfo)) {
422  if (extrainfo & 0x80) {
423  return SDL_MOUSE_EVENT_SOURCE_TOUCH;
424  } else {
425  return SDL_MOUSE_EVENT_SOURCE_PEN;
426  }
427  }
428  return SDL_MOUSE_EVENT_SOURCE_MOUSE;
429 }
430 
431 LRESULT CALLBACK
432 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
433 {
435  LRESULT returnCode = -1;
436 
437  /* Send a SDL_SYSWMEVENT if the application wants them */
439  SDL_SysWMmsg wmmsg;
440 
441  SDL_VERSION(&wmmsg.version);
443  wmmsg.msg.win.hwnd = hwnd;
444  wmmsg.msg.win.msg = msg;
445  wmmsg.msg.win.wParam = wParam;
446  wmmsg.msg.win.lParam = lParam;
447  SDL_SendSysWMEvent(&wmmsg);
448  }
449 
450  /* Get the window data for the window */
451  data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
452  if (!data) {
453  return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
454  }
455 
456 #ifdef WMMSG_DEBUG
457  {
458  char message[1024];
459  if (msg > MAX_WMMSG) {
460  SDL_snprintf(message, sizeof(message), "Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
461  } else {
462  SDL_snprintf(message, sizeof(message), "Received windows message: %p %s -- 0x%X, 0x%X\n", hwnd, wmtab[msg], wParam, lParam);
463  }
464  OutputDebugStringA(message);
465  }
466 #endif /* WMMSG_DEBUG */
467 
468  if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
469  return 0;
470 
471  switch (msg) {
472 
473  case WM_SHOWWINDOW:
474  {
475  if (wParam) {
477  } else {
479  }
480  }
481  break;
482 
483  case WM_NCACTIVATE:
484  {
485  /* Don't immediately clip the cursor in case we're clicking minimize/maximize buttons */
486  data->skip_update_clipcursor = SDL_TRUE;
487  }
488  break;
489 
490  case WM_ACTIVATE:
491  {
492  POINT cursorPos;
493  BOOL minimized;
494 
495  minimized = HIWORD(wParam);
496  if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
497  /* Don't mark the window as shown if it's activated before being shown */
498  if (!IsWindowVisible(hwnd)) {
499  break;
500  }
501  if (LOWORD(wParam) == WA_CLICKACTIVE) {
502  SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
503  if (GetAsyncKeyState(VK_LBUTTON)) {
504  data->focus_click_pending |= !swapButtons ? SDL_BUTTON_LMASK : SDL_BUTTON_RMASK;
505  }
506  if (GetAsyncKeyState(VK_RBUTTON)) {
507  data->focus_click_pending |= !swapButtons ? SDL_BUTTON_RMASK : SDL_BUTTON_LMASK;
508  }
509  if (GetAsyncKeyState(VK_MBUTTON)) {
510  data->focus_click_pending |= SDL_BUTTON_MMASK;
511  }
512  if (GetAsyncKeyState(VK_XBUTTON1)) {
513  data->focus_click_pending |= SDL_BUTTON_X1MASK;
514  }
515  if (GetAsyncKeyState(VK_XBUTTON2)) {
516  data->focus_click_pending |= SDL_BUTTON_X2MASK;
517  }
518  }
519 
521  if (SDL_GetKeyboardFocus() != data->window) {
522  SDL_SetKeyboardFocus(data->window);
523  }
524 
525  GetCursorPos(&cursorPos);
526  ScreenToClient(hwnd, &cursorPos);
527  SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
528 
529  WIN_CheckAsyncMouseRelease(data);
530  WIN_UpdateClipCursor(data->window);
531 
532  /*
533  * FIXME: Update keyboard state
534  */
535  WIN_CheckClipboardUpdate(data->videodata);
536 
537  SDL_ToggleModState(KMOD_CAPS, (GetKeyState(VK_CAPITAL) & 0x0001) != 0);
538  SDL_ToggleModState(KMOD_NUM, (GetKeyState(VK_NUMLOCK) & 0x0001) != 0);
539  } else {
540  RECT rect;
541 
542  data->in_window_deactivation = SDL_TRUE;
543 
544  if (SDL_GetKeyboardFocus() == data->window) {
547  }
548 
549  if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
550  ClipCursor(NULL);
551  SDL_zero(data->cursor_clipped_rect);
552  }
553 
554  data->in_window_deactivation = SDL_FALSE;
555  }
556  }
557  returnCode = 0;
558  break;
559 
560  case WM_POINTERUPDATE:
561  {
562  data->last_pointer_update = lParam;
563  break;
564  }
565 
566  case WM_MOUSEMOVE:
567  {
568  SDL_Mouse *mouse = SDL_GetMouse();
569  if (!mouse->relative_mode || mouse->relative_mode_warp) {
570  /* Only generate mouse events for real mouse */
571  if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
572  lParam != data->last_pointer_update) {
573  SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
574  if (isWin10FCUorNewer && mouse->relative_mode_warp) {
575  /* To work around #3931, Win10 bug introduced in Fall Creators Update, where
576  SetCursorPos() (SDL_WarpMouseInWindow()) doesn't reliably generate mouse events anymore,
577  after each windows mouse event generate a fake event for the middle of the window
578  if relative_mode_warp is used */
579  int center_x = 0, center_y = 0;
580  SDL_GetWindowSize(data->window, &center_x, &center_y);
581  center_x /= 2;
582  center_y /= 2;
583  SDL_SendMouseMotion(data->window, 0, 0, center_x, center_y);
584  }
585  }
586  } else {
587  /* We still need to update focus */
588  SDL_SetMouseFocus(data->window);
589  }
590  }
591  /* don't break here, fall through to check the wParam like the button presses */
592  case WM_LBUTTONUP:
593  case WM_RBUTTONUP:
594  case WM_MBUTTONUP:
595  case WM_XBUTTONUP:
596  case WM_LBUTTONDOWN:
597  case WM_LBUTTONDBLCLK:
598  case WM_RBUTTONDOWN:
599  case WM_RBUTTONDBLCLK:
600  case WM_MBUTTONDOWN:
601  case WM_MBUTTONDBLCLK:
602  case WM_XBUTTONDOWN:
603  case WM_XBUTTONDBLCLK:
604  {
605  SDL_Mouse *mouse = SDL_GetMouse();
606  if (!mouse->relative_mode || mouse->relative_mode_warp) {
607  if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
608  lParam != data->last_pointer_update) {
609  WIN_CheckWParamMouseButtons(wParam, data, 0);
610  }
611  }
612  }
613  break;
614 
615  case WM_INPUT:
616  {
617  SDL_Mouse *mouse = SDL_GetMouse();
618  HRAWINPUT hRawInput = (HRAWINPUT)lParam;
619  RAWINPUT inp;
620  UINT size = sizeof(inp);
621  const SDL_bool isRelative = mouse->relative_mode || mouse->relative_mode_warp;
622  const SDL_bool isCapture = ((data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0);
623 
624  if (!isRelative || mouse->focus != data->window) {
625  if (!isCapture) {
626  break;
627  }
628  }
629 
630  GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
631 
632  /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */
633  if (inp.header.dwType == RIM_TYPEMOUSE) {
634  if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH ||
635  (GetMessageExtraInfo() & 0x82) == 0x82) {
636  break;
637  }
638  if (isRelative) {
639  RAWMOUSE* rawmouse = &inp.data.mouse;
640 
641  if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
642  SDL_SendMouseMotion(data->window, 0, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY);
643  } else if (rawmouse->lLastX || rawmouse->lLastY) {
644  /* synthesize relative moves from the abs position */
645  static SDL_Point lastMousePoint;
646  SDL_bool virtual_desktop = (rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) ? SDL_TRUE : SDL_FALSE;
647  int w = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
648  int h = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
649  int x = (int)(((float)rawmouse->lLastX / 65535.0f) * w);
650  int y = (int)(((float)rawmouse->lLastY / 65535.0f) * h);
651 
652  if (lastMousePoint.x == 0 && lastMousePoint.y == 0) {
653  lastMousePoint.x = x;
654  lastMousePoint.y = y;
655  }
656 
657  SDL_SendMouseMotion(data->window, 0, 1, (int)(x-lastMousePoint.x), (int)(y-lastMousePoint.y));
658 
659  lastMousePoint.x = x;
660  lastMousePoint.y = y;
661  }
662  WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data);
663  } else if (isCapture) {
664  /* we check for where Windows thinks the system cursor lives in this case, so we don't really lose mouse accel, etc. */
665  POINT pt;
666  RECT hwndRect;
667  HWND currentHnd;
668 
669  GetCursorPos(&pt);
670  currentHnd = WindowFromPoint(pt);
671  ScreenToClient(hwnd, &pt);
672  GetClientRect(hwnd, &hwndRect);
673 
674  /* if in the window, WM_MOUSEMOVE, etc, will cover it. */
675  if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
676  SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
677 
678  SDL_SendMouseMotion(data->window, 0, 0, (int)pt.x, (int)pt.y);
679  SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT);
680  SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT);
681  SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
682  SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
683  SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
684  }
685  } else {
686  SDL_assert(0 && "Shouldn't happen");
687  }
688  }
689  }
690  break;
691 
692  case WM_MOUSEWHEEL:
693  case WM_MOUSEHWHEEL:
694  {
695  short amount = GET_WHEEL_DELTA_WPARAM(wParam);
696  float fAmount = (float) amount / WHEEL_DELTA;
697  if (msg == WM_MOUSEWHEEL)
698  SDL_SendMouseWheel(data->window, 0, 0.0f, fAmount, SDL_MOUSEWHEEL_NORMAL);
699  else
700  SDL_SendMouseWheel(data->window, 0, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL);
701  }
702  break;
703 
704 #ifdef WM_MOUSELEAVE
705  case WM_MOUSELEAVE:
706  if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
707  if (!IsIconic(hwnd)) {
708  SDL_Mouse *mouse;
709  POINT cursorPos;
710  GetCursorPos(&cursorPos);
711  ScreenToClient(hwnd, &cursorPos);
712  mouse = SDL_GetMouse();
713  if (!mouse->was_touch_mouse_events) { /* we're not a touch handler causing a mouse leave? */
714  SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
715  } else { /* touch handling? */
716  mouse->was_touch_mouse_events = SDL_FALSE; /* not anymore */
717  if (mouse->touch_mouse_events) { /* convert touch to mouse events */
718  SDL_SendMouseMotion(data->window, SDL_TOUCH_MOUSEID, 0, cursorPos.x, cursorPos.y);
719  } else { /* normal handling */
720  SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
721  }
722  }
723  }
725  }
726  returnCode = 0;
727  break;
728 #endif /* WM_MOUSELEAVE */
729 
730  case WM_KEYDOWN:
731  case WM_SYSKEYDOWN:
732  {
733  SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
734  const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
735 
736  /* Detect relevant keyboard shortcuts */
737  if (keyboardState[SDL_SCANCODE_LALT] == SDL_PRESSED || keyboardState[SDL_SCANCODE_RALT] == SDL_PRESSED) {
738  /* ALT+F4: Close window */
739  if (code == SDL_SCANCODE_F4 && ShouldGenerateWindowCloseOnAltF4()) {
741  }
742  }
743 
744  if (code != SDL_SCANCODE_UNKNOWN) {
746  }
747  }
748 
749  returnCode = 0;
750  break;
751 
752  case WM_SYSKEYUP:
753  case WM_KEYUP:
754  {
755  SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
756  const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
757 
758  if (code != SDL_SCANCODE_UNKNOWN) {
759  if (code == SDL_SCANCODE_PRINTSCREEN &&
760  keyboardState[code] == SDL_RELEASED) {
762  }
764  }
765  }
766  returnCode = 0;
767  break;
768 
769  case WM_UNICHAR:
770  if (wParam == UNICODE_NOCHAR) {
771  returnCode = 1;
772  break;
773  }
774  /* otherwise fall through to below */
775  case WM_CHAR:
776  {
777  char text[5];
778  if (WIN_ConvertUTF32toUTF8((UINT32)wParam, text)) {
780  }
781  }
782  returnCode = 0;
783  break;
784 
785 #ifdef WM_INPUTLANGCHANGE
786  case WM_INPUTLANGCHANGE:
787  {
790  }
791  returnCode = 1;
792  break;
793 #endif /* WM_INPUTLANGCHANGE */
794 
795  case WM_NCLBUTTONDOWN:
796  {
797  data->in_title_click = SDL_TRUE;
798  }
799  break;
800 
801  case WM_CAPTURECHANGED:
802  {
803  data->in_title_click = SDL_FALSE;
804 
805  /* The mouse may have been released during a modal loop */
806  WIN_CheckAsyncMouseRelease(data);
807  }
808  break;
809 
810 #ifdef WM_GETMINMAXINFO
811  case WM_GETMINMAXINFO:
812  {
813  MINMAXINFO *info;
814  RECT size;
815  int x, y;
816  int w, h;
817  int min_w, min_h;
818  int max_w, max_h;
819  BOOL constrain_max_size;
820 
821  if (SDL_IsShapedWindow(data->window)) {
822  Win32_ResizeWindowShape(data->window);
823  }
824 
825  /* If this is an expected size change, allow it */
826  if (data->expected_resize) {
827  break;
828  }
829 
830  /* Get the current position of our window */
831  GetWindowRect(hwnd, &size);
832  x = size.left;
833  y = size.top;
834 
835  /* Calculate current size of our window */
836  SDL_GetWindowSize(data->window, &w, &h);
837  SDL_GetWindowMinimumSize(data->window, &min_w, &min_h);
838  SDL_GetWindowMaximumSize(data->window, &max_w, &max_h);
839 
840  /* Store in min_w and min_h difference between current size and minimal
841  size so we don't need to call AdjustWindowRectEx twice */
842  min_w -= w;
843  min_h -= h;
844  if (max_w && max_h) {
845  max_w -= w;
846  max_h -= h;
847  constrain_max_size = TRUE;
848  } else {
849  constrain_max_size = FALSE;
850  }
851 
852  if (!(SDL_GetWindowFlags(data->window) & SDL_WINDOW_BORDERLESS)) {
853  LONG style = GetWindowLong(hwnd, GWL_STYLE);
854  /* DJM - according to the docs for GetMenu(), the
855  return value is undefined if hwnd is a child window.
856  Apparently it's too difficult for MS to check
857  inside their function, so I have to do it here.
858  */
859  BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
860  size.top = 0;
861  size.left = 0;
862  size.bottom = h;
863  size.right = w;
864 
865  AdjustWindowRectEx(&size, style, menu, 0);
866  w = size.right - size.left;
867  h = size.bottom - size.top;
868  }
869 
870  /* Fix our size to the current size */
871  info = (MINMAXINFO *) lParam;
873  info->ptMinTrackSize.x = w + min_w;
874  info->ptMinTrackSize.y = h + min_h;
875  if (constrain_max_size) {
876  info->ptMaxTrackSize.x = w + max_w;
877  info->ptMaxTrackSize.y = h + max_h;
878  }
879  } else {
880  info->ptMaxSize.x = w;
881  info->ptMaxSize.y = h;
882  info->ptMaxPosition.x = x;
883  info->ptMaxPosition.y = y;
884  info->ptMinTrackSize.x = w;
885  info->ptMinTrackSize.y = h;
886  info->ptMaxTrackSize.x = w;
887  info->ptMaxTrackSize.y = h;
888  }
889  }
890  returnCode = 0;
891  break;
892 #endif /* WM_GETMINMAXINFO */
893 
894  case WM_WINDOWPOSCHANGING:
895 
896  if (data->expected_resize) {
897  returnCode = 0;
898  }
899  break;
900 
901  case WM_WINDOWPOSCHANGED:
902  {
903  RECT rect;
904  int x, y;
905  int w, h;
906 
907  if (data->initializing || data->in_border_change) {
908  break;
909  }
910 
911  if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
912  break;
913  }
914  ClientToScreen(hwnd, (LPPOINT) & rect);
915  ClientToScreen(hwnd, (LPPOINT) & rect + 1);
916 
917  WIN_UpdateClipCursor(data->window);
918 
919  x = rect.left;
920  y = rect.top;
922 
923  w = rect.right - rect.left;
924  h = rect.bottom - rect.top;
926 
927  /* Forces a WM_PAINT event */
928  InvalidateRect(hwnd, NULL, FALSE);
929  }
930  break;
931 
932  case WM_SIZE:
933  {
934  switch (wParam) {
935  case SIZE_MAXIMIZED:
936  SDL_SendWindowEvent(data->window,
938  SDL_SendWindowEvent(data->window,
940  break;
941  case SIZE_MINIMIZED:
942  SDL_SendWindowEvent(data->window,
944  break;
945  default:
946  SDL_SendWindowEvent(data->window,
948  break;
949  }
950  }
951  break;
952 
953  case WM_SETCURSOR:
954  {
955  Uint16 hittest;
956 
957  hittest = LOWORD(lParam);
958  if (hittest == HTCLIENT) {
959  SetCursor(SDL_cursor);
960  returnCode = TRUE;
962  SetCursor(NULL);
963  returnCode = TRUE;
964  }
965  }
966  break;
967 
968  /* We were occluded, refresh our display */
969  case WM_PAINT:
970  {
971  RECT rect;
972  if (GetUpdateRect(hwnd, &rect, FALSE)) {
973  ValidateRect(hwnd, NULL);
975  }
976  }
977  returnCode = 0;
978  break;
979 
980  /* We'll do our own drawing, prevent flicker */
981  case WM_ERASEBKGND:
982  {
983  }
984  return (1);
985 
986  case WM_SYSCOMMAND:
987  {
988  if ((wParam & 0xFFF0) == SC_KEYMENU) {
989  return (0);
990  }
991 
992 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
993  /* Don't start the screensaver or blank the monitor in fullscreen apps */
994  if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
995  (wParam & 0xFFF0) == SC_MONITORPOWER) {
996  if (SDL_GetVideoDevice()->suspend_screensaver) {
997  return (0);
998  }
999  }
1000 #endif /* System has screensaver support */
1001  }
1002  break;
1003 
1004  case WM_CLOSE:
1005  {
1007  }
1008  returnCode = 0;
1009  break;
1010 
1011  case WM_TOUCH:
1012  if (data->videodata->GetTouchInputInfo && data->videodata->CloseTouchInputHandle) {
1013  UINT i, num_inputs = LOWORD(wParam);
1014  SDL_bool isstack;
1015  PTOUCHINPUT inputs = SDL_small_alloc(TOUCHINPUT, num_inputs, &isstack);
1016  if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
1017  RECT rect;
1018  float x, y;
1019 
1020  if (!GetClientRect(hwnd, &rect) ||
1021  (rect.right == rect.left && rect.bottom == rect.top)) {
1022  if (inputs) {
1023  SDL_small_free(inputs, isstack);
1024  }
1025  break;
1026  }
1027  ClientToScreen(hwnd, (LPPOINT) & rect);
1028  ClientToScreen(hwnd, (LPPOINT) & rect + 1);
1029  rect.top *= 100;
1030  rect.left *= 100;
1031  rect.bottom *= 100;
1032  rect.right *= 100;
1033 
1034  for (i = 0; i < num_inputs; ++i) {
1035  PTOUCHINPUT input = &inputs[i];
1036 
1037  const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
1038 
1039  /* TODO: Can we use GetRawInputDeviceInfo and HID info to
1040  determine if this is a direct or indirect touch device?
1041  */
1042  if (SDL_AddTouch(touchId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
1043  continue;
1044  }
1045 
1046  /* Get the normalized coordinates for the window */
1047  x = (float)(input->x - rect.left)/(rect.right - rect.left);
1048  y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
1049 
1050  if (input->dwFlags & TOUCHEVENTF_DOWN) {
1051  SDL_SendTouch(touchId, input->dwID, data->window, SDL_TRUE, x, y, 1.0f);
1052  }
1053  if (input->dwFlags & TOUCHEVENTF_MOVE) {
1054  SDL_SendTouchMotion(touchId, input->dwID, data->window, x, y, 1.0f);
1055  }
1056  if (input->dwFlags & TOUCHEVENTF_UP) {
1057  SDL_SendTouch(touchId, input->dwID, data->window, SDL_FALSE, x, y, 1.0f);
1058  }
1059  }
1060  }
1061  SDL_small_free(inputs, isstack);
1062 
1063  data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
1064  return 0;
1065  }
1066  break;
1067 
1068  case WM_DROPFILES:
1069  {
1070  UINT i;
1071  HDROP drop = (HDROP) wParam;
1072  UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
1073  for (i = 0; i < count; ++i) {
1074  SDL_bool isstack;
1075  UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
1076  LPTSTR buffer = SDL_small_alloc(TCHAR, size, &isstack);
1077  if (buffer) {
1078  if (DragQueryFile(drop, i, buffer, size)) {
1079  char *file = WIN_StringToUTF8(buffer);
1080  SDL_SendDropFile(data->window, file);
1081  SDL_free(file);
1082  }
1083  SDL_small_free(buffer, isstack);
1084  }
1085  }
1086  SDL_SendDropComplete(data->window);
1087  DragFinish(drop);
1088  return 0;
1089  }
1090  break;
1091 
1092  case WM_DISPLAYCHANGE:
1093  {
1094  // Reacquire displays if any were added or removed
1096  }
1097  break;
1098 
1099  case WM_NCCALCSIZE:
1100  {
1101  Uint32 window_flags = SDL_GetWindowFlags(data->window);
1102  if (wParam == TRUE && (window_flags & SDL_WINDOW_BORDERLESS) && !(window_flags & SDL_WINDOW_FULLSCREEN)) {
1103  /* When borderless, need to tell windows that the size of the non-client area is 0 */
1104  if (!(window_flags & SDL_WINDOW_RESIZABLE)) {
1105  int w, h;
1106  NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS *)lParam;
1107  w = data->window->windowed.w;
1108  h = data->window->windowed.h;
1109  params->rgrc[0].right = params->rgrc[0].left + w;
1110  params->rgrc[0].bottom = params->rgrc[0].top + h;
1111  }
1112  return 0;
1113  }
1114  }
1115  break;
1116 
1117  case WM_NCHITTEST:
1118  {
1119  SDL_Window *window = data->window;
1120  if (window->hit_test) {
1121  POINT winpoint = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1122  if (ScreenToClient(hwnd, &winpoint)) {
1123  const SDL_Point point = { (int) winpoint.x, (int) winpoint.y };
1124  const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
1125  switch (rc) {
1126  #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
1127  case SDL_HITTEST_DRAGGABLE: POST_HIT_TEST(HTCAPTION);
1128  case SDL_HITTEST_RESIZE_TOPLEFT: POST_HIT_TEST(HTTOPLEFT);
1129  case SDL_HITTEST_RESIZE_TOP: POST_HIT_TEST(HTTOP);
1130  case SDL_HITTEST_RESIZE_TOPRIGHT: POST_HIT_TEST(HTTOPRIGHT);
1131  case SDL_HITTEST_RESIZE_RIGHT: POST_HIT_TEST(HTRIGHT);
1132  case SDL_HITTEST_RESIZE_BOTTOMRIGHT: POST_HIT_TEST(HTBOTTOMRIGHT);
1133  case SDL_HITTEST_RESIZE_BOTTOM: POST_HIT_TEST(HTBOTTOM);
1134  case SDL_HITTEST_RESIZE_BOTTOMLEFT: POST_HIT_TEST(HTBOTTOMLEFT);
1135  case SDL_HITTEST_RESIZE_LEFT: POST_HIT_TEST(HTLEFT);
1136  #undef POST_HIT_TEST
1137  case SDL_HITTEST_NORMAL: return HTCLIENT;
1138  }
1139  }
1140  /* If we didn't return, this will call DefWindowProc below. */
1141  }
1142  }
1143  break;
1144  }
1145 
1146  /* If there's a window proc, assume it's going to handle messages */
1147  if (data->wndproc) {
1148  return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
1149  } else if (returnCode >= 0) {
1150  return returnCode;
1151  } else {
1152  return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
1153  }
1154 }
1155 
1156 static void WIN_UpdateClipCursorForWindows()
1157 {
1159  SDL_Window *window;
1160  Uint32 now = SDL_GetTicks();
1161  const Uint32 CLIPCURSOR_UPDATE_INTERVAL_MS = 3000;
1162 
1163  if (_this) {
1164  for (window = _this->windows; window; window = window->next) {
1165  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
1166  if (data) {
1167  if (data->skip_update_clipcursor) {
1168  data->skip_update_clipcursor = SDL_FALSE;
1170  } else if ((now - data->last_updated_clipcursor) >= CLIPCURSOR_UPDATE_INTERVAL_MS) {
1172  }
1173  }
1174  }
1175  }
1176 }
1177 
1178 /* A message hook called before TranslateMessage() */
1179 static SDL_WindowsMessageHook g_WindowsMessageHook = NULL;
1180 static void *g_WindowsMessageHookData = NULL;
1181 
1183 {
1184  g_WindowsMessageHook = callback;
1185  g_WindowsMessageHookData = userdata;
1186 }
1187 
1188 void
1190 {
1191  const Uint8 *keystate;
1192  MSG msg;
1193  DWORD start_ticks = GetTickCount();
1194  int new_messages = 0;
1195 
1197  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1198  if (g_WindowsMessageHook) {
1199  g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
1200  }
1201 
1202  /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */
1203  TranslateMessage(&msg);
1204  DispatchMessage(&msg);
1205 
1206  /* Make sure we don't busy loop here forever if there are lots of events coming in */
1207  if (SDL_TICKS_PASSED(msg.time, start_ticks)) {
1208  /* We might get a few new messages generated by the Steam overlay or other application hooks
1209  In this case those messages will be processed before any pending input, so we want to continue after those messages.
1210  (thanks to Peter Deayton for his investigation here)
1211  */
1212  const int MAX_NEW_MESSAGES = 3;
1213  ++new_messages;
1214  if (new_messages > MAX_NEW_MESSAGES) {
1215  break;
1216  }
1217  }
1218  }
1219  }
1220 
1221  /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one.
1222  You won't get a KEYUP until both are released, and that keyup will only be for the second
1223  key you released. Take heroic measures and check the keystate as of the last handled event,
1224  and if we think a key is pressed when Windows doesn't, unstick it in SDL's state. */
1225  keystate = SDL_GetKeyboardState(NULL);
1226  if ((keystate[SDL_SCANCODE_LSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
1228  }
1229  if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
1231  }
1232 
1233  /* Update the clipping rect in case someone else has stolen it */
1234  WIN_UpdateClipCursorForWindows();
1235 }
1236 
1237 /* to work around #3931, a bug introduced in Win10 Fall Creators Update (build nr. 16299)
1238  we need to detect the windows version. this struct and the function below does that.
1239  usually this struct and the corresponding function (RtlGetVersion) are in <Ntddk.h>
1240  but here we just load it dynamically */
1241 struct SDL_WIN_OSVERSIONINFOW {
1242  ULONG dwOSVersionInfoSize;
1243  ULONG dwMajorVersion;
1244  ULONG dwMinorVersion;
1245  ULONG dwBuildNumber;
1246  ULONG dwPlatformId;
1247  WCHAR szCSDVersion[128];
1248 };
1249 
1250 static SDL_bool
1251 IsWin10FCUorNewer(void)
1252 {
1253  HMODULE handle = GetModuleHandleW(L"ntdll.dll");
1254  if (handle) {
1255  typedef LONG(WINAPI* RtlGetVersionPtr)(struct SDL_WIN_OSVERSIONINFOW*);
1256  RtlGetVersionPtr getVersionPtr = (RtlGetVersionPtr)GetProcAddress(handle, "RtlGetVersion");
1257  if (getVersionPtr != NULL) {
1258  struct SDL_WIN_OSVERSIONINFOW info;
1259  SDL_zero(info);
1260  info.dwOSVersionInfoSize = sizeof(info);
1261  if (getVersionPtr(&info) == 0) { /* STATUS_SUCCESS == 0 */
1262  if ((info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && info.dwBuildNumber >= 16299) ||
1263  (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) ||
1264  (info.dwMajorVersion > 10))
1265  {
1266  return SDL_TRUE;
1267  }
1268  }
1269  }
1270  }
1271  return SDL_FALSE;
1272 }
1273 
1274 static int app_registered = 0;
1275 LPTSTR SDL_Appname = NULL;
1276 Uint32 SDL_Appstyle = 0;
1278 
1279 /* Register the class for this application */
1280 int
1281 SDL_RegisterApp(char *name, Uint32 style, void *hInst)
1282 {
1283  const char *hint;
1284  WNDCLASSEX wcex;
1285  TCHAR path[MAX_PATH];
1286 
1287  /* Only do this once... */
1288  if (app_registered) {
1289  ++app_registered;
1290  return (0);
1291  }
1292  if (!name && !SDL_Appname) {
1293  name = "SDL_app";
1294 #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
1295  SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
1296 #endif
1297  SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
1298  }
1299 
1300  if (name) {
1302  SDL_Appstyle = style;
1303  SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
1304  }
1305 
1306  /* Register the application class */
1307  wcex.cbSize = sizeof(WNDCLASSEX);
1308  wcex.hCursor = NULL;
1309  wcex.hIcon = NULL;
1310  wcex.hIconSm = NULL;
1311  wcex.lpszMenuName = NULL;
1312  wcex.lpszClassName = SDL_Appname;
1313  wcex.style = SDL_Appstyle;
1314  wcex.hbrBackground = NULL;
1315  wcex.lpfnWndProc = WIN_WindowProc;
1316  wcex.hInstance = SDL_Instance;
1317  wcex.cbClsExtra = 0;
1318  wcex.cbWndExtra = 0;
1319 
1321  if (hint && *hint) {
1322  wcex.hIcon = LoadIcon(SDL_Instance, MAKEINTRESOURCE(SDL_atoi(hint)));
1323 
1325  if (hint && *hint) {
1326  wcex.hIconSm = LoadIcon(SDL_Instance, MAKEINTRESOURCE(SDL_atoi(hint)));
1327  }
1328  } else {
1329  /* Use the first icon as a default icon, like in the Explorer */
1330  GetModuleFileName(SDL_Instance, path, MAX_PATH);
1331  ExtractIconEx(path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
1332  }
1333 
1334  if (!RegisterClassEx(&wcex)) {
1335  return SDL_SetError("Couldn't register application class");
1336  }
1337 
1338  isWin10FCUorNewer = IsWin10FCUorNewer();
1339 
1340  app_registered = 1;
1341  return 0;
1342 }
1343 
1344 /* Unregisters the windowclass registered in SDL_RegisterApp above. */
1345 void
1347 {
1348  WNDCLASSEX wcex;
1349 
1350  /* SDL_RegisterApp might not have been called before */
1351  if (!app_registered) {
1352  return;
1353  }
1354  --app_registered;
1355  if (app_registered == 0) {
1356  /* Check for any registered window classes. */
1357  if (GetClassInfoEx(SDL_Instance, SDL_Appname, &wcex)) {
1358  UnregisterClass(SDL_Appname, SDL_Instance);
1359  if (wcex.hIcon) DestroyIcon(wcex.hIcon);
1360  if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);
1361  }
1363  SDL_Appname = NULL;
1364  }
1365 }
1366 
1367 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
1368 
1369 /* vi: set ts=4 sw=4 expandtab: */
#define _THIS
#define SDL_assert(condition)
Definition: SDL_assert.h:171
int SDL_SendDropFile(SDL_Window *window, const char *file)
int SDL_SendDropComplete(SDL_Window *window)
#define SDL_SetError
#define SDL_GetWindowSize
#define SDL_GetMouseState
#define SDL_GetWindowFlags
#define SDL_GetKeyboardFocus
#define SDL_GetWindowMinimumSize
#define SDL_GetWindowMaximumSize
#define SDL_GetKeyboardState
#define SDL_free
#define SDL_memcmp
#define SDL_GetMouseFocus
#define SDL_GetHintBoolean
#define SDL_IsShapedWindow
#define SDL_atoi
#define SDL_snprintf
#define SDL_GetHint
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:1066
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:1049
@ SDL_SYSWMEVENT
Definition: SDL_events.h:95
#define SDL_GetEventState(type)
Definition: SDL_events.h:808
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_ENABLE
Definition: SDL_events.h:795
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_HINT_WINDOWS_INTRESOURCE_ICON
A variable to specify custom icon resource id from RC file on Windows platform.
Definition: SDL_hints.h:272
#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
Allow mouse click events when clicking to focus an SDL window.
Definition: SDL_hints.h:348
#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4
Tell SDL not to generate window-close events for Alt+F4 on Windows.
Definition: SDL_hints.h:1147
#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL
Definition: SDL_hints.h:273
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
Definition: SDL_keyboard.c:924
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:634
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:848
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:806
@ KMOD_CAPS
Definition: SDL_keycode.h:339
@ KMOD_NUM
Definition: SDL_keycode.h:338
int SDL_RegisterApp(char *name, Uint32 style, void *hInst)
void SDL_UnregisterApp(void)
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:599
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:175
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:208
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:605
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:298
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:285
#define SDL_BUTTON_X2
Definition: SDL_mouse.h:286
#define SDL_BUTTON_MIDDLE
Definition: SDL_mouse.h:283
#define SDL_BUTTON_RIGHT
Definition: SDL_mouse.h:284
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
@ SDL_MOUSEWHEEL_NORMAL
Definition: SDL_mouse.h:68
#define SDL_BUTTON_MMASK
Definition: SDL_mouse.h:288
#define SDL_BUTTON_LMASK
Definition: SDL_mouse.h:287
#define SDL_BUTTON_X1MASK
Definition: SDL_mouse.h:290
#define SDL_BUTTON_RMASK
Definition: SDL_mouse.h:289
#define SDL_BUTTON(X)
Definition: SDL_mouse.h:281
#define SDL_BUTTON_X2MASK
Definition: SDL_mouse.h:291
Uint32 SDL_MouseID
Definition: SDL_mouse_c.h:28
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
const GLfloat * params
GLuint GLsizei const GLchar * message
GLuint buffer
GLuint const GLchar * name
GLsizeiptr size
GLsizei const GLchar *const * path
GLenum GLenum GLenum input
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
SDL_Scancode
The SDL keyboard scancode representation.
Definition: SDL_scancode.h:44
@ SDL_SCANCODE_END
Definition: SDL_scancode.h:174
@ SDL_SCANCODE_F15
Definition: SDL_scancode.h:217
@ SDL_SCANCODE_KP_PLUS
Definition: SDL_scancode.h:186
@ SDL_SCANCODE_F4
Definition: SDL_scancode.h:156
@ SDL_SCANCODE_CAPSLOCK
Definition: SDL_scancode.h:151
@ SDL_SCANCODE_NONUSBACKSLASH
Definition: SDL_scancode.h:200
@ SDL_SCANCODE_KP_0
Definition: SDL_scancode.h:197
@ SDL_SCANCODE_KP_PERIOD
Definition: SDL_scancode.h:198
@ SDL_SCANCODE_F24
Definition: SDL_scancode.h:226
@ SDL_SCANCODE_AUDIOMUTE
Definition: SDL_scancode.h:355
@ SDL_SCANCODE_DELETE
Definition: SDL_scancode.h:173
@ SDL_SCANCODE_SLASH
Definition: SDL_scancode.h:149
@ SDL_SCANCODE_KP_EQUALS
Definition: SDL_scancode.h:214
@ SDL_SCANCODE_F21
Definition: SDL_scancode.h:223
@ SDL_SCANCODE_KP_6
Definition: SDL_scancode.h:193
@ SDL_SCANCODE_KP_7
Definition: SDL_scancode.h:194
@ SDL_SCANCODE_AC_REFRESH
Definition: SDL_scancode.h:366
@ SDL_SCANCODE_KP_9
Definition: SDL_scancode.h:196
@ SDL_SCANCODE_EXSEL
Definition: SDL_scancode.h:279
@ SDL_SCANCODE_VOLUMEUP
Definition: SDL_scancode.h:239
@ SDL_SCANCODE_APP2
Definition: SDL_scancode.h:389
@ SDL_SCANCODE_CRSEL
Definition: SDL_scancode.h:278
@ SDL_SCANCODE_NUMLOCKCLEAR
Definition: SDL_scancode.h:181
@ SDL_SCANCODE_PRINTSCREEN
Definition: SDL_scancode.h:166
@ SDL_SCANCODE_MAIL
Definition: SDL_scancode.h:358
@ SDL_SCANCODE_KP_3
Definition: SDL_scancode.h:190
@ SDL_SCANCODE_AUDIOPREV
Definition: SDL_scancode.h:352
@ SDL_SCANCODE_PAUSE
Definition: SDL_scancode.h:168
@ SDL_SCANCODE_RETURN
Definition: SDL_scancode.h:92
@ SDL_SCANCODE_HELP
Definition: SDL_scancode.h:228
@ SDL_SCANCODE_PAGEDOWN
Definition: SDL_scancode.h:175
@ SDL_SCANCODE_LSHIFT
Definition: SDL_scancode.h:329
@ SDL_SCANCODE_AUDIOSTOP
Definition: SDL_scancode.h:353
@ SDL_SCANCODE_LCTRL
Definition: SDL_scancode.h:328
@ SDL_SCANCODE_F16
Definition: SDL_scancode.h:218
@ SDL_SCANCODE_F22
Definition: SDL_scancode.h:224
@ SDL_SCANCODE_UNKNOWN
Definition: SDL_scancode.h:45
@ SDL_SCANCODE_AC_STOP
Definition: SDL_scancode.h:365
@ SDL_SCANCODE_AC_SEARCH
Definition: SDL_scancode.h:361
@ SDL_SCANCODE_F19
Definition: SDL_scancode.h:221
@ SDL_SCANCODE_EXECUTE
Definition: SDL_scancode.h:227
@ SDL_SCANCODE_RALT
Definition: SDL_scancode.h:334
@ SDL_SCANCODE_SYSREQ
Definition: SDL_scancode.h:269
@ SDL_SCANCODE_F17
Definition: SDL_scancode.h:219
@ SDL_SCANCODE_KP_ENTER
Definition: SDL_scancode.h:187
@ SDL_SCANCODE_AC_BACK
Definition: SDL_scancode.h:363
@ SDL_SCANCODE_PAGEUP
Definition: SDL_scancode.h:172
@ SDL_SCANCODE_AUDIOPLAY
Definition: SDL_scancode.h:354
@ SDL_SCANCODE_F23
Definition: SDL_scancode.h:225
@ SDL_SCANCODE_KP_1
Definition: SDL_scancode.h:188
@ SDL_SCANCODE_AC_BOOKMARKS
Definition: SDL_scancode.h:367
@ SDL_SCANCODE_DOWN
Definition: SDL_scancode.h:178
@ SDL_SCANCODE_RIGHT
Definition: SDL_scancode.h:176
@ SDL_SCANCODE_MODE
Definition: SDL_scancode.h:337
@ SDL_SCANCODE_KP_2
Definition: SDL_scancode.h:189
@ SDL_SCANCODE_KP_MULTIPLY
Definition: SDL_scancode.h:184
@ SDL_SCANCODE_APP1
Definition: SDL_scancode.h:388
@ SDL_SCANCODE_UP
Definition: SDL_scancode.h:179
@ SDL_SCANCODE_LEFT
Definition: SDL_scancode.h:177
@ SDL_SCANCODE_AUDIONEXT
Definition: SDL_scancode.h:351
@ SDL_SCANCODE_SELECT
Definition: SDL_scancode.h:230
@ SDL_SCANCODE_KP_4
Definition: SDL_scancode.h:191
@ SDL_SCANCODE_HOME
Definition: SDL_scancode.h:171
@ SDL_SCANCODE_F14
Definition: SDL_scancode.h:216
@ SDL_SCANCODE_LALT
Definition: SDL_scancode.h:330
@ SDL_SCANCODE_KP_8
Definition: SDL_scancode.h:195
@ SDL_SCANCODE_RCTRL
Definition: SDL_scancode.h:332
@ SDL_SCANCODE_F20
Definition: SDL_scancode.h:222
@ SDL_SCANCODE_CLEAR
Definition: SDL_scancode.h:271
@ SDL_SCANCODE_AC_HOME
Definition: SDL_scancode.h:362
@ SDL_SCANCODE_VOLUMEDOWN
Definition: SDL_scancode.h:240
@ SDL_SCANCODE_KP_DIVIDE
Definition: SDL_scancode.h:183
@ SDL_SCANCODE_F18
Definition: SDL_scancode.h:220
@ SDL_SCANCODE_F13
Definition: SDL_scancode.h:215
@ SDL_SCANCODE_MEDIASELECT
Definition: SDL_scancode.h:356
@ SDL_SCANCODE_RSHIFT
Definition: SDL_scancode.h:333
@ SDL_SCANCODE_INSERT
Definition: SDL_scancode.h:169
@ SDL_SCANCODE_AC_FORWARD
Definition: SDL_scancode.h:364
uint16_t Uint16
Definition: SDL_stdinc.h:197
#define SDL_zero(x)
Definition: SDL_stdinc.h:426
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
uint32_t Uint32
Definition: SDL_stdinc.h:209
void(* SDL_WindowsMessageHook)(void *userdata, void *hWnd, unsigned int message, Uint64 wParam, Sint64 lParam)
Set a function that is called for every windows message, before TranslateMessage()
Definition: SDL_system.h:49
void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:587
@ SDL_SYSWM_WINDOWS
Definition: SDL_syswm.h:130
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:241
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:154
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure)
Definition: SDL_touch.c:355
@ SDL_TOUCH_DEVICE_DIRECT
Definition: SDL_touch.h:47
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:61
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
Definition: SDL_version.h:79
static SDL_VideoDevice * _this
Definition: SDL_video.c:126
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:1027
@ SDL_HITTEST_DRAGGABLE
Definition: SDL_video.h:1029
@ SDL_HITTEST_RESIZE_LEFT
Definition: SDL_video.h:1037
@ SDL_HITTEST_RESIZE_TOP
Definition: SDL_video.h:1031
@ SDL_HITTEST_RESIZE_TOPRIGHT
Definition: SDL_video.h:1032
@ SDL_HITTEST_NORMAL
Definition: SDL_video.h:1028
@ SDL_HITTEST_RESIZE_BOTTOM
Definition: SDL_video.h:1035
@ SDL_HITTEST_RESIZE_BOTTOMRIGHT
Definition: SDL_video.h:1034
@ SDL_HITTEST_RESIZE_BOTTOMLEFT
Definition: SDL_video.h:1036
@ SDL_HITTEST_RESIZE_RIGHT
Definition: SDL_video.h:1033
@ SDL_HITTEST_RESIZE_TOPLEFT
Definition: SDL_video.h:1030
@ SDL_WINDOW_MOUSE_CAPTURE
Definition: SDL_video.h:115
@ SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:104
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:99
@ SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:103
@ SDL_WINDOWEVENT_HIDDEN
Definition: SDL_video.h:150
@ SDL_WINDOWEVENT_CLOSE
Definition: SDL_video.h:167
@ SDL_WINDOWEVENT_RESIZED
Definition: SDL_video.h:155
@ SDL_WINDOWEVENT_SHOWN
Definition: SDL_video.h:149
@ SDL_WINDOWEVENT_MOVED
Definition: SDL_video.h:153
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
@ SDL_WINDOWEVENT_MAXIMIZED
Definition: SDL_video.h:160
@ SDL_WINDOWEVENT_RESTORED
Definition: SDL_video.h:161
@ SDL_WINDOWEVENT_EXPOSED
Definition: SDL_video.h:151
#define VK_OEM_102
Definition: SDL_vkeys.h:74
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
void WIN_CheckClipboardUpdate(struct SDL_VideoData *data)
HINSTANCE SDL_Instance
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
LPTSTR SDL_Appname
void WIN_PumpEvents(_THIS)
Uint32 SDL_Appstyle
void WIN_ResetDeadKeys(void)
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata)
void WIN_UpdateKeymap(void)
void WIN_RefreshDisplays(_THIS)
HCURSOR SDL_cursor
int Win32_ResizeWindowShape(SDL_Window *window)
#define TOUCHEVENTF_MOVE
#define TOUCHEVENTF_DOWN
SDL_bool g_WindowFrameUsableWhileCursorHidden
#define TOUCHEVENTF_UP
SDL_bool g_WindowsEnableMessageLoop
void WIN_UpdateClipCursor(SDL_Window *window)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
#define TRUE
Definition: edid-parse.c:33
#define FALSE
Definition: edid-parse.c:34
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
static const SDL_Scancode windows_scancode_table[]
SDL_bool relative_mode
Definition: SDL_mouse_c.h:87
SDL_Window * focus
Definition: SDL_mouse_c.h:77
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:88
SDL_bool touch_mouse_events
Definition: SDL_mouse_c.h:95
SDL_bool was_touch_mouse_events
Definition: SDL_mouse_c.h:97
The structure that defines a point (integer)
Definition: SDL_rect.h:49
int x
Definition: SDL_rect.h:50
int y
Definition: SDL_rect.h:51
union SDL_SysWMmsg::@8 msg
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:150
SDL_version version
Definition: SDL_syswm.h:149
SDL_Window * windows
Definition: SDL_sysvideo.h:327
The type used to identify a window.
Definition: SDL_sysvideo.h:75
SDL_Window * next
Definition: SDL_sysvideo.h:115
SDL_Texture * button
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
SDL_Rect rect
Definition: testrelative.c:27
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
struct HINSTANCE__ * HINSTANCE
Definition: vulkan.hpp:72
typedef int(__stdcall *FARPROC)()
#define MAX_WMMSG
Definition: wmmsg.h:22
char * wmtab[]
Definition: wmmsg.h:24