src/events/SDL_mouse.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 06 Dec 2008 17:50:50 +0000
changeset 2842 97ba0be8b565
parent 2794 f7872b7a8732
child 2849 523b10db69f8
permissions -rw-r--r--
Date: Sat, 06 Dec 2008 15:27:00 +0100
From: Couriersud
Subject: SDL: Relative mouse movements

The patch below will reenable processing of relative mouse movements.
The DirectFB drivers generates those in "grabbed" mode. These ensure,
that even in fullscreen mode relative movements are reported. SDLMAME
depends on this for games with trackballs.

Looking at the code I ask myself whether relative movements should be
handled in the drivers (x11, directfb). Both x11 and directfb are able
to report relative movements. This would leave it to the driver to use
the most appropriate method for relative movements when at the border of
a fullscreen window or being "grabbed".
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@2794
   367
        SDL_GetWindowSize(windowID, &mouse->x_max, &mouse->y_max);
slouken@2794
   368
    }
slouken@2794
   369
}
slouken@2794
   370
slouken@2794
   371
void
slouken@2794
   372
SDL_SetMouseFocusSize(SDL_WindowID windowID, int w, int h)
slouken@2794
   373
{
slouken@2794
   374
    int i;
slouken@2794
   375
slouken@2794
   376
    for (i = 0; i < SDL_num_mice; ++i) {
slouken@2794
   377
        SDL_Mouse *mouse = SDL_GetMouse(i);
slouken@2794
   378
        if (mouse && mouse->focus == windowID) {
slouken@2794
   379
            mouse->x_max = w;
slouken@2794
   380
            mouse->y_max = h;
slouken@2794
   381
        }
slouken@1895
   382
    }
slouken@1895
   383
}
slouken@1895
   384
slouken@1895
   385
int
slouken@2710
   386
SDL_SendProximity(int id, int x, int y, int type)
slouken@1895
   387
{
slouken@2712
   388
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   389
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   390
    int posted = 0;
slouken@2727
   391
slouken@2727
   392
    if (!mouse) {
slouken@2727
   393
        return 0;
slouken@2727
   394
    }
slouken@2727
   395
slouken@2710
   396
    last_x = x;
slouken@2710
   397
    last_y = y;
slouken@2710
   398
    if (SDL_ProcessEvents[type] == SDL_ENABLE) {
slouken@2710
   399
        SDL_Event event;
slouken@2710
   400
        event.proximity.which = (Uint8) index;
slouken@2710
   401
        event.proximity.x = x;
slouken@2710
   402
        event.proximity.y = y;
slouken@2710
   403
        event.proximity.cursor = mouse->current_end;
slouken@2710
   404
        event.proximity.type = type;
slouken@2710
   405
        posted = (SDL_PushEvent(&event) > 0);
slouken@2710
   406
        if (type == SDL_PROXIMITYIN) {
slouken@2710
   407
            mouse->proximity = SDL_TRUE;
slouken@2710
   408
        } else {
slouken@2710
   409
            mouse->proximity = SDL_FALSE;
slouken@2710
   410
        }
slouken@2710
   411
    }
slouken@2710
   412
    return posted;
slouken@2710
   413
}
slouken@2710
   414
slouken@2710
   415
int
slouken@2710
   416
