src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 06 Jul 2006 07:17:11 +0000
branchSDL-1.3
changeset 1724 6c63fc2bd986
parent 1722 5daa04d862f1
child 1731 875c3cf1a12c
permissions -rw-r--r--
Proof of concept done - Win32 GDI implementation mostly complete.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* General mouse handling code for SDL */
slouken@0
    25
slouken@0
    26
#include "SDL_events.h"
slouken@0
    27
#include "SDL_events_c.h"
slouken@1671
    28
#include "default_cursor.h"
slouken@0
    29
slouken@0
    30
slouken@1670
    31
static int SDL_num_mice;
slouken@1670
    32
static int SDL_current_mouse;
slouken@1671
    33
static SDL_Mouse **SDL_mice;
slouken@0
    34
slouken@0
    35
slouken@0
    36
/* Public functions */
slouken@1662
    37
int
slouken@1668
    38
SDL_MouseInit(void)
slouken@0
    39
{
slouken@1670
    40
    return (0);
slouken@1670
    41
}
slouken@0
    42
slouken@1670
    43
SDL_Mouse *
slouken@1670
    44
SDL_GetMouse(int index)
slouken@1670
    45
{
slouken@1670
    46
    if (index < 0 || index >= SDL_num_mice) {
slouken@1670
    47
        return NULL;
slouken@1670
    48
    }
slouken@1671
    49
    return SDL_mice[index];
slouken@1671
    50
}
slouken@1671
    51
slouken@1671
    52
int
slouken@1671
    53
SDL_AddMouse(const SDL_Mouse * mouse, int index)
slouken@1671
    54
{
slouken@1671
    55
    SDL_Mouse **mice;
slouken@1671
    56
    int selected_mouse;
slouken@1671
    57
slouken@1671
    58
    /* Add the mouse to the list of mice */
slouken@1671
    59
    if (index < 0 || index >= SDL_num_mice || SDL_mice[index]) {
slouken@1671
    60
        mice =
slouken@1671
    61
            (SDL_Mouse **) SDL_realloc(SDL_mice,
slouken@1671
    62
                                       (SDL_num_mice + 1) * sizeof(*mice));
slouken@1671
    63
        if (!mice) {
slouken@1671
    64
            SDL_OutOfMemory();
slouken@1671
    65
            return -1;
slouken@1671
    66
        }
slouken@1671
    67
slouken@1671
    68
        SDL_mice = mice;
slouken@1671
    69
        index = SDL_num_mice++;
slouken@1671
    70
    }
slouken@1671
    71
    SDL_mice[index] = (SDL_Mouse *) SDL_malloc(sizeof(*SDL_mice[index]));
slouken@1671
    72
    if (!SDL_mice[index]) {
slouken@1671
    73
        SDL_OutOfMemory();
slouken@1671
    74
        return -1;
slouken@1671
    75
    }
slouken@1671
    76
    *SDL_mice[index] = *mouse;
slouken@1671
    77
slouken@1671
    78
    /* Create the default cursor for the mouse */
slouken@1671
    79
    SDL_mice[index]->cursor_shown = SDL_TRUE;
slouken@1671
    80
    selected_mouse = SDL_SelectMouse(index);
slouken@1671
    81
    SDL_mice[index]->cur_cursor = NULL;
slouken@1671
    82
    SDL_mice[index]->def_cursor =
slouken@1671
    83
        SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH,
slouken@1671
    84
                         DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
slouken@1671
    85
    SDL_SetCursor(SDL_mice[index]->def_cursor);
slouken@1671
    86
    SDL_SelectMouse(selected_mouse);
slouken@1671
    87
slouken@1671
    88
    return index;
slouken@1671
    89
}
slouken@1671
    90
slouken@1671
    91
void
slouken@1671
    92
SDL_DelMouse(int index)
slouken@1671
    93
{
slouken@1671
    94
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1671
    95
slouken@1671
    96
    if (!mouse) {
slouken@1671
    97
        return;
slouken@1671
    98
    }
slouken@1671
    99
slouken@1671
   100
    mouse->def_cursor = NULL;
slouken@1671
   101
    while (mouse->cursors) {
slouken@1671
   102
        SDL_FreeCursor(mouse->cursors);
slouken@1671
   103
    }
slouken@1671
   104
slouken@1671
   105
    if (mouse->FreeMouse) {
slouken@1671
   106
        mouse->FreeMouse(mouse);
slouken@1671
   107
    }
slouken@1671
   108
    SDL_free(mouse);
slouken@1671
   109
slouken@1671
   110
    SDL_mice[index] = NULL;
slouken@1671
   111
}
slouken@1671
   112
