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