src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 07 Dec 2008 21:53:28 +0000
changeset 2849 523b10db69f8
parent 2842 97ba0be8b565
child 2859 99210400e8b9
permissions -rw-r--r--
There's no reason to add extra code to notify the mice of window size changes.
Just query the window size when we care about it. :)
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@1895
    28
#include "default_cursor.h"
slouken@0
    29
slouken@0
    30
slouken@2710
    31
static int SDL_num_mice = 0;
slouken@2710
    32
static int SDL_current_mouse = -1;
slouken@2710
    33
static SDL_Mouse **SDL_mice = NULL;
slouken@2710
    34
static int *SDL_IdIndex = NULL;
slouken@2710
    35
static int SDL_highestId = -1;
slouken@2710
    36
static int last_x, last_y;      /* the last reported x and y coordinates by the system cursor */
slouken@0
    37
slouken@0
    38
slouken@0
    39
/* Public functions */
slouken@1895
    40
int
slouken@1895
    41
SDL_MouseInit(void)
slouken@0
    42
{
slouken@1895
    43
    return (0);
slouken@1123
    44
}
slouken@0
    45
slouken@1895
    46
SDL_Mouse *
slouken@1895
    47
SDL_GetMouse(int index)
slouken@460
    48
{
slouken@1895
    49
    if (index < 0 || index >= SDL_num_mice) {
slouken@1895
    50
        return NULL;
slouken@1895
    51
    }
slouken@1895
    52
    return SDL_mice[index];
slouken@460
    53
}
slouken@460
    54
slouken@1895
    55
int
slouken@2710
    56
SDL_SetMouseIndexId(int id, int index)
slouken@2710
    57
{
slouken@2710
    58
    if (id < 0) {
slouken@2710
    59
        SDL_SetError("Invalid Mouse ID");
slouken@2710
    60
        return -1;
slouken@2710
    61
    }
slouken@2710
    62
    if (id > SDL_highestId) {
slouken@2710
    63
        int *indexes;
slouken@2710
    64
        indexes = (int *) SDL_realloc(SDL_IdIndex, (id + 1) * sizeof(int));
slouken@2710
    65
        if (!indexes) {
slouken@2710
    66
            SDL_OutOfMemory();
slouken@2710
    67
            return -1;
slouken@2710
    68
        }
slouken@2710
    69
        SDL_IdIndex = indexes;
slouken@2710
    70
        SDL_IdIndex[id] = index;
slouken@2710
    71
        SDL_highestId = id;
slouken@2710
    72
    } else {
slouken@2710
    73
        SDL_IdIndex[id] = index;
slouken@2710
    74
    }
slouken@2710
    75
    return 1;
slouken@2710
    76
}
slouken@2710
    77
slouken@2712
    78
int
slouken@2712
    79
SDL_GetMouseIndexId(int id)
slouken@2710
    80
{
slouken@2710
    81
    if (id < 0 || id > SDL_highestId) {
slouken@2712
    82
        return -1;
slouken@2710
    83
    }
slouken@2712
    84
    return SDL_IdIndex[id];
slouken@2710
    85
}
slouken@2710
    86
slouken@2710
    87
int
slouken@2710
    88
SDL_AddMouse(const SDL_Mouse * mouse, int index, char *name, int pressure_max,
slouken@2710
    89
             int pressure_min, int ends)