slouken@1671
   113
void
slouken@1671
   114
SDL_ResetMouse(int index)
slouken@1671
   115
{
slouken@1671
   116
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1671
   117
slouken@1671
   118
    if (!mouse) {
slouken@1671
   119
        return;
slouken@1671
   120
    }
slouken@1671
   121
slouken@1671
   122
    /* FIXME */
slouken@0
   123
}
slouken@1662
   124
slouken@1662
   125
void
slouken@1668
   126
SDL_MouseQuit(void)
slouken@1123
   127
{
slouken@1671
   128
    int i;
slouken@1671
   129
slouken@1671
   130
    for (i = 0; i < SDL_num_mice; ++i) {
slouken@1671
   131
        SDL_DelMouse(i);
slouken@1671
   132
    }
slouken@1670
   133
    SDL_num_mice = 0;
slouken@1670
   134
    SDL_current_mouse = 0;
slouken@1670
   135
slouken@1670
   136
    if (SDL_mice) {
slouken@1670
   137
        SDL_free(SDL_mice);
slouken@1670
   138
        SDL_mice = NULL;
slouken@1670
   139
    }
slouken@1123
   140
}
slouken@0
   141
slouken@1670
   142
int
slouken@1670
   143
SDL_GetNumMice(void)
slouken@460
   144
{
slouken@1670
   145
    return SDL_num_mice;
slouken@1670
   146
}
slouken@1670
   147
slouken@1670
   148
int
slouken@1670
   149
SDL_SelectMouse(int index)
slouken@1670
   150
{
slouken@1670
   151
    if (index >= 0 && index < SDL_num_mice) {
slouken@1670
   152
        SDL_current_mouse = index;
slouken@1662
   153
    }
slouken@1670
   154
    return SDL_current_mouse;
slouken@1670
   155
}
slouken@1670
   156
slouken@1670
   157
SDL_WindowID
slouken@1670
   158
SDL_GetMouseFocusWindow()
slouken@1670
   159
{
slouken@1670
   160
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1670
   161
slouken@1670
   162
    if (!mouse) {
slouken@1670
   163
        return 0;
slouken@1670
   164
    }
slouken@1670
   165
    return mouse->focus;
slouken@460
   166
}
slouken@460
   167
slouken@1722
   168
static int
slouken@1722
   169
FlushMouseMotion(void *param, SDL_Event * event)
slouken@1722
   170
{
slouken@1722
   171
    if (event->type == SDL_MOUSEMOTION
slouken@1722
   172
        && event->motion.which == (Uint8) SDL_current_mouse) {
slouken@1722
   173
        return 0;
slouken@1722
   174
    } else {
slouken@1722
   175
        return 1;
slouken@1722
   176
    }
slouken@1722
   177
}
slouken@1722
   178
slouken@1722
   179
int
slouken@1722
   180
SDL_SetRelativeMouseMode(SDL_bool enabled)
slouken@1722
   181
{
slouken@1722
   182
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1722
   183
slouken@1722
   184
    if (!mouse) {
slouken@1722
   185
        return -1;
slouken@1722
   186
    }
slouken@1722
   187
slouken@1722
   188
    /* Flush pending mouse motion */
slouken@1722
   189
    mouse->flush_motion = SDL_TRUE;
slouken@1722
   190
    SDL_PumpEvents();
slouken@1722
   191
    mouse->flush_motion = SDL_FALSE;
slouken@1722
   192
    SDL_FilterEvents(FlushMouseMotion, mouse);
slouken@1722
   193
slouken@1722
   194
    /* Set the relative mode */
slouken@1722
   195
    mouse->relative_mode = enabled;
slouken@1722
   196
slouken@1722
   197
    /* Update cursor visibility */
slouken@1722
   198
    SDL_SetCursor(NULL);
slouken@1722
   199
slouken@1722
   200
    if (!enabled) {
slouken@1722
   201
        /* Restore the expected mouse position */
slouken@1722
   202
        SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
slouken@1722
   203
    }
slouken@1722
   204
    return 0;
slouken@1722
   205
}
slouken@1722
   206
