src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 08 Dec 2008 00:52:12 +0000
changeset 2860 6ce28e5287e9
parent 2859 99210400e8b9
child 2940 b93965a16fe0
permissions -rw-r--r--
Date: Sun, 07 Dec 2008 13:35:23 +0100
From: Couriersud
Subject: SDL: Mouse last_x, last_y into SDL_Mouse

the attached diff moves the static vars last_x and last_y into
SDL_Mouse. These, as far as I understand it, should be tied to the
individual mouse.

The patch also makes the code check for out of window conditions of
mouse->x,y when relative movements are passed to MouseSendMotion.

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