src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 02 Dec 2016 21:01:13 -0800
changeset 10673 4f02752f8d85
parent 10609 d702ecbd8ba7
child 10674 120c2e96b094
permissions -rw-r--r--
Added SDL_HINT_MOUSE_NORMAL_SPEED_SCALE and SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE to scale the speed of the mouse.
This currently doesn't affect absolute motion, which would need to be implemented on each windowing system so the cursor matches the reported mouse coordinates.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@0
    22
slouken@0
    23
/* General mouse handling code for SDL */
slouken@0
    24
slouken@6666
    25
#include "SDL_assert.h"
slouken@8071
    26
#include "SDL_hints.h"
slouken@8066
    27
#include "SDL_timer.h"
slouken@0
    28
#include "SDL_events.h"
slouken@0
    29
#include "SDL_events_c.h"
slouken@1895
    30
#include "default_cursor.h"
slouken@3685
    31
#include "../video/SDL_sysvideo.h"
slouken@0
    32
gabomdq@7678
    33
/* #define DEBUG_MOUSE */
slouken@0
    34
slouken@5371
    35
/* The mouse state */
slouken@4465
    36
static SDL_Mouse SDL_mouse;
slouken@8066
    37
static Uint32 SDL_double_click_time = 500;
slouken@8066
    38
static int SDL_double_click_radius = 1;
slouken@0
    39
jorgen@7089
    40
static int
jorgen@7089
    41
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
slouken@0
    42
slouken@10673
    43
static void
slouken@10673
    44
SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
slouken@10673
    45
{
slouken@10673
    46
    SDL_Mouse *mouse = (SDL_Mouse *)userdata;
slouken@10673
    47
slouken@10673
    48
    mouse->normal_speed_scale = SDL_atof(hint);
slouken@10673
    49
}
slouken@10673
    50
slouken@10673
    51
static void
slouken@10673
    52
SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
slouken@10673
    53
{
slouken@10673
    54
    SDL_Mouse *mouse = (SDL_Mouse *)userdata;
slouken@10673
    55
slouken@10673
    56
    mouse->relative_speed_scale = SDL_atof(hint);
slouken@10673
    57
}
slouken@10673
    58
slouken@0
    59
/* Public functions */
slouken@1895
    60
int
slouken@1895
    61
SDL_MouseInit(void)
slouken@0
    62
{
slouken@5376
    63
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5376
    64
slouken@10673
    65
    SDL_AddHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
slouken@10673
    66
                        SDL_MouseNormalSpeedScaleChanged, mouse);
slouken@10673
    67
slouken@10673
    68
    SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
slouken@10673
    69
                        SDL_MouseRelativeSpeedScaleChanged, mouse);
slouken@10673
    70
slouken@5376
    71
    mouse->cursor_shown = SDL_TRUE;
slouken@5376
    72
slouken@1895
    73
    return (0);
slouken@1123
    74
}
slouken@0
    75
slouken@5405
    76
void
slouken@5405
    77
SDL_SetDefaultCursor(SDL_Cursor * cursor)
slouken@5405
    78
{
slouken@5405
    79
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5405
    80
slouken@5405
    81
    mouse->def_cursor = cursor;
slouken@5405
    82
    if (!mouse->cur_cursor) {
slouken@5405
    83
        SDL_SetCursor(cursor);
slouken@5405
    84
    }
slouken@5405
    85
}
slouken@5405
    86
slouken@5371
    87
SDL_Mouse *
slouken@5371
    88
SDL_GetMouse(void)
slouken@5371
    89
{
slouken@5371
    90
    return &SDL_mouse;
slouken@5371
    91
}
slouken@5371
    92
slouken@8066
    93
void
slouken@8066
    94
SDL_SetDoubleClickTime(Uint32 interval)
slouken@8066
    95
{
slouken@8066
    96
    SDL_double_click_time = interval;
slouken@8066
    97
}
slouken@8066
    98
slouken@4465
    99
SDL_Window *
slouken@4465
   100
SDL_GetMouseFocus(void)
slouken@2710
   101
{
slouken@5371
   102
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@2940
   103
slouken@4465
   104
    return mouse->focus;
slouken@0
   105
}
slouken@0
   106
slouken@10609
   107
#if 0
slouken@1895
   108
void
slouken@6666
   109
SDL_ResetMouse(void)
slouken@6666
   110
{
slouken@6666
   111
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@6666
   112
    Uint8 i;
slouken@6666
   113
slouken@6666
   114
#ifdef DEBUG_MOUSE
slouken@6666
   115
    printf("Resetting mouse\n");
slouken@6666
   116
#endif
slouken@6666
   117
    for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) {
slouken@6666
   118
        if (mouse->buttonstate & SDL_BUTTON(i)) {
slouken@6950
   119
            SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i);
slouken@6666
   120
        }
slouken@6666
   121
    }
slouken@6666
   122
    SDL_assert(mouse->buttonstate == 0);
slouken@6666
   123
}
slouken@10609
   124
#endif
slouken@6666
   125
slouken@6666
   126
void
slouken@4465
   127
