2 Simple DirectMedia Layer
3 Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 /* General mouse handling code for SDL */
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"
32 /* #define DEBUG_MOUSE */
35 static SDL_Mouse SDL_mouse;
36 static Uint32 SDL_double_click_time = 500;
37 static int SDL_double_click_radius = 1;
40 SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
43 SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
45 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
48 mouse->normal_speed_scale = (float)SDL_atof(hint);
50 mouse->normal_speed_scale = 1.0f;
55 SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
57 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
60 mouse->relative_speed_scale = (float)SDL_atof(hint);
62 mouse->relative_speed_scale = 1.0f;
67 SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
69 SDL_Mouse *mouse = (SDL_Mouse *)userdata;
71 if (hint && (*hint == '0' || SDL_strcasecmp(hint, "false") == 0)) {
72 mouse->touch_mouse_events = SDL_FALSE;
74 mouse->touch_mouse_events = SDL_TRUE;
78 /* Public functions */
82 SDL_Mouse *mouse = SDL_GetMouse();
86 SDL_AddHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
87 SDL_MouseNormalSpeedScaleChanged, mouse);
89 SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
90 SDL_MouseRelativeSpeedScaleChanged, mouse);
92 SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
93 SDL_TouchMouseEventsChanged, mouse);
95 mouse->cursor_shown = SDL_TRUE;
101 SDL_SetDefaultCursor(SDL_Cursor * cursor)
103 SDL_Mouse *mouse = SDL_GetMouse();
105 mouse->def_cursor = cursor;
106 if (!mouse->cur_cursor) {
107 SDL_SetCursor(cursor);
118 SDL_SetDoubleClickTime(Uint32 interval)
120 SDL_double_click_time = interval;
124 SDL_GetMouseFocus(void)
126 SDL_Mouse *mouse = SDL_GetMouse();
135 SDL_Mouse *mouse = SDL_GetMouse();
139 printf("Resetting mouse\n");
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);
146 SDL_assert(mouse->buttonstate == 0);
151 SDL_SetMouseFocus(SDL_Window * window)
153 SDL_Mouse *mouse = SDL_GetMouse();
155 if (mouse->focus == window) {
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...
165 if (mouse->focus && !window) {
166 /* We won't get anymore mouse messages, so reset mouse state */
171 /* See if the current window has lost focus */
173 SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
176 mouse->focus = window;
177 mouse->has_position = SDL_FALSE;
180 SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
183 /* Update cursor visibility */
187 /* Check to see if we need to synthesize focus events */
189 SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
191 SDL_Mouse *mouse = SDL_GetMouse();
192 SDL_bool inWindow = SDL_TRUE;
194 if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
196 SDL_GetWindowSize(window, &w, &h);
197 if (x < 0 || y < 0 || x >= w || y >= h) {
198 inWindow = SDL_FALSE;
202 /* Linux doesn't give you mouse events outside your window unless you grab
205 Windows doesn't give you mouse events outside your window unless you call
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.
211 #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
212 if (!inWindow && !buttonstate) {
216 if (window == mouse->focus) {
218 printf("Mouse left window, synthesizing move & focus lost event\n");
220 SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
221 SDL_SetMouseFocus(NULL);
226 if (window != mouse->focus) {
228 printf("Mouse entered window, synthesizing focus gain & move event\n");
230 SDL_SetMouseFocus(window);
231 SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
237 SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
239 if (window && !relative) {
240 SDL_Mouse *mouse = SDL_GetMouse();
241 if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
246 return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y);
250 GetScaledMouseDelta(float scale, int value, float *accum)
253 *accum += scale * value;
254 if (*accum >= 0.0f) {
255 value = (int)SDL_floor(*accum);
257 value = (int)SDL_ceil(*accum);
265 SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
267 SDL_Mouse *mouse = SDL_GetMouse();
272 if (mouseID == SDL_TOUCH_MOUSEID && !mouse->touch_mouse_events) {
276 if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
277 int center_x = 0, center_y = 0;
278 SDL_GetWindowSize(window, ¢er_x, ¢er_y);
281 if (x == center_x && y == center_y) {
282 mouse->last_x = center_x;
283 mouse->last_y = center_y;
286 SDL_WarpMouseInWindow(window, center_x, center_y);
290 if (mouse->relative_mode) {
291 x = GetScaledMouseDelta(mouse->relative_speed_scale, x, &mouse->scale_accum_x);
292 y = GetScaledMouseDelta(mouse->relative_speed_scale, y, &mouse->scale_accum_y);
294 x = GetScaledMouseDelta(mouse->normal_speed_scale, x, &mouse->scale_accum_x);
295 y = GetScaledMouseDelta(mouse->normal_speed_scale, y, &mouse->scale_accum_y);
299 x = (mouse->last_x + xrel);
300 y = (mouse->last_y + yrel);
302 xrel = x - mouse->last_x;
303 yrel = y - mouse->last_y;
306 /* Drop events that don't change state */
307 if (!xrel && !yrel) {
309 printf("Mouse event didn't change state - dropped!\n");
314 /* Ignore relative motion when first positioning the mouse */
315 if (!mouse->has_position) {
318 mouse->has_position = SDL_TRUE;
321 /* Ignore relative motion positioning the first touch */
322 if (mouseID == SDL_TOUCH_MOUSEID && !mouse->buttonstate) {
327 /* Update internal mouse coordinates */
328 if (!mouse->relative_mode) {
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;
341 /* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */
342 SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
346 if (mouse->x > x_max) {
353 if (mouse->y > y_max) {
361 mouse->xdelta += xrel;
362 mouse->ydelta += yrel;
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);
370 /* Post the event, if desired */
372 if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) {
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);
385 mouse->last_x = mouse->x;
386 mouse->last_y = mouse->y;
388 /* Use unclamped values if we're getting events outside the window */
395 static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
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));
403 mouse->clickstate = clickstate;
405 for (i = mouse->num_clickstates; i < count; ++i) {
406 SDL_zero(mouse->clickstate[i]);
408 mouse->num_clickstates = count;
410 return &mouse->clickstate[button];
414 SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
416 SDL_Mouse *mouse = SDL_GetMouse();
419 Uint32 buttonstate = mouse->buttonstate;
421 if (mouseID == SDL_TOUCH_MOUSEID && !mouse->touch_mouse_events) {
425 /* Figure out which event to perform */
428 type = SDL_MOUSEBUTTONDOWN;
429 buttonstate |= SDL_BUTTON(button);
432 type = SDL_MOUSEBUTTONUP;
433 buttonstate &= ~SDL_BUTTON(button);
436 /* Invalid state -- bail */
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);
445 if (buttonstate == mouse->buttonstate) {
446 /* Ignore this event, no state change */
449 mouse->buttonstate = buttonstate;
452 SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
454 if (state == SDL_PRESSED) {
455 Uint32 now = SDL_GetTicks();
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;
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;
469 clicks = clickstate->click_count;
475 /* Post the event, if desired */
477 if (SDL_GetEventState(type) == SDL_ENABLE) {
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);
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);
499 SDL_SendMouseButtonClicks(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
501 clicks = SDL_max(clicks, 0);
502 return SDL_PrivateSendMouseButton(window, mouseID, state, button, clicks);
506 SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
508 return SDL_PrivateSendMouseButton(window, mouseID, state, button, -1);
512 SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
514 SDL_Mouse *mouse = SDL_GetMouse();
516 int integral_x, integral_y;
519 SDL_SetMouseFocus(window);
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);
534 mouse->accumulated_wheel_x -= integral_x;
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);
544 mouse->accumulated_wheel_y -= integral_y;
546 /* Post the event, if desired */
548 if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) {
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;
557 event.wheel.x = integral_x;
558 event.wheel.y = integral_y;
559 event.wheel.direction = (Uint32)direction;
560 posted = (SDL_PushEvent(&event) > 0);
568 SDL_Cursor *cursor, *next;
569 SDL_Mouse *mouse = SDL_GetMouse();
571 if (mouse->CaptureMouse) {
572 SDL_CaptureMouse(SDL_FALSE);
574 SDL_SetRelativeMouseMode(SDL_FALSE);
577 cursor = mouse->cursors;
580 SDL_FreeCursor(cursor);
583 mouse->cursors = NULL;
585 if (mouse->def_cursor && mouse->FreeCursor) {
586 mouse->FreeCursor(mouse->def_cursor);
587 mouse->def_cursor = NULL;
590 if (mouse->clickstate) {
591 SDL_free(mouse->clickstate);
592 mouse->clickstate = NULL;
595 SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
596 SDL_MouseNormalSpeedScaleChanged, mouse);
598 SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
599 SDL_MouseRelativeSpeedScaleChanged, mouse);
603 SDL_GetMouseState(int *x, int *y)
605 SDL_Mouse *mouse = SDL_GetMouse();
613 return mouse->buttonstate;
617 SDL_GetRelativeMouseState(int *x, int *y)
619 SDL_Mouse *mouse = SDL_GetMouse();
629 return mouse->buttonstate;
633 SDL_GetGlobalMouseState(int *x, int *y)
635 SDL_Mouse *mouse = SDL_GetMouse();
638 /* make sure these are never NULL for the backend implementations... */
648 if (!mouse->GetGlobalMouseState) {
652 return mouse->GetGlobalMouseState(x, y);
656 SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
658 SDL_Mouse *mouse = SDL_GetMouse();
660 if (window == NULL) {
661 window = mouse->focus;
664 if (window == NULL) {
668 if (mouse->WarpMouse) {
669 mouse->WarpMouse(window, x, y);
671 SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
676 SDL_WarpMouseGlobal(int x, int y)
678 SDL_Mouse *mouse = SDL_GetMouse();
680 if (mouse->WarpMouseGlobal) {
681 return mouse->WarpMouseGlobal(x, y);
684 return SDL_Unsupported();
688 ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
690 if (!mouse->SetRelativeMouseMode) {
694 return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
698 SDL_SetRelativeMouseMode(SDL_bool enabled)
700 SDL_Mouse *mouse = SDL_GetMouse();
701 SDL_Window *focusWindow = SDL_GetKeyboardFocus();
703 if (enabled == mouse->relative_mode) {
707 if (enabled && focusWindow) {
708 /* Center it in the focused window to prevent clicks from going through
709 * to background windows.
711 SDL_SetMouseFocus(focusWindow);
712 SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
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) {
722 /* Fall back to warp mode if native relative mode failed */
723 mouse->relative_mode_warp = SDL_TRUE;
726 mouse->relative_mode = enabled;
727 mouse->scale_accum_x = 0.0f;
728 mouse->scale_accum_y = 0.0f;
731 SDL_UpdateWindowGrab(mouse->focus);
733 /* Put the cursor back to where the application expects it */
735 SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
739 /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */
740 SDL_FlushEvent(SDL_MOUSEMOTION);
742 /* Update cursor visibility */
749 SDL_GetRelativeMouseMode()
751 SDL_Mouse *mouse = SDL_GetMouse();
753 return mouse->relative_mode;
757 SDL_CaptureMouse(SDL_bool enabled)
759 SDL_Mouse *mouse = SDL_GetMouse();
760 SDL_Window *focusWindow;
763 if (!mouse->CaptureMouse) {
764 return SDL_Unsupported();
767 focusWindow = SDL_GetKeyboardFocus();
769 isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
770 if (isCaptured == enabled) {
771 return 0; /* already done! */
776 return SDL_SetError("No window has focus");
777 } else if (mouse->CaptureMouse(focusWindow) == -1) {
778 return -1; /* CaptureMouse() should call SetError */
780 focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
782 if (mouse->CaptureMouse(NULL) == -1) {
783 return -1; /* CaptureMouse() should call SetError */
785 focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
792 SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
793 int w, int h, int hot_x, int hot_y)
795 SDL_Surface *surface;
799 Uint8 datab = 0, maskb = 0;
800 const Uint32 black = 0xFF000000;
801 const Uint32 white = 0xFFFFFFFF;
802 const Uint32 transparent = 0x00000000;
804 /* Make sure the width is a multiple of 8 */
807 /* Create the surface from a bitmap */
808 surface = SDL_CreateRGBSurface(0, w, h, 32,
816 for (y = 0; y < h; ++y) {
817 pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
818 for (x = 0; x < w; ++x) {
824 *pixel++ = (datab & 0x80) ? black : white;
826 *pixel++ = (datab & 0x80) ? black : transparent;
833 cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
835 SDL_FreeSurface(surface);
841 SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
843 SDL_Mouse *mouse = SDL_GetMouse();
844 SDL_Surface *temp = NULL;
848 SDL_SetError("Passed NULL cursor surface");
852 if (!mouse->CreateCursor) {
853 SDL_SetError("Cursors are not currently supported");
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");
864 if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
865 temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
872 cursor = mouse->CreateCursor(surface, hot_x, hot_y);
874 cursor->next = mouse->cursors;
875 mouse->cursors = cursor;
878 SDL_FreeSurface(temp);
884 SDL_CreateSystemCursor(SDL_SystemCursor id)
886 SDL_Mouse *mouse = SDL_GetMouse();
889 if (!mouse->CreateSystemCursor) {
890 SDL_SetError("CreateSystemCursor is not currently supported");
894 cursor = mouse->CreateSystemCursor(id);
896 cursor->next = mouse->cursors;
897 mouse->cursors = cursor;
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.
908 SDL_SetCursor(SDL_Cursor * cursor)
910 SDL_Mouse *mouse = SDL_GetMouse();
912 /* Set the new cursor */
914 /* Make sure the cursor is still valid for this mouse */
915 if (cursor != mouse->def_cursor) {
917 for (found = mouse->cursors; found; found = found->next) {
918 if (found == cursor) {
923 SDL_SetError("Cursor not associated with the current mouse");
927 mouse->cur_cursor = cursor;
930 cursor = mouse->cur_cursor;
932 cursor = mouse->def_cursor;
936 if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
937 if (mouse->ShowCursor) {
938 mouse->ShowCursor(cursor);
941 if (mouse->ShowCursor) {
942 mouse->ShowCursor(NULL);
950 SDL_Mouse *mouse = SDL_GetMouse();
955 return mouse->cur_cursor;
959 SDL_GetDefaultCursor(void)
961 SDL_Mouse *mouse = SDL_GetMouse();
966 return mouse->def_cursor;
970 SDL_FreeCursor(SDL_Cursor * cursor)
972 SDL_Mouse *mouse = SDL_GetMouse();
973 SDL_Cursor *curr, *prev;
979 if (cursor == mouse->def_cursor) {
982 if (cursor == mouse->cur_cursor) {
983 SDL_SetCursor(mouse->def_cursor);
986 for (prev = NULL, curr = mouse->cursors; curr;
987 prev = curr, curr = curr->next) {
988 if (curr == cursor) {
990 prev->next = curr->next;
992 mouse->cursors = curr->next;
995 if (mouse->FreeCursor) {
996 mouse->FreeCursor(curr);
1004 SDL_ShowCursor(int toggle)
1006 SDL_Mouse *mouse = SDL_GetMouse();
1013 shown = mouse->cursor_shown;
1016 mouse->cursor_shown = SDL_TRUE;
1018 mouse->cursor_shown = SDL_FALSE;
1020 if (mouse->cursor_shown != shown) {
1021 SDL_SetCursor(NULL);
1027 /* vi: set ts=4 sw=4 expandtab: */