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