SDL_SetMouseFocus(SDL_Window * window)
slouken@0
   128
{
slouken@5371
   129
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   130
slouken@4465
   131
    if (mouse->focus == window) {
slouken@1895
   132
        return;
slouken@1895
   133
    }
slouken@1895
   134
slouken@6829
   135
    /* Actually, this ends up being a bad idea, because most operating
slouken@6829
   136
       systems have an implicit grab when you press the mouse button down
slouken@6829
   137
       so you can drag things out of the window and then get the mouse up
slouken@6829
   138
       when it happens.  So, #if 0...
slouken@6829
   139
    */
slouken@6829
   140
#if 0
slouken@6666
   141
    if (mouse->focus && !window) {
slouken@6666
   142
        /* We won't get anymore mouse messages, so reset mouse state */
slouken@6666
   143
        SDL_ResetMouse();
slouken@6666
   144
    }
slouken@6829
   145
#endif
slouken@6666
   146
slouken@1895
   147
    /* See if the current window has lost focus */
slouken@1895
   148
    if (mouse->focus) {
slouken@4465
   149
        SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
slouken@1895
   150
    }
slouken@1895
   151
slouken@3685
   152
    mouse->focus = window;
slouken@1895
   153
slouken@1895
   154
    if (mouse->focus) {
slouken@4465
   155
        SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
slouken@1895
   156
    }
slouken@6666
   157
slouken@6666
   158
    /* Update cursor visibility */
slouken@6666
   159
    SDL_SetCursor(NULL);
slouken@6666
   160
}
slouken@6666
   161
slouken@6666
   162
/* Check to see if we need to synthesize focus events */
slouken@6666
   163
static SDL_bool
slouken@6673
   164
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
slouken@6666
   165
{
slouken@6666
   166
    SDL_Mouse *mouse = SDL_GetMouse();
icculus@8927
   167
    SDL_bool inWindow = SDL_TRUE;
slouken@6666
   168
slouken@8983
   169
    if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
icculus@8927
   170
        int w, h;
icculus@8927
   171
        SDL_GetWindowSize(window, &w, &h);
icculus@8927
   172
        if (x < 0 || y < 0 || x >= w || y >= h) {
icculus@8927
   173
            inWindow = SDL_FALSE;
icculus@8927
   174
        }
slouken@6666
   175
    }
slouken@6667
   176
icculus@8783
   177
/* Linux doesn't give you mouse events outside your window unless you grab
icculus@8783
   178
   the pointer.
icculus@8783
   179
icculus@8783
   180
   Windows doesn't give you mouse events outside your window unless you call
icculus@8783
   181
   SetCapture().
icculus@8783
   182
icculus@8783
   183
   Both of these are slightly scary changes, so for now we'll punt and if the
icculus@8783
   184
   mouse leaves the window you'll lose mouse focus and reset button state.
icculus@8783
   185
*/
icculus@8783
   186
#ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
icculus@8783
   187
    if (!inWindow && !buttonstate) {
icculus@8783
   188
#else
slouken@6667
   189
    if (!inWindow) {
icculus@8783
   190
#endif
slouken@6666
   191
        if (window == mouse->focus) {
slouken@6666
   192
#ifdef DEBUG_MOUSE
jorgen@7089
   193
            printf("Mouse left window, synthesizing move & focus lost event\n");
slouken@6666
   194
#endif
jorgen@7089
   195
            SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
slouken@6666
   196
            SDL_SetMouseFocus(NULL);
slouken@6666
   197
        }
slouken@6666
   198
        return SDL_FALSE;
slouken@6666
   199
    }
slouken@6666
   200
slouken@6666
   201
    if (window != mouse->focus) {
slouken@6666
   202
#ifdef DEBUG_MOUSE
jorgen@7097
   203
         printf("Mouse entered window, synthesizing focus gain & move event\n");
slouken@6666
   204
#endif
jorgen@7097
   205
         SDL_SetMouseFocus(window);
jorgen@7097
   206
         SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
slouken@6666
   207
    }
slouken@6666
   208
    return SDL_TRUE;
slouken@1895
   209
}
slouken@1895
   210
slouken@1895
   211
int
slouken@6950
   212
SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
slouken@1895
   213
{
jorgen@7089
   214
    if (window && !relative) {
jorgen@7089
   215
        SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7089
   216
        if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
jorgen@7089
   217
            return 0;
jorgen@7089
   218
        }
jorgen@7089
   219
    }
jorgen@7089
   220
jorgen@7089
   221
    return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y);
jorgen@7089
   222
}
jorgen@7089
   223
jorgen@7089
   224
static int
slouken@10673
   225
GetScaledMouseDelta(float scale, int value, float *accum)
slouken@10673
   226
{
slouken@10673
   227
    if (scale != 1.0f) {
slouken@10673
   228
        *accum += scale * value;
slouken@10673
   229
        if (*accum >= 0.0f) {
slouken@10673
   230
            value = (int)SDL_floor(*accum);
slouken@10673
   231
        } else {
slouken@10673
   232
            value = (int)SDL_ceil(*accum);
slouken@10673
   233
        }
slouken@10673
   234
        *accum -= value;
slouken@10673
   235
    }
slouken@10673
   236
    return value;
slouken@10673
   237
}
slouken@10673
   238
slouken@10673
   239