SDL_SendMouseMotion(int id, int relative, int x, int y, int pressure)
slouken@2710
   417
{
slouken@2712
   418
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   419
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   420
    int posted;
slouken@1895
   421
    int xrel;
slouken@1895
   422
    int yrel;
slouken@1895
   423
slouken@1895
   424
    if (!mouse || mouse->flush_motion) {
slouken@1895
   425
        return 0;
slouken@1895
   426
    }
slouken@1895
   427
slouken@2710
   428
    /* if the mouse is out of proximity we don't to want to have any motion from it */
slouken@2710
   429
    if (mouse->proximity == SDL_FALSE) {
slouken@2710
   430
        last_x = x;
slouken@2710
   431
        last_y = y;
slouken@2710
   432
        return 0;
slouken@1895
   433
    }
slouken@1895
   434
slouken@2710
   435
    /* the relative motion is calculated regarding the system cursor last position */
slouken@2842
   436
    if (relative) {
slouken@2842
   437
        xrel = x;
slouken@2842
   438
        yrel = y;
slouken@2842
   439
        x = (last_x + x);
slouken@2842
   440
        y = (last_y + y);
slouken@2842
   441
    } else {
slouken@2842
   442
        xrel = x - last_x;
slouken@2842
   443
        yrel = y - last_y;
slouken@2842
   444
    }
slouken@2710
   445
slouken@1895
   446
    /* Drop events that don't change state */
slouken@1895
   447
    if (!xrel && !yrel) {
slouken@1895
   448
#if 0
slouken@1895
   449
        printf("Mouse event didn't change state - dropped!\n");
slouken@1895
   450
#endif
slouken@1895
   451
        return 0;
slouken@1895
   452
    }
slouken@1895
   453
slouken@2710
   454
    /* Update internal mouse coordinates */
slouken@2710
   455
    if (mouse->relative_mode == SDL_FALSE) {
slouken@1895
   456
        mouse->x = x;
slouken@1895
   457
        mouse->y = y;
slouken@2710
   458
    } else {
slouken@2794
   459
        /* while using the relative mode and many windows, we have to be
slouken@2794
   460
           sure that the pointers find themselves inside the windows */
slouken@2794
   461
        if (mouse->x + xrel > mouse->x_max) {
slouken@2794
   462
            mouse->x = mouse->x_max;
slouken@2710
   463
        } else if (mouse->x + xrel < 0) {
slouken@2710
   464
            mouse->x = 0;
slouken@2710
   465
        } else {
slouken@2710
   466
            mouse->x += xrel;
slouken@2710
   467
        }
slouken@2794
   468
        if (mouse->y + yrel > mouse->y_max) {
slouken@2794
   469
            mouse->y = mouse->y_max;
slouken@2710
   470
        } else if (mouse->y + yrel < 0) {
slouken@2710
   471
            mouse->y = 0;
slouken@2710
   472
        } else {
slouken@2710
   473
            mouse->y += yrel;
slouken@2710
   474
        }
slouken@1895
   475
    }
slouken@1895
   476
    mouse->xdelta += xrel;
slouken@1895
   477
    mouse->ydelta += yrel;
slouken@2710
   478
    mouse->pressure = pressure;
slouken@1895
   479
slouken@1895
   480
    /* Move the mouse cursor, if needed */
slouken@1895
   481
    if (mouse->cursor_shown && !mouse->relative_mode &&
slouken@1895
   482
        mouse->MoveCursor && mouse->cur_cursor) {
slouken@1895
   483
        mouse->MoveCursor(mouse->cur_cursor);
slouken@1895
   484
    }
slouken@1895
   485
slouken@1895
   486
    /* Post the event, if desired */
slouken@1895
   487
    posted = 0;
slouken@2710
   488
    if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE &&
slouken@2710
   489
        mouse->proximity == SDL_TRUE) {
slouken@1895
   490
        SDL_Event event;
slouken@1895
   491
        event.motion.type = SDL_MOUSEMOTION;
slouken@1895
   492
        event.motion.which = (Uint8) index;
slouken@1895
   493
        event.motion.state = mouse->buttonstate;
slouken@1895
   494
        event.motion.x = mouse->x;
slouken@1895
   495
        event.motion.y = mouse->y;
slouken@2710
   496
        event.motion.pressure = mouse->pressure;
slouken@1895
   497
        event.motion.xrel = xrel;
slouken@1895
   498
        event.motion.yrel = yrel;
slouken@1895
   499
        event.motion.windowID = mouse->focus;
slouken@2710
   500
        event.motion.pressure_max = mouse->pressure_max;
slouken@2710
   501
        event.motion.pressure_min = mouse->pressure_min;
slouken@2710
   502
        event.motion.cursor = mouse->current_end;
slouken@1895
   503
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   504
    }
slouken@2710
   505
    last_x = x;
slouken@2710
   506
    last_y = y;
slouken@1895
   507
    return posted;
slouken@1895
   508
}
slouken@1895
   509
slouken@1895
   510
int
slouken@2710
   511
