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 
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  SDL_assert(0 && "This should really be implemented for every target.");
650  return 0;
651  }
652 
653  return mouse->GetGlobalMouseState(x, y);
654 }
655 
656 void
657 SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
658 {
659  SDL_Mouse *mouse = SDL_GetMouse();
660 
661  if (window == NULL) {
662  window = mouse->focus;
663  }
664 
665  if (window == NULL) {
666  return;
667  }
668 
669  if (mouse->WarpMouse) {
670  mouse->WarpMouse(window, x, y);
671  } else {
672  SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
673  }
674 }
675 
676 int
677 SDL_WarpMouseGlobal(int x, int y)
678 {
679  SDL_Mouse *mouse = SDL_GetMouse();
680 
681  if (mouse->WarpMouseGlobal) {
682  return mouse->WarpMouseGlobal(x, y);
683  }
684 
685  return SDL_Unsupported();
686 }
687 
688 static SDL_bool
690 {
691  if (!mouse->SetRelativeMouseMode) {
692  return SDL_TRUE;
693  }
694 
696 }
697 
698 int
700 {
701  SDL_Mouse *mouse = SDL_GetMouse();
702  SDL_Window *focusWindow = SDL_GetKeyboardFocus();
703 
704  if (enabled == mouse->relative_mode) {
705  return 0;
706  }
707 
708  if (enabled && focusWindow) {
709  /* Center it in the focused window to prevent clicks from going through
710  * to background windows.
711  */
712  SDL_SetMouseFocus(focusWindow);
713  SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
714  }
715 
716  /* Set the relative mode */
717  if (!enabled && mouse->relative_mode_warp) {
718  mouse->relative_mode_warp = SDL_FALSE;
719  } else if (enabled && ShouldUseRelativeModeWarp(mouse)) {
720  mouse->relative_mode_warp = SDL_TRUE;
721  } else if (mouse->SetRelativeMouseMode(enabled) < 0) {
722  if (enabled) {
723  /* Fall back to warp mode if native relative mode failed */
724  mouse->relative_mode_warp = SDL_TRUE;
725  }
726  }
727  mouse->relative_mode = enabled;
728  mouse->scale_accum_x = 0.0f;
729  mouse->scale_accum_y = 0.0f;
730 
731  if (mouse->focus) {
732  SDL_UpdateWindowGrab(mouse->focus);
733 
734  /* Put the cursor back to where the application expects it */
735  if (!enabled) {
736  SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
737  }
738  }
739 
740  /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */
742 
743  /* Update cursor visibility */
745 
746  return 0;
747 }
748 
749 SDL_bool
751 {
752  SDL_Mouse *mouse = SDL_GetMouse();
753 
754  return mouse->relative_mode;
755 }
756 
757 int
759 {
760  SDL_Mouse *mouse = SDL_GetMouse();
761  SDL_Window *focusWindow;
762  SDL_bool isCaptured;
763 
764  if (!mouse->CaptureMouse) {
765  return SDL_Unsupported();
766  }
767 
768  focusWindow = SDL_GetKeyboardFocus();
769 
770  isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
771  if (isCaptured == enabled) {
772  return 0; /* already done! */
773  }
774 
775  if (enabled) {
776  if (!focusWindow) {
777  return SDL_SetError("No window has focus");
778  } else if (mouse->CaptureMouse(focusWindow) == -1) {
779  return -1; /* CaptureMouse() should call SetError */
780  }
781  focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
782  } else {
783  if (mouse->CaptureMouse(NULL) == -1) {
784  return -1; /* CaptureMouse() should call SetError */
785  }
786  focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
787  }
788 
789  return 0;
790 }
791 
792 SDL_Cursor *
794  int w, int h, int hot_x, int hot_y)
795 {
798  int x, y;
799  Uint32 *pixel;
800  Uint8 datab = 0, maskb = 0;
801  const Uint32 black = 0xFF000000;
802  const Uint32 white = 0xFFFFFFFF;
803  const Uint32 transparent = 0x00000000;
804 
805  /* Make sure the width is a multiple of 8 */
806  w = ((w + 7) & ~7);
807 
808  /* Create the surface from a bitmap */
809  surface = SDL_CreateRGBSurface(0, w, h, 32,
810  0x00FF0000,
811  0x0000FF00,
812  0x000000FF,
813  0xFF000000);
814  if (!surface) {
815  return NULL;
816  }
817  for (y = 0; y < h; ++y) {
818  pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
819  for (x = 0; x < w; ++x) {
820  if ((x % 8) == 0) {
821  datab = *data++;
822  maskb = *mask++;
823  }
824  if (maskb & 0x80) {
825  *pixel++ = (datab & 0x80) ? black : white;
826  } else {
827  *pixel++ = (datab & 0x80) ? black : transparent;
828  }
829  datab <<= 1;
830  maskb <<= 1;
831  }
832  }
833 
834  cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
835 
836  SDL_FreeSurface(surface);
837 
838  return cursor;
839 }
840 
841 SDL_Cursor *
843 {
844  SDL_Mouse *mouse = SDL_GetMouse();
845  SDL_Surface *temp = NULL;
847 
848  if (!surface) {
849  SDL_SetError("Passed NULL cursor surface");
850  return NULL;
851  }
852 
853  if (!mouse->CreateCursor) {
854  SDL_SetError("Cursors are not currently supported");
855  return NULL;
856  }
857 
858  /* Sanity check the hot spot */
859  if ((hot_x < 0) || (hot_y < 0) ||
860  (hot_x >= surface->w) || (hot_y >= surface->h)) {
861  SDL_SetError("Cursor hot spot doesn't lie within cursor");
862  return NULL;
863  }
864 
865  if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
867  if (!temp) {
868  return NULL;
869  }
870  surface = temp;
871  }
872 
873  cursor = mouse->CreateCursor(surface, hot_x, hot_y);
874  if (cursor) {
875  cursor->next = mouse->cursors;
876  mouse->cursors = cursor;
877  }
878 
879  SDL_FreeSurface(temp);
880 
881  return cursor;
882 }
883 
884 SDL_Cursor *
886 {
887  SDL_Mouse *mouse = SDL_GetMouse();
889 
890  if (!mouse->CreateSystemCursor) {
891  SDL_SetError("CreateSystemCursor is not currently supported");
892  return NULL;
893  }
894 
895  cursor = mouse->CreateSystemCursor(id);
896  if (cursor) {
897  cursor->next = mouse->cursors;
898  mouse->cursors = cursor;
899  }
900 
901  return cursor;
902 }
903 
904 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
905  if this is desired for any reason. This is used when setting
906  the video mode and when the SDL window gains the mouse focus.
907  */
908 void
910 {
911  SDL_Mouse *mouse = SDL_GetMouse();
912 
913  /* Set the new cursor */
914  if (cursor) {
915  /* Make sure the cursor is still valid for this mouse */
916  if (cursor != mouse->def_cursor) {
917  SDL_Cursor *found;
918  for (found = mouse->cursors; found; found = found->next) {
919  if (found == cursor) {
920  break;
921  }
922  }
923  if (!found) {
924  SDL_SetError("Cursor not associated with the current mouse");
925  return;
926  }
927  }
928  mouse->cur_cursor = cursor;
929  } else {
930  if (mouse->focus) {
931  cursor = mouse->cur_cursor;
932  } else {
933  cursor = mouse->def_cursor;
934  }
935  }
936 
937  if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
938  if (mouse->ShowCursor) {
939  mouse->ShowCursor(cursor);
940  }
941  } else {
942  if (mouse->ShowCursor) {
943  mouse->ShowCursor(NULL);
944  }
945  }
946 }
947 
948 SDL_Cursor *
950 {
951  SDL_Mouse *mouse = SDL_GetMouse();
952 
953  if (!mouse) {
954  return NULL;
955  }
956  return mouse->cur_cursor;
957 }
958 
959 SDL_Cursor *
961 {
962  SDL_Mouse *mouse = SDL_GetMouse();
963 
964  if (!mouse) {
965  return NULL;
966  }
967  return mouse->def_cursor;
968 }
969 
970 void
972 {
973  SDL_Mouse *mouse = SDL_GetMouse();
974  SDL_Cursor *curr, *prev;
975 
976  if (!cursor) {
977  return;
978  }
979 
980  if (cursor == mouse->def_cursor) {
981  return;
982  }
983  if (cursor == mouse->cur_cursor) {
984  SDL_SetCursor(mouse->def_cursor);
985  }
986 
987  for (prev = NULL, curr = mouse->cursors; curr;
988  prev = curr, curr = curr->next) {
989  if (curr == cursor) {
990  if (prev) {
991  prev->next = curr->next;
992  } else {
993  mouse->cursors = curr->next;
994  }
995 
996  if (mouse->FreeCursor) {
997  mouse->FreeCursor(curr);
998  }
999  return;
1000  }
1001  }
1002 }
1003 
1004 int
1005 SDL_ShowCursor(int toggle)
1006 {
1007  SDL_Mouse *mouse = SDL_GetMouse();
1008  SDL_bool shown;
1009 
1010  if (!mouse) {
1011  return 0;
1012  }
1013 
1014  shown = mouse->cursor_shown;
1015  if (toggle >= 0) {
1016  if (toggle) {
1017  mouse->cursor_shown = SDL_TRUE;
1018  } else {
1019  mouse->cursor_shown = SDL_FALSE;
1020  }
1021  if (mouse->cursor_shown != shown) {
1023  }
1024  }
1025  return shown;
1026 }
1027 
1028 /* 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: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:112
SDL_Cursor * SDL_GetCursor(void)
Return the active cursor.
Definition: SDL_mouse.c:949
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: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: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:842
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:909
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:677
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:1005
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:793
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:758
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:657
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:960
SDL_bool SDL_GetRelativeMouseMode()
Query whether relative mouse mode is enabled.
Definition: SDL_mouse.c:750
#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:885
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: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:699
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:971
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:271
static SDL_bool ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
Definition: SDL_mouse.c:689
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