static int
jorgen@7089
   240
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
jorgen@7089
   241
{
slouken@5371
   242
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   243
    int posted;
slouken@1895
   244
    int xrel;
slouken@1895
   245
    int yrel;
slouken@1895
   246
slouken@8071
   247
    if (mouse->relative_mode_warp) {
slouken@8071
   248
        int center_x = 0, center_y = 0;
slouken@8071
   249
        SDL_GetWindowSize(window, &center_x, &center_y);
slouken@8071
   250
        center_x /= 2;
slouken@8071
   251
        center_y /= 2;
slouken@8071
   252
        if (x == center_x && y == center_y) {
slouken@8071
   253
            mouse->last_x = center_x;
slouken@8071
   254
            mouse->last_y = center_y;
slouken@8071
   255
            return 0;
slouken@8071
   256
        }
slouken@8071
   257
        SDL_WarpMouseInWindow(window, center_x, center_y);
slouken@8071
   258
    }
slouken@8071
   259
slouken@2842
   260
    if (relative) {
slouken@10673
   261
        if (mouse->relative_mode) {
slouken@10673
   262
            x = GetScaledMouseDelta(mouse->relative_speed_scale, x, &mouse->scale_accum_x);
slouken@10673
   263
            y = GetScaledMouseDelta(mouse->relative_speed_scale, y, &mouse->scale_accum_y);
slouken@10673
   264
        } else {
slouken@10673
   265
            x = GetScaledMouseDelta(mouse->normal_speed_scale, x, &mouse->scale_accum_x);
slouken@10673
   266
            y = GetScaledMouseDelta(mouse->normal_speed_scale, y, &mouse->scale_accum_y);
slouken@10673
   267
        }
slouken@2842
   268
        xrel = x;
slouken@2842
   269
        yrel = y;
slouken@8071
   270
        x = (mouse->last_x + xrel);
slouken@8071
   271
        y = (mouse->last_y + yrel);
slouken@2842
   272
    } else {
slouken@2860
   273
        xrel = x - mouse->last_x;
slouken@2860
   274
        yrel = y - mouse->last_y;
slouken@2842
   275
    }
slouken@2710
   276
slouken@1895
   277
    /* Drop events that don't change state */
slouken@1895
   278
    if (!xrel && !yrel) {
slouken@6666
   279
#ifdef DEBUG_MOUSE
slouken@1895
   280
        printf("Mouse event didn't change state - dropped!\n");
slouken@1895
   281
#endif
slouken@1895
   282
        return 0;
slouken@1895
   283
    }
slouken@1895
   284
slouken@2710
   285
    /* Update internal mouse coordinates */
slouken@8071
   286
    if (!mouse->relative_mode) {
slouken@1895
   287
        mouse->x = x;
slouken@1895
   288
        mouse->y = y;
slouken@2710
   289
    } else {
slouken@2860
   290
        mouse->x += xrel;
slouken@2860
   291
        mouse->y += yrel;
slouken@2860
   292
    }
slouken@2849
   293
icculus@8927
   294
    /* make sure that the pointers find themselves inside the windows,
icculus@8927
   295
       unless we have the mouse captured. */
slouken@8983
   296
    if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
icculus@8927
   297
        int x_max = 0, y_max = 0;
slouken@2849
   298
icculus@8927
   299
        // !!! FIXME: shouldn't this be (window) instead of (mouse->focus)?
icculus@8927
   300
        SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
icculus@8927
   301
        --x_max;
icculus@8927
   302
        --y_max;
slouken@2860
   303
icculus@8927
   304
        if (mouse->x > x_max) {
icculus@8927
   305
            mouse->x = x_max;
icculus@8927
   306
        }
icculus@8927
   307
        if (mouse->x < 0) {
icculus@8927
   308
            mouse->x = 0;
icculus@8927
   309
        }
icculus@8927
   310
icculus@8927
   311
        if (mouse->y > y_max) {
icculus@8927
   312
            mouse->y = y_max;
icculus@8927
   313
        }
icculus@8927
   314
        if (mouse->y < 0) {
icculus@8927
   315
            mouse->y = 0;
icculus@8927
   316
        }
slouken@2860
   317
    }
slouken@2860
   318
slouken@1895
   319
    mouse->xdelta += xrel;
slouken@1895
   320
    mouse->ydelta += yrel;
slouken@1895
   321
slouken@1895
   322
    /* Move the mouse cursor, if needed */
slouken@1895
   323
    if (mouse->cursor_shown && !mouse->relative_mode &&
slouken@1895
   324
        mouse->MoveCursor && mouse->cur_cursor) {
slouken@1895
   325
        mouse->MoveCursor(mouse->cur_cursor);
slouken@1895
   326
    }
slouken@1895
   327
slouken@1895
   328
    /* Post the event, if desired */
slouken@1895
   329
    posted = 0;
slouken@4465
   330
    if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) {
slouken@1895
   331
        SDL_Event event;
slouken@1895
   332
        event.motion.type = SDL_MOUSEMOTION;
slouken@4465
   333
        event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
slouken@6950
   334
        event.motion.which = mouseID;
slouken@1895
   335
        event.motion.state = mouse->buttonstate;
slouken@1895
   336
        event.motion.x = mouse->x;
slouken@1895
   337
        event.motion.y = mouse->y;
slouken@1895
   338
        event.motion.xrel = xrel;
slouken@1895
   339
        event.motion.yrel = yrel;
slouken@1895
   340
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   341
    }
slouken@9448
   342
    if (relative) {
slouken@9448
   343
        mouse->last_x = mouse->x;
slouken@9448
   344
        mouse->last_y = mouse->y;
slouken@9448
   345
    } else {
slouken@9448
   346
        /* Use unclamped values if we're getting events outside the window */
slouken@9448
   347
        mouse->last_x = x;
slouken@9448
   348
        mouse->last_y = y;
slouken@9448
   349
    }
slouken@1895
   350
    return posted;
slouken@1895
   351
}
slouken@1895
   352
slouken@8066
   353
static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
slouken@8066
   354
{
slouken@8066
   355
    if (button >= mouse->num_clickstates) {
slouken@8066
   356
        int i, count = button + 1;
philipp@9334
   357
        SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
philipp@9334
   358
        if (!clickstate) {
slouken@8066
   359
            return NULL;
slouken@8066
   360
        }
philipp@9334
   361
        mouse->clickstate = clickstate;
slouken@8066
   362
slouken@8066
   363
        for (i = mouse->num_clickstates; i < count; ++i) {
slouken@8066
   364
            SDL_zero(mouse->clickstate[i]);
slouken@8066
   365
        }
slouken@8066
   366
        mouse->num_clickstates = count;
slouken@8066
   367
    }
slouken@8066
   368
    return &mouse->clickstate[button];
slouken@8066
   369
}
slouken@8066
   370
