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