SDL  2.0
SDL_windowsmouse.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 
31 HCURSOR SDL_cursor = NULL;
32 
33 static int rawInputEnableCount = 0;
34 
35 static int
36 ToggleRawInput(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 
72 static SDL_Cursor *
73 WIN_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 
87 static SDL_Cursor *
88 WIN_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) {
118  SDL_OutOfMemory();
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);
154  SDL_OutOfMemory();
155  }
156 
157  return cursor;
158 }
159 
160 static SDL_Cursor *
161 WIN_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 {
193  SDL_OutOfMemory();
194  }
195 
196  return cursor;
197 }
198 
199 static void
200 WIN_FreeCursor(SDL_Cursor * cursor)
201 {
202  HICON hicon = (HICON)cursor->driverdata;
203 
204  DestroyIcon(hicon);
205  SDL_free(cursor);
206 }
207 
208 static int
209 WIN_ShowCursor(SDL_Cursor * cursor)
210 {
211  if (cursor) {
212  SDL_cursor = (HCURSOR)cursor->driverdata;
213  } else {
214  SDL_cursor = NULL;
215  }
216  if (SDL_GetMouseFocus() != NULL) {
217  SetCursor(SDL_cursor);
218  }
219  return 0;
220 }
221 
222 static void
223 WIN_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 
240 static int
241 WIN_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 
251 static int
252 WIN_SetRelativeMouseMode(SDL_bool enabled)
253 {
254  return ToggleRawInput(enabled);
255 }
256 
257 static int
258 WIN_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 
274 static Uint32
275 WIN_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 
292 void
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 
310 void
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: */
SDL_GetMouse
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:170
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:418
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_Mouse::WarpMouseGlobal
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
SDL_SYSTEM_CURSOR_HAND
@ SDL_SYSTEM_CURSOR_HAND
Definition: SDL_mouse.h:59
SDL_Mouse::CaptureMouse
int(* CaptureMouse)(SDL_Window *window)
Definition: SDL_mouse_c.h:70
SDL_small_free
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
SDL_Cursor
Definition: SDL_mouse_c.h:31
SDL_SYSTEM_CURSOR_WAITARROW
@ SDL_SYSTEM_CURSOR_WAITARROW
Definition: SDL_mouse.h:52
if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Definition: pixman-arm-neon-asm.h:469
NULL
#define NULL
Definition: begin_code.h:167
surface
EGLSurface surface
Definition: eglext.h:248
SDL_SYSTEM_CURSOR_CROSSHAIR
@ SDL_SYSTEM_CURSOR_CROSSHAIR
Definition: SDL_mouse.h:51
SDL_SYSTEM_CURSOR_SIZENESW
@ SDL_SYSTEM_CURSOR_SIZENESW
Definition: SDL_mouse.h:54
size_t
unsigned int size_t
Definition: SDL_config_windows.h:68
WIN_QuitMouse
void WIN_QuitMouse(_THIS)
SDL_BUTTON_RMASK
#define SDL_BUTTON_RMASK
Definition: SDL_mouse.h:289
SDL_WindowData
Definition: SDL_androidwindow.h:39
SDL_BUTTON_X2MASK
#define SDL_BUTTON_X2MASK
Definition: SDL_mouse.h:291
SDL_Mouse::SetRelativeMouseMode
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_small_alloc
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
SDL_Cursor::driverdata
void * driverdata
Definition: SDL_mouse_c.h:33
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:75
SDL_GetKeyboardFocus
#define SDL_GetKeyboardFocus
Definition: SDL_dynapi_overrides.h:216
SDL_cursor
HCURSOR SDL_cursor
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
SDL_windowsvideo.h
retval
SDL_bool retval
Definition: testgamecontroller.c:65
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_Mouse::WarpMouse
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:663
SDL_SYSTEM_CURSOR_SIZEALL
@ SDL_SYSTEM_CURSOR_SIZEALL
Definition: SDL_mouse.h:57
SDL_SystemCursor
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:47
SDL_assert.h
SDL_BUTTON_LMASK
#define SDL_BUTTON_LMASK
Definition: SDL_mouse.h:287
SDL_SYSTEM_CURSOR_IBEAM
@ SDL_SYSTEM_CURSOR_IBEAM
Definition: SDL_mouse.h:49
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_Mouse
Definition: SDL_mouse_c.h:44
SDL_Mouse::CreateSystemCursor
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
SDL_PIXELFORMAT_ARGB8888
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:251
hot_x
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
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_BUTTON_X1MASK
#define SDL_BUTTON_X1MASK
Definition: SDL_mouse.h:290
pixels
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
cursor
SDL_Cursor * cursor
Definition: testwm2.c:40
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_Mouse::ShowCursor
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_SYSTEM_CURSOR_NO
@ SDL_SYSTEM_CURSOR_NO
Definition: SDL_mouse.h:58
SDL_SetDefaultCursor
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:159
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
WIN_SetError
int WIN_SetError(const char *prefix)
SDL_SYSTEM_CURSOR_WAIT
@ SDL_SYSTEM_CURSOR_WAIT
Definition: SDL_mouse.h:50
SDL_GetMouseFocus
#define SDL_GetMouseFocus
Definition: SDL_dynapi_overrides.h:245
WIN_InitMouse
void WIN_InitMouse(_THIS)
SDL_Mouse::FreeCursor
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
SDL_Mouse::CreateCursor
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
SDL_Mouse::GetGlobalMouseState
Uint32(* GetGlobalMouseState)(int *x, int *y)
Definition: SDL_mouse_c.h:73
SDL_SYSTEM_CURSOR_SIZEWE
@ SDL_SYSTEM_CURSOR_SIZEWE
Definition: SDL_mouse.h:55
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: SDL_opengl_glext.h:2482
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_GetVideoDevice
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:586
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_WindowData::hwnd
HWND hwnd
Definition: SDL_windowswindow.h:33
SDL_SYSTEM_CURSOR_SIZENWSE
@ SDL_SYSTEM_CURSOR_SIZENWSE
Definition: SDL_mouse.h:53
SDL_SYSTEM_CURSOR_ARROW
@ SDL_SYSTEM_CURSOR_ARROW
Definition: SDL_mouse.h:48
BI_BITFIELDS
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
SDL_SYSTEM_CURSOR_SIZENS
@ SDL_SYSTEM_CURSOR_SIZENS
Definition: SDL_mouse.h:56
SDL_BUTTON_MMASK
#define SDL_BUTTON_MMASK
Definition: SDL_mouse.h:288
WIN_OnWindowEnter
void WIN_OnWindowEnter(_THIS, SDL_Window *window)
FALSE
#define FALSE
Definition: edid-parse.c:34