slime73@10366
   371
static int
slime73@10366
   372
SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
slouken@1895
   373
{
slouken@5371
   374
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   375
    int posted;
slouken@4429
   376
    Uint32 type;
slouken@6673
   377
    Uint32 buttonstate = mouse->buttonstate;
slouken@4484
   378
slouken@1895
   379
    /* Figure out which event to perform */
slouken@1895
   380
    switch (state) {
slouken@1895
   381
    case SDL_PRESSED:
slouken@1895
   382
        type = SDL_MOUSEBUTTONDOWN;
slouken@6666
   383
        buttonstate |= SDL_BUTTON(button);
slouken@1895
   384
        break;
slouken@1895
   385
    case SDL_RELEASED:
slouken@1895
   386
        type = SDL_MOUSEBUTTONUP;
slouken@6666
   387
        buttonstate &= ~SDL_BUTTON(button);
slouken@1895
   388
        break;
slouken@1895
   389
    default:
slouken@1895
   390
        /* Invalid state -- bail */
slouken@1895
   391
        return 0;
slouken@1895
   392
    }
slouken@1895
   393
slouken@6666
   394
    /* We do this after calculating buttonstate so button presses gain focus */
slouken@6666
   395
    if (window && state == SDL_PRESSED) {
slouken@6666
   396
        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
slouken@6666
   397
    }
slouken@6666
   398
slouken@6666
   399
    if (buttonstate == mouse->buttonstate) {
slouken@6666
   400
        /* Ignore this event, no state change */
slouken@6666
   401
        return 0;
slouken@6666
   402
    }
slouken@6666
   403
    mouse->buttonstate = buttonstate;
slouken@6666
   404
slime73@10366
   405
    if (clicks < 0) {
slime73@10366
   406
        SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
philipp@10390
   407
        if (clickstate) {
philipp@10390
   408
            if (state == SDL_PRESSED) {
philipp@10390
   409
                Uint32 now = SDL_GetTicks();
slouken@8066
   410
philipp@10390
   411
                if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) ||
philipp@10390
   412
                    SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius ||
philipp@10390
   413
                    SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) {
philipp@10390
   414
                    clickstate->click_count = 0;
philipp@10390
   415
                }
philipp@10390
   416
                clickstate->last_timestamp = now;
philipp@10390
   417
                clickstate->last_x = mouse->x;
philipp@10390
   418
                clickstate->last_y = mouse->y;
philipp@10390
   419
                if (clickstate->click_count < 255) {
philipp@10390
   420
                    ++clickstate->click_count;
philipp@10390
   421
                }
slouken@8066
   422
            }
philipp@10390
   423
            clicks = clickstate->click_count;
philipp@10390
   424
        } else {
philipp@10390
   425
            clicks = 1;
slouken@8066
   426
        }
slouken@8066
   427
    }
slouken@8066
   428
slouken@1895
   429
    /* Post the event, if desired */
slouken@1895
   430
    posted = 0;
slouken@4429
   431
    if (SDL_GetEventState(type) == SDL_ENABLE) {
slouken@1895
   432
        SDL_Event event;
slouken@1895
   433
        event.type = type;
slouken@6950
   434
        event.button.windowID = mouse->focus ? mouse->focus->id : 0;
slouken@6950
   435
        event.button.which = mouseID;
slouken@1895
   436
        event.button.state = state;
slouken@1895
   437
        event.button.button = button;
slime73@10366
   438
        event.button.clicks = (Uint8) SDL_min(clicks, 255);
slouken@1895
   439
        event.button.x = mouse->x;
slouken@1895
   440
        event.button.y = mouse->y;
slouken@1895
   441
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   442
    }
slouken@6666
   443
slouken@6666
   444
    /* We do this after dispatching event so button releases can lose focus */
slouken@6666
   445
    if (window && state == SDL_RELEASED) {
slouken@6666
   446
        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
slouken@6666
   447
    }
slime73@10366
   448
    
slime73@10366
   449
    return posted;
slime73@10366
   450
}
slouken@6666
   451
slime73@10366
   452
int
slime73@10366
   453
SDL_SendMouseButtonClicks(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
slime73@10366
   454
{
slime73@10366
   455
    clicks = SDL_max(clicks, 0);
slime73@10366
   456
    return SDL_PrivateSendMouseButton(window, mouseID, state, button, clicks);
slime73@10366
   457
}
slime73@10366
   458
slime73@10366
   459
int
slime73@10366
   460
SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
slime73@10366
   461
{
slime73@10366
   462
    return SDL_PrivateSendMouseButton(window, mouseID, state, button, -1);
slouken@1895
   463
}
slouken@1895
   464
slouken@1895
   465
int
urkle@9257
   466
SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction)
slouken@1895
   467
{
slouken@5371
   468
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   469
    int posted;
slouken@1895
   470
slouken@4484
   471
    if (window) {
slouken@4484
   472
        SDL_SetMouseFocus(window);
slouken@4484
   473
    }
slouken@4484
   474
slouken@4465
   475
    if (!x && !y) {
slouken@1895
   476
        return 0;
slouken@1895
   477
    }
slouken@1895
   478
slouken@1895
   479
    /* Post the event, if desired */
slouken@1895
   480
    posted = 0;
slouken@4429
   481
    if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) {
slouken@1895
   482
        SDL_Event event;
slouken@1895
   483
        event.type = SDL_MOUSEWHEEL;
slouken@4465
   484
        event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
slouken@6950
   485
        event.wheel.which = mouseID;
slouken@2152
   486
        event.wheel.x = x;
slouken@2152
   487
        event.wheel.y = y;
urkle@9257
   488
        event.wheel.direction = (Uint32)direction;
slouken@1895
   489
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   490
    }