slouken@0
    90
{
slouken@1895
    91
    SDL_Mouse **mice;
slouken@1895
    92
    int selected_mouse;
slouken@2710
    93
    int length;
slouken@1895
    94
slouken@1895
    95
    /* Add the mouse to the list of mice */
slouken@1895
    96
    if (index < 0 || index >= SDL_num_mice || SDL_mice[index]) {
slouken@1895
    97
        mice =
slouken@1895
    98
            (SDL_Mouse **) SDL_realloc(SDL_mice,
slouken@1895
    99
                                       (SDL_num_mice + 1) * sizeof(*mice));
slouken@1895
   100
        if (!mice) {
slouken@1895
   101
            SDL_OutOfMemory();
slouken@1895
   102
            return -1;
slouken@1895
   103
        }
slouken@1895
   104
slouken@1895
   105
        SDL_mice = mice;
slouken@1895
   106
        index = SDL_num_mice++;
slouken@1895
   107
    }
slouken@1895
   108
    SDL_mice[index] = (SDL_Mouse *) SDL_malloc(sizeof(*SDL_mice[index]));
slouken@1895
   109
    if (!SDL_mice[index]) {
slouken@1895
   110
        SDL_OutOfMemory();
slouken@1895
   111
        return -1;
slouken@1895
   112
    }
slouken@1895
   113
    *SDL_mice[index] = *mouse;
slouken@1895
   114
slouken@2710
   115
    /* we're setting the mouse properties */
slouken@2710
   116
    length = 0;
slouken@2710
   117
    length = SDL_strlen(name);
kazeuser@2718
   118
    SDL_mice[index]->name = SDL_malloc((length + 2) * sizeof(char));
slouken@2725
   119
    SDL_strlcpy(SDL_mice[index]->name, name, length + 1);
slouken@2710
   120
    SDL_mice[index]->pressure_max = pressure_max;
slouken@2710
   121
    SDL_mice[index]->pressure_min = pressure_min;
slouken@1895
   122
    SDL_mice[index]->cursor_shown = SDL_TRUE;
slouken@1895
   123
    selected_mouse = SDL_SelectMouse(index);
slouken@1895
   124
    SDL_mice[index]->cur_cursor = NULL;
slouken@1895
   125
    SDL_mice[index]->def_cursor =
slouken@1895
   126
        SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH,
slouken@1895
   127
                         DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
slouken@1895
   128
    SDL_SetCursor(SDL_mice[index]->def_cursor);
slouken@2710
   129
    /* we're assuming that all mice are in the computer sensing zone */
slouken@2710
   130
    SDL_mice[index]->proximity = SDL_TRUE;
slouken@2710
   131
    /* we're assuming that all mice are working in the absolute position mode
slouken@2710
   132
       thanx to that, the users that don't want to use many mice don't have to
slouken@2710
   133
       worry about anything */
slouken@2710
   134
    SDL_mice[index]->relative_mode = SDL_FALSE;
slouken@2710
   135
    SDL_mice[index]->current_end = 0;
slouken@2710
   136
    SDL_mice[index]->total_ends = ends;
slouken@1895
   137
    SDL_SelectMouse(selected_mouse);
slouken@1895
   138
slouken@1895
   139
    return index;
slouken@0
   140
}
slouken@0
   141
slouken@1895
   142
void
slouken@1895
   143
SDL_DelMouse(int index)
slouken@0
   144
{
slouken@1895
   145
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   146
slouken@1895
   147
    if (!mouse) {
slouken@1895
   148
        return;
slouken@1895
   149
    }
slouken@1895
   150
slouken@1895
   151
    mouse->def_cursor = NULL;
slouken@2710
   152
    SDL_free(mouse->name);
slouken@1895
   153
    while (mouse->cursors) {
slouken@1895
   154
        SDL_FreeCursor(mouse->cursors);
slouken@1895
   155
    }
slouken@1895
   156
slouken@1895
   157
    if (mouse->FreeMouse) {
slouken@1895
   158
        mouse->FreeMouse(mouse);
slouken@1895
   159
    }
slouken@1895
   160
    SDL_free(mouse);
slouken@1895
   161
slouken@1895
   162
    SDL_mice[index] = NULL;
slouken@0
   163
}
slouken@0
   164
slouken@1895
   165
void
slouken@1895
   166
SDL_ResetMouse(int index)
slouken@0
   167
{
slouken@1895
   168
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   169
slouken@1895
   170
    if (!mouse) {
slouken@1895
   171
        return;
slouken@1895
   172
    }
slouken@1895
   173
slouken@1895
   174
    /* FIXME */
slouken@0
   175
}
slouken@0
   176
slouken@1895
   177
void
slouken@1895
   178
SDL_MouseQuit(void)
slouken@0
   179
{
slouken@1895
   180
    int i;
slouken@0
   181
slouken@1895
   182
    for (i = 0; i < SDL_num_mice; ++i) {
slouken@1895
   183
        SDL_DelMouse(i);
slouken@1895
   184
    }
slouken@1895
   185
    SDL_num_mice = 0;
slouken@2765
   186
    SDL_current_mouse = -1;
slouken@0
   187
slouken@1895
   188
    if (SDL_mice) {
slouken@1895
   189
        SDL_free(SDL_mice);
slouken@1895
   190
        SDL_mice = NULL;
slouken@1895
   191
    }
slouken@0
   192
}
slouken@0
   193
slouken@1895
   194
int
slouken@1895
   195
SDL_GetNumMice(void)
slouken@0
   196
{
slouken@1895
   197
    return SDL_num_mice;
slouken@0
   198
}
slouken@0
   199
slouken@1895
   200
int
slouken@1895
   201
SDL_SelectMouse(int index)
slouken@1895
   202
{
slouken@1895
   203
    if (index >= 0 && index < SDL_num_mice) {
slouken@1895
   204
        SDL_current_mouse = index;
slouken@1895
   205
    }
slouken@1895
   206
    return SDL_current_mouse;
slouken@1895
   207
}
slouken@1895
   208
