SDL  2.0
SDL_mouse.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 /* General mouse handling code for SDL */
24 
25 #include "SDL_hints.h"
26 #include "SDL_timer.h"
27 #include "SDL_events.h"
28 #include "SDL_events_c.h"
29 #include "../SDL_hints_c.h"
30 #include "../video/SDL_sysvideo.h"
31 #ifdef __WIN32__
32 #include "../core/windows/SDL_windows.h" // For GetDoubleClickTime()
33 #endif
34 #if defined(__OS2__)
35 #define INCL_WIN
36 #include <os2.h>
37 #endif
38 
39 /* #define DEBUG_MOUSE */
40 
41 /* The mouse state */
43 
44 /* for mapping mouse events to touch */
46 
47 static int
48 SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
49 
50 static void SDLCALL
51 SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
52 {
53  SDL_Mouse *mouse = (SDL_Mouse *)userdata;
54 
55  if (hint && *hint) {
56  mouse->double_click_time = SDL_atoi(hint);
57  } else {
58 #ifdef __WIN32__
59  mouse->double_click_time = GetDoubleClickTime();
60 #elif defined(__OS2__)
61  mouse->double_click_time = WinQuerySysValue(HWND_DESKTOP, SV_DBLCLKTIME);
62 #else
63  mouse->double_click_time = 500;
64 #endif
65  }
66 }
67 
68 static void SDLCALL
69 SDL_MouseDoubleClickRadiusChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
70 {
71  SDL_Mouse *mouse = (SDL_Mouse *)userdata;
72 
73  if (hint && *hint) {
74  mouse->double_click_radius = SDL_atoi(hint);
75  } else {
76  mouse->double_click_radius = 32; /* 32 pixels seems about right for touch interfaces */
77  }
78 }
79 
80 static void SDLCALL
81 SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
82 {
83  SDL_Mouse *mouse = (SDL_Mouse *)userdata;
84 
85  if (hint && *hint) {
86  mouse->normal_speed_scale = (float)SDL_atof(hint);
87  } else {
88  mouse->normal_speed_scale = 1.0f;
89  }
90 }
91 
92 static void SDLCALL
93 SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
94 {
95  SDL_Mouse *mouse = (SDL_Mouse *)userdata;
96 
97  if (hint && *hint) {
98  mouse->relative_speed_scale = (float)SDL_atof(hint);
99  } else {
100  mouse->relative_speed_scale = 1.0f;
101  }
102 }
103 
104 static void SDLCALL
105 SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
106 {
107  SDL_Mouse *mouse = (SDL_Mouse *)userdata;
108 
110 }
111 
112 static void SDLCALL
113 SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
114 {
115  SDL_Mouse *mouse = (SDL_Mouse *)userdata;
116  SDL_bool default_value;
117 
118 #if defined(__ANDROID__) || (defined(__IPHONEOS__) && !defined(__TVOS__))
119  default_value = SDL_TRUE;
120 #else
121  default_value = SDL_FALSE;
122 #endif
123  mouse->mouse_touch_events = SDL_GetStringBoolean(hint, default_value);
124 
125  if (mouse->mouse_touch_events) {
127  }
128 }
129 
130 /* Public functions */
131 int
133 {
134  SDL_Mouse *mouse = SDL_GetMouse();
135 
136  SDL_zerop(mouse);
137 
140 
143 
146 
149 
152 
155 
156  mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
157 
158  mouse->cursor_shown = SDL_TRUE;
159 
160  return (0);
161 }
162 
163 void
165 {
166  SDL_Mouse *mouse = SDL_GetMouse();
167 
168  mouse->def_cursor = cursor;
169  if (!mouse->cur_cursor) {
171  }
172 }
173 
174 SDL_Mouse *
176 {
177  return &SDL_mouse;
178 }
179 
180 SDL_Window *
182 {
183  SDL_Mouse *mouse = SDL_GetMouse();
184 
185  return mouse->focus;
186 }
187 
188 #if 0
189 void
190 SDL_ResetMouse(void)
191 {
192  SDL_Mouse *mouse = SDL_GetMouse();
193  Uint8 i;
194 
195 #ifdef DEBUG_MOUSE
196  printf("Resetting mouse\n");
197 #endif
198  for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) {
199  if (mouse->buttonstate & SDL_BUTTON(i)) {
200  SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i);
201  }
202  }
203  SDL_assert(mouse->buttonstate == 0);
204 }
205 #endif
206 
207 void
209 {
210  SDL_Mouse *mouse = SDL_GetMouse();
211 
212  if (mouse->focus == window) {
213  return;
214  }
215 
216  /* Actually, this ends up being a bad idea, because most operating
217  systems have an implicit grab when you press the mouse button down
218  so you can drag things out of the window and then get the mouse up
219  when it happens. So, #if 0...
220  */
221 #if 0
222  if (mouse->focus && !window) {
223  /* We won't get anymore mouse messages, so reset mouse state */
224  SDL_ResetMouse();
225  }
226 #endif
227 
228  /* See if the current window has lost focus */
229  if (mouse->focus) {
231  }
232 
233  mouse->focus = window;
234  mouse->has_position = SDL_FALSE;
235 
236  if (mouse->focus) {
238  }
239 
240  /* Update cursor visibility */
242 }
243 
244 /* Check to see if we need to synthesize focus events */
245 static SDL_bool
246 SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_bool send_mouse_motion)
247 {
248  SDL_Mouse *mouse = SDL_GetMouse();
249  SDL_bool inWindow = SDL_TRUE;
250 
251  if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
252  int w, h;
254  if (x < 0 || y < 0 || x >= w || y >= h) {
255  inWindow = SDL_FALSE;
256  }
257  }
258 
259 /* Linux doesn't give you mouse events outside your window unless you grab
260  the pointer.
261 
262  Windows doesn't give you mouse events outside your window unless you call
263  SetCapture().
264 
265  Both of these are slightly scary changes, so for now we'll punt and if the
266  mouse leaves the window you'll lose mouse focus and reset button state.
267 */
268 #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
269  if (!inWindow && !buttonstate) {
270 #else
271  if (!inWindow) {
272 #endif
273  if (window == mouse->focus) {
274 #ifdef DEBUG_MOUSE
275  printf("Mouse left window, synthesizing move & focus lost event\n");
276 #endif
277  if (send_mouse_motion) {
279  }
281  }
282  return SDL_FALSE;
283  }
284 
285  if (window != mouse->focus) {
286 #ifdef DEBUG_MOUSE
287  printf("Mouse entered window, synthesizing focus gain & move event\n");
288 #endif
290  if (send_mouse_motion) {
292  }
293  }
294  return SDL_TRUE;
295 }
296 
297 int
298 SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
299 {
300  if (window && !relative) {
301  SDL_Mouse *mouse = SDL_GetMouse();
302  if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate, (mouseID == SDL_TOUCH_MOUSEID) ? SDL_FALSE : SDL_TRUE)) {
303  return 0;
304  }
305  }
306 
307  return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y);
308 }
309 
310 static int
311 GetScaledMouseDelta(float scale, int value, float *accum)
312 {
313  if (scale != 1.0f) {
314  *accum += scale * value;
315  if (*accum >= 0.0f) {
316  value = (int)SDL_floor(*accum);
317  } else {
318  value = (int)SDL_ceil(*accum);
319  }
320  *accum -= value;
321  }
322  return value;
323 }
324 
325 static int
326 SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
327 {
328  SDL_Mouse *mouse = SDL_GetMouse();
329  int posted;
330  int xrel;
331  int yrel;
332 
333  /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */
334  if (mouse->mouse_touch_events) {
335  if (mouseID != SDL_TOUCH_MOUSEID && !relative && track_mouse_down) {
336  if (window) {
337  float fx = (float)x / (float)window->w;
338  float fy = (float)y / (float)window->h;
339  SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, window, fx, fy, 1.0f);
340  }
341  }
342  }
343 
344  /* SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer */
345  if (mouse->touch_mouse_events == 0) {
346  if (mouseID == SDL_TOUCH_MOUSEID) {
347  return 0;
348  }
349  }
350 
351  if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
352  int center_x = 0, center_y = 0;
353  SDL_GetWindowSize(window, &center_x, &center_y);
354  center_x /= 2;
355  center_y /= 2;
356  if (x == center_x && y == center_y) {
357  mouse->last_x = center_x;
358  mouse->last_y = center_y;
359  return 0;
360  }
361  SDL_WarpMouseInWindow(window, center_x, center_y);
362  }
363 
364  if (relative) {
365  if (mouse->relative_mode) {
368  } else {
371  }
372  xrel = x;
373  yrel = y;
374  x = (mouse->last_x + xrel);
375  y = (mouse->last_y + yrel);
376  } else {
377  xrel = x - mouse->last_x;
378  yrel = y - mouse->last_y;
379  }
380 
381  /* Ignore relative motion when first positioning the mouse */
382  if (!mouse->has_position) {
383  xrel = 0;
384  yrel = 0;
385  mouse->has_position = SDL_TRUE;
386  } else if (!xrel && !yrel) { /* Drop events that don't change state */
387 #ifdef DEBUG_MOUSE
388  printf("Mouse event didn't change state - dropped!\n");
389 #endif
390  return 0;
391  }
392 
393  /* Ignore relative motion positioning the first touch */
394  if (mouseID == SDL_TOUCH_MOUSEID && !mouse->buttonstate) {
395  xrel = 0;
396  yrel = 0;
397  }
398 
399  /* Update internal mouse coordinates */
400  if (!mouse->relative_mode) {
401  mouse->x = x;
402  mouse->y = y;
403  } else {
404  mouse->x += xrel;
405  mouse->y += yrel;
406  }
407 
408  /* make sure that the pointers find themselves inside the windows,
409  unless we have the mouse captured. */
410  if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
411  int x_max = 0, y_max = 0;
412 
413  /* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */
414  SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
415  --x_max;
416  --y_max;
417 
418  if (mouse->x > x_max) {
419  mouse->x = x_max;
420  }
421  if (mouse->x < 0) {
422  mouse->x = 0;
423  }
424 
425  if (mouse->y > y_max) {
426  mouse->y = y_max;
427  }
428  if (mouse->y < 0) {
429  mouse->y = 0;
430  }
431  }
432 
433  mouse->xdelta += xrel;
434  mouse->ydelta += yrel;
435 
436  /* Move the mouse cursor, if needed */
437  if (mouse->cursor_shown && !mouse->relative_mode &&
438  mouse->MoveCursor && mouse->cur_cursor) {
439  mouse->MoveCursor(mouse->cur_cursor);
440  }
441 
442  /* Post the event, if desired */
443  posted = 0;
446  event.motion.type = SDL_MOUSEMOTION;
447  event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
448  event.motion.which = mouseID;
449  /* Set us pending (or clear during a normal mouse movement event) as having triggered */
451  event.motion.state = mouse->buttonstate;
452  event.motion.x = mouse->x;
453  event.motion.y = mouse->y;
454  event.motion.xrel = xrel;
455  event.motion.yrel = yrel;
456  posted = (SDL_PushEvent(&event) > 0);
457  }
458  if (relative) {
459  mouse->last_x = mouse->x;
460  mouse->last_y = mouse->y;
461  } else {
462  /* Use unclamped values if we're getting events outside the window */
463  mouse->last_x = x;
464  mouse->last_y = y;
465  }
466  return posted;
467 }
468 
470 {
471  if (button >= mouse->num_clickstates) {
472  int i, count = button + 1;
473  SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
474  if (!clickstate) {
475  return NULL;
476  }
477  mouse->clickstate = clickstate;
478 
479  for (i = mouse->num_clickstates; i < count; ++i) {
480  SDL_zero(mouse->clickstate[i]);
481  }
482  mouse->num_clickstates = count;
483  }
484  return &mouse->clickstate[button];
485 }
486 
487 static int
489 {
490  SDL_Mouse *mouse = SDL_GetMouse();
491  int posted;
492  Uint32 type;
493  Uint32 buttonstate = mouse->buttonstate;
494 
495  /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */
496  if (mouse->mouse_touch_events) {
497  if (mouseID != SDL_TOUCH_MOUSEID && button == SDL_BUTTON_LEFT) {
498  if (state == SDL_PRESSED) {
500  } else {
502  }
503  if (window) {
504  float fx = (float)mouse->x / (float)window->w;
505  float fy = (float)mouse->y / (float)window->h;
507  }
508  }
509  }
510 
511  /* SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer */
512  if (mouse->touch_mouse_events == 0) {
513  if (mouseID == SDL_TOUCH_MOUSEID) {
514  return 0;
515  }
516  }
517 
518  /* Figure out which event to perform */
519  switch (state) {
520  case SDL_PRESSED:
522  buttonstate |= SDL_BUTTON(button);
523  break;
524  case SDL_RELEASED:
526  buttonstate &= ~SDL_BUTTON(button);
527  break;
528  default:
529  /* Invalid state -- bail */
530  return 0;
531  }
532 
533  /* We do this after calculating buttonstate so button presses gain focus */
534  if (window && state == SDL_PRESSED) {
535  SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE);
536  }
537 
538  if (buttonstate == mouse->buttonstate) {
539  /* Ignore this event, no state change */
540  return 0;
541  }
542  mouse->buttonstate = buttonstate;
543 
544  if (clicks < 0) {
545  SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
546  if (clickstate) {
547  if (state == SDL_PRESSED) {
548  Uint32 now = SDL_GetTicks();
549 
550  if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + mouse->double_click_time) ||
551  SDL_abs(mouse->x - clickstate->last_x) > mouse->double_click_radius ||
552  SDL_abs(mouse->y - clickstate->last_y) > mouse->double_click_radius) {
553  clickstate->click_count = 0;
554  }
555  clickstate->last_timestamp = now;
556  clickstate->last_x = mouse->x;
557  clickstate->last_y = mouse->y;
558  if (clickstate->click_count < 255) {
559  ++clickstate->click_count;
560  }
561  }
562  clicks = clickstate->click_count;
563  } else {
564  clicks = 1;
565  }
566  }
567 
568  /* Post the event, if desired */
569  posted = 0;
572  event.type = type;
573  event.button.windowID = mouse->focus ? mouse->focus->id : 0;
574  event.button.which = mouseID;
575  event.button.state = state;
576  event.button.button = button;
577  event.button.clicks = (Uint8) SDL_min(clicks, 255);
578  event.button.x = mouse->x;
579  event.button.y = mouse->y;
580  posted = (SDL_PushEvent(&event) > 0);
581  }
582 
583  /* We do this after dispatching event so button releases can lose focus */
584  if (window && state == SDL_RELEASED) {
585  SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE);
586  }
587 
588  return posted;
589 }
590 
591 int
593 {
594  clicks = SDL_max(clicks, 0);
595  return SDL_PrivateSendMouseButton(window, mouseID, state, button, clicks);
596 }
597 
598 int
600 {
601  return SDL_PrivateSendMouseButton(window, mouseID, state, button, -1);
602 }
603 
604 int
606 {
607  SDL_Mouse *mouse = SDL_GetMouse();
608  int posted;
609  int integral_x, integral_y;
610 
611  if (window) {
613  }
614 
615  if (x == 0.0f && y == 0.0f) {
616  return 0;
617  }
618 
619  mouse->accumulated_wheel_x += x;
620  if (mouse->accumulated_wheel_x > 0) {
621  integral_x = (int)SDL_floor(mouse->accumulated_wheel_x);
622  } else if (mouse->accumulated_wheel_x < 0) {
623  integral_x = (int)SDL_ceil(mouse->accumulated_wheel_x);
624  } else {
625  integral_x = 0;
626  }
627  mouse->accumulated_wheel_x -= integral_x;
628 
629  mouse->accumulated_wheel_y += y;
630  if (mouse->accumulated_wheel_y > 0) {
631  integral_y = (int)SDL_floor(mouse->accumulated_wheel_y);
632  } else if (mouse->accumulated_wheel_y < 0) {
633  integral_y = (int)SDL_ceil(mouse->accumulated_wheel_y);
634  } else {
635  integral_y = 0;
636  }
637  mouse->accumulated_wheel_y -= integral_y;
638 
639  /* Post the event, if desired */
640  posted = 0;
643  event.type = SDL_MOUSEWHEEL;
644  event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
645  event.wheel.which = mouseID;
646 #if 0 /* Uncomment this when it goes in for SDL 2.1 */
647  event.wheel.preciseX = x;
648  event.wheel.preciseY = y;
649 #endif
650  event.wheel.x = integral_x;
651  event.wheel.y = integral_y;
652  event.wheel.direction = (Uint32)direction;
653  posted = (SDL_PushEvent(&event) > 0);
654  }
655  return posted;
656 }
657 
658 void
660 {
661  SDL_Cursor *cursor, *next;
662  SDL_Mouse *mouse = SDL_GetMouse();
663 
664  if (mouse->CaptureMouse) {
666  }
668  SDL_ShowCursor(1);
669 
670  cursor = mouse->cursors;
671  while (cursor) {
672  next = cursor->next;
674  cursor = next;
675  }
676  mouse->cursors = NULL;
677  mouse->cur_cursor = NULL;
678 
679  if (mouse->def_cursor && mouse->FreeCursor) {
680  mouse->FreeCursor(mouse->def_cursor);
681  mouse->def_cursor = NULL;
682  }
683 
684  if (mouse->clickstate) {
685  SDL_free(mouse->clickstate);
686  mouse->clickstate = NULL;
687  }
688 
691 
694 }
695 
696 Uint32
697 SDL_GetMouseState(int *x, int *y)
698 {
699  SDL_Mouse *mouse = SDL_GetMouse();
700 
701  if (x) {
702  *x = mouse->x;
703  }
704  if (y) {
705  *y = mouse->y;
706  }
707  return mouse->buttonstate;
708 }
709 
710 Uint32
712 {
713  SDL_Mouse *mouse = SDL_GetMouse();
714 
715  if (x) {
716  *x = mouse->xdelta;
717  }
718  if (y) {
719  *y = mouse->ydelta;
720  }
721  mouse->xdelta = 0;
722  mouse->ydelta = 0;
723  return mouse->buttonstate;
724 }
725 
726 Uint32
728 {
729  SDL_Mouse *mouse = SDL_GetMouse();
730 
731  if (mouse->GetGlobalMouseState) {
732  int tmpx, tmpy;
733 
734  /* make sure these are never NULL for the backend implementations... */
735  if (!x) {
736  x = &tmpx;
737  }
738  if (!y) {
739  y = &tmpy;
740  }
741 
742  *x = *y = 0;
743 
744  return mouse->GetGlobalMouseState(x, y);
745  } else {
746  return SDL_GetMouseState(x, y);
747  }
748 }
749 
750 void
752 {
753  SDL_Mouse *mouse = SDL_GetMouse();
754 
755  if (window == NULL) {
756  window = mouse->focus;
757  }
758 
759  if (window == NULL) {
760  return;
761  }
762 
763  if (mouse->WarpMouse) {
764  mouse->WarpMouse(window, x, y);
765  } else {
766  SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
767  }
768 }
769 
770 int
772 {
773  SDL_Mouse *mouse = SDL_GetMouse();
774 
775  if (mouse->WarpMouseGlobal) {
776  return mouse->WarpMouseGlobal(x, y);
777  }
778 
779  return SDL_Unsupported();
780 }
781 
782 static SDL_bool
784 {
785  if (!mouse->WarpMouse) {
786  /* Need this functionality for relative mode warp implementation */
787  return SDL_FALSE;
788  }
789 
791 }
792 
793 int
795 {
796  SDL_Mouse *mouse = SDL_GetMouse();
797  SDL_Window *focusWindow = SDL_GetKeyboardFocus();
798 
799  if (enabled == mouse->relative_mode) {
800  return 0;
801  }
802 
803  /* Set the relative mode */
804  if (!enabled && mouse->relative_mode_warp) {
805  mouse->relative_mode_warp = SDL_FALSE;
806  } else if (enabled && ShouldUseRelativeModeWarp(mouse)) {
807  mouse->relative_mode_warp = SDL_TRUE;
808  } else if (!mouse->SetRelativeMouseMode || mouse->SetRelativeMouseMode(enabled) < 0) {
809  if (enabled) {
810  /* Fall back to warp mode if native relative mode failed */
811  if (!mouse->WarpMouse) {
812  return SDL_SetError("No relative mode implementation available");
813  }
814  mouse->relative_mode_warp = SDL_TRUE;
815  }
816  }
817  mouse->relative_mode = enabled;
818  mouse->scale_accum_x = 0.0f;
819  mouse->scale_accum_y = 0.0f;
820 
821  if (enabled && focusWindow) {
822  /* Center it in the focused window to prevent clicks from going through
823  * to background windows.
824  */
825  SDL_SetMouseFocus(focusWindow);
826  SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
827  }
828 
829  if (mouse->focus) {
830  SDL_UpdateWindowGrab(mouse->focus);
831 
832  /* Put the cursor back to where the application expects it */
833  if (!enabled) {
834  SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
835  }
836  }
837 
838  /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */
840 
841  /* Update cursor visibility */
843 
844  return 0;
845 }
846 
847 SDL_bool
849 {
850  SDL_Mouse *mouse = SDL_GetMouse();
851 
852  return mouse->relative_mode;
853 }
854 
855 int
857 {
858  SDL_Mouse *mouse = SDL_GetMouse();
859  SDL_Window *focusWindow;
860  SDL_bool isCaptured;
861 
862  if (!mouse->CaptureMouse) {
863  return SDL_Unsupported();
864  }
865 
866  focusWindow = SDL_GetKeyboardFocus();
867 
868  isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
869  if (isCaptured == enabled) {
870  return 0; /* already done! */
871  }
872 
873  if (enabled) {
874  if (!focusWindow) {
875  return SDL_SetError("No window has focus");
876  } else if (mouse->CaptureMouse(focusWindow) == -1) {
877  return -1; /* CaptureMouse() should call SetError */
878  }
879  focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
880  } else {
881  if (mouse->CaptureMouse(NULL) == -1) {
882  return -1; /* CaptureMouse() should call SetError */
883  }
884  focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
885  }
886 
887  return 0;
888 }
889 
890 SDL_Cursor *
892  int w, int h, int hot_x, int hot_y)
893 {
896  int x, y;
897  Uint32 *pixel;
898  Uint8 datab = 0, maskb = 0;
899  const Uint32 black = 0xFF000000;
900  const Uint32 white = 0xFFFFFFFF;
901  const Uint32 transparent = 0x00000000;
902 
903  /* Make sure the width is a multiple of 8 */
904  w = ((w + 7) & ~7);
905 
906  /* Create the surface from a bitmap */
907  surface = SDL_CreateRGBSurface(0, w, h, 32,
908  0x00FF0000,
909  0x0000FF00,
910  0x000000FF,
911  0xFF000000);
912  if (!surface) {
913  return NULL;
914  }
915  for (y = 0; y < h; ++y) {
916  pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
917  for (x = 0; x < w; ++x) {
918  if ((x % 8) == 0) {
919  datab = *data++;
920  maskb = *mask++;
921  }
922  if (maskb & 0x80) {
923  *pixel++ = (datab & 0x80) ? black : white;
924  } else {
925  *pixel++ = (datab & 0x80) ? black : transparent;
926  }
927  datab <<= 1;
928  maskb <<= 1;
929  }
930  }
931 
933 
935 
936  return cursor;
937 }
938 
939 SDL_Cursor *
941 {
942  SDL_Mouse *mouse = SDL_GetMouse();
943  SDL_Surface *temp = NULL;
945 
946  if (!surface) {
947  SDL_SetError("Passed NULL cursor surface");
948  return NULL;
949  }
950 
951  if (!mouse->CreateCursor) {
952  SDL_SetError("Cursors are not currently supported");
953  return NULL;
954  }
955 
956  /* Sanity check the hot spot */
957  if ((hot_x < 0) || (hot_y < 0) ||
958  (hot_x >= surface->w) || (hot_y >= surface->h)) {
959  SDL_SetError("Cursor hot spot doesn't lie within cursor");
960  return NULL;
961  }
962 
963  if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
965  if (!temp) {
966  return NULL;
967  }
968  surface = temp;
969  }
970 
971  cursor = mouse->CreateCursor(surface, hot_x, hot_y);
972  if (cursor) {
973  cursor->next = mouse->cursors;
974  mouse->cursors = cursor;
975  }
976 
977  SDL_FreeSurface(temp);
978 
979  return cursor;
980 }
981 
982 SDL_Cursor *
984 {
985  SDL_Mouse *mouse = SDL_GetMouse();
987 
988  if (!mouse->CreateSystemCursor) {
989  SDL_SetError("CreateSystemCursor is not currently supported");
990  return NULL;
991  }
992 
993  cursor = mouse->CreateSystemCursor(id);
994  if (cursor) {
995  cursor->next = mouse->cursors;
996  mouse->cursors = cursor;
997  }
998 
999  return cursor;
1000 }
1001 
1002 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
1003  if this is desired for any reason. This is used when setting
1004  the video mode and when the SDL window gains the mouse focus.
1005  */
1006 void
1008 {
1009  SDL_Mouse *mouse = SDL_GetMouse();
1010 
1011  /* Set the new cursor */
1012  if (cursor) {
1013  /* Make sure the cursor is still valid for this mouse */
1014  if (cursor != mouse->def_cursor) {
1015  SDL_Cursor *found;
1016  for (found = mouse->cursors; found; found = found->next) {
1017  if (found == cursor) {
1018  break;
1019  }
1020  }
1021  if (!found) {
1022  SDL_SetError("Cursor not associated with the current mouse");
1023  return;
1024  }
1025  }
1026  mouse->cur_cursor = cursor;
1027  } else {
1028  if (mouse->focus) {
1029  cursor = mouse->cur_cursor;
1030  } else {
1031  cursor = mouse->def_cursor;
1032  }
1033  }
1034 
1035  if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
1036  if (mouse->ShowCursor) {
1037  mouse->ShowCursor(cursor);
1038  }
1039  } else {
1040  if (mouse->ShowCursor) {
1041  mouse->ShowCursor(NULL);
1042  }
1043  }
1044 }
1045 
1046 SDL_Cursor *
1048 {
1049  SDL_Mouse *mouse = SDL_GetMouse();
1050 
1051  if (!mouse) {
1052  return NULL;
1053  }
1054  return mouse->cur_cursor;
1055 }
1056 
1057 SDL_Cursor *
1059 {
1060  SDL_Mouse *mouse = SDL_GetMouse();
1061 
1062  if (!mouse) {
1063  return NULL;
1064  }
1065  return mouse->def_cursor;
1066 }
1067 
1068 void
1070 {
1071  SDL_Mouse *mouse = SDL_GetMouse();
1072  SDL_Cursor *curr, *prev;
1073 
1074  if (!cursor) {
1075  return;
1076  }
1077 
1078  if (cursor == mouse->def_cursor) {
1079  return;
1080  }
1081  if (cursor == mouse->cur_cursor) {
1082  SDL_SetCursor(mouse->def_cursor);
1083  }
1084 
1085  for (prev = NULL, curr = mouse->cursors; curr;
1086  prev = curr, curr = curr->next) {
1087  if (curr == cursor) {
1088  if (prev) {
1089  prev->next = curr->next;
1090  } else {
1091  mouse->cursors = curr->next;
1092  }
1093 
1094  if (mouse->FreeCursor) {
1095  mouse->FreeCursor(curr);
1096  }
1097  return;
1098  }
1099  }
1100 }
1101 
1102 int
1103 SDL_ShowCursor(int toggle)
1104 {
1105  SDL_Mouse *mouse = SDL_GetMouse();
1106  SDL_bool shown;
1107 
1108  if (!mouse) {
1109  return 0;
1110  }
1111 
1112  shown = mouse->cursor_shown;
1113  if (toggle >= 0) {
1114  if (toggle) {
1115  mouse->cursor_shown = SDL_TRUE;
1116  } else {
1117  mouse->cursor_shown = SDL_FALSE;
1118  }
1119  if (mouse->cursor_shown != shown) {
1121  }
1122  }
1123  return shown;
1124 }
1125 
1126 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
#define SDL_SetError
#define SDL_abs
#define SDL_GetWindowSize
#define SDL_DelHintCallback
#define SDL_PushEvent
#define SDL_floor
#define SDL_GetKeyboardFocus
#define SDL_FlushEvent
#define SDL_atof
#define SDL_realloc
#define SDL_ConvertSurfaceFormat
#define SDL_free
#define SDL_GetHintBoolean
#define SDL_CreateRGBSurface
#define SDL_FreeSurface
#define SDL_atoi
#define SDL_AddHintCallback
#define SDL_ceil
#define SDL_Unsupported()
Definition: SDL_error.h:89
@ SDL_MOUSEMOTION
Definition: SDL_events.h:107
@ SDL_MOUSEBUTTONUP
Definition: SDL_events.h:109
@ SDL_MOUSEWHEEL
Definition: SDL_events.h:110
@ SDL_MOUSEBUTTONDOWN
Definition: SDL_events.h:108
#define SDL_GetEventState(type)
Definition: SDL_events.h:808
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_ENABLE
Definition: SDL_events.h:795
#define SDL_PRESSED
Definition: SDL_events.h:50
SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value)
Definition: SDL_hints.c:123
#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE
A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in rela...
Definition: SDL_hints.h:310
#define SDL_HINT_MOUSE_TOUCH_EVENTS
A variable controlling whether mouse events should generate synthetic touch events.
Definition: SDL_hints.h:369
#define SDL_HINT_TOUCH_MOUSE_EVENTS
A variable controlling whether touch events should generate synthetic mouse events.
Definition: SDL_hints.h:359
#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME
A variable setting the double click time, in milliseconds.
Definition: SDL_hints.h:300
#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS
A variable setting the double click radius, in pixels.
Definition: SDL_hints.h:305
#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP
A variable controlling whether relative mouse mode is implemented using mouse warping.
Definition: SDL_hints.h:337
#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE
A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode.
Definition: SDL_hints.h:315
#define SDLCALL
Definition: SDL_internal.h:49
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
static void SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:51
static SDL_bool ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
Definition: SDL_mouse.c:783
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:599
static int SDL_PrivateSendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
Definition: SDL_mouse.c:488
static void SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:113
SDL_Cursor * SDL_GetDefaultCursor(void)
Return the default cursor.
Definition: SDL_mouse.c:1058
static void SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:105
SDL_Cursor * SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y)
Create a cursor, using the specified bitmap data and mask (in MSB format).
Definition: SDL_mouse.c:891
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:175
void SDL_FreeCursor(SDL_Cursor *cursor)
Frees a cursor created with SDL_CreateCursor() or similar functions.
Definition: SDL_mouse.c:1069
Uint32 SDL_GetRelativeMouseState(int *x, int *y)
Retrieve the relative state of the mouse.
Definition: SDL_mouse.c:711
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:164
int SDL_ShowCursor(int toggle)
Toggle whether or not the cursor is shown.
Definition: SDL_mouse.c:1103
SDL_Cursor * SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
Create a color cursor.
Definition: SDL_mouse.c:940
void SDL_SetCursor(SDL_Cursor *cursor)
Set the active cursor.
Definition: SDL_mouse.c:1007
static void SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:93
Uint32 SDL_GetMouseState(int *x, int *y)
Retrieve the current state of the mouse.
Definition: SDL_mouse.c:697
void SDL_WarpMouseInWindow(SDL_Window *window, int x, int y)
Moves the mouse to the given position within the window.
Definition: SDL_mouse.c:751
int SDL_SendMouseButtonClicks(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
Definition: SDL_mouse.c:592
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:208
static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, int x, int y, Uint32 buttonstate, SDL_bool send_mouse_motion)
Definition: SDL_mouse.c:246
static void SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:81
static int GetScaledMouseDelta(float scale, int value, float *accum)
Definition: SDL_mouse.c:311
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:605
static SDL_MouseClickState * GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
Definition: SDL_mouse.c:469
static SDL_bool track_mouse_down
Definition: SDL_mouse.c:45
int SDL_CaptureMouse(SDL_bool enabled)
Capture the mouse, to track input outside an SDL window.
Definition: SDL_mouse.c:856
SDL_Window * SDL_GetMouseFocus(void)
Get the window which currently has mouse focus.
Definition: SDL_mouse.c:181
SDL_Cursor * SDL_GetCursor(void)
Return the active cursor.
Definition: SDL_mouse.c:1047
int SDL_WarpMouseGlobal(int x, int y)
Moves the mouse to the given position in global screen space.
Definition: SDL_mouse.c:771
SDL_Cursor * SDL_CreateSystemCursor(SDL_SystemCursor id)
Create a system cursor.
Definition: SDL_mouse.c:983
int SDL_MouseInit(void)
Definition: SDL_mouse.c:132
SDL_bool SDL_GetRelativeMouseMode()
Query whether relative mouse mode is enabled.
Definition: SDL_mouse.c:848
static void SDL_MouseDoubleClickRadiusChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_mouse.c:69
int SDL_SetRelativeMouseMode(SDL_bool enabled)
Set relative mouse mode.
Definition: SDL_mouse.c:794
Uint32 SDL_GetGlobalMouseState(int *x, int *y)
Get the current state of the mouse, in relation to the desktop.
Definition: SDL_mouse.c:727
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:298
void SDL_MouseQuit(void)
Definition: SDL_mouse.c:659
static SDL_Mouse SDL_mouse
Definition: SDL_mouse.c:42
static int SDL_PrivateSendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:326
SDL_SystemCursor
Cursor types for SDL_CreateSystemCursor().
Definition: SDL_mouse.h:47
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
SDL_MouseWheelDirection
Scroll direction types for the Scroll event.
Definition: SDL_mouse.h:67
#define SDL_BUTTON(X)
Definition: SDL_mouse.h:281
Uint32 SDL_MouseID
Definition: SDL_mouse_c.h:28
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
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
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
struct _cl_event * event
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLenum GLenum GLenum GLenum scale
GLuint const GLchar * name
GLsizei const GLfloat * value
GLenum GLint GLuint mask
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:257
#define SDL_zero(x)
Definition: SDL_stdinc.h:426
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
#define SDL_zerop(x)
Definition: SDL_stdinc.h:427
#define SDL_min(x, y)
Definition: SDL_stdinc.h:412
uint32_t Uint32
Definition: SDL_stdinc.h:209
#define SDL_max(x, y)
Definition: SDL_stdinc.h:413
void SDL_UpdateWindowGrab(SDL_Window *window)
Definition: SDL_video.c:2636
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:241
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:154
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure)
Definition: SDL_touch.c:355
#define SDL_MOUSE_TOUCHID
Definition: SDL_touch.h:64
@ SDL_TOUCH_DEVICE_DIRECT
Definition: SDL_touch.h:47
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:61
@ SDL_WINDOW_MOUSE_CAPTURE
Definition: SDL_video.h:115
@ SDL_WINDOWEVENT_LEAVE
Definition: SDL_video.h:164
@ SDL_WINDOWEVENT_ENTER
Definition: SDL_video.h:163
struct xkb_state * state
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
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)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
EGLSurface surface
Definition: eglext.h:248
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
struct SDL_Cursor * next
Definition: SDL_mouse_c.h:32
SDL_bool has_position
Definition: SDL_mouse_c.h:86
float scale_accum_x
Definition: SDL_mouse_c.h:91
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
SDL_MouseID mouseID
Definition: SDL_mouse_c.h:76
SDL_Cursor * cur_cursor
Definition: SDL_mouse_c.h:105
float accumulated_wheel_x
Definition: SDL_mouse_c.h:83
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:61
int last_y
Definition: SDL_mouse_c.h:82
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:46
SDL_bool relative_mode
Definition: SDL_mouse_c.h:87
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:58
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:52
SDL_Window * focus
Definition: SDL_mouse_c.h:77
int num_clickstates
Definition: SDL_mouse_c.h:100
SDL_MouseClickState * clickstate
Definition: SDL_mouse_c.h:101
int last_x
Definition: SDL_mouse_c.h:82
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:88
SDL_bool cursor_shown
Definition: SDL_mouse_c.h:106
Uint32 double_click_time
Definition: SDL_mouse_c.h:93
SDL_bool touch_mouse_events
Definition: SDL_mouse_c.h:95
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
SDL_Cursor *(* CreateSystemCursor)(SDL_SystemCursor id)
Definition: SDL_mouse_c.h:49
Uint32(* GetGlobalMouseState)(int *x, int *y)
Definition: SDL_mouse_c.h:73
void(* MoveCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:55
float relative_speed_scale
Definition: SDL_mouse_c.h:90
int double_click_radius
Definition: SDL_mouse_c.h:94
SDL_Cursor * def_cursor
Definition: SDL_mouse_c.h:104
float accumulated_wheel_y
Definition: SDL_mouse_c.h:84
float scale_accum_y
Definition: SDL_mouse_c.h:92
int(* CaptureMouse)(SDL_Window *window)
Definition: SDL_mouse_c.h:70
int ydelta
Definition: SDL_mouse_c.h:81
SDL_bool was_touch_mouse_events
Definition: SDL_mouse_c.h:97
Uint32 buttonstate
Definition: SDL_mouse_c.h:85
int xdelta
Definition: SDL_mouse_c.h:80
SDL_bool mouse_touch_events
Definition: SDL_mouse_c.h:96
float normal_speed_scale
Definition: SDL_mouse_c.h:89
SDL_Cursor * cursors
Definition: SDL_mouse_c.h:103
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
The type used to identify a window.
Definition: SDL_sysvideo.h:75
Uint32 flags
Definition: SDL_sysvideo.h:84
Uint32 id
Definition: SDL_sysvideo.h:77
SDL_Texture * button
SDL_Cursor * cursor
Definition: testwm2.c:40
General event structure.
Definition: SDL_events.h:592
typedef int(__stdcall *FARPROC)()