src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 23 Dec 2013 12:17:52 -0800
changeset 8066 658b461d81be
parent 8049 eac8f31e9bbd
child 8071 1ac2db4abe11
permissions -rw-r--r--
Added support for double-clicks, through a new "clicks" field in the mouse button event.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.h"
    22 
    23 /* General mouse handling code for SDL */
    24 
    25 #include "SDL_assert.h"
    26 #include "SDL_timer.h"
    27 #include "SDL_events.h"
    28 #include "SDL_events_c.h"
    29 #include "default_cursor.h"
    30 #include "../video/SDL_sysvideo.h"
    31 
    32 /* #define DEBUG_MOUSE */
    33 
    34 /* The mouse state */
    35 static SDL_Mouse SDL_mouse;
    36 static Uint32 SDL_double_click_time = 500;
    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 /* Public functions */
    43 int
    44 SDL_MouseInit(void)
    45 {
    46     SDL_Mouse *mouse = SDL_GetMouse();
    47 
    48     mouse->cursor_shown = SDL_TRUE;
    49 
    50     return (0);
    51 }
    52 
    53 void
    54 SDL_SetDefaultCursor(SDL_Cursor * cursor)
    55 {
    56     SDL_Mouse *mouse = SDL_GetMouse();
    57 
    58     mouse->def_cursor = cursor;
    59     if (!mouse->cur_cursor) {
    60         SDL_SetCursor(cursor);
    61     }
    62 }
    63 
    64 SDL_Mouse *
    65 SDL_GetMouse(void)
    66 {
    67     return &SDL_mouse;
    68 }
    69 
    70 void
    71 SDL_SetDoubleClickTime(Uint32 interval)
    72 {
    73     SDL_double_click_time = interval;
    74 }
    75 
    76 SDL_Window *
    77 SDL_GetMouseFocus(void)
    78 {
    79     SDL_Mouse *mouse = SDL_GetMouse();
    80 
    81     return mouse->focus;
    82 }
    83 
    84 void
    85 SDL_ResetMouse(void)
    86 {
    87     SDL_Mouse *mouse = SDL_GetMouse();
    88     Uint8 i;
    89 
    90 #ifdef DEBUG_MOUSE
    91     printf("Resetting mouse\n");
    92 #endif
    93     for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) {
    94         if (mouse->buttonstate & SDL_BUTTON(i)) {
    95             SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i);
    96         }
    97     }
    98     SDL_assert(mouse->buttonstate == 0);
    99 }
   100 
   101 void
   102 SDL_SetMouseFocus(SDL_Window * window)
   103 {
   104     SDL_Mouse *mouse = SDL_GetMouse();
   105 
   106     if (mouse->focus == window) {
   107         return;
   108     }
   109 
   110     /* Actually, this ends up being a bad idea, because most operating
   111        systems have an implicit grab when you press the mouse button down
   112        so you can drag things out of the window and then get the mouse up
   113        when it happens.  So, #if 0...
   114     */
   115 #if 0
   116     if (mouse->focus && !window) {
   117         /* We won't get anymore mouse messages, so reset mouse state */
   118         SDL_ResetMouse();
   119     }
   120 #endif
   121 
   122     /* See if the current window has lost focus */
   123     if (mouse->focus) {
   124         SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
   125     }
   126 
   127     mouse->focus = window;
   128 
   129     if (mouse->focus) {
   130         SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
   131     }
   132 
   133     /* Update cursor visibility */
   134     SDL_SetCursor(NULL);
   135 }
   136 
   137 /* Check to see if we need to synthesize focus events */
   138 static SDL_bool
   139 SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
   140 {
   141     SDL_Mouse *mouse = SDL_GetMouse();
   142     int w, h;
   143     SDL_bool inWindow;
   144 
   145     SDL_GetWindowSize(window, &w, &h);
   146     if (x < 0 || y < 0 || x >= w || y >= h) {
   147         inWindow = SDL_FALSE;
   148     } else {
   149         inWindow = SDL_TRUE;
   150     }
   151 
   152 /* Linux doesn't give you mouse events outside your window unless you grab
   153    the pointer.
   154 
   155    Windows doesn't give you mouse events outside your window unless you call
   156    SetCapture().
   157 
   158    Both of these are slightly scary changes, so for now we'll punt and if the
   159    mouse leaves the window you'll lose mouse focus and reset button state.
   160 */
   161 #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
   162     if (!inWindow && !buttonstate) {
   163 #else
   164     if (!inWindow) {
   165 #endif
   166         if (window == mouse->focus) {
   167 #ifdef DEBUG_MOUSE
   168             printf("Mouse left window, synthesizing move & focus lost event\n");
   169 #endif
   170             SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
   171             SDL_SetMouseFocus(NULL);
   172         }
   173         return SDL_FALSE;
   174     }
   175 
   176     if (window != mouse->focus) {
   177 #ifdef DEBUG_MOUSE
   178          printf("Mouse entered window, synthesizing focus gain & move event\n");
   179 #endif
   180          SDL_SetMouseFocus(window);
   181          SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
   182     }
   183     return SDL_TRUE;
   184 }
   185 
   186 int
   187 SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
   188 {
   189     if (window && !relative) {
   190         SDL_Mouse *mouse = SDL_GetMouse();
   191         if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
   192             return 0;
   193         }
   194     }
   195 
   196     return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y);
   197 }
   198 
   199 static int
   200 SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
   201 {
   202     SDL_Mouse *mouse = SDL_GetMouse();
   203     int posted;
   204     int xrel;
   205     int yrel;
   206     int x_max = 0, y_max = 0;
   207 
   208     /* relative motion is calculated regarding the system cursor last position */
   209     if (relative) {
   210         xrel = x;
   211         yrel = y;
   212         x = (mouse->last_x + x);
   213         y = (mouse->last_y + y);
   214     } else {
   215         xrel = x - mouse->last_x;
   216         yrel = y - mouse->last_y;
   217     }
   218 
   219     /* Drop events that don't change state */
   220     if (!xrel && !yrel) {
   221 #ifdef DEBUG_MOUSE
   222         printf("Mouse event didn't change state - dropped!\n");
   223 #endif
   224         return 0;
   225     }
   226 
   227     /* Update internal mouse coordinates */
   228     if (mouse->relative_mode == SDL_FALSE) {
   229         mouse->x = x;
   230         mouse->y = y;
   231     } else {
   232         mouse->x += xrel;
   233         mouse->y += yrel;
   234     }
   235 
   236     SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
   237     --x_max;
   238     --y_max;
   239 
   240     /* make sure that the pointers find themselves inside the windows */
   241     if (mouse->x > x_max) {
   242         mouse->x = x_max;
   243     }
   244     if (mouse->x < 0) {
   245         mouse->x = 0;
   246     }
   247 
   248     if (mouse->y > y_max) {
   249         mouse->y = y_max;
   250     }
   251     if (mouse->y < 0) {
   252         mouse->y = 0;
   253     }
   254 
   255     mouse->xdelta += xrel;
   256     mouse->ydelta += yrel;
   257 
   258     /* Move the mouse cursor, if needed */
   259     if (mouse->cursor_shown && !mouse->relative_mode &&
   260         mouse->MoveCursor && mouse->cur_cursor) {
   261         mouse->MoveCursor(mouse->cur_cursor);
   262     }
   263 
   264     /* Post the event, if desired */
   265     posted = 0;
   266     if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) {
   267         SDL_Event event;
   268         event.motion.type = SDL_MOUSEMOTION;
   269         event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
   270         event.motion.which = mouseID;
   271         event.motion.state = mouse->buttonstate;
   272         event.motion.x = mouse->x;
   273         event.motion.y = mouse->y;
   274         event.motion.xrel = xrel;
   275         event.motion.yrel = yrel;
   276         posted = (SDL_PushEvent(&event) > 0);
   277     }
   278     /* Use unclamped values if we're getting events outside the window */
   279     mouse->last_x = x;
   280     mouse->last_y = y;
   281     return posted;
   282 }
   283 
   284 static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
   285 {
   286     if (button >= mouse->num_clickstates) {
   287         int i, count = button + 1;
   288         mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
   289         if (!mouse->clickstate) {
   290             return NULL;
   291         }
   292 
   293         for (i = mouse->num_clickstates; i < count; ++i) {
   294             SDL_zero(mouse->clickstate[i]);
   295         }
   296         mouse->num_clickstates = count;
   297     }
   298     return &mouse->clickstate[button];
   299 }
   300 
   301 int
   302 SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
   303 {
   304     SDL_Mouse *mouse = SDL_GetMouse();
   305     int posted;
   306     Uint32 type;
   307     Uint32 buttonstate = mouse->buttonstate;
   308     SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
   309     Uint8 click_count;
   310 
   311     /* Figure out which event to perform */
   312     switch (state) {
   313     case SDL_PRESSED:
   314         type = SDL_MOUSEBUTTONDOWN;
   315         buttonstate |= SDL_BUTTON(button);
   316         break;
   317     case SDL_RELEASED:
   318         type = SDL_MOUSEBUTTONUP;
   319         buttonstate &= ~SDL_BUTTON(button);
   320         break;
   321     default:
   322         /* Invalid state -- bail */
   323         return 0;
   324     }
   325 
   326     /* We do this after calculating buttonstate so button presses gain focus */
   327     if (window && state == SDL_PRESSED) {
   328         SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
   329     }
   330 
   331     if (buttonstate == mouse->buttonstate) {
   332         /* Ignore this event, no state change */
   333         return 0;
   334     }
   335     mouse->buttonstate = buttonstate;
   336 
   337     if (clickstate) {
   338         if (state == SDL_PRESSED) {
   339             Uint32 now = SDL_GetTicks();
   340 
   341             if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) ||
   342                 SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius ||
   343                 SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) {
   344                 clickstate->click_count = 0;
   345             }
   346             clickstate->last_timestamp = now;
   347             clickstate->last_x = mouse->x;
   348             clickstate->last_y = mouse->y;
   349             if (clickstate->click_count < 255) {
   350                 ++clickstate->click_count;
   351             }
   352         }
   353         click_count = clickstate->click_count;
   354     } else {
   355         click_count = 1;
   356     }
   357 
   358     /* Post the event, if desired */
   359     posted = 0;
   360     if (SDL_GetEventState(type) == SDL_ENABLE) {
   361         SDL_Event event;
   362         event.type = type;
   363         event.button.windowID = mouse->focus ? mouse->focus->id : 0;
   364         event.button.which = mouseID;
   365         event.button.state = state;
   366         event.button.button = button;
   367         event.button.clicks = click_count;
   368         event.button.x = mouse->x;
   369         event.button.y = mouse->y;
   370         posted = (SDL_PushEvent(&event) > 0);
   371     }
   372 
   373     /* We do this after dispatching event so button releases can lose focus */
   374     if (window && state == SDL_RELEASED) {
   375         SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
   376     }
   377 
   378     return posted;
   379 }
   380 
   381 int
   382 SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y)
   383 {
   384     SDL_Mouse *mouse = SDL_GetMouse();
   385     int posted;
   386 
   387     if (window) {
   388         SDL_SetMouseFocus(window);
   389     }
   390 
   391     if (!x && !y) {
   392         return 0;
   393     }
   394 
   395     /* Post the event, if desired */
   396     posted = 0;
   397     if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) {
   398         SDL_Event event;
   399         event.type = SDL_MOUSEWHEEL;
   400         event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
   401         event.wheel.which = mouseID;
   402         event.wheel.x = x;
   403         event.wheel.y = y;
   404         posted = (SDL_PushEvent(&event) > 0);
   405     }
   406     return posted;
   407 }
   408 
   409 void
   410 SDL_MouseQuit(void)
   411 {
   412     SDL_Cursor *cursor, *next;
   413     SDL_Mouse *mouse = SDL_GetMouse();
   414 
   415     SDL_SetRelativeMouseMode(SDL_FALSE);
   416     SDL_ShowCursor(1);
   417 
   418     cursor = mouse->cursors;
   419     while (cursor) {
   420         next = cursor->next;
   421         SDL_FreeCursor(cursor);
   422         cursor = next;
   423     }
   424 
   425     if (mouse->def_cursor && mouse->FreeCursor) {
   426         mouse->FreeCursor(mouse->def_cursor);
   427     }
   428 
   429     if (mouse->clickstate) {
   430         SDL_free(mouse->clickstate);
   431     }
   432 
   433     SDL_zerop(mouse);
   434 }
   435 
   436 Uint32
   437 SDL_GetMouseState(int *x, int *y)
   438 {
   439     SDL_Mouse *mouse = SDL_GetMouse();
   440 
   441     if (x) {
   442         *x = mouse->x;
   443     }
   444     if (y) {
   445         *y = mouse->y;
   446     }
   447     return mouse->buttonstate;
   448 }
   449 
   450 Uint32
   451 SDL_GetRelativeMouseState(int *x, int *y)
   452 {
   453     SDL_Mouse *mouse = SDL_GetMouse();
   454 
   455     if (x) {
   456         *x = mouse->xdelta;
   457     }
   458     if (y) {
   459         *y = mouse->ydelta;
   460     }
   461     mouse->xdelta = 0;
   462     mouse->ydelta = 0;
   463     return mouse->buttonstate;
   464 }
   465 
   466 void
   467 SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
   468 {
   469     SDL_Mouse *mouse = SDL_GetMouse();
   470 
   471     if ( window == NULL )
   472         window = mouse->focus;
   473 
   474     if ( window == NULL )
   475         return;
   476 
   477     if (mouse->WarpMouse) {
   478         mouse->WarpMouse(window, x, y);
   479     } else {
   480         SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
   481     }
   482 }
   483 
   484 int
   485 SDL_SetRelativeMouseMode(SDL_bool enabled)
   486 {
   487     SDL_Mouse *mouse = SDL_GetMouse();
   488     SDL_Window *focusWindow = SDL_GetKeyboardFocus();
   489     int original_x = mouse->x, original_y = mouse->y;
   490 
   491     if (enabled == mouse->relative_mode) {
   492         return 0;
   493     }
   494 
   495     if (!mouse->SetRelativeMouseMode) {
   496         return SDL_Unsupported();
   497     }
   498 
   499     if (enabled && focusWindow) {
   500         /* Center it in the focused window to prevent clicks from going through
   501          * to background windows.
   502          */
   503         SDL_SetMouseFocus(focusWindow);
   504         SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
   505     }
   506 
   507     if (mouse->SetRelativeMouseMode(enabled) < 0) {
   508         return -1;
   509     }
   510 
   511     /* Set the relative mode */
   512     mouse->relative_mode = enabled;
   513 
   514     if (enabled) {
   515         /* Save the expected mouse position */
   516         mouse->original_x = original_x;
   517         mouse->original_y = original_y;
   518     } else if (mouse->focus) {
   519         /* Restore the expected mouse position */
   520         SDL_WarpMouseInWindow(mouse->focus, mouse->original_x, mouse->original_y);
   521     }
   522 
   523     /* Flush pending mouse motion */
   524     SDL_FlushEvent(SDL_MOUSEMOTION);
   525 
   526     /* Update cursor visibility */
   527     SDL_SetCursor(NULL);
   528 
   529     return 0;
   530 }
   531 
   532 SDL_bool
   533 SDL_GetRelativeMouseMode()
   534 {
   535     SDL_Mouse *mouse = SDL_GetMouse();
   536 
   537     return mouse->relative_mode;
   538 }
   539 
   540 SDL_Cursor *
   541 SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
   542                  int w, int h, int hot_x, int hot_y)
   543 {
   544     SDL_Surface *surface;
   545     SDL_Cursor *cursor;
   546     int x, y;
   547     Uint32 *pixel;
   548     Uint8 datab = 0, maskb = 0;
   549     const Uint32 black = 0xFF000000;
   550     const Uint32 white = 0xFFFFFFFF;
   551     const Uint32 transparent = 0x00000000;
   552 
   553     /* Make sure the width is a multiple of 8 */
   554     w = ((w + 7) & ~7);
   555 
   556     /* Create the surface from a bitmap */
   557     surface = SDL_CreateRGBSurface(0, w, h, 32,
   558                                    0x00FF0000,
   559                                    0x0000FF00,
   560                                    0x000000FF,
   561                                    0xFF000000);
   562     if (!surface) {
   563         return NULL;
   564     }
   565     for (y = 0; y < h; ++y) {
   566         pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
   567         for (x = 0; x < w; ++x) {
   568             if ((x % 8) == 0) {
   569                 datab = *data++;
   570                 maskb = *mask++;
   571             }
   572             if (maskb & 0x80) {
   573                 *pixel++ = (datab & 0x80) ? black : white;
   574             } else {
   575                 *pixel++ = (datab & 0x80) ? black : transparent;
   576             }
   577             datab <<= 1;
   578             maskb <<= 1;
   579         }
   580     }
   581 
   582     cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
   583 
   584     SDL_FreeSurface(surface);
   585 
   586     return cursor;
   587 }
   588 
   589 SDL_Cursor *
   590 SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
   591 {
   592     SDL_Mouse *mouse = SDL_GetMouse();
   593     SDL_Surface *temp = NULL;
   594     SDL_Cursor *cursor;
   595 
   596     if (!surface) {
   597         SDL_SetError("Passed NULL cursor surface");
   598         return NULL;
   599     }
   600 
   601     if (!mouse->CreateCursor) {
   602         SDL_SetError("Cursors are not currently supported");
   603         return NULL;
   604     }
   605 
   606     /* Sanity check the hot spot */
   607     if ((hot_x < 0) || (hot_y < 0) ||
   608         (hot_x >= surface->w) || (hot_y >= surface->h)) {
   609         SDL_SetError("Cursor hot spot doesn't lie within cursor");
   610         return NULL;
   611     }
   612 
   613     if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
   614         temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
   615         if (!temp) {
   616             return NULL;
   617         }
   618         surface = temp;
   619     }
   620 
   621     cursor = mouse->CreateCursor(surface, hot_x, hot_y);
   622     if (cursor) {
   623         cursor->next = mouse->cursors;
   624         mouse->cursors = cursor;
   625     }
   626 
   627     SDL_FreeSurface(temp);
   628 
   629     return cursor;
   630 }
   631 
   632 SDL_Cursor *
   633 SDL_CreateSystemCursor(SDL_SystemCursor id)
   634 {
   635     SDL_Mouse *mouse = SDL_GetMouse();
   636     SDL_Cursor *cursor;
   637 
   638     if (!mouse->CreateSystemCursor) {
   639         SDL_SetError("CreateSystemCursor is not currently supported");
   640         return NULL;
   641     }
   642 
   643     cursor = mouse->CreateSystemCursor(id);
   644     if (cursor) {
   645         cursor->next = mouse->cursors;
   646         mouse->cursors = cursor;
   647     }
   648 
   649     return cursor;
   650 }
   651 
   652 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
   653    if this is desired for any reason.  This is used when setting
   654    the video mode and when the SDL window gains the mouse focus.
   655  */
   656 void
   657 SDL_SetCursor(SDL_Cursor * cursor)
   658 {
   659     SDL_Mouse *mouse = SDL_GetMouse();
   660 
   661     /* Set the new cursor */
   662     if (cursor) {
   663         /* Make sure the cursor is still valid for this mouse */
   664         if (cursor != mouse->def_cursor) {
   665             SDL_Cursor *found;
   666             for (found = mouse->cursors; found; found = found->next) {
   667                 if (found == cursor) {
   668                     break;
   669                 }
   670             }
   671             if (!found) {
   672                 SDL_SetError("Cursor not associated with the current mouse");
   673                 return;
   674             }
   675         }
   676         mouse->cur_cursor = cursor;
   677     } else {
   678         if (mouse->focus) {
   679             cursor = mouse->cur_cursor;
   680         } else {
   681             cursor = mouse->def_cursor;
   682         }
   683     }
   684 
   685     if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
   686         if (mouse->ShowCursor) {
   687             mouse->ShowCursor(cursor);
   688         }
   689     } else {
   690         if (mouse->ShowCursor) {
   691             mouse->ShowCursor(NULL);
   692         }
   693     }
   694 }
   695 
   696 SDL_Cursor *
   697 SDL_GetCursor(void)
   698 {
   699     SDL_Mouse *mouse = SDL_GetMouse();
   700 
   701     if (!mouse) {
   702         return NULL;
   703     }
   704     return mouse->cur_cursor;
   705 }
   706 
   707 SDL_Cursor *
   708 SDL_GetDefaultCursor(void)
   709 {
   710     SDL_Mouse *mouse = SDL_GetMouse();
   711 
   712     if (!mouse) {
   713         return NULL;
   714     }
   715     return mouse->def_cursor;
   716 }
   717 
   718 void
   719 SDL_FreeCursor(SDL_Cursor * cursor)
   720 {
   721     SDL_Mouse *mouse = SDL_GetMouse();
   722     SDL_Cursor *curr, *prev;
   723 
   724     if (!cursor) {
   725         return;
   726     }
   727 
   728     if (cursor == mouse->def_cursor) {
   729         return;
   730     }
   731     if (cursor == mouse->cur_cursor) {
   732         SDL_SetCursor(mouse->def_cursor);
   733     }
   734 
   735     for (prev = NULL, curr = mouse->cursors; curr;
   736          prev = curr, curr = curr->next) {
   737         if (curr == cursor) {
   738             if (prev) {
   739                 prev->next = curr->next;
   740             } else {
   741                 mouse->cursors = curr->next;
   742             }
   743 
   744             if (mouse->FreeCursor) {
   745                 mouse->FreeCursor(curr);
   746             }
   747             return;
   748         }
   749     }
   750 }
   751 
   752 int
   753 SDL_ShowCursor(int toggle)
   754 {
   755     SDL_Mouse *mouse = SDL_GetMouse();
   756     SDL_bool shown;
   757 
   758     if (!mouse) {
   759         return 0;
   760     }
   761 
   762     shown = mouse->cursor_shown;
   763     if (toggle >= 0) {
   764         if (toggle) {
   765             mouse->cursor_shown = SDL_TRUE;
   766         } else {
   767             mouse->cursor_shown = SDL_FALSE;
   768         }
   769         if (mouse->cursor_shown != shown) {
   770             SDL_SetCursor(NULL);
   771         }
   772     }
   773     return shown;
   774 }
   775 
   776 /* vi: set ts=4 sw=4 expandtab: */