2 Simple DirectMedia Layer
3 Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_WINDOWS
25 #include "SDL_assert.h"
26 #include "SDL_windowsvideo.h"
28 #include "../../events/SDL_mouse_c.h"
31 HCURSOR SDL_cursor = NULL;
33 static int rawInputEnableCount = 0;
36 ToggleRawInput(SDL_bool enabled)
38 RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
41 rawInputEnableCount++;
42 if (rawInputEnableCount > 1) {
43 return 0; /* already done. */
46 if (rawInputEnableCount == 0) {
47 return 0; /* already done. */
49 rawInputEnableCount--;
50 if (rawInputEnableCount > 0) {
51 return 0; /* not time to disable yet */
56 rawMouse.dwFlags |= RIDEV_REMOVE;
59 /* (Un)register raw input for mice */
60 if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
62 /* Only return an error when registering. If we unregister and fail,
63 then it's probably that we unregistered twice. That's OK. */
65 return SDL_Unsupported();
73 WIN_CreateDefaultCursor()
77 cursor = SDL_calloc(1, sizeof(*cursor));
79 cursor->driverdata = LoadCursor(NULL, IDC_ARROW);
88 WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
90 /* msdn says cursor mask has to be padded out to word alignment. Not sure
91 if that means machine word or WORD, but this handles either case. */
92 const size_t pad = (sizeof (size_t) * 8); /* 32 or 64, or whatever. */
103 bmh.bV4Size = sizeof(bmh);
104 bmh.bV4Width = surface->w;
105 bmh.bV4Height = -surface->h; /* Invert the image */
107 bmh.bV4BitCount = 32;
108 bmh.bV4V4Compression = BI_BITFIELDS;
109 bmh.bV4AlphaMask = 0xFF000000;
110 bmh.bV4RedMask = 0x00FF0000;
111 bmh.bV4GreenMask = 0x0000FF00;
112 bmh.bV4BlueMask = 0x000000FF;
114 maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h;
115 maskbits = SDL_stack_alloc(Uint8,maskbitslen);
116 if (maskbits == NULL) {
121 /* AND the cursor against full bits: no change. We already have alpha. */
122 SDL_memset(maskbits, 0xFF, maskbitslen);
127 ii.xHotspot = (DWORD)hot_x;
128 ii.yHotspot = (DWORD)hot_y;
129 ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0);
130 ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits);
131 ReleaseDC(NULL, hdc);
132 SDL_stack_free(maskbits);
134 SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
135 SDL_assert(surface->pitch == surface->w * 4);
136 SDL_memcpy(pixels, surface->pixels, surface->h * surface->pitch);
138 hicon = CreateIconIndirect(&ii);
140 DeleteObject(ii.hbmColor);
141 DeleteObject(ii.hbmMask);
144 WIN_SetError("CreateIconIndirect()");
148 cursor = SDL_calloc(1, sizeof(*cursor));
150 cursor->driverdata = hicon;
160 WIN_CreateSystemCursor(SDL_SystemCursor id)
170 case SDL_SYSTEM_CURSOR_ARROW: name = IDC_ARROW; break;
171 case SDL_SYSTEM_CURSOR_IBEAM: name = IDC_IBEAM; break;
172 case SDL_SYSTEM_CURSOR_WAIT: name = IDC_WAIT; break;
173 case SDL_SYSTEM_CURSOR_CROSSHAIR: name = IDC_CROSS; break;
174 case SDL_SYSTEM_CURSOR_WAITARROW: name = IDC_WAIT; break;
175 case SDL_SYSTEM_CURSOR_SIZENWSE: name = IDC_SIZENWSE; break;
176 case SDL_SYSTEM_CURSOR_SIZENESW: name = IDC_SIZENESW; break;
177 case SDL_SYSTEM_CURSOR_SIZEWE: name = IDC_SIZEWE; break;
178 case SDL_SYSTEM_CURSOR_SIZENS: name = IDC_SIZENS; break;
179 case SDL_SYSTEM_CURSOR_SIZEALL: name = IDC_SIZEALL; break;
180 case SDL_SYSTEM_CURSOR_NO: name = IDC_NO; break;
181 case SDL_SYSTEM_CURSOR_HAND: name = IDC_HAND; break;
184 cursor = SDL_calloc(1, sizeof(*cursor));
188 hicon = LoadCursor(NULL, name);
190 cursor->driverdata = hicon;
199 WIN_FreeCursor(SDL_Cursor * cursor)
201 HICON hicon = (HICON)cursor->driverdata;
208 WIN_ShowCursor(SDL_Cursor * cursor)
211 SDL_cursor = (HCURSOR)cursor->driverdata;
215 if (SDL_GetMouseFocus() != NULL) {
216 SetCursor(SDL_cursor);
222 WIN_WarpMouse(SDL_Window * window, int x, int y)
224 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
225 HWND hwnd = data->hwnd;
228 /* Don't warp the mouse while we're doing a modal interaction */
229 if (data->in_title_click || data->focus_click_pending) {
235 ClientToScreen(hwnd, &pt);
236 SetCursorPos(pt.x, pt.y);
240 WIN_WarpMouseGlobal(int x, int y)
246 SetCursorPos(pt.x, pt.y);
251 WIN_SetRelativeMouseMode(SDL_bool enabled)
253 return ToggleRawInput(enabled);
257 WIN_CaptureMouse(SDL_Window *window)
260 SDL_Window *focusWin = SDL_GetKeyboardFocus();
262 WIN_OnWindowEnter(SDL_GetVideoDevice(), focusWin); /* make sure WM_MOUSELEAVE messages are (re)enabled. */
266 /* While we were thinking of SetCapture() when designing this API in SDL,
267 we didn't count on the fact that SetCapture() only tracks while the
268 left mouse button is held down! Instead, we listen for raw mouse input
269 and manually query the mouse when it leaves the window. :/ */
270 return ToggleRawInput(window != NULL);
274 WIN_GetGlobalMouseState(int *x, int *y)
282 retval |= GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_BUTTON_LMASK : 0;
283 retval |= GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_BUTTON_RMASK : 0;
284 retval |= GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_BUTTON_MMASK : 0;
285 retval |= GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_BUTTON_X1MASK : 0;
286 retval |= GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_BUTTON_X2MASK : 0;
294 SDL_Mouse *mouse = SDL_GetMouse();
296 mouse->CreateCursor = WIN_CreateCursor;
297 mouse->CreateSystemCursor = WIN_CreateSystemCursor;
298 mouse->ShowCursor = WIN_ShowCursor;
299 mouse->FreeCursor = WIN_FreeCursor;
300 mouse->WarpMouse = WIN_WarpMouse;
301 mouse->WarpMouseGlobal = WIN_WarpMouseGlobal;
302 mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
303 mouse->CaptureMouse = WIN_CaptureMouse;
304 mouse->GetGlobalMouseState = WIN_GetGlobalMouseState;
306 SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
308 SDL_SetDoubleClickTime(GetDoubleClickTime());
314 if (rawInputEnableCount) { /* force RAWINPUT off here. */
315 rawInputEnableCount = 1;
316 ToggleRawInput(SDL_FALSE);
320 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
322 /* vi: set ts=4 sw=4 expandtab: */