src/events/SDL_mouse.c
author Sam Lantinga
Mon, 08 Dec 2008 00:27:32 +0000
changeset 2859 99210400e8b9
parent 2849 523b10db69f8
child 2860 6ce28e5287e9
permissions -rw-r--r--
Updated copyright date
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 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     }
   368 }
   369 
   370 int
   371 SDL_SendProximity(int id, int x, int y, int type)
   372 {
   373     int index = SDL_GetMouseIndexId(id);
   374     SDL_Mouse *mouse = SDL_GetMouse(index);
   375     int posted = 0;
   376 
   377     if (!mouse) {
   378         return 0;
   379     }
   380 
   381     last_x = x;
   382     last_y = y;
   383     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   384         SDL_Event event;
   385         event.proximity.which = (Uint8) index;
   386         event.proximity.x = x;
   387         event.proximity.y = y;
   388         event.proximity.cursor = mouse->current_end;
   389         event.proximity.type = type;
   390         posted = (SDL_PushEvent(&event) > 0);
   391         if (type == SDL_PROXIMITYIN) {
   392             mouse->proximity = SDL_TRUE;
   393         } else {
   394             mouse->proximity = SDL_FALSE;
   395         }
   396     }
   397     return posted;
   398 }
   399 
   400 int
   401 SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure)
   402 {
   403     int index = SDL_GetMouseIndexId(id);
   404     SDL_Mouse *mouse = SDL_GetMouse(index);
   405     int posted;
   406     int xrel;
   407     int yrel;
   408 
   409     if (!mouse || mouse->flush_motion) {
   410         return 0;
   411     }
   412 
   413     /* if the mouse is out of proximity we don't to want to have any motion from it */
   414     if (mouse->proximity == SDL_FALSE) {
   415         last_x = x;
   416         last_y = y;
   417         return 0;
   418     }
   419 
   420     /* the relative motion is calculated regarding the system cursor last position */
   421     if (relative) {
   422         xrel = x;
   423         yrel = y;
   424         x = (last_x + x);
   425         y = (last_y + y);
   426     } else {
   427         xrel = x - last_x;
   428         yrel = y - last_y;
   429     }
   430 
   431     /* Drop events that don't change state */
   432     if (!xrel && !yrel) {
   433 #if 0
   434         printf("Mouse event didn't change state - dropped!\n");
   435 #endif
   436         return 0;
   437     }
   438 
   439     /* Update internal mouse coordinates */
   440     if (mouse->relative_mode == SDL_FALSE) {
   441         mouse->x = x;
   442         mouse->y = y;
   443     } else {
   444         /* while using the relative mode and many windows, we have to be
   445            sure that the pointers find themselves inside the windows */
   446         int x_max, y_max;
   447 
   448         SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
   449 
   450         if (mouse->x + xrel > x_max) {
   451             mouse->x = x_max;
   452         } else if (mouse->x + xrel < 0) {
   453             mouse->x = 0;
   454         } else {
   455             mouse->x += xrel;
   456         }
   457         if (mouse->y + yrel > y_max) {
   458             mouse->y = y_max;
   459         } else if (mouse->y + yrel < 0) {
   460             mouse->y = 0;
   461         } else {
   462             mouse->y += yrel;
   463         }
   464     }
   465     mouse->xdelta += xrel;
   466     mouse->ydelta += yrel;
   467     mouse->pressure = pressure;
   468 
   469     /* Move the mouse cursor, if needed */
   470     if (mouse->cursor_shown && !mouse->relative_mode &&
   471         mouse->MoveCursor && mouse->cur_cursor) {
   472         mouse->MoveCursor(mouse->cur_cursor);
   473     }
   474 
   475     /* Post the event, if desired */
   476     posted = 0;
   477     if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE &&
   478         mouse->proximity == SDL_TRUE) {
   479         SDL_Event event;
   480         event.motion.type = SDL_MOUSEMOTION;
   481         event.motion.which = (Uint8) index;
   482         event.motion.state = mouse->buttonstate;
   483         event.motion.x = mouse->x;
   484         event.motion.y = mouse->y;
   485         event.motion.pressure = mouse->pressure;
   486         event.motion.xrel = xrel;
   487         event.motion.yrel = yrel;
   488         event.motion.windowID = mouse->focus;
   489         event.motion.pressure_max = mouse->pressure_max;
   490         event.motion.pressure_min = mouse->pressure_min;
   491         event.motion.cursor = mouse->current_end;
   492         posted = (SDL_PushEvent(&event) > 0);
   493     }
   494     last_x = x;
   495     last_y = y;
   496     return posted;
   497 }
   498 
   499 int
   500 SDL_SendMouseButton(int id, Uint8 state, Uint8 button)
   501 {
   502     int index = SDL_GetMouseIndexId(id);
   503     SDL_Mouse *mouse = SDL_GetMouse(index);
   504     int posted;
   505     Uint8 type;
   506 
   507     if (!mouse) {
   508         return 0;
   509     }
   510 
   511     /* Figure out which event to perform */
   512     switch (state) {
   513     case SDL_PRESSED:
   514         if (mouse->buttonstate & SDL_BUTTON(button)) {
   515             /* Ignore this event, no state change */
   516             return 0;
   517         }
   518         type = SDL_MOUSEBUTTONDOWN;
   519         mouse->buttonstate |= SDL_BUTTON(button);
   520         break;
   521     case SDL_RELEASED:
   522         if (!(mouse->buttonstate & SDL_BUTTON(button))) {
   523             /* Ignore this event, no state change */
   524             return 0;
   525         }
   526         type = SDL_MOUSEBUTTONUP;
   527         mouse->buttonstate &= ~SDL_BUTTON(button);
   528         break;
   529     default:
   530         /* Invalid state -- bail */
   531         return 0;
   532     }
   533 
   534     /* Post the event, if desired */
   535     posted = 0;
   536     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   537         SDL_Event event;
   538         event.type = type;
   539         event.button.which = (Uint8) index;
   540         event.button.state = state;
   541         event.button.button = button;
   542         event.button.x = mouse->x;
   543         event.button.y = mouse->y;
   544         event.button.windowID = mouse->focus;
   545         posted = (SDL_PushEvent(&event) > 0);
   546     }
   547     return posted;
   548 }
   549 
   550 int
   551 SDL_SendMouseWheel(int index, int x, int y)
   552 {
   553     SDL_Mouse *mouse = SDL_GetMouse(index);
   554     int posted;
   555 
   556     if (!mouse || (!x && !y)) {
   557         return 0;
   558     }
   559 
   560     /* Post the event, if desired */
   561     posted = 0;
   562     if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) {
   563         SDL_Event event;
   564         event.type = SDL_MOUSEWHEEL;
   565         event.wheel.which = (Uint8) index;
   566         event.wheel.x = x;
   567         event.wheel.y = y;
   568         event.wheel.windowID = mouse->focus;
   569         posted = (SDL_PushEvent(&event) > 0);
   570     }
   571     return posted;
   572 }
   573 
   574 void
   575 SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
   576 {
   577     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   578 
   579     if (!mouse) {
   580         return;
   581     }
   582 
   583     if (mouse->WarpMouse) {
   584         mouse->WarpMouse(mouse, windowID, x, y);
   585     } else {
   586         SDL_SetMouseFocus(SDL_current_mouse, windowID);
   587         SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0);
   588     }
   589 }
   590 
   591 SDL_Cursor *
   592 SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
   593                  int w, int h, int hot_x, int hot_y)
   594 {
   595     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   596     SDL_Surface *surface;
   597     SDL_Cursor *cursor;
   598     int x, y;
   599     Uint32 *pixel;
   600     Uint8 datab, maskb;
   601     const Uint32 black = 0xFF000000;
   602     const Uint32 white = 0xFFFFFFFF;
   603     const Uint32 transparent = 0x00000000;
   604 
   605     if (!mouse) {
   606         SDL_SetError("No mice are initialized");
   607         return NULL;
   608     }
   609 
   610     if (!mouse->CreateCursor) {
   611         SDL_SetError("Current mouse doesn't have cursor support");
   612         return NULL;
   613     }
   614 
   615     /* Sanity check the hot spot */
   616     if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) {
   617         SDL_SetError("Cursor hot spot doesn't lie within cursor");
   618         return NULL;
   619     }
   620 
   621     /* Make sure the width is a multiple of 8 */
   622     w = ((w + 7) & ~7);
   623 
   624     /* Create the surface from a bitmap */
   625     surface =
   626         SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
   627                              0xFF000000);
   628     if (!surface) {
   629         return NULL;
   630     }
   631     for (y = 0; y < h; ++y) {
   632         pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
   633         for (x = 0; x < w; ++x) {
   634             if ((x % 8) == 0) {
   635                 datab = *data++;
   636                 maskb = *mask++;
   637             }
   638             if (maskb & 0x80) {
   639                 *pixel++ = (datab & 0x80) ? black : white;
   640             } else {
   641                 *pixel++ = (datab & 0x80) ? black : transparent;
   642             }
   643             datab <<= 1;
   644             maskb <<= 1;
   645         }
   646     }
   647 
   648     cursor = mouse->CreateCursor(surface, hot_x, hot_y);
   649     if (cursor) {
   650         cursor->mouse = mouse;
   651         cursor->next = mouse->cursors;
   652         mouse->cursors = cursor;
   653     }
   654 
   655     SDL_FreeSurface(surface);
   656 
   657     return cursor;
   658 }
   659 
   660 /* SDL_SetCursor(NULL) can be used to force the cursor redraw,
   661    if this is desired for any reason.  This is used when setting
   662    the video mode and when the SDL window gains the mouse focus.
   663  */
   664 void
   665 SDL_SetCursor(SDL_Cursor * cursor)
   666 {
   667     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   668 
   669     if (!mouse) {
   670         SDL_SetError("No mice are initialized");
   671         return;
   672     }
   673 
   674     /* Set the new cursor */
   675     if (cursor) {
   676         /* Make sure the cursor is still valid for this mouse */
   677         SDL_Cursor *found;
   678         for (found = mouse->cursors; found; found = found->next) {
   679             if (found == cursor) {
   680                 break;
   681             }
   682         }
   683         if (!found) {
   684             SDL_SetError("Cursor not associated with the current mouse");
   685             return;
   686         }
   687         mouse->cur_cursor = cursor;
   688     } else {
   689         cursor = mouse->cur_cursor;
   690     }
   691 
   692     if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
   693         if (mouse->ShowCursor) {
   694             mouse->ShowCursor(cursor);
   695         }
   696     } else {
   697         if (mouse->ShowCursor) {
   698             mouse->ShowCursor(NULL);
   699         }
   700     }
   701 }
   702 
   703 SDL_Cursor *
   704 SDL_GetCursor(void)
   705 {
   706     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   707 
   708     if (!mouse) {
   709         return NULL;
   710     }
   711     return mouse->cur_cursor;
   712 }
   713 
   714 void
   715 SDL_FreeCursor(SDL_Cursor * cursor)
   716 {
   717     SDL_Mouse *mouse;
   718     SDL_Cursor *curr, *prev;
   719 
   720     if (!cursor) {
   721         return;
   722     }
   723     mouse = cursor->mouse;
   724 
   725     if (cursor == mouse->def_cursor) {
   726         return;
   727     }
   728     if (cursor == mouse->cur_cursor) {
   729         SDL_SetCursor(mouse->def_cursor);
   730     }
   731 
   732     for (prev = NULL, curr = mouse->cursors; curr;
   733          prev = curr, curr = curr->next) {
   734         if (curr == cursor) {
   735             if (prev) {
   736                 prev->next = curr->next;
   737             } else {
   738                 mouse->cursors = curr->next;
   739             }
   740 
   741             if (mouse->FreeCursor) {
   742                 mouse->FreeCursor(curr);
   743             }
   744             return;
   745         }
   746     }
   747 }
   748 
   749 int
   750 SDL_ShowCursor(int toggle)
   751 {
   752     SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
   753     SDL_bool shown;
   754 
   755     if (!mouse) {
   756         return 0;
   757     }
   758 
   759     shown = mouse->cursor_shown;
   760     if (toggle >= 0) {
   761         if (toggle) {
   762             mouse->cursor_shown = SDL_TRUE;
   763         } else {
   764             mouse->cursor_shown = SDL_FALSE;
   765         }
   766         if (mouse->cursor_shown != shown) {
   767             SDL_SetCursor(NULL);
   768         }
   769     }
   770     return shown;
   771 }
   772 
   773 char *
   774 SDL_GetMouseName(int index)
   775 {
   776     SDL_Mouse *mouse = SDL_GetMouse(index);
   777     if (!mouse) {
   778         return NULL;
   779     }
   780     return mouse->name;
   781 }
   782 
   783 void
   784 SDL_ChangeEnd(int id, int end)
   785 {
   786     int index = SDL_GetMouseIndexId(id);
   787     SDL_Mouse *mouse = SDL_GetMouse(index);
   788 
   789     if (mouse) {
   790         mouse->current_end = end;
   791     }
   792 }
   793 
   794 int
   795 SDL_GetCursorsNumber(int index)
   796 {
   797     SDL_Mouse *mouse = SDL_GetMouse(index);
   798 
   799     if (!mouse) {
   800         return -1;
   801     }
   802     return mouse->total_ends;
   803 }
   804 
   805 int
   806 SDL_GetCurrentCursor(int index)
   807 {
   808     SDL_Mouse *mouse = SDL_GetMouse(index);
   809 
   810     if (!mouse) {
   811         return -1;
   812     }
   813     return mouse->current_end;
   814 }
   815 
   816 /* vi: set ts=4 sw=4 expandtab: */