slouken@1895
   209
SDL_WindowID
slouken@2710
   210
SDL_GetMouseFocusWindow(int index)
slouken@1895
   211
{
slouken@2710
   212
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   213
slouken@1895
   214
    if (!mouse) {
slouken@1895
   215
        return 0;
slouken@1895
   216
    }
slouken@1895
   217
    return mouse->focus;
slouken@1895
   218
}
slouken@1895
   219
icculus@2049
   220
static int SDLCALL
slouken@1895
   221
FlushMouseMotion(void *param, SDL_Event * event)
slouken@1895
   222
{
slouken@1895
   223
    if (event->type == SDL_MOUSEMOTION
slouken@1895
   224
        && event->motion.which == (Uint8) SDL_current_mouse) {
slouken@1895
   225
        return 0;
slouken@1895
   226
    } else {
slouken@1895
   227
        return 1;
slouken@1895
   228
    }
slouken@1895
   229
}
slouken@1895
   230
slouken@1895
   231
int
slouken@2710
   232
SDL_SetRelativeMouseMode(int index, SDL_bool enabled)
slouken@1895
   233
{
slouken@2710
   234
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   235
slouken@1895
   236
    if (!mouse) {
slouken@1895
   237
        return -1;
slouken@1895
   238
    }
slouken@1895
   239
slouken@1895
   240
    /* Flush pending mouse motion */
slouken@1895
   241
    mouse->flush_motion = SDL_TRUE;
slouken@1895
   242
    SDL_PumpEvents();
slouken@1895
   243
    mouse->flush_motion = SDL_FALSE;
slouken@1895
   244
    SDL_FilterEvents(FlushMouseMotion, mouse);
slouken@1895
   245
slouken@1895
   246
    /* Set the relative mode */
slouken@1895
   247
    mouse->relative_mode = enabled;
slouken@1895
   248
slouken@1895
   249
    /* Update cursor visibility */
slouken@1895
   250
    SDL_SetCursor(NULL);
slouken@1895
   251
slouken@1895
   252
    if (!enabled) {
slouken@1895
   253
        /* Restore the expected mouse position */
slouken@1895
   254
        SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
slouken@1895
   255
    }
slouken@1895
   256
    return 0;
slouken@1895
   257
}
slouken@1895
   258
slouken@1895
   259
SDL_bool
slouken@2710
   260
SDL_GetRelativeMouseMode(int index)
slouken@1895
   261
{
slouken@2710
   262
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   263
slouken@1895
   264
    if (!mouse) {
slouken@1895
   265
        return SDL_FALSE;
slouken@1895
   266
    }
slouken@1895
   267
    return mouse->relative_mode;
slouken@1895
   268
}
slouken@1895
   269
slouken@1895
   270
Uint8
slouken@2710
   271
SDL_GetMouseState(int index, int *x, int *y)
slouken@1895
   272
{
slouken@2710
   273
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   274
slouken@1895
   275
    if (!mouse) {
slouken@1895
   276
        if (x) {
slouken@1895
   277
            *x = 0;
slouken@1895
   278
        }
slouken@1895
   279
        if (y) {
slouken@1895
   280
            *y = 0;
slouken@1895
   281
        }
slouken@1895
   282
        return 0;
slouken@1895
   283
    }
slouken@1895
   284
slouken@1895
   285
    if (x) {
slouken@1895
   286
        *x = mouse->x;
slouken@1895
   287
    }
slouken@1895
   288
    if (y) {
slouken@1895
   289
        *y = mouse->y;
slouken@1895
   290
    }
slouken@1895
   291
    return mouse->buttonstate;
slouken@1895
   292
}
slouken@1895
   293
slouken@1895
   294
Uint8
slouken@2710
   295
SDL_GetRelativeMouseState(int index, int *x, int *y)
slouken@1895
   296
{
slouken@2710
   297
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   298
slouken@1895
   299
    if (!mouse) {
slouken@1895
   300
        if (x) {
slouken@1895
   301
            *x = 0;
slouken@1895
   302
        }
slouken@1895
   303
        if (y) {
slouken@1895
   304
            *y = 0;
slouken@1895
   305
        }
slouken@1895
   306
        return 0;
slouken@1895
   307
    }
slouken@1895
   308
slouken@1895
   309
    if (x) {
slouken@1895
   310
        *x = mouse->xdelta;
slouken@1895
   311
    }
slouken@1895
   312
    if (y) {
slouken@1895
   313
        *y = mouse->ydelta;
slouken@1895
   314
    }
slouken@1895
   315
    mouse->xdelta = 0;
slouken@1895
   316
    mouse->ydelta = 0;
slouken@1895
   317
    return mouse->buttonstate;
slouken@1895
   318
}
slouken@1895
   319
