src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 05 Dec 2013 09:14:56 -0800
changeset 8049 eac8f31e9bbd
parent 7753 e4c38f17bfad
child 8066 658b461d81be
permissions -rw-r--r--
Clean up the cursor clipping area when quitting SDL.
This fixes the cursor being clipped after the streaming client quits when streaming Dungeons of Dredmor
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@0
    22
slouken@0
    23
/* General mouse handling code for SDL */
slouken@0
    24
slouken@6666
    25
#include "SDL_assert.h"
slouken@0
    26
#include "SDL_events.h"
slouken@0
    27
#include "SDL_events_c.h"
slouken@1895
    28
#include "default_cursor.h"
slouken@3685
    29
#include "../video/SDL_sysvideo.h"
slouken@0
    30
gabomdq@7678
    31
/* #define DEBUG_MOUSE */
slouken@0
    32
slouken@5371
    33
/* The mouse state */
slouken@4465
    34
static SDL_Mouse SDL_mouse;
slouken@0
    35
jorgen@7089
    36
static int
jorgen@7089
    37
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
slouken@0
    38
slouken@0
    39
/* Public functions */
slouken@1895
    40
int
slouken@1895
    41
SDL_MouseInit(void)
slouken@0
    42
{
slouken@5376
    43
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5376
    44
slouken@5376
    45
    mouse->cursor_shown = SDL_TRUE;
slouken@5376
    46
slouken@1895
    47
    return (0);
slouken@1123
    48
}
slouken@0
    49
slouken@5405
    50
void
slouken@5405
    51
SDL_SetDefaultCursor(SDL_Cursor * cursor)
slouken@5405
    52
{
slouken@5405
    53
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5405
    54
slouken@5405
    55
    mouse->def_cursor = cursor;
slouken@5405
    56
    if (!mouse->cur_cursor) {
slouken@5405
    57
        SDL_SetCursor(cursor);
slouken@5405
    58
    }
slouken@5405
    59
}
slouken@5405
    60
slouken@5371
    61
SDL_Mouse *
slouken@5371
    62
SDL_GetMouse(void)
slouken@5371
    63
{
slouken@5371
    64
    return &SDL_mouse;
slouken@5371
    65
}
slouken@5371
    66
slouken@4465
    67
SDL_Window *
slouken@4465
    68
SDL_GetMouseFocus(void)
slouken@2710
    69
{
slouken@5371
    70
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@2940
    71
slouken@4465
    72
    return mouse->focus;
slouken@0
    73
}
slouken@0
    74
slouken@1895
    75
void
slouken@6666
    76
SDL_ResetMouse(void)
slouken@6666
    77
{
slouken@6666
    78
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@6666
    79
    Uint8 i;
slouken@6666
    80
slouken@6666
    81
#ifdef DEBUG_MOUSE
slouken@6666
    82
    printf("Resetting mouse\n");
slouken@6666
    83
#endif
slouken@6666
    84
    for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) {
slouken@6666
    85
        if (mouse->buttonstate & SDL_BUTTON(i)) {
slouken@6950
    86
            SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i);
slouken@6666
    87
        }
slouken@6666
    88
    }
slouken@6666
    89
    SDL_assert(mouse->buttonstate == 0);
slouken@6666
    90
}
slouken@6666
    91
slouken@6666
    92
void
slouken@4465
    93
SDL_SetMouseFocus(SDL_Window * window)
slouken@0
    94
{
slouken@5371
    95
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
    96
slouken@4465
    97
    if (mouse->focus == window) {
slouken@1895
    98
        return;
slouken@1895
    99
    }
slouken@1895
   100
slouken@6829
   101
    /* Actually, this ends up being a bad idea, because most operating
slouken@6829
   102
       systems have an implicit grab when you press the mouse button down
slouken@6829
   103
       so you can drag things out of the window and then get the mouse up
slouken@6829
   104
       when it happens.  So, #if 0...
slouken@6829
   105
    */
slouken@6829
   106
#if 0
slouken@6666
   107
    if (mouse->focus && !window) {
slouken@6666
   108
        /* We won't get anymore mouse messages, so reset mouse state */
slouken@6666
   109
        SDL_ResetMouse();
slouken@6666
   110
    }
slouken@6829
   111
#endif
slouken@6666
   112
slouken@1895
   113
    /* See if the current window has lost focus */
slouken@1895
   114
    if (mouse->focus) {
slouken@4465
   115
        SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
slouken@1895
   116
    }
slouken@1895
   117
slouken@3685
   118
    mouse->focus = window;
slouken@1895
   119
slouken@1895
   120
    if (mouse->focus) {
slouken@4465
   121
        SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
slouken@1895
   122
    }
slouken@6666
   123
slouken@6666
   124
    /* Update cursor visibility */
slouken@6666
   125
    SDL_SetCursor(NULL);
slouken@6666
   126
}
slouken@6666
   127