slouken@1722
   207
SDL_bool
slouken@1722
   208
SDL_GetRelativeMouseMode()
slouken@1722
   209
{
slouken@1722
   210
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1722
   211
slouken@1722
   212
    if (!mouse) {
slouken@1722
   213
        return SDL_FALSE;
slouken@1722
   214
    }
slouken@1722
   215
    return mouse->relative_mode;
slouken@1722
   216
}
slouken@1722
   217
slouken@1662
   218
Uint8
slouken@1668
   219
SDL_GetMouseState(int *x, int *y)
slouken@0
   220
{
slouken@1670
   221
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1670
   222
slouken@1670
   223
    if (!mouse) {
slouken@1670
   224
        if (x) {
slouken@1670
   225
            *x = 0;
slouken@1670
   226
        }
slouken@1670
   227
        if (y) {
slouken@1670
   228
            *y = 0;
slouken@1670
   229
        }
slouken@1670
   230
        return 0;
slouken@1670
   231
    }
slouken@1670
   232
slouken@1662
   233
    if (x) {
slouken@1670
   234
        *x = mouse->x;
slouken@1662
   235
    }
slouken@1662
   236
    if (y) {
slouken@1670
   237
        *y = mouse->y;
slouken@1662
   238
    }
slouken@1670
   239
    return mouse->buttonstate;
slouken@0
   240
}
slouken@0
   241
slouken@1662
   242
Uint8
slouken@1668
   243
SDL_GetRelativeMouseState(int *x, int *y)
slouken@0
   244
{
slouken@1670
   245
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1670
   246
slouken@1670
   247
    if (!mouse) {
slouken@1670
   248
        if (x) {
slouken@1670
   249
            *x = 0;
slouken@1670
   250
        }
slouken@1670
   251
        if (y) {
slouken@1670
   252
            *y = 0;
slouken@1670
   253
        }
slouken@1670
   254
        return 0;
slouken@1670
   255
    }
slouken@1670
   256
slouken@1670
   257
    if (x) {
slouken@1670
   258
        *x = mouse->xdelta;
slouken@1670
   259
    }
slouken@1670
   260
    if (y) {
slouken@1670
   261
        *y = mouse->ydelta;
slouken@1670
   262
    }
slouken@1670
   263
    mouse->xdelta = 0;
slouken@1670
   264
    mouse->ydelta = 0;
slouken@1670
   265
    return mouse->buttonstate;
slouken@0
   266
}
slouken@0
   267
slouken@1724
   268
void
slouken@1724
   269
SDL_SetMouseFocus(int index, SDL_WindowID windowID)
slouken@1724
   270
{
slouken@1724
   271
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1724
   272
    int i;
slouken@1724
   273
    SDL_bool focus;
slouken@1724
   274
slouken@1724
   275
    if (!mouse || (mouse->focus == windowID)) {
slouken@1724
   276
        return;
slouken@1724
   277
    }
slouken@1724
   278
slouken@1724
   279
    /* See if the current window has lost focus */
slouken@1724
   280
    if (mouse->focus) {
slouken@1724
   281
        focus = SDL_FALSE;
slouken@1724
   282
        for (i = 0; i < SDL_num_mice; ++i) {
slouken@1724
   283
            SDL_Mouse *check;
slouken@1724
   284
            if (i != index) {
slouken@1724
   285
                check = SDL_GetMouse(i);
slouken@1724
   286
                if (check && check->focus == mouse->focus) {
slouken@1724
   287
                    focus = SDL_TRUE;
slouken@1724
   288
                    break;
slouken@1724
   289
                }
slouken@1724
   290
            }
slouken@1724
   291
        }
slouken@1724
   292
        if (!focus) {
slouken@1724
   293
            SDL_SendWindowEvent(windowID, SDL_WINDOWEVENT_LEAVE, 0, 0);
slouken@1724
   294
        }
slouken@1724
   295
    }
slouken@1724
   296
slouken@1724
   297
    mouse->focus = windowID;
slouken@1724
   298
slouken@1724
   299
    if (mouse->focus) {
slouken@1724
   300
        focus = SDL_FALSE;
slouken@1724
   301
        for (i = 0; i < SDL_num_mice; ++i) {
slouken@1724
   302
            SDL_Mouse *check;
slouken@1724
   303
            if (i != index) {
slouken@1724
   304
                check = SDL_GetMouse(i);
slouken@1724
   305
                if (check && check->focus == mouse->focus) {
slouken@1724
   306
                    focus = SDL_TRUE;
slouken@1724
   307
                    break;
slouken@1724
   308
                }
slouken@1724
   309
            }
slouken@1724
   310
        }
slouken@1724
   311
        if (!focus) {
slouken@1724
   312
            SDL_SendWindowEvent(windowID, SDL_WINDOWEVENT_ENTER, 0, 0);
slouken@1724
   313
        }
slouken@1724
   314
    }
slouken@1724
   315
}
slouken@1724
   316
