src/events/SDL_mouse.c
author Ryan C. Gordon
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 6950 1ddb72193079
child 7089 257fc4e541e1
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


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