SDL_SendMouseButton(int id, Uint8 state, Uint8 button)
slouken@1895
   512
{
slouken@2712
   513
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   514
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   515
    int posted;
slouken@1895
   516
    Uint8 type;
slouken@1895
   517
slouken@1895
   518
    if (!mouse) {
slouken@1895
   519
        return 0;
slouken@1895
   520
    }
slouken@1895
   521
slouken@1895
   522
    /* Figure out which event to perform */
slouken@1895
   523
    switch (state) {
slouken@1895
   524
    case SDL_PRESSED:
slouken@1895
   525
        if (mouse->buttonstate & SDL_BUTTON(button)) {
slouken@1895
   526
            /* Ignore this event, no state change */
slouken@1895
   527
            return 0;
slouken@1895
   528
        }
slouken@1895
   529
        type = SDL_MOUSEBUTTONDOWN;
slouken@1895
   530
        mouse->buttonstate |= SDL_BUTTON(button);
slouken@1895
   531
        break;
slouken@1895
   532
    case SDL_RELEASED:
slouken@2725
   533
        if (!(mouse->buttonstate & SDL_BUTTON(button))) {
kazeuser@2718
   534
            /* Ignore this event, no state change */
kazeuser@2718
   535
            return 0;
kazeuser@2718
   536
        }
slouken@1895
   537
        type = SDL_MOUSEBUTTONUP;
slouken@1895
   538
        mouse->buttonstate &= ~SDL_BUTTON(button);
slouken@1895
   539
        break;
slouken@1895
   540
    default:
slouken@1895
   541
        /* Invalid state -- bail */
slouken@1895
   542
        return 0;
slouken@1895
   543
    }
slouken@1895
   544
slouken@1895
   545
    /* Post the event, if desired */
slouken@1895
   546
    posted = 0;
slouken@1895
   547
    if (SDL_ProcessEvents[type] == SDL_ENABLE) {
slouken@1895
   548
        SDL_Event event;
slouken@1895
   549
        event.type = type;
slouken@1895
   550
        event.button.which = (Uint8) index;
slouken@1895
   551
        event.button.state = state;
slouken@1895
   552
        event.button.button = button;
slouken@1895
   553
        event.button.x = mouse->x;
slouken@1895
   554
        event.button.y = mouse->y;
slouken@1895
   555
        event.button.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
int
slouken@2152
   562
SDL_SendMouseWheel(int index, int x, int y)
slouken@1895
   563
{
slouken@1895
   564
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@1895
   565
    int posted;
slouken@1895
   566
slouken@2152
   567
    if (!mouse || (!x && !y)) {
slouken@1895
   568
        return 0;
slouken@1895
   569
    }
slouken@1895
   570
slouken@1895
   571
    /* Post the event, if desired */
slouken@1895
   572
    posted = 0;
slouken@1895
   573
    if (SDL_ProcessEvents[SDL_MOUSEWHEEL] == SDL_ENABLE) {
slouken@1895
   574
        SDL_Event event;
slouken@1895
   575
        event.type = SDL_MOUSEWHEEL;
slouken@1895
   576
        event.wheel.which = (Uint8) index;
slouken@2152
   577
        event.wheel.x = x;
slouken@2152
   578
        event.wheel.y = y;
slouken@1895
   579
        event.wheel.windowID = mouse->focus;
slouken@1895
   580
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   581
    }
slouken@1895
   582
    return posted;
slouken@1895
   583
}
slouken@1895
   584
slouken@1895
   585
void
slouken@1895
   586
SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y)
slouken@1895
   587
{
slouken@1895
   588
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   589
slouken@1895
   590
    if (!mouse) {
slouken@1895
   591
        return;
slouken@1895
   592
    }
slouken@1895
   593
slouken@1895
   594
    if (mouse->WarpMouse) {
slouken@1895
   595
        mouse->WarpMouse(mouse, windowID, x, y);
slouken@1895
   596
    } else {
slouken@1895
   597
        SDL_SetMouseFocus(SDL_current_mouse, windowID);
slouken@2710
   598
        SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0);
slouken@1895
   599
    }
slouken@1895
   600
}
slouken@1895
   601
slouken@1895
   602
SDL_Cursor *
slouken@1895
   603
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
slouken@1895
   604
                 int w, int h, int hot_x, int hot_y)
slouken@1895
   605
{
slouken@1895
   606
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   607
    SDL_Surface *surface;
slouken@1895
   608
    SDL_Cursor *cursor;
slouken@1895
   609
    int x, y;
slouken@1895
   610
    Uint32 *pixel;
slouken@1895
   611
    Uint8 datab, maskb;
slouken@1895
   612
    const Uint32 black = 0xFF000000;
slouken@1895
   613
    const Uint32 white = 0xFFFFFFFF;
slouken@1895
   614
    const Uint32 transparent = 0x00000000;
slouken@1895
   615
slouken@1895
   616
    if (!mouse) {
slouken@1895
   617
        SDL_SetError("No mice are initialized");
slouken@1895
   618
        return NULL;
slouken@1895
   619
    }
slouken@1895
   620
slouken@1895
   621
    if (!mouse->CreateCursor) {
slouken@1895
   622
        SDL_SetError("Current mouse doesn't have cursor support");
slouken@1895
   623
        return NULL;
slouken@1895
   624
    }
slouken@1895
   625
slouken@1895
   626
    /* Sanity check the hot spot */
slouken@1895
   627
    if ((hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h)) {
slouken@1895
   628
        SDL_SetError("Cursor hot spot doesn't lie within cursor");
slouken@1895
   629
        return NULL;
slouken@1895
   630
    }
slouken@1895
   631
slouken@1895
   632
    /* Make sure the width is a multiple of 8 */
slouken@1895
   633
    w = ((w + 7) & ~7);
slouken@1895
   634
slouken@1895
   635
    /* Create the surface from a bitmap */
slouken@1895
   636
    surface =
slouken@1895
   637
        SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
slouken@1895
   638
                             0xFF000000);