slouken@6666
   128
/* Check to see if we need to synthesize focus events */
slouken@6666
   129
static SDL_bool
slouken@6673
   130
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
slouken@6666
   131
{
slouken@6666
   132
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@6666
   133
    int w, h;
slouken@6666
   134
    SDL_bool inWindow;
slouken@6666
   135
slouken@6666
   136
    SDL_GetWindowSize(window, &w, &h);
slouken@6666
   137
    if (x < 0 || y < 0 || x >= w || y >= h) {
slouken@6666
   138
        inWindow = SDL_FALSE;
slouken@6666
   139
    } else {
slouken@6666
   140
        inWindow = SDL_TRUE;
slouken@6666
   141
    }
slouken@6667
   142
slouken@6667
   143
/* Linux doesn't give you mouse events outside your window unless you grab
slouken@6667
   144
   the pointer.
slouken@6667
   145
slouken@6667
   146
   Windows doesn't give you mouse events outside your window unless you call
slouken@6667
   147
   SetCapture().
slouken@6667
   148
slouken@6667
   149
   Both of these are slightly scary changes, so for now we'll punt and if the
slouken@6667
   150
   mouse leaves the window you'll lose mouse focus and reset button state.
slouken@6667
   151
*/
slouken@6667
   152
#ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
slouken@6666
   153
    if (!inWindow && !buttonstate) {
slouken@6667
   154
#else
slouken@6667
   155
    if (!inWindow) {
slouken@6667
   156
#endif
slouken@6666
   157
        if (window == mouse->focus) {
slouken@6666
   158
#ifdef DEBUG_MOUSE
jorgen@7089
   159
            printf("Mouse left window, synthesizing move & focus lost event\n");
slouken@6666
   160
#endif
jorgen@7089
   161
            SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
slouken@6666
   162
            SDL_SetMouseFocus(NULL);
slouken@6666
   163
        }
slouken@6666
   164
        return SDL_FALSE;
slouken@6666
   165
    }
slouken@6666
   166
slouken@6666
   167
    if (window != mouse->focus) {
slouken@6666
   168
#ifdef DEBUG_MOUSE
jorgen@7097
   169
         printf("Mouse entered window, synthesizing focus gain & move event\n");
slouken@6666
   170
#endif
jorgen@7097
   171
         SDL_SetMouseFocus(window);
jorgen@7097
   172
         SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
slouken@6666
   173
    }
slouken@6666
   174
    return SDL_TRUE;
slouken@1895
   175
}
slouken@1895
   176
slouken@1895
   177
int
slouken@6950
   178
SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
slouken@1895
   179
{
jorgen@7089
   180
    if (window && !relative) {
jorgen@7089
   181
        SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7089
   182
        if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
jorgen@7089
   183
            return 0;
jorgen@7089
   184
        }
jorgen@7089
   185
    }
jorgen@7089
   186
jorgen@7089
   187
    return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y);
jorgen@7089
   188
}
jorgen@7089
   189
jorgen@7089
   190
static int
jorgen@7089
   191
SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
jorgen@7089
   192
{
slouken@5371
   193
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   194
    int posted;
slouken@1895
   195
    int xrel;
slouken@1895
   196
    int yrel;
slouken@2860
   197
    int x_max = 0, y_max = 0;
slouken@1895
   198
slouken@6666
   199
    /* relative motion is calculated regarding the system cursor last position */
slouken@2842
   200
    if (relative) {
slouken@2842
   201
        xrel = x;
slouken@2842
   202
        yrel = y;
slouken@2860
   203
        x = (mouse->last_x + x);
slouken@2860
   204
        y = (mouse->last_y + y);
slouken@2842
   205
    } else {
slouken@2860
   206
        xrel = x - mouse->last_x;
slouken@2860
   207
        yrel = y - mouse->last_y;
slouken@2842
   208
    }
slouken@2710
   209
slouken@1895
   210
    /* Drop events that don't change state */
slouken@1895
   211
    if (!xrel && !yrel) {
slouken@6666
   212
#ifdef DEBUG_MOUSE
slouken@1895
   213
        printf("Mouse event didn't change state - dropped!\n");
slouken@1895
   214
#endif
slouken@1895
   215
        return 0;
slouken@1895
   216
    }
slouken@1895
   217
slouken@2710
   218
    /* Update internal mouse coordinates */
slouken@2710
   219
    if (mouse->relative_mode == SDL_FALSE) {
slouken@1895
   220
        mouse->x = x;
slouken@1895
   221
        mouse->y = y;
slouken@2710
   222
    } else {
slouken@2860
   223
        mouse->x += xrel;
slouken@2860
   224
        mouse->y += yrel;
slouken@2860
   225
    }
slouken@2849
   226
slouken@2860
   227
    SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
slouken@5370
   228
    --x_max;
slouken@5370
   229
    --y_max;
slouken@2849
   230
slouken@2860
   231
    /* make sure that the pointers find themselves inside the windows */
slouken@5370
   232
    if (mouse->x > x_max) {
slouken@2860
   233
        mouse->x = x_max;
slouken@5370
   234
    }
slouken@5370
   235
    if (mouse->x < 0) {
slouken@2860
   236
        mouse->x = 0;
slouken@1895
   237
    }
slouken@2860
   238
slouken@5370
   239
    if (mouse->y > y_max) {
slouken@2860
   240
        mouse->y = y_max;
slouken@5370
   241
    }
slouken@5370
   242
    if (mouse->y < 0) {
slouken@2860
   243
        mouse->y = 0;
slouken@2860
   244
    }
slouken@2860
   245
slouken@1895
   246
    mouse->xdelta += xrel;
slouken@1895
   247
    mouse->ydelta += yrel;
slouken@1895
   248
slouken@1895
   249
    /* Move the mouse cursor, if needed */
slouken@1895
   250
    if (mouse->cursor_shown && !mouse->relative_mode &&
slouken@1895
   251
        mouse->MoveCursor && mouse->cur_cursor) {
slouken@1895
   252
        mouse->MoveCursor(mouse->cur_cursor);
slouken@1895
   253
    }
slouken@1895
   254
slouken@1895
   255
    /* Post the event, if desired */
slouken@1895
   256
    posted = 0;
slouken@4465
   257
    if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) {
slouken@1895
   258
        SDL_Event event;
slouken@1895
   259
        event.motion.type = SDL_MOUSEMOTION;
slouken@4465
   260
        event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
slouken@6950
   261
        event.motion.which = mouseID;
slouken@1895
   262
        event.motion.state = mouse->buttonstate;
slouken@1895
   263
        event.motion.x = mouse->x;
slouken@1895
   264
        event.motion.y = mouse->y;
slouken@1895
   265
        event.motion.xrel = xrel;
slouken@1895
   266
        event.motion.yrel = yrel;
slouken@1895
   267
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   268
    }
slouken@6666
   269
    /* Use unclamped values if we're getting events outside the window */
slouken@6666
   270
    mouse->last_x = x;
slouken@6666
   271
    mouse->last_y = y;
slouken@1895
   272
    return posted;
slouken@1895
   273
}
slouken@1895
   274
slouken@1895
   275
int
slouken@6950
   276
SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
slouken@1895
   277
{
slouken@5371
   278
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   279
    int posted;
slouken@4429
   280
    Uint32 type;
slouken@6673
   281
    Uint32 buttonstate = mouse->buttonstate;
slouken@4484
   282
slouken@1895
   283
    /* Figure out which event to perform */
slouken@1895
   284
    switch (state) {
slouken@1895
   285
    case SDL_PRESSED:
slouken@1895
   286
        type = SDL_MOUSEBUTTONDOWN;
slouken@6666
   287
        buttonstate |= SDL_BUTTON(button);
slouken@1895
   288
        break;
slouken@1895
   289
    case SDL_RELEASED:
slouken@1895
   290
        type = SDL_MOUSEBUTTONUP;
slouken@6666
   291
        buttonstate &= ~SDL_BUTTON(button);
slouken@1895
   292
        break;
slouken@1895
   293
    default:
slouken@1895
   294
        /* Invalid state -- bail */
slouken@1895
   295
        return 0;
slouken@1895
   296
    }
slouken@1895
   297
slouken@6666
   298
    /* We do this after calculating buttonstate so button presses gain focus */
slouken@6666
   299
    if (window && state == SDL_PRESSED) {
slouken@6666
   300
        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
slouken@6666
   301
    }
slouken@6666
   302
slouken@6666
   303
    if (buttonstate == mouse->buttonstate) {
slouken@6666
   304
        /* Ignore this event, no state change */
slouken@6666
   305
        return 0;
slouken@6666
   306
    }
slouken@6666
   307
    mouse->buttonstate = buttonstate;
slouken@6666
   308
slouken@1895
   309
    /* Post the event, if desired */
slouken@1895
   310
    posted = 0;
slouken@4429
   311
    if (SDL_GetEventState(type) == SDL_ENABLE) {
slouken@1895
   312
        SDL_Event event;
slouken@1895
   313
        event.type = type;
slouken@6950
   314
        event.button.windowID = mouse->focus ? mouse->focus->id : 0;
slouken@6950
   315
        event.button.which = mouseID;
slouken@1895
   316
        event.button.state = state;
slouken@1895
   317
        event.button.button = button;
slouken@1895
   318
        event.button.x = mouse->x;
slouken@1895
   319
        event.button.y = mouse->y;
slouken@1895
   320
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   321
    }
slouken@6666
   322
slouken@6666
   323
    /* We do this after dispatching event so button releases can lose focus */
slouken@6666
   324
    if (window && state == SDL_RELEASED) {
slouken@6666
   325
        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
slouken@6666
   326
    }
slouken@6666
   327
slouken@1895
   328
    return posted;
slouken@1895
   329
}
slouken@1895
   330
slouken@1895
   331
int
slouken@6950
   332
SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y)
slouken@1895
   333
{
slouken@5371
   334
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   335
    int posted;
slouken@1895
   336
slouken@4484
   337
    if (window) {
slouken@4484
   338
        SDL_SetMouseFocus(window);
slouken@4484
   339
    }
slouken@4484
   340
slouken@4465
   341
    if (!x && !y) {
slouken@1895
   342
        return 0;
slouken@1895
   343
    }
slouken@1895
   344
slouken@1895
   345
    /* Post the event, if desired */
slouken@1895
   346
    posted = 0;
slouken@4429
   347
    if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) {
slouken@1895
   348
        SDL_Event event;
slouken@1895
   349
        event.type = SDL_MOUSEWHEEL;
slouken@4465
   350
        event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
slouken@6950
   351
        event.wheel.which = mouseID;
slouken@2152
   352
        event.wheel.x = x;
slouken@2152
   353
        event.wheel.y = y;
slouken@1895
   354
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   355
    }
slouken@1895
   356
    return posted;
slouken@1895
   357
}
slouken@1895
   358
slouken@1895
   359
void
slouken@4465
   360
SDL_MouseQuit(void)
slouken@4465
   361
{
slouken@7493
   362
    SDL_Cursor *cursor, *next;
slouken@7493
   363
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@7493
   364
slouken@8049
   365
    SDL_SetRelativeMouseMode(SDL_FALSE);
slouken@7493
   366
    SDL_ShowCursor(1);
slouken@7493
   367
slouken@7493
   368
    cursor = mouse->cursors;
slouken@7493
   369
    while (cursor) {
slouken@7493
   370
        next = cursor->next;
slouken@7493
   371
        SDL_FreeCursor(cursor);
slouken@7493
   372
        cursor = next;
slouken@7493
   373
    }
slouken@7493
   374
slouken@7493
   375
    if (mouse->def_cursor && mouse->FreeCursor) {
slouken@7493
   376
        mouse->FreeCursor(mouse->def_cursor);
slouken@7493
   377
    }
slouken@7493
   378
slouken@7493
   379
    SDL_zerop(mouse);
slouken@4465
   380
}
slouken@4465
   381