slouken@1670
   317
int
slouken@1724
   318
SDL_SendMouseMotion(int index, int relative, int x, int y)
slouken@0
   319
{
slouken@1670
   320
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1670
   321
    int posted;
slouken@1670
   322
    int xrel;
slouken@1670
   323
    int yrel;
slouken@1662
   324
slouken@1722
   325
    if (!mouse || mouse->flush_motion) {
slouken@1670
   326
        return 0;
slouken@1662
   327
    }
slouken@0
   328
slouken@1662
   329
    if (relative) {
slouken@1662
   330
        /* Push the cursor around */
slouken@1670
   331
        xrel = x;
slouken@1670
   332
        yrel = y;
slouken@1670
   333
        x = (mouse->x + xrel);
slouken@1670
   334
        y = (mouse->y + yrel);
slouken@1662
   335
    } else {
slouken@1670
   336
        xrel = x - mouse->x;
slouken@1670
   337
        yrel = y - mouse->y;
slouken@1662
   338
    }
slouken@0
   339
slouken@1662
   340
    /* Drop events that don't change state */
slouken@1670
   341
    if (!xrel && !yrel) {
slouken@1283
   342
#if 0
slouken@1668
   343
        printf("Mouse event didn't change state - dropped!\n");
slouken@1283
   344
#endif
slouken@1670
   345
        return 0;
slouken@1662
   346
    }
slouken@1283
   347
slouken@1662
   348
    /* Update internal mouse state */
slouken@1722
   349
    if (!mouse->relative_mode) {
slouken@1722
   350
        mouse->x = x;
slouken@1722
   351
        mouse->y = y;
slouken@1722
   352
    }
slouken@1670
   353
    mouse->xdelta += xrel;
slouken@1670
   354
    mouse->ydelta += yrel;
slouken@0
   355
slouken@1671
   356
    /* Move the mouse cursor, if needed */
slouken@1722
   357
    if (mouse->cursor_shown && !mouse->relative_mode &&
slouken@1722
   358
        mouse->MoveCursor && mouse->cur_cursor) {
slouken@1671
   359
        mouse->MoveCursor(mouse->cur_cursor);
slouken@1671
   360
    }
slouken@1671
   361
slouken@1662
   362
    /* Post the event, if desired */
slouken@1662
   363
    posted = 0;
slouken@1662
   364
    if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE) {
slouken@1662
   365
        SDL_Event event;
slouken@1670
   366
        event.motion.type = SDL_MOUSEMOTION;
slouken@1670
   367
        event.motion.which = (Uint8) index;
slouken@1670
   368
        event.motion.state = mouse->buttonstate;
slouken@1670
   369
        event.motion.x = mouse->x;
slouken@1670
   370
        event.motion.y = mouse->y;
slouken@1670
   371
        event.motion.xrel = xrel;
slouken@1670
   372
        event.motion.yrel = yrel;
slouken@1670
   373
        event.motion.windowID = mouse->focus;
slouken@1722
   374
        if ((SDL_EventOK == NULL)
slouken@1722
   375
            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@1662
   376
            posted = 1;
slouken@1668
   377
            SDL_PushEvent(&event);
slouken@1662
   378
        }
slouken@1662
   379
    }
slouken@1670
   380
    return posted;
slouken@0
   381
}
slouken@0
   382
slouken@1662
   383
int
slouken@1724
   384