slouken@1895
   491
    return posted;
slouken@1895
   492
}
slouken@1895
   493
slouken@1895
   494
void
slouken@4465
   495
SDL_MouseQuit(void)
slouken@4465
   496
{
slouken@7493
   497
    SDL_Cursor *cursor, *next;
slouken@7493
   498
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@7493
   499
slouken@9161
   500
    if (mouse->CaptureMouse) {
slouken@9161
   501
        SDL_CaptureMouse(SDL_FALSE);
slouken@9161
   502
    }
slouken@8049
   503
    SDL_SetRelativeMouseMode(SDL_FALSE);
slouken@7493
   504
    SDL_ShowCursor(1);
slouken@7493
   505
slouken@7493
   506
    cursor = mouse->cursors;
slouken@7493
   507
    while (cursor) {
slouken@7493
   508
        next = cursor->next;
slouken@7493
   509
        SDL_FreeCursor(cursor);
slouken@7493
   510
        cursor = next;
slouken@7493
   511
    }
slouken@7493
   512
slouken@7493
   513
    if (mouse->def_cursor && mouse->FreeCursor) {
slouken@7493
   514
        mouse->FreeCursor(mouse->def_cursor);
slouken@7493
   515
    }
slouken@7493
   516
slouken@8066
   517
    if (mouse->clickstate) {
slouken@8066
   518
        SDL_free(mouse->clickstate);
slouken@8066
   519
    }
slouken@8066
   520
slouken@7493
   521
    SDL_zerop(mouse);
slouken@10673
   522
slouken@10673
   523
    SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
slouken@10673
   524
                        SDL_MouseNormalSpeedScaleChanged, mouse);
slouken@10673
   525
slouken@10673
   526
    SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
slouken@10673
   527
                        SDL_MouseRelativeSpeedScaleChanged, mouse);
slouken@4465
   528
}
slouken@4465
   529
slouken@6673
   530
Uint32
slouken@4465
   531
SDL_GetMouseState(int *x, int *y)
slouken@4465
   532
{
slouken@5371
   533
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@4465
   534
slouken@4465
   535
    if (x) {
slouken@4465
   536
        *x = mouse->x;
slouken@4465
   537
    }
slouken@4465
   538
    if (y) {
slouken@4465
   539
        *y = mouse->y;
slouken@4465
   540
    }
slouken@4465
   541
    return mouse->buttonstate;
slouken@4465
   542
}
slouken@4465
   543
slouken@6673
   544
Uint32
slouken@4465
   545
SDL_GetRelativeMouseState(int *x, int *y)
slouken@4465
   546
{
slouken@5371
   547
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@4465
   548
slouken@4465
   549
    if (x) {
slouken@4465
   550
        *x = mouse->xdelta;
slouken@4465
   551
    }
slouken@4465
   552
    if (y) {
slouken@4465
   553
        *y = mouse->ydelta;
slouken@4465
   554
    }
slouken@4465
   555
    mouse->xdelta = 0;
slouken@4465
   556
    mouse->ydelta = 0;
slouken@4465
   557
    return mouse->buttonstate;
slouken@4465
   558
}
slouken@4465
   559
icculus@8945
   560
Uint32
icculus@8952
   561
SDL_GetGlobalMouseState(int *x, int *y)
icculus@8945
   562
{
icculus@8945
   563
    SDL_Mouse *mouse = SDL_GetMouse();
icculus@8945
   564
    int tmpx, tmpy;
icculus@8945
   565
icculus@8945
   566
    /* make sure these are never NULL for the backend implementations... */
icculus@8945
   567
    if (!x) {
icculus@8945
   568
        x = &tmpx;
icculus@8945
   569
    }
icculus@8945
   570
    if (!y) {
icculus@8945
   571
        y = &tmpy;
icculus@8945
   572
    }
icculus@8945
   573
icculus@8945
   574
    *x = *y = 0;
icculus@8945
   575
icculus@8952
   576
    if (!mouse->GetGlobalMouseState) {
icculus@8945
   577
        SDL_assert(0 && "This should really be implemented for every target.");
icculus@8945
   578
        return 0;
icculus@8945
   579
    }
icculus@8945
   580
icculus@8952
   581
    return mouse->GetGlobalMouseState(x, y);
icculus@8945
   582
}
icculus@8945
   583
slouken@4465
   584
void
slouken@3685
   585
SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
slouken@1895
   586
{
slouken@5371
   587
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@7191
   588
icculus@8953
   589
    if (window == NULL) {
slouken@7191
   590
        window = mouse->focus;
icculus@8944
   591
    }
slouken@7191
   592
icculus@8953
   593
    if (window == NULL) {
slouken@7191
   594
        return;
icculus@8944
   595
    }
slouken@1895
   596
slouken@1895
   597
    if (mouse->WarpMouse) {
slouken@5371
   598
        mouse->WarpMouse(window, x, y);
slouken@1895
   599
    } else {
slouken@6950
   600
        SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
slouken@1895
   601
    }
slouken@1895
   602
}
slouken@1895
   603
icculus@9807
   604
int
slouken@8815
   605