slouken@6673
   382
Uint32
slouken@4465
   383
SDL_GetMouseState(int *x, int *y)
slouken@4465
   384
{
slouken@5371
   385
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@4465
   386
slouken@4465
   387
    if (x) {
slouken@4465
   388
        *x = mouse->x;
slouken@4465
   389
    }
slouken@4465
   390
    if (y) {
slouken@4465
   391
        *y = mouse->y;
slouken@4465
   392
    }
slouken@4465
   393
    return mouse->buttonstate;
slouken@4465
   394
}
slouken@4465
   395
slouken@6673
   396
Uint32
slouken@4465
   397
SDL_GetRelativeMouseState(int *x, int *y)
slouken@4465
   398
{
slouken@5371
   399
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@4465
   400
slouken@4465
   401
    if (x) {
slouken@4465
   402
        *x = mouse->xdelta;
slouken@4465
   403
    }
slouken@4465
   404
    if (y) {
slouken@4465
   405
        *y = mouse->ydelta;
slouken@4465
   406
    }
slouken@4465
   407
    mouse->xdelta = 0;
slouken@4465
   408
    mouse->ydelta = 0;
slouken@4465
   409
    return mouse->buttonstate;
slouken@4465
   410
}
slouken@4465
   411
slouken@4465
   412
void
slouken@3685
   413
SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
slouken@1895
   414
{
slouken@5371
   415
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@7191
   416
slouken@7191
   417
    if ( window == NULL )
slouken@7191
   418
        window = mouse->focus;
slouken@7191
   419
slouken@7191
   420
    if ( window == NULL )
slouken@7191
   421
        return;
slouken@1895
   422
slouken@1895
   423
    if (mouse->WarpMouse) {
slouken@5371
   424
        mouse->WarpMouse(window, x, y);
slouken@1895
   425
    } else {
slouken@6950
   426
        SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
slouken@1895
   427
    }
slouken@1895
   428
}
slouken@1895
   429
slouken@4465
   430
int
slouken@4465
   431
SDL_SetRelativeMouseMode(SDL_bool enabled)
slouken@4465
   432
{
slouken@5371
   433
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7107
   434
    SDL_Window *focusWindow = SDL_GetKeyboardFocus();
jorgen@7107
   435
    int original_x = mouse->x, original_y = mouse->y;
slouken@4465
   436
slouken@5406
   437
    if (enabled == mouse->relative_mode) {
slouken@5406
   438
        return 0;
slouken@5406
   439
    }
slouken@5406
   440
slouken@5406
   441
    if (!mouse->SetRelativeMouseMode) {
icculus@7037
   442
        return SDL_Unsupported();
slouken@5406
   443
    }
slouken@5406
   444
jorgen@7107
   445
    if (enabled && focusWindow) {
jorgen@7107
   446
        /* Center it in the focused window to prevent clicks from going through
jorgen@7107
   447
         * to background windows.
jorgen@7107
   448
         */
jorgen@7107
   449
        SDL_SetMouseFocus(focusWindow);
jorgen@7107
   450
        SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
jorgen@7107
   451
    }
jorgen@7107
   452
slouken@5406
   453
    if (mouse->SetRelativeMouseMode(enabled) < 0) {
slouken@5406
   454
        return -1;
slouken@5406
   455
    }
slouken@4465
   456
slouken@4465
   457
    /* Set the relative mode */
slouken@4465
   458
    mouse->relative_mode = enabled;
slouken@4465
   459
ghostunderscore@6302
   460
    if (enabled) {
ghostunderscore@6302
   461
        /* Save the expected mouse position */
jorgen@7107
   462
        mouse->original_x = original_x;
jorgen@7107
   463
        mouse->original_y = original_y;
ghostunderscore@6302
   464
    } else if (mouse->focus) {
slouken@4465
   465
        /* Restore the expected mouse position */
ghostunderscore@6302
   466
        SDL_WarpMouseInWindow(mouse->focus, mouse->original_x, mouse->original_y);
slouken@4465
   467
    }
slouken@4465
   468
slouken@5406
   469
    /* Flush pending mouse motion */
slouken@5406
   470
    SDL_FlushEvent(SDL_MOUSEMOTION);
slouken@5406
   471
slouken@4465
   472
    /* Update cursor visibility */
slouken@4465
   473
    SDL_SetCursor(NULL);
slouken@4465
   474
slouken@4465
   475
    return 0;
slouken@4465
   476
}
slouken@4465
   477