SDL_SendMouseButton(int index, Uint8 state, Uint8 button)
slouken@0
   385
{
slouken@1670
   386
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1662
   387
    int posted;
slouken@1670
   388
    Uint8 type;
slouken@0
   389
slouken@1670
   390
    if (!mouse) {
slouken@1670
   391
        return 0;
slouken@1670
   392
    }
slouken@0
   393
slouken@1662
   394
    /* Figure out which event to perform */
slouken@1662
   395
    switch (state) {
slouken@1662
   396
    case SDL_PRESSED:
slouken@1670
   397
        if (mouse->buttonstate & SDL_BUTTON(button)) {
slouken@1670
   398
            /* Ignore this event, no state change */
slouken@1670
   399
            return 0;
slouken@1670
   400
        }
slouken@1670
   401
        type = SDL_MOUSEBUTTONDOWN;
slouken@1670
   402
        mouse->buttonstate |= SDL_BUTTON(button);
slouken@1662
   403
        break;
slouken@1662
   404
    case SDL_RELEASED:
slouken@1670
   405
        if (!(mouse->buttonstate & SDL_BUTTON(button))) {
slouken@1670
   406
            /* Ignore this event, no state change */
slouken@1670
   407
            return 0;
slouken@1670
   408
        }
slouken@1670
   409
        type = SDL_MOUSEBUTTONUP;
slouken@1670
   410
        mouse->buttonstate &= ~SDL_BUTTON(button);
slouken@1662
   411
        break;
slouken@1662
   412
    default:
slouken@1662
   413
        /* Invalid state -- bail */
slouken@1670
   414
        return 0;
slouken@1662
   415
    }
slouken@0
   416
slouken@1662
   417
    /* Post the event, if desired */
slouken@1662
   418
    posted = 0;
slouken@1670
   419
    if (SDL_ProcessEvents[type] == SDL_ENABLE) {
slouken@1670
   420
        SDL_Event event;
slouken@1670
   421
        event.type = type;
slouken@1670
   422
        event.button.which = (Uint8) index;
slouken@1662
   423
        event.button.state = state;
slouken@1662
   424
        event.button.button = button;
slouken@1670
   425
        event.button.x = mouse->x;
slouken@1670
   426
        event.button.y = mouse->y;
slouken@1674
   427
        event.button.windowID = mouse->focus;
slouken@1722
   428
        if ((SDL_EventOK == NULL)
slouken@1722
   429
            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@1662
   430
            posted = 1;
slouken@1668
   431
            SDL_PushEvent(&event);
slouken@1662
   432
        }
slouken@1662
   433
    }
slouken@1670
   434
    return posted;
slouken@0
   435
}
slouken@0
   436
slouken@1724
   437
int
slouken@1724
   438
SDL_SendMouseWheel(int index, int motion)
slouken@1724
   439
{
slouken@1724
   440
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1724
   441
    int posted;
slouken@1724
   442
slouken@1724
   443
    if (!mouse || !motion) {
slouken@1724
   444
        return 0;
slouken@1724
   445
    }
slouken@1724
   446
slouken@1724
   447
    /* Post the event, if desired */
slouken@1724
   448
    posted = 0;
slouken@1724
   449
    if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) {
slouken@1724
   450
        SDL_Event event;
slouken@1724
   451
        event.type = SDL_MOUSEWHEEL;
slouken@1724
   452
        event.wheel.which = (Uint8) index;
slouken@1724
   453
        event.wheel.motion = motion;
slouken@1724
   454
        event.wheel.windowID = mouse->focus;
slouken@1724
   455
        if ((SDL_EventOK == NULL)
slouken@1724
   456
            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@1724
   457
            posted = 1;
slouken@1724
   458
            SDL_PushEvent(&event);
slouken@1724
   459
        }
slouken@1724
   460
    }
slouken@1724
   461
    return posted;
slouken@1724
   462
}
slouken@1724
   463
slouken@1671
   464
void
slouken@1671
   465
SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
slouken@1671
   466
{
slouken@1671
   467
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1671
   468
slouken@1671
   469
    if (!mouse) {
slouken@1671
   470
        return;
slouken@1671
   471
    }
slouken@1671
   472
slouken@1671
   473
    if (mouse->WarpMouse) {
slouken@1671
   474
        mouse->WarpMouse(mouse, windowID, x, y);
slouken@1671
   475
    } else {
slouken@1724
   476
        SDL_SetMouseFocus(SDL_current_mouse, windowID);
slouken@1724
   477
        SDL_SendMouseMotion(SDL_current_mouse, 0, x, y);
slouken@1671
   478
    }
slouken@1671
   479
}
slouken@1671
   480
slouken@1671
   481
