src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 10 Jun 2009 14:00:21 +0000
changeset 3191 91b335df6fc8
parent 3188 102b7880543a
child 3195 08747e24a50f
permissions -rw-r--r--
Fixed bug #750
Since many different event structures include windowID it should be placed near
the beginning of the structure (preferably right after type) so it's position
is the same between different events.

This is to avoid code like this:
if (event.type == SDL_WINDOWEVENT)
win = event.window.windowID;
else if ((SDL_EVENTMASK(event.type) & SDL_KEYEVENTMASK) != 0)
win = event.key.windowID;
else if (event.type == SDL_TEXTINPUT)
win = event.text.windowID;
else if (event.type == SDL_MOUSEMOTION)
win = event.motion.windowID;
else if ((SDL_EVENTMASK(event.type) & (SDL_MOUBUTTONDOWNMASK |
SDL_MOUBUTTONUPMASK)) != 0)
win = event.button.windowID;
else if (event.type == SDL_MOUSEWHEEL)
win = event.wheel.windowID;
...

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