21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_WINDOWS
32 #include "../../events/SDL_events_c.h"
33 #include "../../events/SDL_touch_c.h"
34 #include "../../events/scancodes_windows.h"
51 #define MOUSEEVENTF_FROMTOUCH 0xFF515700
54 #define REPEATED_KEYMASK (1<<30)
55 #define EXTENDED_KEYMASK (1<<24)
58 #ifndef VK_OEM_NEC_EQUAL
59 #define VK_OEM_NEC_EQUAL 0x92
63 #ifndef WM_XBUTTONDOWN
64 #define WM_XBUTTONDOWN 0x020B
67 #define WM_XBUTTONUP 0x020C
69 #ifndef GET_XBUTTON_WPARAM
70 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
73 #define WM_INPUT 0x00ff
76 #define WM_TOUCH 0x0240
78 #ifndef WM_MOUSEHWHEEL
79 #define WM_MOUSEHWHEEL 0x020E
82 #define WM_UNICHAR 0x0109
86 VKeytoScancode(WPARAM vkey)
144 WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
147 int nScanCode = (lParam >> 16) & 0xFF;
148 SDL_bool bIsExtended = (lParam & (1 << 24)) != 0;
150 code = VKeytoScancode(wParam);
219 WIN_ShouldIgnoreFocusClick()
229 if (!bwParamMousePressed) {
233 if (WIN_ShouldIgnoreFocusClick()) {
238 if (bwParamMousePressed && !bSDLMousePressed) {
240 }
else if (!bwParamMousePressed && bSDLMousePressed) {
252 if (wParam !=
data->mouse_button_flags) {
259 data->mouse_button_flags = wParam;
267 if (rawButtons !=
data->mouse_button_flags) {
269 if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
271 if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
273 if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
275 if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
277 if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
279 if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
281 if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
283 if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
285 if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
287 if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
289 data->mouse_button_flags = rawButtons;
304 keyState = GetAsyncKeyState(VK_LBUTTON);
305 if (!(keyState & 0x8000)) {
308 keyState = GetAsyncKeyState(VK_RBUTTON);
309 if (!(keyState & 0x8000)) {
312 keyState = GetAsyncKeyState(VK_MBUTTON);
313 if (!(keyState & 0x8000)) {
316 keyState = GetAsyncKeyState(VK_XBUTTON1);
317 if (!(keyState & 0x8000)) {
320 keyState = GetAsyncKeyState(VK_XBUTTON2);
321 if (!(keyState & 0x8000)) {
324 data->mouse_button_flags = 0;
328 WIN_ConvertUTF32toUTF8(UINT32 codepoint,
char *
text)
330 if (codepoint <= 0x7F) {
331 text[0] = (char) codepoint;
333 }
else if (codepoint <= 0x7FF) {
334 text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
335 text[1] = 0x80 | (char) (codepoint & 0x3F);
337 }
else if (codepoint <= 0xFFFF) {
338 text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
339 text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
340 text[2] = 0x80 | (char) (codepoint & 0x3F);
342 }
else if (codepoint <= 0x10FFFF) {
343 text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
344 text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
345 text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
346 text[3] = 0x80 | (char) (codepoint & 0x3F);
355 ShouldGenerateWindowCloseOnAltF4(
void)
369 LRESULT returnCode = -1;
377 wmmsg.
msg.win.hwnd = hwnd;
379 wmmsg.
msg.win.wParam = wParam;
380 wmmsg.
msg.win.lParam = lParam;
387 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
394 SDL_snprintf(
message,
sizeof(
message),
"Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
430 if (!IsWindowVisible(hwnd)) {
434 minimized = HIWORD(wParam);
435 if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
436 if (LOWORD(wParam) == WA_CLICKACTIVE) {
437 if (GetAsyncKeyState(VK_LBUTTON)) {
440 if (GetAsyncKeyState(VK_RBUTTON)) {
443 if (GetAsyncKeyState(VK_MBUTTON)) {
446 if (GetAsyncKeyState(VK_XBUTTON1)) {
449 if (GetAsyncKeyState(VK_XBUTTON2)) {
459 GetCursorPos(&cursorPos);
460 ScreenToClient(hwnd, &cursorPos);
463 WIN_CheckAsyncMouseRelease(
data);
504 int center_x = 0, center_y = 0;
518 case WM_LBUTTONDBLCLK:
520 case WM_RBUTTONDBLCLK:
522 case WM_MBUTTONDBLCLK:
524 case WM_XBUTTONDBLCLK:
529 WIN_CheckWParamMouseButtons(wParam,
data, mouseID);
537 HRAWINPUT hRawInput = (HRAWINPUT)lParam;
543 if (!isRelative || mouse->
focus !=
data->window) {
549 GetRawInputData(hRawInput, RID_INPUT, &inp, &
size,
sizeof(RAWINPUTHEADER));
552 if (inp.header.dwType == RIM_TYPEMOUSE) {
554 RAWMOUSE* rawmouse = &inp.data.mouse;
556 if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
561 if (initialMousePoint.
x == 0 && initialMousePoint.
y == 0) {
562 initialMousePoint.
x = rawmouse->lLastX;
563 initialMousePoint.
y = rawmouse->lLastY;
566 SDL_SendMouseMotion(
data->window, 0, 1, (
int)(rawmouse->lLastX-initialMousePoint.
x), (
int)(rawmouse->lLastY-initialMousePoint.
y));
568 initialMousePoint.
x = rawmouse->lLastX;
569 initialMousePoint.
y = rawmouse->lLastY;
571 WIN_CheckRawMouseButtons(rawmouse->usButtonFlags,
data);
572 }
else if (isCapture) {
579 currentHnd = WindowFromPoint(pt);
580 ScreenToClient(hwnd, &pt);
581 GetClientRect(hwnd, &hwndRect);
584 if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
602 short amount = GET_WHEEL_DELTA_WPARAM(wParam);
603 float fAmount = (float) amount / WHEEL_DELTA;
604 if (msg == WM_MOUSEWHEEL)
614 if (!IsIconic(hwnd)) {
616 GetCursorPos(&cursorPos);
617 ScreenToClient(hwnd, &cursorPos);
629 SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
651 SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
666 if (wParam == UNICODE_NOCHAR) {
674 if (WIN_ConvertUTF32toUTF8((UINT32)wParam,
text)) {
681 #ifdef WM_INPUTLANGCHANGE
682 case WM_INPUTLANGCHANGE:
691 case WM_NCLBUTTONDOWN:
697 case WM_CAPTURECHANGED:
702 WIN_CheckAsyncMouseRelease(
data);
706 #ifdef WM_GETMINMAXINFO
707 case WM_GETMINMAXINFO:
715 BOOL constrain_max_size;
721 if (
data->expected_resize) {
726 GetWindowRect(hwnd, &
size);
739 if (max_w && max_h) {
742 constrain_max_size =
TRUE;
744 constrain_max_size =
FALSE;
748 LONG style = GetWindowLong(hwnd, GWL_STYLE);
754 BOOL menu = (style & WS_CHILDWINDOW) ?
FALSE : (GetMenu(hwnd) !=
NULL);
760 AdjustWindowRectEx(&
size, style, menu, 0);
766 info = (MINMAXINFO *) lParam;
768 info->ptMinTrackSize.x =
w + min_w;
769 info->ptMinTrackSize.y =
h + min_h;
770 if (constrain_max_size) {
771 info->ptMaxTrackSize.x =
w + max_w;
772 info->ptMaxTrackSize.y =
h + max_h;
775 info->ptMaxSize.x =
w;
776 info->ptMaxSize.y =
h;
777 info->ptMaxPosition.x =
x;
778 info->ptMaxPosition.y =
y;
779 info->ptMinTrackSize.x =
w;
780 info->ptMinTrackSize.y =
h;
781 info->ptMaxTrackSize.x =
w;
782 info->ptMaxTrackSize.y =
h;
789 case WM_WINDOWPOSCHANGING:
791 if (
data->expected_resize) {
796 case WM_WINDOWPOSCHANGED:
802 if (
data->initializing ||
data->in_border_change) {
806 if (!GetClientRect(hwnd, &
rect) || IsRectEmpty(&
rect)) {
809 ClientToScreen(hwnd, (LPPOINT) &
rect);
810 ClientToScreen(hwnd, (LPPOINT) &
rect + 1);
853 hittest = LOWORD(lParam);
854 if (hittest == HTCLIENT) {
869 ValidateRect(hwnd,
NULL);
885 if ((wParam & 0xFFF0) == SC_KEYMENU) {
889 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
891 if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
892 (wParam & 0xFFF0) == SC_MONITORPOWER) {
909 if (
data->videodata->GetTouchInputInfo &&
data->videodata->CloseTouchInputHandle) {
910 UINT i, num_inputs = LOWORD(wParam);
912 if (
data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs,
sizeof(
TOUCHINPUT))) {
916 if (!GetClientRect(hwnd, &
rect) ||
923 ClientToScreen(hwnd, (LPPOINT) &
rect);
924 ClientToScreen(hwnd, (LPPOINT) &
rect + 1);
930 for (
i = 0;
i < num_inputs; ++
i) {
955 data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
963 HDROP drop = (HDROP) wParam;
990 NCCALCSIZE_PARAMS *
params = (NCCALCSIZE_PARAMS *)lParam;
991 w =
data->window->windowed.w;
992 h =
data->window->windowed.h;
1005 POINT winpoint = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1006 if (ScreenToClient(hwnd, &winpoint)) {
1007 const SDL_Point point = { (
int) winpoint.
x, (
int) winpoint.y };
1010 #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
1020 #undef POST_HIT_TEST
1031 if (
data->wndproc) {
1032 return CallWindowProc(
data->wndproc, hwnd, msg, wParam, lParam);
1033 }
else if (returnCode >= 0) {
1036 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
1040 static void WIN_UpdateClipCursorForWindows()
1047 if (
window->driverdata) {
1056 static void *g_WindowsMessageHookData =
NULL;
1061 g_WindowsMessageHookData = userdata;
1067 const Uint8 *keystate;
1069 DWORD start_ticks = GetTickCount();
1072 while (PeekMessage(&msg,
NULL, 0, 0, PM_REMOVE)) {
1073 if (g_WindowsMessageHook) {
1074 g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
1078 TranslateMessage(&msg);
1079 DispatchMessage(&msg);
1101 WIN_UpdateClipCursorForWindows();
1108 struct SDL_WIN_OSVERSIONINFOW {
1109 ULONG dwOSVersionInfoSize;
1110 ULONG dwMajorVersion;
1111 ULONG dwMinorVersion;
1112 ULONG dwBuildNumber;
1114 WCHAR szCSDVersion[128];
1118 IsWin10FCUorNewer(
void)
1120 HMODULE
handle = GetModuleHandleW(L
"ntdll.dll");
1122 typedef LONG(WINAPI* RtlGetVersionPtr)(
struct SDL_WIN_OSVERSIONINFOW*);
1123 RtlGetVersionPtr getVersionPtr = (RtlGetVersionPtr)GetProcAddress(
handle,
"RtlGetVersion");
1124 if (getVersionPtr !=
NULL) {
1125 struct SDL_WIN_OSVERSIONINFOW info;
1127 info.dwOSVersionInfoSize =
sizeof(info);
1128 if (getVersionPtr(&info) == 0) {
1129 if ((info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && info.dwBuildNumber >= 16299) ||
1130 (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) ||
1131 (info.dwMajorVersion > 10))
1141 static int app_registered = 0;
1152 TCHAR
path[MAX_PATH];
1155 if (app_registered) {
1161 #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
1174 wcex.cbSize =
sizeof(WNDCLASSEX);
1175 wcex.hCursor =
NULL;
1177 wcex.hIconSm =
NULL;
1178 wcex.lpszMenuName =
NULL;
1181 wcex.hbrBackground =
NULL;
1184 wcex.cbClsExtra = 0;
1185 wcex.cbWndExtra = 0;
1188 if (hint && *hint) {
1192 if (hint && *hint) {
1198 ExtractIconEx(
path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
1201 if (!RegisterClassEx(&wcex)) {
1202 return SDL_SetError(
"Couldn't register application class");
1205 isWin10FCUorNewer = IsWin10FCUorNewer();
1218 if (!app_registered) {
1222 if (app_registered == 0) {
1226 if (wcex.hIcon) DestroyIcon(wcex.hIcon);
1227 if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);