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