SDL_WarpMouseGlobal(int x, int y)
slouken@8815
   606
{
slouken@8815
   607
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@8815
   608
slouken@8815
   609
    if (mouse->WarpMouseGlobal) {
icculus@9807
   610
        return mouse->WarpMouseGlobal(x, y);
slouken@8815
   611
    }
icculus@9807
   612
icculus@9807
   613
    return SDL_Unsupported();
slouken@8815
   614
}
slouken@8815
   615
slouken@8071
   616
static SDL_bool
slouken@8071
   617
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
slouken@8071
   618
{
slouken@8071
   619
    if (!mouse->SetRelativeMouseMode) {
slouken@8071
   620
        return SDL_TRUE;
slouken@8071
   621
    }
slouken@8071
   622
slouken@10499
   623
    return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
slouken@8071
   624
}
slouken@8071
   625
slouken@4465
   626
int
slouken@4465
   627
SDL_SetRelativeMouseMode(SDL_bool enabled)
slouken@4465
   628
{
slouken@5371
   629
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7107
   630
    SDL_Window *focusWindow = SDL_GetKeyboardFocus();
slouken@4465
   631
slouken@5406
   632
    if (enabled == mouse->relative_mode) {
slouken@5406
   633
        return 0;
slouken@5406
   634
    }
slouken@5406
   635
jorgen@7107
   636
    if (enabled && focusWindow) {
jorgen@7107
   637
        /* Center it in the focused window to prevent clicks from going through
jorgen@7107
   638
         * to background windows.
jorgen@7107
   639
         */
jorgen@7107
   640
        SDL_SetMouseFocus(focusWindow);
jorgen@7107
   641
        SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
jorgen@7107
   642
    }
jorgen@7107
   643
slouken@8071
   644
    /* Set the relative mode */
slouken@8071
   645
    if (!enabled && mouse->relative_mode_warp) {
slouken@8071
   646
        mouse->relative_mode_warp = SDL_FALSE;
slouken@8071
   647
    } else if (enabled && ShouldUseRelativeModeWarp(mouse)) {
slouken@8071
   648
        mouse->relative_mode_warp = SDL_TRUE;
slouken@8071
   649
    } else if (mouse->SetRelativeMouseMode(enabled) < 0) {
slouken@8269
   650
        if (enabled) {
philipp@8776
   651
            /* Fall back to warp mode if native relative mode failed */
slouken@8269
   652
            mouse->relative_mode_warp = SDL_TRUE;
slouken@8269
   653
        }
slouken@5406
   654
    }
slouken@4465
   655
    mouse->relative_mode = enabled;
slouken@10673
   656
    mouse->scale_accum_x = 0.0f;
slouken@10673
   657
    mouse->scale_accum_y = 0.0f;
slouken@4465
   658
slouken@8071
   659
    if (mouse->focus) {
slouken@8071
   660
        SDL_UpdateWindowGrab(mouse->focus);
slouken@8071
   661
slouken@8071
   662
        /* Put the cursor back to where the application expects it */
slouken@8071
   663
        if (!enabled) {
slouken@8071
   664
            SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
slouken@8071
   665
        }
slouken@4465
   666
    }
slouken@4465
   667
slouken@8071
   668
    /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */
slouken@5406
   669
    SDL_FlushEvent(SDL_MOUSEMOTION);
slouken@5406
   670
slouken@4465
   671
    /* Update cursor visibility */
slouken@4465
   672
    SDL_SetCursor(NULL);
slouken@4465
   673
slouken@4465
   674
    return 0;
slouken@4465
   675
}
slouken@4465
   676
slouken@4465
   677
SDL_bool
slouken@4465
   678
SDL_GetRelativeMouseMode()
slouken@4465
   679
{
slouken@5371
   680
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@4465
   681
slouken@4465
   682
    return mouse->relative_mode;
slouken@4465
   683
}
slouken@4465
   684
icculus@8955
   685
int
icculus@8955
   686
SDL_CaptureMouse(SDL_bool enabled)
icculus@8955
   687
{
icculus@8955
   688
    SDL_Mouse *mouse = SDL_GetMouse();
icculus@8955
   689
    SDL_Window *focusWindow;
icculus@8955
   690
    SDL_bool isCaptured;
icculus@8955
   691
icculus@8955
   692
    if (!mouse->CaptureMouse) {
icculus@8955
   693
        return SDL_Unsupported();
icculus@8955
   694
    }
icculus@8955
   695
icculus@8955
   696
    focusWindow = SDL_GetKeyboardFocus();
icculus@8955
   697
icculus@8955
   698
    isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
icculus@8955
   699
    if (isCaptured == enabled) {
icculus@8955
   700
        return 0;  /* already done! */
icculus@8955
   701
    }
icculus@8955
   702
icculus@8955
   703
    if (enabled) {
icculus@8955
   704
        if (!focusWindow) {
icculus@8955
   705
            return SDL_SetError("No window has focus");
icculus@8955
   706
        } else if (mouse->CaptureMouse(focusWindow) == -1) {
icculus@8955
   707
            return -1;  /* CaptureMouse() should call SetError */
icculus@8955
   708
        }
icculus@8955
   709
        focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
icculus@8955
   710
    } else {
icculus@8955
   711
        if (mouse->CaptureMouse(NULL) == -1) {
icculus@8955
   712
            return -1;  /* CaptureMouse() should call SetError */
icculus@8955
   713
        }
icculus@8955
   714
        focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
icculus@8955
   715
    }
icculus@8955
   716
icculus@8955
   717
    return 0;
icculus@8955
   718
}
icculus@8955
   719
slouken@1895
   720
