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