SDL_Cursor *
slouken@1671
   482
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
slouken@1671
   483
                 int w, int h, int hot_x, int hot_y)
slouken@1671
   484
{
slouken@1671
   485
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1671
   486
    SDL_Surface *surface;
slouken@1671
   487
    SDL_Cursor *cursor;
slouken@1671
   488
    int x, y;
slouken@1671
   489
    Uint32 *pixel;
slouken@1671
   490
    Uint8 datab, maskb;
slouken@1671
   491
    const Uint32 black = 0xFF000000;
slouken@1671
   492
    const Uint32 white = 0xFFFFFFFF;
slouken@1671
   493
    const Uint32 transparent = 0x00000000;
slouken@1671
   494
slouken@1671
   495
    if (!mouse) {
slouken@1671
   496
        SDL_SetError("No mice are initialized");
slouken@1671
   497
        return NULL;
slouken@1671
   498
    }
slouken@1671
   499
slouken@1671
   500
    if (!mouse->CreateCursor) {
slouken@1671
   501
        SDL_SetError("Current mouse doesn't have cursor support");
slouken@1671
   502
        return NULL;
slouken@1671
   503
    }
slouken@1671
   504
slouken@1671
   505
    /* Sanity check the hot spot */
slouken@1671
   506
    if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) {
slouken@1671
   507
        SDL_SetError("Cursor hot spot doesn't lie within cursor");
slouken@1671
   508
        return NULL;
slouken@1671
   509
    }
slouken@1671
   510
slouken@1671
   511
    /* Make sure the width is a multiple of 8 */
slouken@1671
   512
    w = ((w + 7) & ~7);
slouken@1671
   513
slouken@1671
   514
    /* Create the surface from a bitmap */
slouken@1671
   515
    surface =
slouken@1671
   516
        SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
slouken@1671
   517
                             0xFF000000);
slouken@1671
   518
    if (!surface) {
slouken@1671
   519
        return NULL;
slouken@1671
   520
    }
slouken@1671
   521
    for (y = 0; y < h; ++y) {
slouken@1720
   522
        pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
slouken@1671
   523
        for (x = 0; x < w; ++x) {
slouken@1671
   524
            if ((x % 8) == 0) {
slouken@1671
   525
                datab = *data++;
slouken@1671
   526
                maskb = *mask++;
slouken@1671
   527
            }
slouken@1671
   528
            if (maskb & 0x80) {
slouken@1671
   529
                *pixel++ = (datab & 0x80) ? black : white;
slouken@1671
   530
            } else {
slouken@1671
   531
                *pixel++ = (datab & 0x80) ? black : transparent;
slouken@1671
   532
            }
slouken@1671
   533
            datab <<= 1;
slouken@1671
   534
            maskb <<= 1;
slouken@1671
   535
        }
slouken@1671
   536
    }
slouken@1671
   537
slouken@1671
   538
    cursor = mouse->CreateCursor(surface, hot_x, hot_y);
slouken@1671
   539
    if (cursor) {
slouken@1671
   540
        cursor->mouse = mouse;
slouken@1671
   541
        cursor->next = mouse->cursors;
slouken@1671
   542
        mouse->cursors = cursor;
slouken@1671
   543
    }
slouken@1671
   544
slouken@1671
   545
    SDL_FreeSurface(surface);
slouken@1671
   546
slouken@1671
   547
    return cursor;
slouken@1671
   548
}
slouken@1671
   549
slouken@1671
   550
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
slouken@1671
   551
   if this is desired for any reason.  This is used when setting
slouken@1671
   552
   the video mode and when the SDL window gains the mouse focus.
slouken@1671
   553
 */
slouken@1671
   554
void
slouken@1671
   555
