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 REPEATED_KEYMASK (1<<30)
52 #define EXTENDED_KEYMASK (1<<24)
55 #ifndef VK_OEM_NEC_EQUAL
56 #define VK_OEM_NEC_EQUAL 0x92
60 #ifndef WM_XBUTTONDOWN
61 #define WM_XBUTTONDOWN 0x020B
64 #define WM_XBUTTONUP 0x020C
66 #ifndef GET_XBUTTON_WPARAM
67 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
70 #define WM_INPUT 0x00ff
73 #define WM_TOUCH 0x0240
75 #ifndef WM_MOUSEHWHEEL
76 #define WM_MOUSEHWHEEL 0x020E
79 #define WM_UNICHAR 0x0109
83 VKeytoScancode(WPARAM vkey)
148 WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
151 int nScanCode = (lParam >> 16) & 0xFF;
152 SDL_bool bIsExtended = (lParam & (1 << 24)) != 0;
154 code = VKeytoScancode(wParam);
223 WIN_ShouldIgnoreFocusClick()
233 if (!bwParamMousePressed) {
237 if (WIN_ShouldIgnoreFocusClick()) {
242 if (bwParamMousePressed && !bSDLMousePressed) {
244 }
else if (!bwParamMousePressed && bSDLMousePressed) {
256 if (wParam !=
data->mouse_button_flags) {
263 data->mouse_button_flags = wParam;
270 if (rawButtons !=
data->mouse_button_flags) {
272 if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
274 if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
276 if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
278 if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
280 if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
282 if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
284 if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
286 if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
288 if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
290 if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
292 data->mouse_button_flags = rawButtons;
307 keyState = GetAsyncKeyState(VK_LBUTTON);
308 if (!(keyState & 0x8000)) {
311 keyState = GetAsyncKeyState(VK_RBUTTON);
312 if (!(keyState & 0x8000)) {
315 keyState = GetAsyncKeyState(VK_MBUTTON);
316 if (!(keyState & 0x8000)) {
319 keyState = GetAsyncKeyState(VK_XBUTTON1);
320 if (!(keyState & 0x8000)) {
323 keyState = GetAsyncKeyState(VK_XBUTTON2);
324 if (!(keyState & 0x8000)) {
327 data->mouse_button_flags = 0;
331 WIN_ConvertUTF32toUTF8(UINT32 codepoint,
char *
text)
333 if (codepoint <= 0x7F) {
334 text[0] = (char) codepoint;
336 }
else if (codepoint <= 0x7FF) {
337 text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
338 text[1] = 0x80 | (char) (codepoint & 0x3F);
340 }
else if (codepoint <= 0xFFFF) {
341 text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
342 text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
343 text[2] = 0x80 | (char) (codepoint & 0x3F);
345 }
else if (codepoint <= 0x10FFFF) {
346 text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
347 text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
348 text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
349 text[3] = 0x80 | (char) (codepoint & 0x3F);
358 ShouldGenerateWindowCloseOnAltF4(
void)
369 #define MI_WP_SIGNATURE 0xFF515700
370 #define MI_WP_SIGNATURE_MASK 0xFFFFFF00
371 #define IsTouchEvent(dw) ((dw) & MI_WP_SIGNATURE_MASK) == MI_WP_SIGNATURE
375 SDL_MOUSE_EVENT_SOURCE_UNKNOWN,
376 SDL_MOUSE_EVENT_SOURCE_MOUSE,
377 SDL_MOUSE_EVENT_SOURCE_TOUCH,
378 SDL_MOUSE_EVENT_SOURCE_PEN,
379 } SDL_MOUSE_EVENT_SOURCE;
381 static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource()
383 LPARAM extrainfo = GetMessageExtraInfo();
389 if (IsTouchEvent(extrainfo)) {
390 if (extrainfo & 0x80) {
391 return SDL_MOUSE_EVENT_SOURCE_TOUCH;
393 return SDL_MOUSE_EVENT_SOURCE_PEN;
396 return SDL_MOUSE_EVENT_SOURCE_MOUSE;
403 LRESULT returnCode = -1;
411 wmmsg.
msg.win.hwnd = hwnd;
413 wmmsg.
msg.win.wParam = wParam;
414 wmmsg.
msg.win.lParam = lParam;
421 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
428 SDL_snprintf(
message,
sizeof(
message),
"Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
463 minimized = HIWORD(wParam);
464 if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
466 if (!IsWindowVisible(hwnd)) {
469 if (LOWORD(wParam) == WA_CLICKACTIVE) {
470 if (GetAsyncKeyState(VK_LBUTTON)) {
473 if (GetAsyncKeyState(VK_RBUTTON)) {
476 if (GetAsyncKeyState(VK_MBUTTON)) {
479 if (GetAsyncKeyState(VK_XBUTTON1)) {
482 if (GetAsyncKeyState(VK_XBUTTON2)) {
492 GetCursorPos(&cursorPos);
493 ScreenToClient(hwnd, &cursorPos);
496 WIN_CheckAsyncMouseRelease(
data);
531 if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH) {
538 int center_x = 0, center_y = 0;
556 case WM_LBUTTONDBLCLK:
558 case WM_RBUTTONDBLCLK:
560 case WM_MBUTTONDBLCLK:
562 case WM_XBUTTONDBLCLK:
566 if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH) {
567 WIN_CheckWParamMouseButtons(wParam,
data, 0);
576 HRAWINPUT hRawInput = (HRAWINPUT)lParam;
582 if (!isRelative || mouse->
focus !=
data->window) {
588 GetRawInputData(hRawInput, RID_INPUT, &inp, &
size,
sizeof(RAWINPUTHEADER));
591 if (inp.header.dwType == RIM_TYPEMOUSE) {
592 if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH) {
596 RAWMOUSE* rawmouse = &inp.data.mouse;
598 if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
604 int w = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
605 int h = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
606 int x = (
int)(((
float)rawmouse->lLastX / 65535.0f) *
w);
607 int y = (
int)(((
float)rawmouse->lLastY / 65535.0f) *
h);
609 if (lastMousePoint.
x == 0 && lastMousePoint.
y == 0) {
610 lastMousePoint.
x =
x;
611 lastMousePoint.
y =
y;
616 lastMousePoint.
x =
x;
617 lastMousePoint.
y =
y;
619 WIN_CheckRawMouseButtons(rawmouse->usButtonFlags,
data);
620 }
else if (isCapture) {
627 currentHnd = WindowFromPoint(pt);
628 ScreenToClient(hwnd, &pt);
629 GetClientRect(hwnd, &hwndRect);
632 if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
650 short amount = GET_WHEEL_DELTA_WPARAM(wParam);
651 float fAmount = (float) amount / WHEEL_DELTA;
652 if (msg == WM_MOUSEWHEEL)
662 if (!IsIconic(hwnd)) {
665 GetCursorPos(&cursorPos);
666 ScreenToClient(hwnd, &cursorPos);
688 SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
710 SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
725 if (wParam == UNICODE_NOCHAR) {
733 if (WIN_ConvertUTF32toUTF8((UINT32)wParam,
text)) {
740 #ifdef WM_INPUTLANGCHANGE
741 case WM_INPUTLANGCHANGE:
750 case WM_NCLBUTTONDOWN:
756 case WM_CAPTURECHANGED:
761 WIN_CheckAsyncMouseRelease(
data);
765 #ifdef WM_GETMINMAXINFO
766 case WM_GETMINMAXINFO:
774 BOOL constrain_max_size;
781 if (
data->expected_resize) {
786 GetWindowRect(hwnd, &
size);
799 if (max_w && max_h) {
802 constrain_max_size =
TRUE;
804 constrain_max_size =
FALSE;
808 LONG style = GetWindowLong(hwnd, GWL_STYLE);
814 BOOL menu = (style & WS_CHILDWINDOW) ?
FALSE : (GetMenu(hwnd) !=
NULL);
820 AdjustWindowRectEx(&
size, style, menu, 0);
826 info = (MINMAXINFO *) lParam;
828 info->ptMinTrackSize.x =
w + min_w;
829 info->ptMinTrackSize.y =
h + min_h;
830 if (constrain_max_size) {
831 info->ptMaxTrackSize.x =
w + max_w;
832 info->ptMaxTrackSize.y =
h + max_h;
835 info->ptMaxSize.x =
w;
836 info->ptMaxSize.y =
h;
837 info->ptMaxPosition.x =
x;
838 info->ptMaxPosition.y =
y;
839 info->ptMinTrackSize.x =
w;
840 info->ptMinTrackSize.y =
h;
841 info->ptMaxTrackSize.x =
w;
842 info->ptMaxTrackSize.y =
h;
849 case WM_WINDOWPOSCHANGING:
851 if (
data->expected_resize) {
856 case WM_WINDOWPOSCHANGED:
862 if (
data->initializing ||
data->in_border_change) {
866 if (!GetClientRect(hwnd, &
rect) || IsRectEmpty(&
rect)) {
869 ClientToScreen(hwnd, (LPPOINT) &
rect);
870 ClientToScreen(hwnd, (LPPOINT) &
rect + 1);
912 hittest = LOWORD(lParam);
913 if (hittest == HTCLIENT) {
928 ValidateRect(hwnd,
NULL);
943 if ((wParam & 0xFFF0) == SC_KEYMENU) {
947 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
949 if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
950 (wParam & 0xFFF0) == SC_MONITORPOWER) {
967 if (
data->videodata->GetTouchInputInfo &&
data->videodata->CloseTouchInputHandle) {
968 UINT i, num_inputs = LOWORD(wParam);
971 if (
data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs,
sizeof(
TOUCHINPUT))) {
975 if (!GetClientRect(hwnd, &
rect) ||
982 ClientToScreen(hwnd, (LPPOINT) &
rect);
983 ClientToScreen(hwnd, (LPPOINT) &
rect + 1);
989 for (
i = 0;
i < num_inputs; ++
i) {
1018 data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
1026 HDROP drop = (HDROP) wParam;
1054 NCCALCSIZE_PARAMS *
params = (NCCALCSIZE_PARAMS *)lParam;
1055 w =
data->window->windowed.w;
1056 h =
data->window->windowed.h;
1069 POINT winpoint = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1070 if (ScreenToClient(hwnd, &winpoint)) {
1071 const SDL_Point point = { (
int) winpoint.
x, (
int) winpoint.y };
1074 #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
1084 #undef POST_HIT_TEST
1095 if (
data->wndproc) {
1096 return CallWindowProc(
data->wndproc, hwnd, msg, wParam, lParam);
1097 }
else if (returnCode >= 0) {
1100 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
1104 static void WIN_UpdateClipCursorForWindows()
1111 if (
window->driverdata) {
1120 static void *g_WindowsMessageHookData =
NULL;
1125 g_WindowsMessageHookData = userdata;
1131 const Uint8 *keystate;
1133 DWORD start_ticks = GetTickCount();
1134 int new_messages = 0;
1137 while (PeekMessage(&msg,
NULL, 0, 0, PM_REMOVE)) {
1138 if (g_WindowsMessageHook) {
1139 g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
1143 TranslateMessage(&msg);
1144 DispatchMessage(&msg);
1152 const int MAX_NEW_MESSAGES = 3;
1154 if (new_messages > MAX_NEW_MESSAGES) {
1174 WIN_UpdateClipCursorForWindows();
1181 struct SDL_WIN_OSVERSIONINFOW {
1182 ULONG dwOSVersionInfoSize;
1183 ULONG dwMajorVersion;
1184 ULONG dwMinorVersion;
1185 ULONG dwBuildNumber;
1187 WCHAR szCSDVersion[128];
1191 IsWin10FCUorNewer(
void)
1193 HMODULE
handle = GetModuleHandleW(L
"ntdll.dll");
1195 typedef LONG(WINAPI* RtlGetVersionPtr)(
struct SDL_WIN_OSVERSIONINFOW*);
1196 RtlGetVersionPtr getVersionPtr = (RtlGetVersionPtr)GetProcAddress(
handle,
"RtlGetVersion");
1197 if (getVersionPtr !=
NULL) {
1198 struct SDL_WIN_OSVERSIONINFOW info;
1200 info.dwOSVersionInfoSize =
sizeof(info);
1201 if (getVersionPtr(&info) == 0) {
1202 if ((info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && info.dwBuildNumber >= 16299) ||
1203 (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) ||
1204 (info.dwMajorVersion > 10))
1214 static int app_registered = 0;
1225 TCHAR
path[MAX_PATH];
1228 if (app_registered) {
1234 #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
1247 wcex.cbSize =
sizeof(WNDCLASSEX);
1248 wcex.hCursor =
NULL;
1250 wcex.hIconSm =
NULL;
1251 wcex.lpszMenuName =
NULL;
1254 wcex.hbrBackground =
NULL;
1257 wcex.cbClsExtra = 0;
1258 wcex.cbWndExtra = 0;
1261 if (hint && *hint) {
1265 if (hint && *hint) {
1271 ExtractIconEx(
path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
1274 if (!RegisterClassEx(&wcex)) {
1275 return SDL_SetError(
"Couldn't register application class");
1278 isWin10FCUorNewer = IsWin10FCUorNewer();
1291 if (!app_registered) {
1295 if (app_registered == 0) {
1299 if (wcex.hIcon) DestroyIcon(wcex.hIcon);
1300 if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);