slouken@1895
   639
    if (!surface) {
slouken@1895
   640
        return NULL;
slouken@1895
   641
    }
slouken@1895
   642
    for (y = 0; y < h; ++y) {
slouken@1895
   643
        pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
slouken@1895
   644
        for (x = 0; x < w; ++x) {
slouken@1895
   645
            if ((x % 8) == 0) {
slouken@1895
   646
                datab = *data++;
slouken@1895
   647
                maskb = *mask++;
slouken@1895
   648
            }
slouken@1895
   649
            if (maskb & 0x80) {
slouken@1895
   650
                *pixel++ = (datab & 0x80) ? black : white;
slouken@1895
   651
            } else {
slouken@1895
   652
                *pixel++ = (datab & 0x80) ? black : transparent;
slouken@1895
   653
            }
slouken@1895
   654
            datab <<= 1;
slouken@1895
   655
            maskb <<= 1;
slouken@1895
   656
        }
slouken@1895
   657
    }
slouken@1895
   658
slouken@1895
   659
    cursor = mouse->CreateCursor(surface, hot_x, hot_y);
slouken@1895
   660
    if (cursor) {
slouken@1895
   661
        cursor->mouse = mouse;
slouken@1895
   662
        cursor->next = mouse->cursors;
slouken@1895
   663
        mouse->cursors = cursor;
slouken@1895
   664
    }
slouken@1895
   665
slouken@1895
   666
    SDL_FreeSurface(surface);
slouken@1895
   667
slouken@1895
   668
    return cursor;
slouken@1895
   669
}
slouken@1895
   670
slouken@1895
   671
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
slouken@1895
   672
   if this is desired for any reason.  This is used when setting
slouken@1895
   673
   the video mode and when the SDL window gains the mouse focus.
slouken@1895
   674
 */
slouken@1895
   675
void
slouken@1895
   676
SDL_SetCursor(SDL_Cursor * cursor)
slouken@1895
   677
{
slouken@1895
   678
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   679
slouken@1895
   680
    if (!mouse) {
slouken@1895
   681
        SDL_SetError("No mice are initialized");
slouken@1895
   682
        return;
slouken@1895
   683
    }
slouken@1895
   684
slouken@1895
   685
    /* Set the new cursor */
slouken@1895
   686
    if (cursor) {
slouken@1895
   687
        /* Make sure the cursor is still valid for this mouse */
slouken@1895
   688
        SDL_Cursor *found;
slouken@1895
   689
        for (found = mouse->cursors; found; found = found->next) {
slouken@1895
   690
            if (found == cursor) {
slouken@1895
   691
                break;
slouken@1895
   692
            }
slouken@1895
   693
        }
slouken@1895
   694
        if (!found) {
slouken@1895
   695
            SDL_SetError("Cursor not associated with the current mouse");
slouken@1895
   696
            return;
slouken@1895
   697
        }
slouken@1895
   698
        mouse->cur_cursor = cursor;
slouken@1895
   699
    } else {
slouken@1895
   700
        cursor = mouse->cur_cursor;
slouken@1895
   701
    }
slouken@1895
   702
slouken@1895
   703
    if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
slouken@1895
   704
        if (mouse->ShowCursor) {
slouken@1895
   705
            mouse->ShowCursor(cursor);
slouken@1895
   706
        }
slouken@1895
   707
    } else {
slouken@1895
   708
        if (mouse->ShowCursor) {
slouken@1895
   709
            mouse->ShowCursor(NULL);
slouken@1895
   710
        }
slouken@1895
   711
    }
slouken@1895
   712
}
slouken@1895
   713
slouken@1895
   714
SDL_Cursor *
slouken@1895
   715
