src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 27 Nov 2008 21:53:18 +0000
changeset 2794 f7872b7a8732
parent 2765 f55c87ae336b
child 2842 97ba0be8b565
permissions -rw-r--r--
Fixed mouse coordinate range on Mac OS X
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* General mouse handling code for SDL */
    25 
    26 #include "SDL_events.h"
    27 #include "SDL_events_c.h"
    28 #include "default_cursor.h"
    29 
    30 
    31 static int SDL_num_mice = 0;
    32 static int SDL_current_mouse = -1;
    33 static SDL_Mouse **SDL_mice = NULL;
    34 static int *SDL_IdIndex = NULL;
    35 static int SDL_highestId = -1;
    36 static int last_x, last_y;      /* the last reported x and y coordinates by the system cursor */
    37 
    38 
    39 /* Public functions */
    40 int
    41 SDL_MouseInit(void)
    42 {
    43     return (0);
    44 }
    45 
    46 SDL_Mouse *
    47 SDL_GetMouse(int index)
    48 {
    49     if (index < 0 || index >= SDL_num_mice) {
    50         return NULL;
    51     }
    52     return SDL_mice[index];
    53 }
    54 
    55 int
    56 SDL_SetMouseIndexId(int id, int index)
    57 {
    58     if (id < 0) {
    59         SDL_SetError("Invalid Mouse ID");
    60         return -1;
    61     }
    62     if (id > SDL_highestId) {
    63         int *indexes;
    64         indexes = (int *) SDL_realloc(SDL_IdIndex, (id + 1) * sizeof(int));
    65         if (!indexes) {
    66             SDL_OutOfMemory();
    67             return -1;
    68         }
    69         SDL_IdIndex = indexes;
    70         SDL_IdIndex[id] = index;
    71         SDL_highestId = id;
    72     } else {
    73         SDL_IdIndex[id] = index;
    74     }
    75     return 1;
    76 }
    77 
    78 int
    79 SDL_GetMouseIndexId(int id)
    80 {
    81     if (id < 0 || id > SDL_highestId) {
    82         return -1;
    83     }
    84     return SDL_IdIndex[id];
    85 }
    86 
    87 int
    88 SDL_AddMouse(const SDL_Mouse * mouse, int index, char *name, int pressure_max,
    89              int pressure_min, int ends)
    90 {
    91     SDL_Mouse **mice;
    92     int selected_mouse;
    93     int length;
    94 
    95     /* Add the mouse to the list of mice */
    96     if (index < 0 || index >= SDL_num_mice || SDL_mice[index]) {
    97         mice =
    98             (SDL_Mouse **) SDL_realloc(SDL_mice,
    99                                        (SDL_num_mice + 1) * sizeof(*mice));
   100         if (!mice) {
   101             SDL_OutOfMemory();
   102             return -1;
   103         }
   104 
   105         SDL_mice = mice;
   106         index = SDL_num_mice++;
   107     }
   108     SDL_mice[index] = (SDL_Mouse *) SDL_malloc(sizeof(*SDL_mice[index]));
   109     if (!SDL_mice[index]) {
   110         SDL_OutOfMemory();
   111         return -1;
   112     }
   113     *SDL_mice[index] = *mouse;
   114 
   115     /* we're setting the mouse properties */
   116     length = 0;
   117     length = SDL_strlen(name);
   118     SDL_mice[index]->name = SDL_malloc((length + 2) * sizeof(char));
   119     SDL_strlcpy(SDL_mice[index]->name, name, length + 1);
   120     SDL_mice[index]->pressure_max = pressure_max;
   121     SDL_mice[index]->pressure_min = pressure_min;
   122     SDL_mice[index]->cursor_shown = SDL_TRUE;
   123     selected_mouse = SDL_SelectMouse(index);
   124     SDL_mice[index]->cur_cursor = NULL;
   125     SDL_mice[index]->def_cursor =
   126         SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH,
   127                          DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
   128     SDL_SetCursor(SDL_mice[index]->def_cursor);
   129     /* we're assuming that all mice are in the computer sensing zone */
   130     SDL_mice[index]->proximity = SDL_TRUE;
   131     /* we're assuming that all mice are working in the absolute position mode
   132        thanx to that, the users that don't want to use many mice don't have to
   133        worry about anything */
   134     SDL_mice[index]->relative_mode = SDL_FALSE;
   135     SDL_mice[index]->current_end = 0;
   136     SDL_mice[index]->total_ends = ends;
   137     SDL_SelectMouse(selected_mouse);
   138 
   139     return index;
   140 }
   141 
   142 void
   143 SDL_DelMouse(int index)
   144 {
   145     SDL_Mouse *mouse = SDL_GetMouse(index);
   146 
   147     if (!mouse) {
   148         return;
   149     }
   150 
   151     mouse->def_cursor = NULL;
   152     SDL_free(mouse->name);
   153     while (mouse->cursors) {
   154         SDL_FreeCursor(mouse->cursors);
   155     }
   156 
   157     if (mouse->FreeMouse) {
   158         mouse->FreeMouse(mouse);
   159     }
   160     SDL_free(mouse);
   161 
   162     SDL_mice[index] = NULL;
   163 }
   164 
   165 void
   166 SDL_ResetMouse(int index)
   167 {
   168     SDL_Mouse *mouse = SDL_GetMouse(index);
   169 
   170     if (!mouse) {
   171         return;
   172     }
   173 
   174     /* FIXME */
   175 }
   176 
   177 void
   178 SDL_MouseQuit(void)
   179 {
   180     int i;
   181 
   182     for (i = 0; i < SDL_num_mice; ++i) {
   183         SDL_DelMouse(i);
   184     }
   185     SDL_num_mice = 0;
   186     SDL_current_mouse = -1;
   187 
   188     if (SDL_mice) {
   189         SDL_free(SDL_mice);
   190         SDL_mice = NULL;
   191     }
   192 }
   193 
   194 int
   195 SDL_GetNumMice(void)
   196 {
   197     return SDL_num_mice;
   198 }
   199 
   200 int
   201 SDL_SelectMouse(int index)
   202 {
   203     if (index >= 0 && index < SDL_num_mice) {
   204         SDL_current_mouse = index;
   205     }
   206     return SDL_current_mouse;
   207 }
   208 
   209 SDL_WindowID
   210 SDL_GetMouseFocusWindow(int index)
   211 {
   212     SDL_Mouse *mouse = SDL_GetMouse(index);
   213 
   214     if (!mouse) {
   215         return 0;
   216     }
   217     return mouse->focus;
   218 }
   219 
   220 static int SDLCALL
   221 FlushMouseMotion(void *param, SDL_Event * event)
   222 {
   223     if (event->type == SDL_MOUSEMOTION
   224         && event->motion.which == (Uint8) SDL_current_mouse) {
   225         return 0;
   226     } else {
   227         return 1;
   228     }
   229 }
   230 
   231 int
   232 SDL_SetRelativeMouseMode(int index, SDL_bool enabled)
   233 {
   234     SDL_Mouse *mouse = SDL_GetMouse(index);
   235 
   236     if (!mouse) {
   237         return -1;
   238     }
   239 
   240     /* Flush pending mouse motion */
   241     mouse->flush_motion = SDL_TRUE;
   242     SDL_PumpEvents();
   243     mouse->flush_motion = SDL_FALSE;
   244     SDL_FilterEvents(FlushMouseMotion, mouse);
   245 
   246     /* Set the relative mode */
   247     mouse->relative_mode = enabled;
   248 
   249     /* Update cursor visibility */
   250     SDL_SetCursor(NULL);
   251 
   252     if (!enabled) {
   253         /* Restore the expected mouse position */
   254         SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
   255     }
   256     return 0;
   257 }
   258 
   259 SDL_bool
   260 SDL_GetRelativeMouseMode(int index)
   261 {
   262     SDL_Mouse *mouse = SDL_GetMouse(index);
   263 
   264     if (!mouse) {
   265         return SDL_FALSE;
   266     }
   267     return mouse->relative_mode;
   268 }
   269 
   270 Uint8
   271 SDL_GetMouseState(int index, int *x, int *y)
   272 {
   273     SDL_Mouse *mouse = SDL_GetMouse(index);
   274 
   275     if (!mouse) {
   276         if (x) {
   277             *x = 0;
   278         }
   279         if (y) {
   280             *y = 0;
   281         }
   282         return 0;
   283     }
   284 
   285     if (x) {
   286         *x = mouse->x;
   287     }
   288     if (y) {
   289         *y = mouse->y;
   290     }
   291     return mouse->buttonstate;
   292 }
   293 
   294 Uint8
   295 SDL_GetRelativeMouseState(int index, int *x, int *y)
   296 {
   297     SDL_Mouse *mouse = SDL_GetMouse(index);
   298 
   299     if (!mouse) {
   300         if (x) {
   301             *x = 0;
   302         }
   303         if (y) {
   304             *y = 0;
   305         }
   306         return 0;
   307     }
   308 
   309     if (x) {
   310         *x = mouse->xdelta;
   311     }
   312     if (y) {
   313         *y = mouse->ydelta;
   314     }
   315     mouse->xdelta = 0;
   316     mouse->ydelta = 0;
   317     return mouse->buttonstate;
   318 }
   319 
   320 void
   321 SDL_SetMouseFocus(int id, SDL_WindowID windowID)
   322 {
   323     int index = SDL_GetMouseIndexId(id);
   324     SDL_Mouse *mouse = SDL_GetMouse(index);
   325     int i;
   326     SDL_bool focus;
   327 
   328     if (!mouse || (mouse->focus == windowID)) {
   329         return;
   330     }
   331 
   332     /* See if the current window has lost focus */
   333     if (mouse->focus) {
   334         focus = SDL_FALSE;
   335         for (i = 0; i < SDL_num_mice; ++i) {
   336             SDL_Mouse *check;
   337             if (i != index) {
   338                 check = SDL_GetMouse(i);
   339                 if (check && check->focus == mouse->focus) {
   340                     focus = SDL_TRUE;
   341                     break;
   342                 }
   343             }
   344         }
   345         if (!focus) {
   346             SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
   347         }
   348     }
   349 
   350     mouse->focus = windowID;
   351 
   352     if (mouse->focus) {
   353         focus = SDL_FALSE;
   354         for (i = 0; i < SDL_num_mice; ++i) {
   355             SDL_Mouse *check;
   356             if (i != index) {
   357                 check = SDL_GetMouse(i);
   358                 if (check && check->focus == mouse->focus) {
   359                     focus = SDL_TRUE;
   360                     break;
   361                 }
   362             }
   363         }
   364         if (!focus) {
   365             SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
   366         }
   367         SDL_GetWindowSize(windowID, &mouse->x_max, &mouse->y_max);
   368     }
   369 }
   370 
   371 void
   372 SDL_SetMouseFocusSize(SDL_WindowID windowID, int w, int h)
   373 {
   374     int i;
   375 
   376     for (i = 0; i < SDL_num_mice; ++i) {
   377         SDL_Mouse *mouse = SDL_GetMouse(i);
   378         if (mouse && mouse->focus == windowID) {
   379             mouse->x_max = w;
   380             mouse->y_max = h;
   381         }
   382     }
   383 }
   384 
   385 int
   386 SDL_SendProximity(int id, int x, int y, int type)
   387 {
   388     int index = SDL_GetMouseIndexId(id);
   389     SDL_Mouse *mouse = SDL_GetMouse(index);
   390     int posted = 0;
   391 
   392     if (!mouse) {
   393         return 0;
   394     }
   395 
   396     last_x = x;
   397     last_y = y;
   398     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   399         SDL_Event event;
   400         event.proximity.which = (Uint8) index;
   401         event.proximity.x = x;
   402         event.proximity.y = y;
   403         event.proximity.cursor = mouse->current_end;
   404         event.proximity.type = type;
   405         posted = (SDL_PushEvent(&event) > 0);
   406         if (type == SDL_PROXIMITYIN) {
   407             mouse->proximity = SDL_TRUE;
   408         } else {
   409             mouse->proximity = SDL_FALSE;
   410         }
   411     }
   412     return posted;
   413 }
   414 
   415 int
   416 SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure)
   417 {
   418     int index = SDL_GetMouseIndexId(id);
   419     SDL_Mouse *mouse = SDL_GetMouse(index);
   420     int posted;
   421     int xrel;
   422     int yrel;
   423 
   424     if (!mouse || mouse->flush_motion) {
   425         return 0;
   426     }
   427 
   428     /* if the mouse is out of proximity we don't to want to have any motion from it */
   429     if (mouse->proximity == SDL_FALSE) {
   430         last_x = x;
   431         last_y = y;
   432         return 0;
   433     }
   434 
   435     /* the relative motion is calculated regarding the system cursor last position */
   436 
   437     xrel = x - last_x;
   438     yrel = y - last_y;
   439 
   440     /* Drop events that don't change state */
   441     if (!xrel && !yrel) {
   442 #if 0
   443         printf("Mouse event didn't change state - dropped!\n");
   444 #endif
   445         return 0;
   446     }
   447 
   448     /* Update internal mouse coordinates */
   449     if (mouse->relative_mode == SDL_FALSE) {
   450         mouse->x = x;
   451         mouse->y = y;
   452     } else {
   453         /* while using the relative mode and many windows, we have to be
   454            sure that the pointers find themselves inside the windows */
   455         if (mouse->x + xrel > mouse->x_max) {
   456             mouse->x = mouse->x_max;
   457         } else if (mouse->x + xrel < 0) {
   458             mouse->x = 0;
   459         } else {
   460             mouse->x += xrel;
   461         }
   462         if (mouse->y + yrel > mouse->y_max) {
   463             mouse->y = mouse->y_max;
   464         } else if (mouse->y + yrel < 0) {
   465             mouse->y = 0;
   466         } else {
   467             mouse->y += yrel;
   468         }
   469     }
   470     mouse->xdelta += xrel;
   471     mouse->ydelta += yrel;
   472     mouse->pressure = pressure;
   473 
   474     /* Move the mouse cursor, if needed */
   475     if (mouse->cursor_shown && !mouse->relative_mode &&
   476         mouse->MoveCursor && mouse->cur_cursor) {
   477         mouse->MoveCursor(mouse->cur_cursor);
   478     }
   479 
   480     /* Post the event, if desired */
   481     posted = 0;
   482     if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE &&
   483         mouse->proximity == SDL_TRUE) {
   484         SDL_Event event;
   485         event.motion.type = SDL_MOUSEMOTION;
   486         event.motion.which = (Uint8) index;
   487         event.motion.state = mouse->buttonstate;
   488         event.motion.x = mouse->x;
   489         event.motion.y = mouse->y;
   490         event.motion.pressure = mouse->pressure;
   491         event.motion.xrel = xrel;
   492         event.motion.yrel = yrel;
   493         event.motion.windowID = mouse->focus;
   494         event.motion.pressure_max = mouse->pressure_max;
   495         event.motion.pressure_min = mouse->pressure_min;
   496         event.motion.cursor = mouse->current_end;
   497         posted = (SDL_PushEvent(&event) > 0);
   498     }
   499     last_x = x;
   500     last_y = y;
   501     return posted;
   502 }
   503 
   504 int
   505 SDL_SendMouseButton(int id, Uint8 state, Uint8 button)
   506 {
   507     int index = SDL_GetMouseIndexId(id);
   508     SDL_Mouse *mouse = SDL_GetMouse(index);
   509     int posted;
   510     Uint8 type;
   511 
   512     if (!mouse) {
   513         return 0;
   514     }
   515 
   516     /* Figure out which event to perform */
   517     switch (state) {
   518     case SDL_PRESSED:
   519         if (mouse->buttonstate & SDL_BUTTON(button)) {
   520             /* Ignore this event, no state change */
   521             return 0;
   522         }
   523         type = SDL_MOUSEBUTTONDOWN;
   524         mouse->buttonstate |= SDL_BUTTON(button);
   525         break;
   526     case SDL_RELEASED:
   527         if (!(mouse->buttonstate & SDL_BUTTON(button))) {
   528             /* Ignore this event, no state change */
   529             return 0;
   530         }
   531         type = SDL_MOUSEBUTTONUP;
   532         mouse->buttonstate &= ~SDL_BUTTON(button);
   533         break;
   534     default:
   535         /* Invalid state -- bail */
   536         return 0;
   537     }
   538 
   539     /* Post the event, if desired */
   540     posted = 0;
   541     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   542         SDL_Event event;
   543         event.type = type;
   544         event.button.which = (Uint8) index;
   545         event.button.state = state;
   546         event.button.button = button;
   547         event.button.x = mouse->x;
   548         event.button.y = mouse->y;
   549         event.button.windowID = mouse->focus;
   550         posted = (SDL_PushEvent(&event) > 0);
   551     }
   552     return posted;
   553 }
   554 
   555 int
   556 SDL_SendMouseWheel(int index, int x, int y)
   557 {
   558     SDL_Mouse *mouse = SDL_GetMouse(index);
   559     int posted;
   560 
   561     if (!mouse || (!x && !y)) {
   562         return 0;
   563     }
   564 
   565     /* Post the event, if desired */
   566     posted = 0;
   567     if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) {
   568         SDL_Event event;
   569         event.type = SDL_MOUSEWHEEL;
   570         event.wheel.which = (Uint8) index;
   571         event.wheel.x = x;
   572         event.wheel.y = y;
   573         event.wheel.windowID = mouse->focus;
   574         posted = (SDL_PushEvent(&event) > 0);
   575     }
   576     return posted;
   577 }
   578 
   579 void
   580 SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
   581 {
   582     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   583 
   584     if (!mouse) {
   585         return;
   586     }
   587 
   588     if (mouse->WarpMouse) {
   589         mouse->WarpMouse(mouse, windowID, x, y);
   590     } else {
   591         SDL_SetMouseFocus(SDL_current_mouse, windowID);
   592         SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0);
   593     }
   594 }
   595 
   596 SDL_Cursor *
   597 SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
   598                  int w, int h, int hot_x, int hot_y)
   599 {
   600     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   601     SDL_Surface *surface;
   602     SDL_Cursor *cursor;
   603     int x, y;
   604     Uint32 *pixel;
   605     Uint8 datab, maskb;
   606     const Uint32 black = 0xFF000000;
   607     const Uint32 white = 0xFFFFFFFF;
   608     const Uint32 transparent = 0x00000000;
   609 
   610     if (!mouse) {
   611         SDL_SetError("No mice are initialized");
   612         return NULL;
   613     }
   614 
   615     if (!mouse->CreateCursor) {
   616         SDL_SetError("Current mouse doesn't have cursor support");
   617         return NULL;
   618     }
   619 
   620     /* Sanity check the hot spot */
   621     if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) {
   622         SDL_SetError("Cursor hot spot doesn't lie within cursor");
   623         return NULL;
   624     }
   625 
   626     /* Make sure the width is a multiple of 8 */
   627     w = ((w + 7) & ~7);
   628 
   629     /* Create the surface from a bitmap */
   630     surface =
   631         SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
   632                              0xFF000000);
   633     if (!surface) {
   634         return NULL;
   635     }
   636     for (y = 0; y < h; ++y) {
   637         pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
   638         for (x = 0; x < w; ++x) {
   639             if ((x % 8) == 0) {
   640                 datab = *data++;
   641                 maskb = *mask++;
   642             }
   643             if (maskb & 0x80) {
   644                 *pixel++ = (datab & 0x80) ? black : white;
   645             } else {
   646                 *pixel++ = (datab & 0x80) ? black : transparent;
   647             }
   648             datab <<= 1;
   649             maskb <<= 1;
   650         }
   651     }
   652 
   653     cursor = mouse->CreateCursor(surface, hot_x, hot_y);
   654     if (cursor) {
   655         cursor->mouse = mouse;
   656         cursor->next = mouse->cursors;
   657         mouse->cursors = cursor;
   658     }
   659 
   660     SDL_FreeSurface(surface);
   661 
   662     return cursor;
   663 }
   664 
   665 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
   666    if this is desired for any reason.  This is used when setting
   667    the video mode and when the SDL window gains the mouse focus.
   668  */
   669 void
   670 SDL_SetCursor(SDL_Cursor * cursor)
   671 {
   672     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   673 
   674     if (!mouse) {
   675         SDL_SetError("No mice are initialized");
   676         return;
   677     }
   678 
   679     /* Set the new cursor */
   680     if (cursor) {
   681         /* Make sure the cursor is still valid for this mouse */
   682         SDL_Cursor *found;
   683         for (found = mouse->cursors; found; found = found->next) {
   684             if (found == cursor) {
   685                 break;
   686             }
   687         }
   688         if (!found) {
   689             SDL_SetError("Cursor not associated with the current mouse");
   690             return;
   691         }
   692         mouse->cur_cursor = cursor;
   693     } else {
   694         cursor = mouse->cur_cursor;
   695     }
   696 
   697     if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
   698         if (mouse->ShowCursor) {
   699             mouse->ShowCursor(cursor);
   700         }
   701     } else {
   702         if (mouse->ShowCursor) {
   703             mouse->ShowCursor(NULL);
   704         }
   705     }
   706 }
   707 
   708 SDL_Cursor *
   709 SDL_GetCursor(void)
   710 {
   711     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   712 
   713     if (!mouse) {
   714         return NULL;
   715     }
   716     return mouse->cur_cursor;
   717 }
   718 
   719 void
   720 SDL_FreeCursor(SDL_Cursor * cursor)
   721 {
   722     SDL_Mouse *mouse;
   723     SDL_Cursor *curr, *prev;
   724 
   725     if (!cursor) {
   726         return;
   727     }
   728     mouse = cursor->mouse;
   729 
   730     if (cursor == mouse->def_cursor) {
   731         return;
   732     }
   733     if (cursor == mouse->cur_cursor) {
   734         SDL_SetCursor(mouse->def_cursor);
   735     }
   736 
   737     for (prev = NULL, curr = mouse->cursors; curr;
   738          prev = curr, curr = curr->next) {
   739         if (curr == cursor) {
   740             if (prev) {
   741                 prev->next = curr->next;
   742             } else {
   743                 mouse->cursors = curr->next;
   744             }
   745 
   746             if (mouse->FreeCursor) {
   747                 mouse->FreeCursor(curr);
   748             }
   749             return;
   750         }
   751     }
   752 }
   753 
   754 int
   755 SDL_ShowCursor(int toggle)
   756 {
   757     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   758     SDL_bool shown;
   759 
   760     if (!mouse) {
   761         return 0;
   762     }
   763 
   764     shown = mouse->cursor_shown;
   765     if (toggle >= 0) {
   766         if (toggle) {
   767             mouse->cursor_shown = SDL_TRUE;
   768         } else {
   769             mouse->cursor_shown = SDL_FALSE;
   770         }
   771         if (mouse->cursor_shown != shown) {
   772             SDL_SetCursor(NULL);
   773         }
   774     }
   775     return shown;
   776 }
   777 
   778 char *
   779 SDL_GetMouseName(int index)
   780 {
   781     SDL_Mouse *mouse = SDL_GetMouse(index);
   782     if (!mouse) {
   783         return NULL;
   784     }
   785     return mouse->name;
   786 }
   787 
   788 void
   789 SDL_ChangeEnd(int id, int end)
   790 {
   791     int index = SDL_GetMouseIndexId(id);
   792     SDL_Mouse *mouse = SDL_GetMouse(index);
   793 
   794     if (mouse) {
   795         mouse->current_end = end;
   796     }
   797 }
   798 
   799 int
   800 SDL_GetCursorsNumber(int index)
   801 {
   802     SDL_Mouse *mouse = SDL_GetMouse(index);
   803 
   804     if (!mouse) {
   805         return -1;
   806     }
   807     return mouse->total_ends;
   808 }
   809 
   810 int
   811 SDL_GetCurrentCursor(int index)
   812 {
   813     SDL_Mouse *mouse = SDL_GetMouse(index);
   814 
   815     if (!mouse) {
   816         return -1;
   817     }
   818     return mouse->current_end;
   819 }
   820 
   821 /* vi: set ts=4 sw=4 expandtab: */