SDL 2.0
SDL_windowsmouse.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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_assert.h"
26#include "SDL_windowsvideo.h"
27
28#include "../../events/SDL_mouse_c.h"
29
30
31HCURSOR SDL_cursor = NULL;
32
33static int rawInputEnableCount = 0;
34
35static int
36ToggleRawInput(SDL_bool enabled)
37{
38 RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
39
40 if (enabled) {
41 rawInputEnableCount++;
42 if (rawInputEnableCount > 1) {
43 return 0; /* already done. */
44 }
45 } else {
46 if (rawInputEnableCount == 0) {
47 return 0; /* already done. */
48 }
49 rawInputEnableCount--;
50 if (rawInputEnableCount > 0) {
51 return 0; /* not time to disable yet */
52 }
53 }
54
55 if (!enabled) {
56 rawMouse.dwFlags |= RIDEV_REMOVE;
57 }
58
59 /* (Un)register raw input for mice */
60 if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
61
62 /* Only return an error when registering. If we unregister and fail,
63 then it's probably that we unregistered twice. That's OK. */
64 if (enabled) {
65 return SDL_Unsupported();
66 }
67 }
68 return 0;
69}
70
71
72static SDL_Cursor *
73WIN_CreateDefaultCursor()
74{
76
77 cursor = SDL_calloc(1, sizeof(*cursor));
78 if (cursor) {
79 cursor->driverdata = LoadCursor(NULL, IDC_ARROW);
80 } else {
82 }
83
84 return cursor;
85}
86
87static SDL_Cursor *
88WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
89{
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. */
94 HICON hicon;
95 HDC hdc;
96 BITMAPV4HEADER bmh;
97 LPVOID pixels;
98 LPVOID maskbits;
99 size_t maskbitslen;
100 SDL_bool isstack;
101 ICONINFO ii;
102
103 SDL_zero(bmh);
104 bmh.bV4Size = sizeof(bmh);
105 bmh.bV4Width = surface->w;
106 bmh.bV4Height = -surface->h; /* Invert the image */
107 bmh.bV4Planes = 1;
108 bmh.bV4BitCount = 32;
109 bmh.bV4V4Compression = BI_BITFIELDS;
110 bmh.bV4AlphaMask = 0xFF000000;
111 bmh.bV4RedMask = 0x00FF0000;
112 bmh.bV4GreenMask = 0x0000FF00;
113 bmh.bV4BlueMask = 0x000000FF;
114
115 maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h;
116 maskbits = SDL_small_alloc(Uint8, maskbitslen, &isstack);
117 if (maskbits == NULL) {
119 return NULL;
120 }
121
122 /* AND the cursor against full bits: no change. We already have alpha. */
123 SDL_memset(maskbits, 0xFF, maskbitslen);
124
125 hdc = GetDC(NULL);
126 SDL_zero(ii);
127 ii.fIcon = FALSE;
128 ii.xHotspot = (DWORD)hot_x;
129 ii.yHotspot = (DWORD)hot_y;
130 ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0);
131 ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits);
132 ReleaseDC(NULL, hdc);
133 SDL_small_free(maskbits, isstack);
134
135 SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
136 SDL_assert(surface->pitch == surface->w * 4);
137 SDL_memcpy(pixels, surface->pixels, surface->h * surface->pitch);
138
139 hicon = CreateIconIndirect(&ii);
140
141 DeleteObject(ii.hbmColor);
142 DeleteObject(ii.hbmMask);
143
144 if (!hicon) {
145 WIN_SetError("CreateIconIndirect()");
146 return NULL;
147 }
148
149 cursor = SDL_calloc(1, sizeof(*cursor));
150 if (cursor) {
151 cursor->driverdata = hicon;
152 } else {
153 DestroyIcon(hicon);
155 }
156
157 return cursor;
158}
159
160static SDL_Cursor *
161WIN_CreateSystemCursor(SDL_SystemCursor id)
162{
164 LPCTSTR name;
165
166 switch(id)
167 {
168 default:
169 SDL_assert(0);
170 return NULL;
171 case SDL_SYSTEM_CURSOR_ARROW: name = IDC_ARROW; break;
172 case SDL_SYSTEM_CURSOR_IBEAM: name = IDC_IBEAM; break;
173 case SDL_SYSTEM_CURSOR_WAIT: name = IDC_WAIT; break;
174 case SDL_SYSTEM_CURSOR_CROSSHAIR: name = IDC_CROSS; break;
175 case SDL_SYSTEM_CURSOR_WAITARROW: name = IDC_WAIT; break;
176 case SDL_SYSTEM_CURSOR_SIZENWSE: name = IDC_SIZENWSE; break;
177 case SDL_SYSTEM_CURSOR_SIZENESW: name = IDC_SIZENESW; break;
178 case SDL_SYSTEM_CURSOR_SIZEWE: name = IDC_SIZEWE; break;
179 case SDL_SYSTEM_CURSOR_SIZENS: name = IDC_SIZENS; break;
180 case SDL_SYSTEM_CURSOR_SIZEALL: name = IDC_SIZEALL; break;
181 case SDL_SYSTEM_CURSOR_NO: name = IDC_NO; break;
182 case SDL_SYSTEM_CURSOR_HAND: name = IDC_HAND; break;
183 }
184
185 cursor = SDL_calloc(1, sizeof(*cursor));
186 if (cursor) {
187 HICON hicon;
188
189 hicon = LoadCursor(NULL, name);
190
191 cursor->driverdata = hicon;
192 } else {
194 }
195
196 return cursor;
197}
198
199static void
200WIN_FreeCursor(SDL_Cursor * cursor)
201{
202 HICON hicon = (HICON)cursor->driverdata;
203
204 DestroyIcon(hicon);
206}
207
208static int
209WIN_ShowCursor(SDL_Cursor * cursor)
210{
211 if (cursor) {
212 SDL_cursor = (HCURSOR)cursor->driverdata;
213 } else {
215 }
216 if (SDL_GetMouseFocus() != NULL) {
217 SetCursor(SDL_cursor);
218 }
219 return 0;
220}
221
222static void
223WIN_WarpMouse(SDL_Window * window, int x, int y)
224{
225 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
226 HWND hwnd = data->hwnd;
227 POINT pt;
228
229 /* Don't warp the mouse while we're doing a modal interaction */
230 if (data->in_title_click || data->focus_click_pending) {
231 return;
232 }
233
234 pt.x = x;
235 pt.y = y;
236 ClientToScreen(hwnd, &pt);
237 SetCursorPos(pt.x, pt.y);
238}
239
240static int
241WIN_WarpMouseGlobal(int x, int y)
242{
243 POINT pt;
244
245 pt.x = x;
246 pt.y = y;
247 SetCursorPos(pt.x, pt.y);
248 return 0;
249}
250
251static int
252WIN_SetRelativeMouseMode(SDL_bool enabled)
253{
254 return ToggleRawInput(enabled);
255}
256
257static int
258WIN_CaptureMouse(SDL_Window *window)
259{
260 if (!window) {
261 SDL_Window *focusWin = SDL_GetKeyboardFocus();
262 if (focusWin) {
263 WIN_OnWindowEnter(SDL_GetVideoDevice(), focusWin); /* make sure WM_MOUSELEAVE messages are (re)enabled. */
264 }
265 }
266
267 /* While we were thinking of SetCapture() when designing this API in SDL,
268 we didn't count on the fact that SetCapture() only tracks while the
269 left mouse button is held down! Instead, we listen for raw mouse input
270 and manually query the mouse when it leaves the window. :/ */
271 return ToggleRawInput(window != NULL);
272}
273
274static Uint32
275WIN_GetGlobalMouseState(int *x, int *y)
276{
277 Uint32 retval = 0;
278 POINT pt = { 0, 0 };
279 GetCursorPos(&pt);
280 *x = (int) pt.x;
281 *y = (int) pt.y;
282
283 retval |= GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_BUTTON_LMASK : 0;
284 retval |= GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_BUTTON_RMASK : 0;
285 retval |= GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_BUTTON_MMASK : 0;
286 retval |= GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_BUTTON_X1MASK : 0;
287 retval |= GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_BUTTON_X2MASK : 0;
288
289 return retval;
290}
291
292void
294{
295 SDL_Mouse *mouse = SDL_GetMouse();
296
297 mouse->CreateCursor = WIN_CreateCursor;
298 mouse->CreateSystemCursor = WIN_CreateSystemCursor;
299 mouse->ShowCursor = WIN_ShowCursor;
300 mouse->FreeCursor = WIN_FreeCursor;
301 mouse->WarpMouse = WIN_WarpMouse;
302 mouse->WarpMouseGlobal = WIN_WarpMouseGlobal;
303 mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
304 mouse->CaptureMouse = WIN_CaptureMouse;
305 mouse->GetGlobalMouseState = WIN_GetGlobalMouseState;
306
307 SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
308}
309
310void
312{
313 if (rawInputEnableCount) { /* force RAWINPUT off here. */
314 rawInputEnableCount = 1;
315 ToggleRawInput(SDL_FALSE);
316 }
317}
318
319#endif /* SDL_VIDEO_DRIVER_WINDOWS */
320
321/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
unsigned int size_t
#define SDL_memset
#define SDL_GetKeyboardFocus
#define SDL_free
#define SDL_GetMouseFocus
#define SDL_memcpy
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
int uint32_t uint32_t uint32_t uint32_t uint32_t int drmModeModeInfoPtr mode int uint32_t uint32_t uint32_t uint32_t int32_t hot_x
Definition: SDL_kmsdrmsym.h:57
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:167
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:47
@ SDL_SYSTEM_CURSOR_SIZENS
Definition: SDL_mouse.h:56
@ SDL_SYSTEM_CURSOR_HAND
Definition: SDL_mouse.h:59
@ SDL_SYSTEM_CURSOR_ARROW
Definition: SDL_mouse.h:48
@ SDL_SYSTEM_CURSOR_SIZENWSE
Definition: SDL_mouse.h:53
@ SDL_SYSTEM_CURSOR_SIZENESW
Definition: SDL_mouse.h:54
@ SDL_SYSTEM_CURSOR_IBEAM
Definition: SDL_mouse.h:49
@ SDL_SYSTEM_CURSOR_NO
Definition: SDL_mouse.h:58
@ SDL_SYSTEM_CURSOR_WAITARROW
Definition: SDL_mouse.h:52
@ SDL_SYSTEM_CURSOR_SIZEALL
Definition: SDL_mouse.h:57
@ SDL_SYSTEM_CURSOR_WAIT
Definition: SDL_mouse.h:50
@ SDL_SYSTEM_CURSOR_SIZEWE
Definition: SDL_mouse.h:55
@ SDL_SYSTEM_CURSOR_CROSSHAIR
Definition: SDL_mouse.h:51
#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_X2MASK
Definition: SDL_mouse.h:291
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
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
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint const GLchar * name
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_FALSE
Definition: SDL_stdinc.h:163
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
int WIN_SetError(const char *prefix)
HCURSOR SDL_cursor
void WIN_InitMouse(_THIS)
void WIN_QuitMouse(_THIS)
void WIN_OnWindowEnter(_THIS, SDL_Window *window)
#define NULL
Definition: begin_code.h:167
#define FALSE
Definition: edid-parse.c:34
EGLSurface surface
Definition: eglext.h:248
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
void * driverdata
Definition: SDL_mouse_c.h:33
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
Uint32(* GetGlobalMouseState)(int *x, int *y)
Definition: SDL_mouse_c.h:73
int(* CaptureMouse)(SDL_Window *window)
Definition: SDL_mouse_c.h:70
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
The type used to identify a window.
Definition: SDL_sysvideo.h:74
SDL_bool retval
SDL_Cursor * cursor
Definition: testwm2.c:40