SDL_Cursor *
slouken@1895
   721
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
slouken@1895
   722
                 int w, int h, int hot_x, int hot_y)
slouken@1895
   723
{
slouken@1895
   724
    SDL_Surface *surface;
slouken@1895
   725
    SDL_Cursor *cursor;
slouken@1895
   726
    int x, y;
slouken@1895
   727
    Uint32 *pixel;
slouken@4465
   728
    Uint8 datab = 0, maskb = 0;
slouken@1895
   729
    const Uint32 black = 0xFF000000;
slouken@1895
   730
    const Uint32 white = 0xFFFFFFFF;
slouken@1895
   731
    const Uint32 transparent = 0x00000000;
slouken@1895
   732
slouken@1895
   733
    /* Make sure the width is a multiple of 8 */
slouken@1895
   734
    w = ((w + 7) & ~7);
slouken@1895
   735
slouken@1895
   736
    /* Create the surface from a bitmap */
slouken@5473
   737
    surface = SDL_CreateRGBSurface(0, w, h, 32,
slouken@5473
   738
                                   0x00FF0000,
slouken@5473
   739
                                   0x0000FF00,
slouken@5473
   740
                                   0x000000FF,
slouken@5473
   741
                                   0xFF000000);
slouken@1895
   742
    if (!surface) {
slouken@1895
   743
        return NULL;
slouken@1895
   744
    }
slouken@1895
   745
    for (y = 0; y < h; ++y) {
slouken@1895
   746
        pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
slouken@1895
   747
        for (x = 0; x < w; ++x) {
slouken@1895
   748
            if ((x % 8) == 0) {
slouken@1895
   749
                datab = *data++;
slouken@1895
   750
                maskb = *mask++;
slouken@1895
   751
            }
slouken@1895
   752
            if (maskb & 0x80) {
slouken@1895
   753
                *pixel++ = (datab & 0x80) ? black : white;
slouken@1895
   754
            } else {
slouken@1895
   755
                *pixel++ = (datab & 0x80) ? black : transparent;
slouken@1895
   756
            }
slouken@1895
   757
            datab <<= 1;
slouken@1895
   758
            maskb <<= 1;
slouken@1895
   759
        }
slouken@1895
   760
    }
slouken@1895
   761
slouken@5473
   762
    cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
slouken@5473
   763
slouken@5473
   764
    SDL_FreeSurface(surface);
slouken@5473
   765
slouken@5473
   766
    return cursor;
slouken@5473
   767
}
slouken@5473
   768
slouken@5473
   769
SDL_Cursor *
slouken@5473
   770
SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
slouken@5473
   771
{
slouken@5473
   772
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5473
   773
    SDL_Surface *temp = NULL;
slouken@5473
   774
    SDL_Cursor *cursor;
slouken@5473
   775
slouken@5473
   776
    if (!surface) {
slouken@5473
   777
        SDL_SetError("Passed NULL cursor surface");
slouken@5473
   778
        return NULL;
slouken@5473
   779
    }
slouken@5473
   780
slouken@5473
   781
    if (!mouse->CreateCursor) {
slouken@5473
   782
        SDL_SetError("Cursors are not currently supported");
slouken@5473
   783
        return NULL;
slouken@5473
   784
    }
slouken@5473
   785
slouken@5473
   786
    /* Sanity check the hot spot */
slouken@5473
   787
    if ((hot_x < 0) || (hot_y < 0) ||
slouken@5473
   788
        (hot_x >= surface->w) || (hot_y >= surface->h)) {
slouken@5473
   789
        SDL_SetError("Cursor hot spot doesn't lie within cursor");
slouken@5473
   790
        return NULL;
slouken@5473
   791
    }
slouken@5473
   792
slouken@5473
   793
    if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
slouken@5473
   794
        temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
slouken@5473
   795
        if (!temp) {
slouken@5473
   796
            return NULL;
slouken@5473
   797
        }
slouken@5473
   798
        surface = temp;
slouken@5473
   799
    }
slouken@5473
   800
slouken@1895
   801
    cursor = mouse->CreateCursor(surface, hot_x, hot_y);
slouken@1895
   802
    if (cursor) {
slouken@1895
   803
        cursor->next = mouse->cursors;
slouken@1895
   804
        mouse->cursors = cursor;
slouken@1895
   805
    }
slouken@1895
   806
slouken@7720
   807
    SDL_FreeSurface(temp);
slouken@1895
   808
slouken@1895
   809
    return cursor;
slouken@1895
   810
}
slouken@1895
   811
mikesart@6675
   812
SDL_Cursor *
mikesart@6675
   813
SDL_CreateSystemCursor(SDL_SystemCursor id)
mikesart@6675
   814
{
mikesart@6675
   815
    SDL_Mouse *mouse = SDL_GetMouse();
mikesart@6675
   816
    SDL_Cursor *cursor;
mikesart@6675
   817
mikesart@6675
   818
    if (!mouse->CreateSystemCursor) {
mikesart@6675
   819
        SDL_SetError("CreateSystemCursor is not currently supported");
mikesart@6675
   820
        return NULL;
mikesart@6675
   821
    }
mikesart@6675
   822
slouken@7191
   823
    cursor = mouse->CreateSystemCursor(id);
mikesart@6675
   824
    if (cursor) {
mikesart@6675
   825
        cursor->next = mouse->cursors;
mikesart@6675
   826
        mouse->cursors = cursor;
mikesart@6675
   827
    }
mikesart@6675
   828
slouken@7191
   829
    return cursor;
mikesart@6675
   830
}
mikesart@6675
   831
slouken@1895
   832
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
slouken@1895
   833
   if this is desired for any reason.  This is used when setting
