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