slouken@1895
   320
void
slouken@2710
   321
SDL_SetMouseFocus(int id, SDL_WindowID windowID)
slouken@1895
   322
{
slouken@2712
   323
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   324
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2712
   325
    int i;
slouken@1895
   326
    SDL_bool focus;
slouken@1895
   327
slouken@1895
   328
    if (!mouse || (mouse->focus == windowID)) {
slouken@1895
   329
        return;
slouken@1895
   330
    }
slouken@1895
   331
slouken@1895
   332
    /* See if the current window has lost focus */
slouken@1895
   333
    if (mouse->focus) {
slouken@1895
   334
        focus = SDL_FALSE;
slouken@1895
   335
        for (i = 0; i < SDL_num_mice; ++i) {
slouken@1895
   336
            SDL_Mouse *check;
slouken@1895
   337
            if (i != index) {
slouken@1895
   338
                check = SDL_GetMouse(i);
slouken@1895
   339
                if (check && check->focus == mouse->focus) {
slouken@1895
   340
                    focus = SDL_TRUE;
slouken@1895
   341
                    break;
slouken@1895
   342
                }
slouken@1895
   343
            }
slouken@1895
   344
        }
slouken@1895
   345
        if (!focus) {
slouken@1895
   346
            SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
slouken@1895
   347
        }
slouken@1895
   348
    }
slouken@1895
   349
slouken@1895
   350
    mouse->focus = windowID;
slouken@1895
   351
slouken@1895
   352
    if (mouse->focus) {
slouken@1895
   353
        focus = SDL_FALSE;
slouken@1895
   354
        for (i = 0; i < SDL_num_mice; ++i) {
slouken@1895
   355
            SDL_Mouse *check;
slouken@1895
   356
            if (i != index) {
slouken@1895
   357
                check = SDL_GetMouse(i);
slouken@1895
   358
                if (check && check->focus == mouse->focus) {
slouken@1895
   359
                    focus = SDL_TRUE;
slouken@1895
   360
                    break;
slouken@1895
   361
                }
slouken@1895
   362
            }
slouken@1895
   363
        }
slouken@1895
   364
        if (!focus) {
slouken@1895
   365
            SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
slouken@1895
   366
        }
slouken@1895
   367
    }
slouken@1895
   368
}
slouken@1895
   369
slouken@1895
   370
int
slouken@2710
   371
SDL_SendProximity(int id, int x, int y, int type)
slouken@1895
   372
{
slouken@2712
   373
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   374
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   375
    int posted = 0;
slouken@2727
   376
slouken@2727
   377
    if (!mouse) {
slouken@2727
   378
        return 0;
slouken@2727
   379
    }
slouken@2727
   380
slouken@2710
   381
    last_x = x;
slouken@2710
   382
    last_y = y;
slouken@2710
   383
    if (SDL_ProcessEvents[type] == SDL_ENABLE) {
slouken@2710
   384
        SDL_Event event;
slouken@2710
   385
        event.proximity.which = (Uint8) index;
slouken@2710
   386
        event.proximity.x = x;
slouken@2710
   387
        event.proximity.y = y;
slouken@2710
   388
        event.proximity.cursor = mouse->current_end;
slouken@2710
   389
        event.proximity.type = type;
slouken@2710
   390
        posted = (SDL_PushEvent(&event) > 0);
slouken@2710
   391
        if (type == SDL_PROXIMITYIN) {
slouken@2710
   392
            mouse->proximity = SDL_TRUE;
slouken@2710
   393
        } else {
slouken@2710
   394
            mouse->proximity = SDL_FALSE;
slouken@2710
   395
        }
slouken@2710
   396
    }
slouken@2710
   397
    return posted;
slouken@2710
   398
}
slouken@2710
   399
slouken@2710
   400
int
slouken@2710
   401
SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure)
slouken@2710
   402
{
slouken@2712
   403
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   404
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   405
    int posted;
slouken@1895
   406
    int xrel;
slouken@1895
   407
    int yrel;
slouken@1895
   408
slouken@1895
   409
    if (!mouse || mouse->flush_motion) {
slouken@1895
   410
        return 0;
slouken@1895
   411
    }
slouken@1895
   412
slouken@2710
   413
    /* if the mouse is out of proximity we don't to want to have any motion from it */
slouken@2710
   414
    if (mouse->proximity == SDL_FALSE) {
slouken@2710
   415
        last_x = x;
slouken@2710
   416
        last_y = y;
slouken@2710
   417
        return 0;
slouken@1895
   418
    }
slouken@1895
   419
slouken@2710
   420
    /* the relative motion is calculated regarding the system cursor last position */
slouken@2842
   421
    if (relative) {
slouken@2842
   422
        xrel = x;
slouken@2842
   423
        yrel = y;
slouken@2842
   424
        x = (last_x + x);
slouken@2842
   425
        y = (last_y + y);
slouken@2842
   426
    } else {
slouken@2842
   427
        xrel = x - last_x;
slouken@2842
   428
        yrel = y - last_y;
slouken@2842
   429
    }
slouken@2710
   430
slouken@1895
   431
    /* Drop events that don't change state */
slouken@1895
   432
    if (!xrel && !yrel) {
slouken@1895
   433
#if 0
slouken@1895
   434
        printf("Mouse event didn't change state - dropped!\n");
slouken@1895
   435
#endif
slouken@1895
   436
        return 0;
slouken@1895
   437
    }
slouken@1895
   438
slouken@2710
   439
    /* Update internal mouse coordinates */
slouken@2710
   440
    if (mouse->relative_mode == SDL_FALSE) {
slouken@1895
   441
        mouse->x = x;
slouken@1895
   442
        mouse->y = y;
slouken@2710
   443
    } else {
slouken@2794
   444
        /* while using the relative mode and many windows, we have to be
slouken@2794
   445
           sure that the pointers find themselves inside the windows */
slouken@2849
   446
        int x_max, y_max;
slouken@2849
   447
slouken@2849
   448
        SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
slouken@2849
   449
slouken@2849
   450
        if (mouse->x + xrel > x_max) {
slouken@2849
   451
            mouse->x = x_max;
slouken@2710
   452
        } else if (mouse->x + xrel < 0) {
slouken@2710
   453
            mouse->x = 0;
slouken@2710
   454
        } else {
slouken@2710
   455
            mouse->x += xrel;
slouken@2710
   456
        }
slouken@2849
   457
        if (mouse->y + yrel > y_max) {
slouken@2849
   458
            mouse->y = y_max;
slouken@2710
   459
        } else if (mouse->y + yrel < 0) {
slouken@2710
   460
            mouse->y = 0;
slouken@2710
   461
        } else {
slouken@2710
   462
            mouse->y += yrel;
slouken@2710
   463
        }
slouken@1895
   464
    }
slouken@1895
   465
    mouse->xdelta += xrel;
slouken@1895
   466
    mouse->ydelta += yrel;
slouken@2710
   467
    mouse->pressure = pressure;
slouken@1895
   468
slouken@1895
   469
    /* Move the mouse cursor, if needed */
slouken@1895
   470
    if (mouse->cursor_shown && !mouse->relative_mode &&
slouken@1895
   471
        mouse->MoveCursor && mouse->cur_cursor) {
slouken@1895
   472
        mouse->MoveCursor(mouse->cur_cursor);
slouken@1895
   473
    }
slouken@1895
   474
slouken@1895
   475
    /* Post the event, if desired */
slouken@1895
   476
    posted = 0;
slouken@2710
   477
    if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE &&
slouken@2710
   478
        mouse->proximity == SDL_TRUE) {
slouken@1895
   479
        SDL_Event event;
slouken@1895
   480
        event.motion.type = SDL_MOUSEMOTION;
slouken@1895
   481
        event.motion.which = (Uint8) index;
slouken@1895
   482
        event.motion.state = mouse->buttonstate;
slouken@1895
   483
        event.motion.x = mouse->x;
slouken@1895
   484
        event.motion.y = mouse->y;
slouken@2710
   485
        event.motion.pressure = mouse->pressure;
slouken@1895
   486
        event.motion.xrel = xrel;
slouken@1895
   487
        event.motion.yrel = yrel;
slouken@1895
   488
        event.motion.windowID = mouse->focus;
slouken@2710
   489
        event.motion.pressure_max = mouse->pressure_max;
slouken@2710
   490
        event.motion.pressure_min = mouse->pressure_min;
slouken@2710
   491
        event.motion.cursor = mouse->current_end;
slouken@1895
   492
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   493
    }
slouken@2710
   494
    last_x = x;
slouken@2710
   495
    last_y = y;
slouken@1895
   496
    return posted;
slouken@1895
   497
}
slouken@1895
   498
slouken@1895
   499
int
slouken@2710
   500