slouken@4465
   478
SDL_bool
slouken@4465
   479
SDL_GetRelativeMouseMode()
slouken@4465
   480
{
slouken@5371
   481
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@4465
   482
slouken@4465
   483
    return mouse->relative_mode;
slouken@4465
   484
}
slouken@4465
   485
slouken@1895
   486
SDL_Cursor *
slouken@1895
   487
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
slouken@1895
   488
                 int w, int h, int hot_x, int hot_y)
slouken@1895
   489
{
slouken@1895
   490
    SDL_Surface *surface;
slouken@1895
   491
    SDL_Cursor *cursor;
slouken@1895
   492
    int x, y;
slouken@1895
   493
    Uint32 *pixel;
slouken@4465
   494
    Uint8 datab = 0, maskb = 0;
slouken@1895
   495
    const Uint32 black = 0xFF000000;
slouken@1895
   496
    const Uint32 white = 0xFFFFFFFF;
slouken@1895
   497
    const Uint32 transparent = 0x00000000;
slouken@1895
   498
slouken@1895
   499
    /* Make sure the width is a multiple of 8 */
slouken@1895
   500
    w = ((w + 7) & ~7);
slouken@1895
   501
slouken@1895
   502
    /* Create the surface from a bitmap */
slouken@5473
   503
    surface = SDL_CreateRGBSurface(0, w, h, 32,
slouken@5473
   504
                                   0x00FF0000,
slouken@5473
   505
                                   0x0000FF00,
slouken@5473
   506
                                   0x000000FF,
slouken@5473
   507
                                   0xFF000000);
slouken@1895
   508
    if (!surface) {
slouken@1895
   509
        return NULL;
slouken@1895
   510
    }
slouken@1895
   511
    for (y = 0; y < h; ++y) {
slouken@1895
   512
        pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
slouken@1895
   513
        for (x = 0; x < w; ++x) {
slouken@1895
   514
            if ((x % 8) == 0) {
slouken@1895
   515
                datab = *data++;
slouken@1895
   516
                maskb = *mask++;
slouken@1895
   517
            }
slouken@1895
   518
            if (maskb & 0x80) {
slouken@1895
   519
                *pixel++ = (datab & 0x80) ? black : white;
slouken@1895
   520
            } else {
slouken@1895
   521
                *pixel++ = (datab & 0x80) ? black : transparent;
slouken@1895
   522
            }
slouken@1895
   523
            datab <<= 1;
slouken@1895
   524
            maskb <<= 1;
slouken@1895
   525
        }
slouken@1895
   526
    }
slouken@1895
   527
slouken@5473
   528
    cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
slouken@5473
   529
slouken@5473
   530
    SDL_FreeSurface(surface);
slouken@5473
   531
slouken@5473
   532
    return cursor;
slouken@5473
   533
}
slouken@5473
   534
slouken@5473
   535
SDL_Cursor *
slouken@5473
   536
SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
slouken@5473
   537
{
slouken@5473
   538
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5473
   539
    SDL_Surface *temp = NULL;
slouken@5473
   540
    SDL_Cursor *cursor;
slouken@5473
   541
slouken@5473
   542
    if (!surface) {
slouken@5473
   543
        SDL_SetError("Passed NULL cursor surface");
slouken@5473
   544
        return NULL;
slouken@5473
   545
    }
slouken@5473
   546
slouken@5473
   547
    if (!mouse->CreateCursor) {
slouken@5473
   548
        SDL_SetError("Cursors are not currently supported");
slouken@5473
   549
        return NULL;
slouken@5473
   550
    }
slouken@5473
   551
slouken@5473
   552
    /* Sanity check the hot spot */
slouken@5473
   553
    if ((hot_x < 0) || (hot_y < 0) ||
slouken@5473
   554
        (hot_x >= surface->w) || (hot_y >= surface->h)) {
slouken@5473
   555
        SDL_SetError("Cursor hot spot doesn't lie within cursor");
slouken@5473
   556
        return NULL;
slouken@5473
   557
    }
slouken@5473
   558
slouken@5473
   559
    if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
slouken@5473
   560
        temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
slouken@5473
   561
        if (!temp) {
slouken@5473
   562
            return NULL;
slouken@5473
   563
        }
slouken@5473
   564
        surface = temp;
slouken@5473
   565
    }
slouken@5473
   566
slouken@1895
   567
    cursor = mouse->CreateCursor(surface, hot_x, hot_y);
slouken@1895
   568
    if (cursor) {
slouken@1895
   569
        cursor->next = mouse->cursors;
slouken@1895
   570
        mouse->cursors = cursor;
slouken@1895
   571
    }
slouken@1895
   572
slouken@7720
   573
    SDL_FreeSurface(temp);
slouken@1895
   574
slouken@1895
   575
    return cursor;
slouken@1895
   576
}
slouken@1895
   577
mikesart@6675
   578
SDL_Cursor *
mikesart@6675
   579
SDL_CreateSystemCursor(SDL_SystemCursor id)
mikesart@6675
   580
{
mikesart@6675
   581
    SDL_Mouse *mouse = SDL_GetMouse();
mikesart@6675
   582
    SDL_Cursor *cursor;
mikesart@6675
   583
mikesart@6675
   584
    if (!mouse->CreateSystemCursor) {
mikesart@6675
   585
        SDL_SetError("CreateSystemCursor is not currently supported");
mikesart@6675
   586
        return NULL;
mikesart@6675
   587
    }
mikesart@6675
   588
slouken@7191
   589
    cursor = mouse->CreateSystemCursor(id);
mikesart@6675
   590
    if (cursor) {
mikesart@6675
   591
        cursor->next = mouse->cursors;
mikesart@6675
   592
        mouse->cursors = cursor;
mikesart@6675
   593
    }
mikesart@6675
   594
slouken@7191
   595
    return cursor;
mikesart@6675
   596
}
mikesart@6675
   597
slouken@1895
   598
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
slouken@1895
   599
   if this is desired for any reason.  This is used when setting
slouken@1895
   600
   the video mode and when the SDL window gains the mouse focus.
slouken@1895
   601
 */
slouken@1895
   602
void
slouken@1895
   603
SDL_SetCursor(SDL_Cursor * cursor)
slouken@1895
   604
{
slouken@5371
   605
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   606
slouken@1895
   607
    /* Set the new cursor */
slouken@1895
   608
    if (cursor) {
slouken@1895
   609
        /* Make sure the cursor is still valid for this mouse */
slouken@5405
   610
        if (cursor != mouse->def_cursor) {
slouken@5405
   611
            SDL_Cursor *found;
slouken@5405
   612
            for (found = mouse->cursors; found; found = found->next) {
slouken@5405
   613
                if (found == cursor) {
slouken@5405
   614
                    break;
slouken@5405
   615
                }
slouken@1895
   616
            }
slouken@5405
   617
            if (!found) {
slouken@5405
   618
                SDL_SetError("Cursor not associated with the current mouse");
slouken@5405
   619
                return;
slouken@5405
   620
            }
slouken@1895
   621
        }
slouken@1895
   622
        mouse->cur_cursor = cursor;
slouken@1895
   623
    } else {
ghostunderscore@6301
   624
        if (mouse->focus) {
ghostunderscore@6301
   625
            cursor = mouse->cur_cursor;
ghostunderscore@6301
   626
        } else {
ghostunderscore@6301
   627
            cursor = mouse->def_cursor;
ghostunderscore@6301
   628
        }
slouken@1895
   629
    }
slouken@1895
   630
slouken@1895
   631
    if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
slouken@1895
   632
        if (mouse->ShowCursor) {
slouken@1895
   633
            mouse->ShowCursor(cursor);
slouken@1895
   634
        }
slouken@1895
   635
    } else {
slouken@1895
   636
        if (mouse->ShowCursor) {
slouken@1895
   637
            mouse->ShowCursor(NULL);
slouken@1895
   638
        }
slouken@1895
   639
    }