slouken@1895
   834
   the video mode and when the SDL window gains the mouse focus.
slouken@1895
   835
 */
slouken@1895
   836
void
slouken@1895
   837
SDL_SetCursor(SDL_Cursor * cursor)
slouken@1895
   838
{
slouken@5371
   839
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   840
slouken@1895
   841
    /* Set the new cursor */
slouken@1895
   842
    if (cursor) {
slouken@1895
   843
        /* Make sure the cursor is still valid for this mouse */
slouken@5405
   844
        if (cursor != mouse->def_cursor) {
slouken@5405
   845
            SDL_Cursor *found;
slouken@5405
   846
            for (found = mouse->cursors; found; found = found->next) {
slouken@5405
   847
                if (found == cursor) {
slouken@5405
   848
                    break;
slouken@5405
   849
                }
slouken@1895
   850
            }
slouken@5405
   851
            if (!found) {
slouken@5405
   852
                SDL_SetError("Cursor not associated with the current mouse");
slouken@5405
   853
                return;
slouken@5405
   854
            }
slouken@1895
   855
        }
slouken@1895
   856
        mouse->cur_cursor = cursor;
slouken@1895
   857
    } else {
ghostunderscore@6301
   858
        if (mouse->focus) {
ghostunderscore@6301
   859
            cursor = mouse->cur_cursor;
ghostunderscore@6301
   860
        } else {
ghostunderscore@6301
   861
            cursor = mouse->def_cursor;
ghostunderscore@6301
   862
        }
slouken@1895
   863
    }
slouken@1895
   864
slouken@1895
   865
    if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
slouken@1895
   866
        if (mouse->ShowCursor) {
slouken@1895
   867
            mouse->ShowCursor(cursor);
slouken@1895
   868
        }
slouken@1895
   869
    } else {
slouken@1895
   870
        if (mouse->ShowCursor) {
slouken@1895
   871
            mouse->ShowCursor(NULL);
slouken@1895
   872
        }
slouken@1895
   873
    }
slouken@1895
   874
}
slouken@1895
   875
slouken@1895
   876
SDL_Cursor *
slouken@1895
   877
SDL_GetCursor(void)
slouken@1895
   878
{
slouken@5371
   879
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   880
slouken@1895
   881
    if (!mouse) {
slouken@1895
   882
        return NULL;
slouken@1895
   883
    }
slouken@1895
   884
    return mouse->cur_cursor;
slouken@1895
   885
}
slouken@1895
   886
jorgen@7104
   887
SDL_Cursor *
jorgen@7104
   888
SDL_GetDefaultCursor(void)
jorgen@7104
   889
{
jorgen@7104
   890
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7104
   891
jorgen@7104
   892
    if (!mouse) {
jorgen@7104
   893
        return NULL;
jorgen@7104
   894
    }
jorgen@7104
   895
    return mouse->def_cursor;
jorgen@7104
   896
}
jorgen@7104
   897
slouken@1895
   898
void
slouken@1895
   899
SDL_FreeCursor(SDL_Cursor * cursor)
slouken@1895
   900
{
slouken@5371
   901
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   902
    SDL_Cursor *curr, *prev;
slouken@1895
   903
slouken@1895
   904
    if (!cursor) {
slouken@1895
   905
        return;
slouken@1895
   906
    }
slouken@1895
   907
slouken@1895
   908
    if (cursor == mouse->def_cursor) {
slouken@1895
   909
        return;
slouken@1895
   910
    }
slouken@1895
   911
    if (cursor == mouse->cur_cursor) {
slouken@1895
   912
        SDL_SetCursor(mouse->def_cursor);
slouken@1895
   913
    }
slouken@1895
   914
slouken@1895
   915
    for (prev = NULL, curr = mouse->cursors; curr;
slouken@1895
   916
         prev = curr, curr = curr->next) {
slouken@1895
   917
        if (curr == cursor) {
slouken@1895
   918
            if (prev) {
slouken@1895
   919
                prev->next = curr->next;
slouken@1895
   920
            } else {
slouken@1895
   921
                mouse->cursors = curr->next;
slouken@1895
   922
            }
slouken@1895
   923
slouken@1895
   924
            if (mouse->FreeCursor) {
slouken@1895
   925
                mouse->FreeCursor(curr);
slouken@1895
   926
            }
slouken@1895
   927
            return;
slouken@1895
   928
        }
slouken@1895
   929
    }
slouken@1895
   930
}
slouken@1895
   931
slouken@1895
   932
int
slouken@1895
   933
SDL_ShowCursor(int toggle)
slouken@1895
   934
{
slouken@5371
   935
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   936
    SDL_bool shown;
slouken@1895
   937
slouken@1895
   938
    if (!mouse) {
slouken@1895
   939
        return 0;
slouken@1895
   940
    }
slouken@1895
   941
slouken@1895
   942
    shown = mouse->cursor_shown;
slouken@1895
   943
    if (toggle >= 0) {
slouken@1895
   944
        if (toggle) {
slouken@1895
   945
            mouse->cursor_shown = SDL_TRUE;
slouken@1895
   946
        } else {
slouken@1895
   947
            mouse->cursor_shown = SDL_FALSE;
slouken@1895
   948
        }
slouken@1895
   949
        if (mouse->cursor_shown != shown) {
slouken@1895
   950
            SDL_SetCursor(NULL);
slouken@1895
   951
        }
slouken@1895
   952
    }
slouken@1895
   953
    return shown;
slouken@1895
   954
}
slouken@1895
   955
jorgen@7097
   956
/* vi: set ts=4 sw=4 expandtab: */