SDL_SendMouseButton(int id, Uint8 state, Uint8 button)
slouken@1895
   501
{
slouken@2712
   502
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   503
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   504
    int posted;
slouken@1895
   505
    Uint8 type;
slouken@1895
   506
slouken@1895
   507
    if (!mouse) {
slouken@1895
   508
        return 0;
slouken@1895
   509
    }
slouken@1895
   510
slouken@1895
   511
    /* Figure out which event to perform */
slouken@1895
   512
    switch (state) {
slouken@1895
   513
    case SDL_PRESSED:
slouken@1895
   514
        if (mouse->buttonstate & SDL_BUTTON(button)) {
slouken@1895
   515
            /* Ignore this event, no state change */
slouken@1895
   516
            return 0;
slouken@1895
   517
        }
slouken@1895
   518
        type = SDL_MOUSEBUTTONDOWN;
slouken@1895
   519
        mouse->buttonstate |= SDL_BUTTON(button);
slouken@1895
   520
        break;
slouken@1895
   521
    case SDL_RELEASED:
slouken@2725
   522
        if (!(mouse->buttonstate & SDL_BUTTON(button))) {
kazeuser@2718
   523
            /* Ignore this event, no state change */
kazeuser@2718
   524
            return 0;
kazeuser@2718
   525
        }
slouken@1895
   526
        type = SDL_MOUSEBUTTONUP;
slouken@1895
   527
        mouse->buttonstate &= ~SDL_BUTTON(button);
slouken@1895
   528
        break;
slouken@1895
   529
    default:
slouken@1895
   530
        /* Invalid state -- bail */
slouken@1895
   531
        return 0;
slouken@1895
   532
    }
slouken@1895
   533
slouken@1895
   534
    /* Post the event, if desired */
slouken@1895
   535
    posted = 0;
slouken@1895
   536
    if (SDL_ProcessEvents[type] == SDL_ENABLE) {
slouken@1895
   537
        SDL_Event event;
slouken@1895
   538
        event.type = type;
slouken@1895
   539
        event.button.which = (Uint8) index;
slouken@1895
   540
        event.button.state = state;
slouken@1895
   541
        event.button.button = button;
slouken@1895
   542
        event.button.x = mouse->x;
slouken@1895
   543
        event.button.y = mouse->y;
slouken@1895
   544
        event.button.windowID = mouse->focus;
slouken@1895
   545
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   546
    }
slouken@1895
   547
    return posted;
slouken@1895
   548
}
slouken@1895
   549
slouken@1895
   550
int
slouken@2152
   551
SDL_SendMouseWheel(int index, int x, int y)
slouken@1895
   552
{
slouken@1895
   553
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   554
    int posted;
slouken@1895
   555
slouken@2152
   556
    if (!mouse || (!x && !y)) {
slouken@1895
   557
        return 0;
slouken@1895
   558
    }
slouken@1895
   559
slouken@1895
   560
    /* Post the event, if desired */
slouken@1895
   561
    posted = 0;
slouken@1895
   562
    if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) {
slouken@1895
   563
        SDL_Event event;
slouken@1895
   564
        event.type = SDL_MOUSEWHEEL;
slouken@1895
   565
        event.wheel.which = (Uint8) index;
slouken@2152
   566
        event.wheel.x = x;
slouken@2152
   567
        event.wheel.y = y;
slouken@1895
   568
        event.wheel.windowID = mouse->focus;
slouken@1895
   569
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   570
    }
slouken@1895
   571
    return posted;
slouken@1895
   572
}
slouken@1895
   573
slouken@1895
   574
void
slouken@1895
   575
SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
slouken@1895
   576
{
slouken@1895
   577
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   578
slouken@1895
   579
    if (!mouse) {
slouken@1895
   580
        return;
slouken@1895
   581
    }
slouken@1895
   582
slouken@1895
   583
    if (mouse->WarpMouse) {
slouken@1895
   584
        mouse->WarpMouse(mouse, windowID, x, y);
slouken@1895
   585
    } else {
slouken@1895
   586
        SDL_SetMouseFocus(SDL_current_mouse, windowID);
slouken@2710
   587
        SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0);
slouken@1895
   588
    }
slouken@1895
   589
}
slouken@1895
   590
slouken@1895
   591
SDL_Cursor *
slouken@1895
   592
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
slouken@1895
   593
                 int w, int h, int hot_x, int hot_y)
slouken@1895
   594
{
slouken@1895
   595
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   596
    SDL_Surface *surface;
slouken@1895
   597
    SDL_Cursor *cursor;
slouken@1895
   598
    int x, y;
slouken@1895
   599
    Uint32 *pixel;
slouken@1895
   600
    Uint8 datab, maskb;
slouken@1895
   601
    const Uint32 black = 0xFF000000;
slouken@1895
   602
    const Uint32 white = 0xFFFFFFFF;
slouken@1895
   603
    const Uint32 transparent = 0x00000000;
slouken@1895
   604
slouken@1895
   605
    if (!mouse) {
slouken@1895
   606
        SDL_SetError("No mice are initialized");
slouken@1895
   607
        return NULL;
slouken@1895
   608
    }
slouken@1895
   609
slouken@1895
   610
    if (!mouse->CreateCursor) {
slouken@1895
   611
        SDL_SetError("Current mouse doesn't have cursor support");
slouken@1895
   612
        return NULL;
slouken@1895
   613
    }
slouken@1895
   614
slouken@1895
   615
    /* Sanity check the hot spot */
slouken@1895
   616
    if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) {
slouken@1895
   617
        SDL_SetError("Cursor hot spot doesn't lie within cursor");
slouken@1895
   618
        return NULL;
slouken@1895
   619
    }