slouken@1895
   640
}
slouken@1895
   641
slouken@1895
   642
SDL_Cursor *
slouken@1895
   643
SDL_GetCursor(void)
slouken@1895
   644
{
slouken@5371
   645
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   646
slouken@1895
   647
    if (!mouse) {
slouken@1895
   648
        return NULL;
slouken@1895
   649
    }
slouken@1895
   650
    return mouse->cur_cursor;
slouken@1895
   651
}
slouken@1895
   652
jorgen@7104
   653
SDL_Cursor *
jorgen@7104
   654
SDL_GetDefaultCursor(void)
jorgen@7104
   655
{
jorgen@7104
   656
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7104
   657
jorgen@7104
   658
    if (!mouse) {
jorgen@7104
   659
        return NULL;
jorgen@7104
   660
    }
jorgen@7104
   661
    return mouse->def_cursor;
jorgen@7104
   662
}
jorgen@7104
   663
slouken@1895
   664
void
slouken@1895
   665
SDL_FreeCursor(SDL_Cursor * cursor)
slouken@1895
   666
{
slouken@5371
   667
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   668
    SDL_Cursor *curr, *prev;
slouken@1895
   669
slouken@1895
   670
    if (!cursor) {
slouken@1895
   671
        return;
slouken@1895
   672
    }
slouken@1895
   673
slouken@1895
   674
    if (cursor == mouse->def_cursor) {
slouken@1895
   675
        return;
slouken@1895
   676
    }
slouken@1895
   677
    if (cursor == mouse->cur_cursor) {
slouken@1895
   678
        SDL_SetCursor(mouse->def_cursor);
slouken@1895
   679
    }
slouken@1895
   680
slouken@1895
   681
    for (prev = NULL, curr = mouse->cursors; curr;
slouken@1895
   682
         prev = curr, curr = curr->next) {
slouken@1895
   683
        if (curr == cursor) {
slouken@1895
   684
            if (prev) {
slouken@1895
   685
                prev->next = curr->next;
slouken@1895
   686
            } else {
slouken@1895
   687
                mouse->cursors = curr->next;
slouken@1895
   688
            }
slouken@1895
   689
slouken@1895
   690
            if (mouse->FreeCursor) {
slouken@1895
   691
                mouse->FreeCursor(curr);
slouken@1895
   692
            }
slouken@1895
   693
            return;
slouken@1895
   694
        }
slouken@1895
   695
    }
slouken@1895
   696
}
slouken@1895
   697
slouken@1895
   698
int
slouken@1895
   699
SDL_ShowCursor(int toggle)
slouken@1895
   700
{
slouken@5371
   701
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@1895
   702
    SDL_bool shown;
slouken@1895
   703
slouken@1895
   704
    if (!mouse) {
slouken@1895
   705
        return 0;
slouken@1895
   706
    }
slouken@1895
   707
slouken@1895
   708
    shown = mouse->cursor_shown;
slouken@1895
   709
    if (toggle >= 0) {
slouken@1895
   710
        if (toggle) {
slouken@1895
   711
            mouse->cursor_shown = SDL_TRUE;
slouken@1895
   712
        } else {
slouken@1895
   713
            mouse->cursor_shown = SDL_FALSE;
slouken@1895
   714
        }
slouken@1895
   715
        if (mouse->cursor_shown != shown) {
slouken@1895
   716
            SDL_SetCursor(NULL);
slouken@1895
   717
        }
slouken@1895
   718
    }
slouken@1895
   719
    return shown;
slouken@1895
   720
}
slouken@1895
   721
jorgen@7097
   722
/* vi: set ts=4 sw=4 expandtab: */