SDL_SetCursor(SDL_Cursor * cursor)
slouken@1671
   556
{
slouken@1671
   557
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1671
   558
slouken@1671
   559
    if (!mouse) {
slouken@1671
   560
        SDL_SetError("No mice are initialized");
slouken@1671
   561
        return;
slouken@1671
   562
    }
slouken@1671
   563
slouken@1671
   564
    /* Set the new cursor */
slouken@1671
   565
    if (cursor) {
slouken@1671
   566
        /* Make sure the cursor is still valid for this mouse */
slouken@1671
   567
        SDL_Cursor *found;
slouken@1671
   568
        for (found = mouse->cursors; found; found = found->next) {
slouken@1671
   569
            if (found == cursor) {
slouken@1671
   570
                break;
slouken@1671
   571
            }
slouken@1671
   572
        }
slouken@1671
   573
        if (!found) {
slouken@1671
   574
            SDL_SetError("Cursor not associated with the current mouse");
slouken@1671
   575
            return;
slouken@1671
   576
        }
slouken@1671
   577
        mouse->cur_cursor = cursor;
slouken@1671
   578
    } else {
slouken@1671
   579
        cursor = mouse->cur_cursor;
slouken@1671
   580
    }
slouken@1671
   581
slouken@1722
   582
    if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
slouken@1671
   583
        if (mouse->ShowCursor) {
slouken@1671
   584
            mouse->ShowCursor(cursor);
slouken@1671
   585
        }
slouken@1671
   586
    } else {
slouken@1671
   587
        if (mouse->ShowCursor) {
slouken@1671
   588
            mouse->ShowCursor(NULL);
slouken@1671
   589
        }
slouken@1671
   590
    }
slouken@1671
   591
}
slouken@1671
   592
slouken@1671
   593
SDL_Cursor *
slouken@1671
   594
SDL_GetCursor(void)
slouken@1671
   595
{
slouken@1671
   596
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1671
   597
slouken@1671
   598
    if (!mouse) {
slouken@1671
   599
        return NULL;
slouken@1671
   600
    }
slouken@1671
   601
    return mouse->cur_cursor;
slouken@1671
   602
}
slouken@1671
   603
slouken@1671
   604
void
slouken@1671
   605
SDL_FreeCursor(SDL_Cursor * cursor)
slouken@1671
   606
{
slouken@1671
   607
    SDL_Mouse *mouse;
slouken@1671
   608
    SDL_Cursor *curr, *prev;
slouken@1671
   609
slouken@1671
   610
    if (!cursor) {
slouken@1671
   611
        return;
slouken@1671
   612
    }
slouken@1671
   613
    mouse = cursor->mouse;
slouken@1671
   614
slouken@1671
   615
    if (cursor == mouse->def_cursor) {
slouken@1671
   616
        return;
slouken@1671
   617
    }
slouken@1671
   618
    if (cursor == mouse->cur_cursor) {
slouken@1671
   619
        SDL_SetCursor(mouse->def_cursor);
slouken@1671
   620
    }
slouken@1671
   621
slouken@1671
   622
    for (prev = NULL, curr = mouse->cursors; curr;
slouken@1671
   623
         prev = curr, curr = curr->next) {
slouken@1671
   624
        if (curr == cursor) {
slouken@1671
   625
            if (prev) {
slouken@1671
   626
                prev->next = curr->next;
slouken@1671
   627
            } else {
slouken@1671
   628
                mouse->cursors = curr->next;
slouken@1671
   629
            }
slouken@1671
   630
slouken@1671
   631
            if (mouse->FreeCursor) {
slouken@1671
   632
                mouse->FreeCursor(curr);
slouken@1671
   633
            }
slouken@1671
   634
            return;
slouken@1671
   635
        }
slouken@1671
   636
    }
slouken@1671
   637
}
slouken@1671
   638
slouken@1671
   639
int
slouken@1671
   640
SDL_ShowCursor(int toggle)
slouken@1671
   641
{
slouken@1671
   642
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1671
   643
    SDL_bool shown;
slouken@1671
   644
slouken@1671
   645
    if (!mouse) {
slouken@1671
   646
        return 0;
slouken@1671
   647
    }
slouken@1671
   648
slouken@1671
   649
    shown = mouse->cursor_shown;
slouken@1671
   650
    if (toggle >= 0) {
slouken@1671
   651
        if (toggle) {
slouken@1671
   652
            mouse->cursor_shown = SDL_TRUE;
slouken@1671
   653
        } else {
slouken@1671
   654
            mouse->cursor_shown = SDL_FALSE;
slouken@1671
   655
        }
slouken@1671
   656
        if (mouse->cursor_shown != shown) {
slouken@1671
   657
            SDL_SetCursor(NULL);
slouken@1671
   658
        }
slouken@1671
   659
    }
slouken@1671
   660
    return shown;
slouken@1671
   661
}
slouken@1671
   662
slouken@1662
   663
/* vi: set ts=4 sw=4 expandtab: */