slouken@1895
   620
slouken@1895
   621
    /* Make sure the width is a multiple of 8 */
slouken@1895
   622
    w = ((w + 7) & ~7);
slouken@1895
   623
slouken@1895
   624
    /* Create the surface from a bitmap */
slouken@1895
   625
    surface =
slouken@1895
   626
        SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
slouken@1895
   627
                             0xFF000000);
slouken@1895
   628
    if (!surface) {
slouken@1895
   629
        return NULL;
slouken@1895
   630
    }
slouken@1895
   631
    for (y = 0; y < h; ++y) {
slouken@1895
   632
        pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
slouken@1895
   633
        for (x = 0; x < w; ++x) {
slouken@1895
   634
            if ((x % 8) == 0) {
slouken@1895
   635
                datab = *data++;
slouken@1895
   636
                maskb = *mask++;
slouken@1895
   637
            }
slouken@1895
   638
            if (maskb & 0x80) {
slouken@1895
   639
                *pixel++ = (datab & 0x80) ? black : white;
slouken@1895
   640
            } else {
slouken@1895
   641
                *pixel++ = (datab & 0x80) ? black : transparent;
slouken@1895
   642
            }
slouken@1895
   643
            datab <<= 1;
slouken@1895
   644
            maskb <<= 1;
slouken@1895
   645
        }
slouken@1895
   646
    }
slouken@1895
   647
slouken@1895
   648
    cursor = mouse->CreateCursor(surface, hot_x, hot_y);
slouken@1895
   649
    if (cursor) {
slouken@1895
   650
        cursor->mouse = mouse;
slouken@1895
   651
        cursor->next = mouse->cursors;
slouken@1895
   652
        mouse->cursors = cursor;
slouken@1895
   653
    }
slouken@1895
   654
slouken@1895
   655
    SDL_FreeSurface(surface);
slouken@1895
   656
slouken@1895
   657
    return cursor;
slouken@1895
   658
}
slouken@1895
   659
slouken@1895
   660
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
slouken@1895
   661
   if this is desired for any reason.  This is used when setting
slouken@1895
   662
   the video mode and when the SDL window gains the mouse focus.
slouken@1895
   663
 */
slouken@1895
   664
void
slouken@1895
   665
SDL_SetCursor(SDL_Cursor * cursor)
slouken@1895
   666
{
slouken@1895
   667
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   668
slouken@1895
   669
    if (!mouse) {
slouken@1895
   670
        SDL_SetError("No mice are initialized");
slouken@1895
   671
        return;
slouken@1895
   672
    }
slouken@1895
   673
slouken@1895
   674
    /* Set the new cursor */
slouken@1895
   675
    if (cursor) {
slouken@1895
   676
        /* Make sure the cursor is still valid for this mouse */
slouken@1895
   677
        SDL_Cursor *found;
slouken@1895
   678
        for (found = mouse->cursors; found; found = found->next) {
slouken@1895
   679
            if (found == cursor) {
slouken@1895
   680
                break;
slouken@1895
   681
            }
slouken@1895
   682
        }
slouken@1895
   683
        if (!found) {
slouken@1895
   684
            SDL_SetError("Cursor not associated with the current mouse");
slouken@1895
   685
            return;
slouken@1895
   686
        }
slouken@1895
   687
        mouse->cur_cursor = cursor;
slouken@1895
   688
    } else {
slouken@1895
   689
        cursor = mouse->cur_cursor;
slouken@1895
   690
    }
slouken@1895
   691
slouken@1895
   692
    if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
slouken@1895
   693
        if (mouse->ShowCursor) {
slouken@1895
   694
            mouse->ShowCursor(cursor);
slouken@1895
   695
        }
slouken@1895
   696
    } else {
slouken@1895
   697
        if (mouse->ShowCursor) {
slouken@1895
   698
            mouse->ShowCursor(NULL);
slouken@1895
   699
        }
slouken@1895
   700
    }
slouken@1895
   701
}
slouken@1895
   702
slouken@1895
   703
SDL_Cursor *
slouken@1895
   704