SDL_GetCursor(void)
slouken@1895
   716
{
slouken@1895
   717
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   718
slouken@1895
   719
    if (!mouse) {
slouken@1895
   720
        return NULL;
slouken@1895
   721
    }
slouken@1895
   722
    return mouse->cur_cursor;
slouken@1895
   723
}
slouken@1895
   724
slouken@1895
   725
void
slouken@1895
   726
SDL_FreeCursor(SDL_Cursor * cursor)
slouken@1895
   727
{
slouken@1895
   728
    SDL_Mouse *mouse;
slouken@1895
   729
    SDL_Cursor *curr, *prev;
slouken@1895
   730
slouken@1895
   731
    if (!cursor) {
slouken@1895
   732
        return;
slouken@1895
   733
    }
slouken@1895
   734
    mouse = cursor->mouse;
slouken@1895
   735
slouken@1895
   736
    if (cursor == mouse->def_cursor) {
slouken@1895
   737
        return;
slouken@1895
   738
    }
slouken@1895
   739
    if (cursor == mouse->cur_cursor) {
slouken@1895
   740
        SDL_SetCursor(mouse->def_cursor);
slouken@1895
   741
    }
slouken@1895
   742
slouken@1895
   743
    for (prev = NULL, curr = mouse->cursors; curr;
slouken@1895
   744
         prev = curr, curr = curr->next) {
slouken@1895
   745
        if (curr == cursor) {
slouken@1895
   746
            if (prev) {
slouken@1895
   747
                prev->next = curr->next;
slouken@1895
   748
            } else {
slouken@1895
   749
                mouse->cursors = curr->next;
slouken@1895
   750
            }
slouken@1895
   751
slouken@1895
   752
            if (mouse->FreeCursor) {
slouken@1895
   753
                mouse->FreeCursor(curr);
slouken@1895
   754
            }
slouken@1895
   755
            return;
slouken@1895
   756
        }
slouken@1895
   757
    }
slouken@1895
   758
}
slouken@1895
   759
slouken@1895
   760
int
slouken@1895
   761
SDL_ShowCursor(int toggle)
slouken@1895
   762
{
slouken@1895
   763
    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
slouken@1895
   764
    SDL_bool shown;
slouken@1895
   765
slouken@1895
   766
    if (!mouse) {
slouken@1895
   767
        return 0;
slouken@1895
   768
    }
slouken@1895
   769
slouken@1895
   770
    shown = mouse->cursor_shown;
slouken@1895
   771
    if (toggle >= 0) {
slouken@1895
   772
        if (toggle) {
slouken@1895
   773
            mouse->cursor_shown = SDL_TRUE;
slouken@1895
   774
        } else {
slouken@1895
   775
            mouse->cursor_shown = SDL_FALSE;
slouken@1895
   776
        }
slouken@1895
   777
        if (mouse->cursor_shown != shown) {
slouken@1895
   778
            SDL_SetCursor(NULL);
slouken@1895
   779
        }
slouken@1895
   780
    }
slouken@1895
   781
    return shown;
slouken@1895
   782
}
slouken@1895
   783
slouken@2710
   784
char *
slouken@2710
   785
SDL_GetMouseName(int index)
slouken@2710
   786
{
slouken@2710
   787
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   788
    if (!mouse) {
slouken@2710
   789
        return NULL;
slouken@2710
   790
    }
slouken@2710
   791
    return mouse->name;
slouken@2710
   792
}
slouken@2710
   793
slouken@2710
   794
void
slouken@2710
   795
SDL_ChangeEnd(int id, int end)
slouken@2710
   796
{
slouken@2712
   797
    int index = SDL_GetMouseIndexId(id);
slouken@2712
   798
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   799
slouken@2710
   800
    if (mouse) {
slouken@2710
   801
        mouse->current_end = end;
slouken@2710
   802
    }
slouken@2710
   803
}
slouken@2710
   804
slouken@2710
   805
int
slouken@2710
   806
SDL_GetCursorsNumber(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->total_ends;
slouken@2710
   814
}
slouken@2710
   815
slouken@2710
   816
int
slouken@2710
   817
SDL_GetCurrentCursor(int index)
slouken@2710
   818
{
slouken@2710
   819
    SDL_Mouse *mouse = SDL_GetMouse(index);
slouken@2710
   820
slouken@2710
   821
    if (!mouse) {
slouken@2710
   822
        return -1;
slouken@2710
   823
    }
slouken@2710
   824
    return mouse->current_end;
slouken@2710
   825
}
slouken@2710
   826
slouken@1895
   827
/* vi: set ts=4 sw=4 expandtab: */