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
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
79#define WM_MOUSEHWHEEL 0x020E
82#define WM_UNICHAR 0x0109
86VKeytoScancode(WPARAM vkey)
146WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
149 int nScanCode = (lParam >> 16) & 0xFF;
150 SDL_bool bIsExtended = (lParam & (1 << 24)) != 0;
152 code = VKeytoScancode(wParam);
221WIN_ShouldIgnoreFocusClick()
231 if (!bwParamMousePressed) {
232 data->focus_click_pending &= ~SDL_BUTTON(
button);
235 if (WIN_ShouldIgnoreFocusClick()) {
240 if (bwParamMousePressed && !bSDLMousePressed) {
242 }
else if (!bwParamMousePressed && bSDLMousePressed) {
254 if (wParam !=
data->mouse_button_flags) {
261 data->mouse_button_flags = wParam;
269 if (rawButtons !=
data->mouse_button_flags) {
271 if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
273 if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
275 if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
277 if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
279 if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
281 if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
283 if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
285 if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
287 if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
289 if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
291 data->mouse_button_flags = rawButtons;
306 keyState = GetAsyncKeyState(VK_LBUTTON);
307 if (!(keyState & 0x8000)) {
310 keyState = GetAsyncKeyState(VK_RBUTTON);
311 if (!(keyState & 0x8000)) {
314 keyState = GetAsyncKeyState(VK_MBUTTON);
315 if (!(keyState & 0x8000)) {
318 keyState = GetAsyncKeyState(VK_XBUTTON1);
319 if (!(keyState & 0x8000)) {
322 keyState = GetAsyncKeyState(VK_XBUTTON2);
323 if (!(keyState & 0x8000)) {
326 data->mouse_button_flags = 0;
330WIN_ConvertUTF32toUTF8(UINT32 codepoint,
char *
text)
332 if (codepoint <= 0x7F) {
333 text[0] = (char) codepoint;
335 }
else if (codepoint <= 0x7FF) {
336 text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
337 text[1] = 0x80 | (char) (codepoint & 0x3F);
339 }
else if (codepoint <= 0xFFFF) {
340 text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
341 text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
342 text[2] = 0x80 | (char) (codepoint & 0x3F);
344 }
else if (codepoint <= 0x10FFFF) {
345 text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
346 text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
347 text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
348 text[3] = 0x80 | (char) (codepoint & 0x3F);
357ShouldGenerateWindowCloseOnAltF4(
void)
372GetMessageExtraInfoAndCheckMousePacketTouch(
int *checkTouch) {
373 LPARAM extrainfo = GetMessageExtraInfo();
379 *checkTouch = (!(((extrainfo & 0x7F) && (isVistaOrNewer ? (extrainfo & 0x80) : 1)) || ((extrainfo & 0xFFFFFF00) == 0xFF515700)));
389 LRESULT returnCode = -1;
397 wmmsg.
msg.win.hwnd = hwnd;
399 wmmsg.
msg.win.wParam = wParam;
400 wmmsg.
msg.win.lParam = lParam;
407 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
414 SDL_snprintf(
message,
sizeof(
message),
"Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
449 minimized = HIWORD(wParam);
450 if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
452 if (!IsWindowVisible(hwnd)) {
455 if (LOWORD(wParam) == WA_CLICKACTIVE) {
456 if (GetAsyncKeyState(VK_LBUTTON)) {
459 if (GetAsyncKeyState(VK_RBUTTON)) {
462 if (GetAsyncKeyState(VK_MBUTTON)) {
465 if (GetAsyncKeyState(VK_XBUTTON1)) {
468 if (GetAsyncKeyState(VK_XBUTTON2)) {
478 GetCursorPos(&cursorPos);
479 ScreenToClient(hwnd, &cursorPos);
482 WIN_CheckAsyncMouseRelease(
data);
515 extrainfo = GetMessageExtraInfoAndCheckMousePacketTouch(&checkTouch);
518 if (((extrainfo & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH) && checkTouch) {
525 int center_x = 0, center_y = 0;
540 case WM_LBUTTONDBLCLK:
542 case WM_RBUTTONDBLCLK:
544 case WM_MBUTTONDBLCLK:
546 case WM_XBUTTONDBLCLK:
549 if (checkTouch < 0) {
550 extrainfo = GetMessageExtraInfoAndCheckMousePacketTouch(&checkTouch);
553 if (((extrainfo & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH) && checkTouch) {
554 WIN_CheckWParamMouseButtons(wParam,
data, 0);
563 HRAWINPUT hRawInput = (HRAWINPUT)lParam;
565 UINT
size =
sizeof(inp);
569 if (!isRelative || mouse->
focus !=
data->window) {
575 GetRawInputData(hRawInput, RID_INPUT, &inp, &
size,
sizeof(RAWINPUTHEADER));
578 if (inp.header.dwType == RIM_TYPEMOUSE) {
579 extrainfo = GetMessageExtraInfoAndCheckMousePacketTouch(&checkTouch);
583 RAWMOUSE* rawmouse = &inp.data.mouse;
585 if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
590 if (initialMousePoint.
x == 0 && initialMousePoint.
y == 0) {
591 initialMousePoint.
x = rawmouse->lLastX;
592 initialMousePoint.
y = rawmouse->lLastY;
595 SDL_SendMouseMotion(
data->window, 0, 1, (
int)(rawmouse->lLastX-initialMousePoint.
x), (
int)(rawmouse->lLastY-initialMousePoint.
y));
597 initialMousePoint.
x = rawmouse->lLastX;
598 initialMousePoint.
y = rawmouse->lLastY;
600 WIN_CheckRawMouseButtons(rawmouse->usButtonFlags,
data);
601 }
else if (isCapture) {
608 currentHnd = WindowFromPoint(pt);
609 ScreenToClient(hwnd, &pt);
610 GetClientRect(hwnd, &hwndRect);
613 if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
631 short amount = GET_WHEEL_DELTA_WPARAM(wParam);
632 float fAmount = (float) amount / WHEEL_DELTA;
633 if (msg == WM_MOUSEWHEEL)
643 if (!IsIconic(hwnd)) {
646 GetCursorPos(&cursorPos);
647 ScreenToClient(hwnd, &cursorPos);
669 SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
691 SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
706 if (wParam == UNICODE_NOCHAR) {
714 if (WIN_ConvertUTF32toUTF8((UINT32)wParam,
text)) {
721#ifdef WM_INPUTLANGCHANGE
722 case WM_INPUTLANGCHANGE:
731 case WM_NCLBUTTONDOWN:
737 case WM_CAPTURECHANGED:
742 WIN_CheckAsyncMouseRelease(
data);
746#ifdef WM_GETMINMAXINFO
747 case WM_GETMINMAXINFO:
755 BOOL constrain_max_size;
761 if (
data->expected_resize) {
766 GetWindowRect(hwnd, &
size);
779 if (max_w && max_h) {
782 constrain_max_size =
TRUE;
784 constrain_max_size =
FALSE;
788 LONG style = GetWindowLong(hwnd, GWL_STYLE);
794 BOOL menu = (style & WS_CHILDWINDOW) ?
FALSE : (GetMenu(hwnd) !=
NULL);
800 AdjustWindowRectEx(&
size, style, menu, 0);
806 info = (MINMAXINFO *) lParam;
808 info->ptMinTrackSize.x =
w + min_w;
809 info->ptMinTrackSize.y =
h + min_h;
810 if (constrain_max_size) {
811 info->ptMaxTrackSize.x =
w + max_w;
812 info->ptMaxTrackSize.y =
h + max_h;
815 info->ptMaxSize.x =
w;
816 info->ptMaxSize.y =
h;
817 info->ptMaxPosition.x =
x;
818 info->ptMaxPosition.y =
y;
819 info->ptMinTrackSize.x =
w;
820 info->ptMinTrackSize.y =
h;
821 info->ptMaxTrackSize.x =
w;
822 info->ptMaxTrackSize.y =
h;
829 case WM_WINDOWPOSCHANGING:
831 if (
data->expected_resize) {
836 case WM_WINDOWPOSCHANGED:
842 if (
data->initializing ||
data->in_border_change) {
846 if (!GetClientRect(hwnd, &
rect) || IsRectEmpty(&
rect)) {
849 ClientToScreen(hwnd, (LPPOINT) &
rect);
850 ClientToScreen(hwnd, (LPPOINT) &
rect + 1);
893 hittest = LOWORD(lParam);
894 if (hittest == HTCLIENT) {
909 ValidateRect(hwnd,
NULL);
925 if ((wParam & 0xFFF0) == SC_KEYMENU) {
929#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
931 if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
932 (wParam & 0xFFF0) == SC_MONITORPOWER) {
949 if (
data->videodata->GetTouchInputInfo &&
data->videodata->CloseTouchInputHandle) {
950 UINT
i, num_inputs = LOWORD(wParam);
953 if (
data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs,
sizeof(
TOUCHINPUT))) {
957 if (!GetClientRect(hwnd, &
rect) ||
964 ClientToScreen(hwnd, (LPPOINT) &
rect);
965 ClientToScreen(hwnd, (LPPOINT) &
rect + 1);
971 for (
i = 0;
i < num_inputs; ++
i) {
972 PTOUCHINPUT
input = &inputs[
i];
1000 data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
1008 HDROP drop = (HDROP) wParam;
1009 UINT
count = DragQueryFile(drop, 0xFFFFFFFF,
NULL, 0);
1012 UINT
size = DragQueryFile(drop,
i,
NULL, 0) + 1;
1036 NCCALCSIZE_PARAMS *
params = (NCCALCSIZE_PARAMS *)lParam;
1037 w =
data->window->windowed.w;
1038 h =
data->window->windowed.h;
1051 POINT winpoint = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1052 if (ScreenToClient(hwnd, &winpoint)) {
1053 const SDL_Point point = { (int) winpoint.
x, (
int) winpoint.y };
1056 #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
1066 #undef POST_HIT_TEST
1077 if (
data->wndproc) {
1078 return CallWindowProc(
data->wndproc, hwnd, msg, wParam, lParam);
1079 }
else if (returnCode >= 0) {
1082 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
1086static void WIN_UpdateClipCursorForWindows()
1093 if (
window->driverdata) {
1102static void *g_WindowsMessageHookData =
NULL;
1107 g_WindowsMessageHookData = userdata;
1113 const Uint8 *keystate;
1115 DWORD start_ticks = GetTickCount();
1118 while (PeekMessage(&msg,
NULL, 0, 0, PM_REMOVE)) {
1119 if (g_WindowsMessageHook) {
1120 g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
1124 TranslateMessage(&msg);
1125 DispatchMessage(&msg);
1147 WIN_UpdateClipCursorForWindows();
1154struct SDL_WIN_OSVERSIONINFOW {
1155 ULONG dwOSVersionInfoSize;
1156 ULONG dwMajorVersion;
1157 ULONG dwMinorVersion;
1158 ULONG dwBuildNumber;
1160 WCHAR szCSDVersion[128];
1164IsWinVistaOrNewer(
void)
1166 DWORD version = GetVersion();
1167 DWORD major = (DWORD)(LOBYTE(LOWORD(version)));
1172IsWin10FCUorNewer(
void)
1174 HMODULE
handle = GetModuleHandleW(L
"ntdll.dll");
1176 typedef LONG(WINAPI* RtlGetVersionPtr)(
struct SDL_WIN_OSVERSIONINFOW*);
1177 RtlGetVersionPtr getVersionPtr = (RtlGetVersionPtr)GetProcAddress(
handle,
"RtlGetVersion");
1178 if (getVersionPtr !=
NULL) {
1179 struct SDL_WIN_OSVERSIONINFOW info;
1181 info.dwOSVersionInfoSize =
sizeof(info);
1182 if (getVersionPtr(&info) == 0) {
1183 if ((info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && info.dwBuildNumber >= 16299) ||
1184 (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) ||
1185 (info.dwMajorVersion > 10))
1195static int app_registered = 0;
1206 TCHAR
path[MAX_PATH];
1209 if (app_registered) {
1215#if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
1228 wcex.cbSize =
sizeof(WNDCLASSEX);
1229 wcex.hCursor =
NULL;
1231 wcex.hIconSm =
NULL;
1232 wcex.lpszMenuName =
NULL;
1235 wcex.hbrBackground =
NULL;
1238 wcex.cbClsExtra = 0;
1239 wcex.cbWndExtra = 0;
1242 if (hint && *hint) {
1246 if (hint && *hint) {
1252 ExtractIconEx(
path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
1255 if (!RegisterClassEx(&wcex)) {
1256 return SDL_SetError(
"Couldn't register application class");
1259 isVistaOrNewer = IsWinVistaOrNewer();
1260 isWin10FCUorNewer = IsWin10FCUorNewer();
1273 if (!app_registered) {
1277 if (app_registered == 0) {
1281 if (wcex.hIcon) DestroyIcon(wcex.hIcon);
1282 if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);
#define SDL_assert(condition)
int SDL_SendDropFile(SDL_Window *window, const char *file)
int SDL_SendDropComplete(SDL_Window *window)
#define SDL_GetWindowSize
#define SDL_GetMouseState
#define SDL_GetWindowFlags
#define SDL_GetKeyboardFocus
#define SDL_GetWindowMinimumSize
#define SDL_GetWindowMaximumSize
#define SDL_GetKeyboardState
#define SDL_GetMouseFocus
#define SDL_GetHintBoolean
#define SDL_IsShapedWindow
int SDL_SendKeymapChangedEvent(void)
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
#define SDL_GetEventState(type)
#define SDL_HINT_WINDOWS_INTRESOURCE_ICON
A variable to specify custom icon resource id from RC file on Windows platform.
#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
Allow mouse click events when clicking to focus an SDL window.
#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4
Tell SDL not to generate window-close events for Alt+F4 on Windows.
#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL
#define SDL_small_alloc(type, count, pisstack)
#define SDL_small_free(ptr, isstack)
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
void SDL_SetKeyboardFocus(SDL_Window *window)
int SDL_SendKeyboardText(const char *text)
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
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)
void SDL_SetMouseFocus(SDL_Window *window)
SDL_Mouse * SDL_GetMouse(void)
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
#define SDL_BUTTON_MIDDLE
#define SDL_BUTTON_X1MASK
#define SDL_BUTTON_X2MASK
GLint GLint GLint GLint GLint GLint y
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLint GLint GLint GLint GLint x
GLuint GLsizei const GLchar * message
GLuint const GLchar * name
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.
@ SDL_SCANCODE_NONUSBACKSLASH
@ SDL_SCANCODE_AC_REFRESH
@ SDL_SCANCODE_NUMLOCKCLEAR
@ SDL_SCANCODE_PRINTSCREEN
@ SDL_SCANCODE_AC_BOOKMARKS
@ SDL_SCANCODE_KP_MULTIPLY
@ SDL_SCANCODE_VOLUMEDOWN
@ SDL_SCANCODE_MEDIASELECT
@ SDL_SCANCODE_AC_FORWARD
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()
void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
SDL_VideoDevice * SDL_GetVideoDevice(void)
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
@ SDL_TOUCH_DEVICE_DIRECT
#define SDL_TOUCH_MOUSEID
#define SDL_VERSION(x)
Macro to determine SDL version program was compiled against.
static SDL_VideoDevice * _this
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
@ SDL_HITTEST_RESIZE_LEFT
@ SDL_HITTEST_RESIZE_TOPRIGHT
@ SDL_HITTEST_RESIZE_BOTTOM
@ SDL_HITTEST_RESIZE_BOTTOMRIGHT
@ SDL_HITTEST_RESIZE_BOTTOMLEFT
@ SDL_HITTEST_RESIZE_RIGHT
@ SDL_HITTEST_RESIZE_TOPLEFT
@ SDL_WINDOW_MOUSE_CAPTURE
@ SDL_WINDOWEVENT_RESIZED
@ SDL_WINDOWEVENT_MINIMIZED
@ SDL_WINDOWEVENT_MAXIMIZED
@ SDL_WINDOWEVENT_RESTORED
@ SDL_WINDOWEVENT_EXPOSED
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
#define WIN_UTF8ToString(S)
#define WIN_StringToUTF8(S)
void WIN_CheckClipboardUpdate(struct SDL_VideoData *data)
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
void WIN_PumpEvents(_THIS)
void WIN_ResetDeadKeys(void)
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata)
void WIN_UpdateKeymap(void)
int Win32_ResizeWindowShape(SDL_Window *window)
SDL_bool g_WindowFrameUsableWhileCursorHidden
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)
EGLImageKHR EGLint EGLint * handle
EGLSurface EGLNativeWindowType * window
static const SDL_Scancode windows_scancode_table[]
SDL_bool relative_mode_warp
SDL_bool touch_mouse_events
SDL_bool was_touch_mouse_events
The structure that defines a point (integer)
union SDL_SysWMmsg::@15 msg
The type used to identify a window.
static char text[MAX_TEXT_LENGTH]
static Uint32 callback(Uint32 interval, void *param)