SDL_GetCursor(void)
slouken@1895
   705
{
slouken@1895
   706
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   707
slouken@1895
   708
    if (!mouse) {
slouken@1895
   709
        return NULL;
slouken@1895
   710
    }
slouken@1895
   711
    return mouse->cur_cursor;
slouken@1895
   712
}
slouken@1895
   713
slouken@1895
   714
void
slouken@1895
   715
SDL_FreeCursor(SDL_Cursor * cursor)
slouken@1895
   716
{
slouken@1895
   717
    SDL_Mouse *mouse;
slouken@1895
   718
    SDL_Cursor *curr, *prev;
slouken@1895
   719
slouken@1895
   720
    if (!cursor) {
slouken@1895
   721
        return;
slouken@1895
   722
    }
slouken@1895
   723
    mouse = cursor->mouse;
slouken@1895
   724
slouken@1895
   725
    if (cursor == mouse->def_cursor) {
slouken@1895
   726
        return;
slouken@1895
   727
    }
slouken@1895
   728
    if (cursor == mouse->cur_cursor) {
slouken@1895
   729
        SDL_SetCursor(mouse->def_cursor);
slouken@1895
   730
    }
slouken@1895
   731
slouken@1895
   732
    for (prev = NULL, curr = mouse->cursors; curr;
slouken@1895
   733
         prev = curr, curr = curr->next) {
slouken@1895
   734
        if (curr == cursor) {
slouken@1895
   735
            if (prev) {
slouken@1895
   736
                prev->next = curr->next;
slouken@1895
   737
            } else {
slouken@1895
   738
                mouse->cursors = curr->next;
slouken@1895
   739
            }
slouken@1895
   740
slouken@1895
   741
            if (mouse->FreeCursor) {
slouken@1895
   742
                mouse->FreeCursor(curr);
slouken@1895
   743
            }
slouken@1895
   744
            return;
slouken@1895
   745
        }
slouken@1895
   746
    }
slouken@1895
   747
}
slouken@1895
   748
slouken@1895
   749
int
slouken@1895
   750
SDL_ShowCursor(int toggle)
slouken@1895
   751
{
slouken@1895
   752
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   753
    SDL_bool shown;
slouken@1895
   754
slouken@1895
   755
    if (!mouse) {
slouken@1895
   756
        return 0;
slouken@1895
   757
    }
slouken@1895
   758
slouken@1895
   759
    shown = mouse->cursor_shown;
slouken@1895
   760
    if (toggle >= 0) {
slouken@1895
   761
        if (toggle) {
slouken@1895
   762
            mouse->cursor_shown = SDL_TRUE;
slouken@1895
   763
        } else {
slouken@1895
   764
            mouse->cursor_shown = SDL_FALSE;
slouken@1895
   765
        }
slouken@1895
   766
        if (mouse->cursor_shown != shown) {
slouken@1895
   767
            SDL_SetCursor(NULL);
slouken@1895
   768
        }
slouken@1895
   769
    }
slouken@1895
   770
    return shown;
slouken@1895
   771
}
slouken@1895
   772
slouken@2710
   773
char *
slouken@2710
   774
SDL_GetMouseName(int index)
slouken@2710
   775
{
slouken@2710
   776
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   777
    if (!mouse) {
slouken@2710
   778
        return NULL;
slouken@2710
   779
    }
slouken@2710
   780
    return mouse->name;
slouken@2710
   781
}
slouken@2710
   782
slouken@2710
   783
void
slouken@2710
   784
SDL_ChangeEnd(int id, int end)
slouken@2710
   785
{
slouken@2712
   786
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   787
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   788
slouken@2710
   789
    if (mouse) {
slouken@2710
   790
        mouse->current_end = end;
slouken@2710
   791
    }
slouken@2710
   792
}
slouken@2710
   793
slouken@2710
   794
int
slouken@2710
   795
SDL_GetCursorsNumber(int index)
slouken@2710
   796
{
slouken@2710
   797
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   798
slouken@2710
   799
    if (!mouse) {
slouken@2710
   800
        return -1;
slouken@2710
   801
    }
slouken@2710
   802
    return mouse->total_ends;
slouken@2710
   803
}
slouken@2710
   804
slouken@2710
   805
int
slouken@2710
   806
SDL_GetCurrentCursor(int index)
slouken@2710
   807
{
slouken@2710
   808
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   809
slouken@2710
   810
    if (!mouse) {
slouken@2710
   811
        return -1;
slouken@2710
   812
    }
slouken@2710
   813
    return mouse->current_end;
slouken@2710
   814
}
slouken@2710
   815
slouken@1895
   816
/* vi: set ts=4 sw=4 expandtab: */