src/joystick/SDL_joystick.c
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Wed, 05 Jun 2013 15:11:38 -0700
changeset 7279 f7805b13b485
parent 7191 75360622e65f
child 7294 0923de98a63a
permissions -rw-r--r--
Joystick: Only send joy events when focused.

This changes makes it so that you only receive joystick (and implicitly
gamecontroller) input events when your application has keyboard focus.
If you'd like to still receive events when your application is in the
background, set the SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS hint to "1".

This fixes http://bugzilla.libsdl.org/show_bug.cgi?id=1892
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@0
    22
slouken@0
    23
/* This is the joystick API for Simple DirectMedia Layer */
slouken@0
    24
slouken@0
    25
#include "SDL_events.h"
slouken@1361
    26
#include "SDL_sysjoystick.h"
icculus@5861
    27
#include "SDL_assert.h"
jorgen@7279
    28
#include "SDL_hints.h"
icculus@5861
    29
slouken@1361
    30
#if !SDL_EVENTS_DISABLED
slouken@1361
    31
#include "../events/SDL_events_c.h"
slouken@0
    32
#endif
slouken@0
    33
slouken@6712
    34
static SDL_Joystick *SDL_joysticks = NULL;
slouken@6712
    35
static SDL_Joystick *SDL_updating_joystick = NULL;
slouken@0
    36
slouken@1895
    37
int
slouken@1895
    38
SDL_JoystickInit(void)
slouken@0
    39
{
slouken@1895
    40
    int status;
slouken@0
    41
slouken@1895
    42
    status = SDL_SYS_JoystickInit();
slouken@1895
    43
    if (status >= 0) {
slouken@6690
    44
      status = 0;
slouken@1895
    45
    }
slouken@1895
    46
    return (status);
slouken@0
    47
}
slouken@0
    48
slouken@0
    49
/*
slouken@0
    50
 * Count the number of joysticks attached to the system
slouken@0
    51
 */
slouken@1895
    52
int
slouken@1895
    53
SDL_NumJoysticks(void)
slouken@0
    54
{
slouken@6690
    55
    return SDL_SYS_NumJoysticks();
slouken@0
    56
}
slouken@0
    57
slouken@0
    58
/*
slouken@0
    59
 * Get the implementation dependent name of a joystick
slouken@0
    60
 */
slouken@1895
    61
const char *
slouken@6690
    62
SDL_JoystickNameForIndex(int device_index)
slouken@0
    63
{
slouken@6690
    64
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@6690
    65
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@1895
    66
        return (NULL);
slouken@1895
    67
    }
slouken@6707
    68
    return (SDL_SYS_JoystickNameForDeviceIndex(device_index));
slouken@0
    69
}
slouken@0
    70
slouken@0
    71
/*
slouken@0
    72
 * Open a joystick for use - the index passed as an argument refers to
slouken@0
    73
 * the N'th joystick on the system.  This index is the value which will
slouken@0
    74
 * identify this joystick in future joystick events.
slouken@0
    75
 *
slouken@0
    76
 * This function returns a joystick identifier, or NULL if an error occurred.
slouken@0
    77
 */
slouken@1895
    78
SDL_Joystick *
slouken@1895
    79
SDL_JoystickOpen(int device_index)
slouken@0
    80
{
slouken@1895
    81
    SDL_Joystick *joystick;
slouken@7191
    82
    SDL_Joystick *joysticklist;
slouken@7191
    83
    const char *joystickname = NULL;
slouken@0
    84
slouken@6690
    85
    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
slouken@6690
    86
        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
slouken@1895
    87
        return (NULL);
slouken@1895
    88
    }
slouken@0
    89
slouken@7191
    90
    joysticklist = SDL_joysticks;
slouken@7191
    91
    /* If the joystick is already open, return it
slouken@7191
    92
    * it is important that we have a single joystick * for each instance id
slouken@7191
    93
    */
slouken@7191
    94
    while ( joysticklist )
slouken@7191
    95
    {
slouken@7191
    96
        if ( SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id ) {
slouken@7191
    97
                joystick = joysticklist;
slouken@7191
    98
                ++joystick->ref_count;
slouken@7191
    99
                return (joystick);
slouken@7191
   100
        }
slouken@7191
   101
        joysticklist = joysticklist->next;
slouken@1895
   102
    }
slouken@0
   103
slouken@1895
   104
    /* Create and initialize the joystick */
slouken@1895
   105
    joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
icculus@3608
   106
    if (joystick == NULL) {
icculus@3608
   107
        SDL_OutOfMemory();
icculus@3608
   108
        return NULL;
slouken@1895
   109
    }
icculus@3608
   110
icculus@3608
   111
    SDL_memset(joystick, 0, (sizeof *joystick));
slouken@6690
   112
    if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
icculus@3608
   113
        SDL_free(joystick);
icculus@3608
   114
        return NULL;
slouken@1895
   115
    }
slouken@6690
   116
slouken@7191
   117
    joystickname = SDL_SYS_JoystickNameForDeviceIndex( device_index );
slouken@7191
   118
    if ( joystickname )
slouken@7191
   119
        joystick->name = SDL_strdup( joystickname );
slouken@7191
   120
    else
slouken@7191
   121
        joystick->name = NULL;
slouken@6690
   122
icculus@3608
   123
    if (joystick->naxes > 0) {
icculus@3608
   124
        joystick->axes = (Sint16 *) SDL_malloc
icculus@3608
   125
            (joystick->naxes * sizeof(Sint16));
icculus@3608
   126
    }
icculus@3608
   127
    if (joystick->nhats > 0) {
icculus@3608
   128
        joystick->hats = (Uint8 *) SDL_malloc
icculus@3608
   129
            (joystick->nhats * sizeof(Uint8));
icculus@3608
   130
    }
icculus@3608
   131
    if (joystick->nballs > 0) {
icculus@3608
   132
        joystick->balls = (struct balldelta *) SDL_malloc
icculus@3608
   133
            (joystick->nballs * sizeof(*joystick->balls));
icculus@3608
   134
    }
icculus@3608
   135
    if (joystick->nbuttons > 0) {
icculus@3608
   136
        joystick->buttons = (Uint8 *) SDL_malloc
icculus@3608
   137
            (joystick->nbuttons * sizeof(Uint8));
icculus@3608
   138
    }
icculus@3608
   139
    if (((joystick->naxes > 0) && !joystick->axes)
icculus@3608
   140
        || ((joystick->nhats > 0) && !joystick->hats)
icculus@3608
   141
        || ((joystick->nballs > 0) && !joystick->balls)
icculus@3608
   142
        || ((joystick->nbuttons > 0) && !joystick->buttons)) {
icculus@3608
   143
        SDL_OutOfMemory();
icculus@3608
   144
        SDL_JoystickClose(joystick);
icculus@3608
   145
        return NULL;
icculus@3608
   146
    }
icculus@3608
   147
    if (joystick->axes) {
icculus@3608
   148
        SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
icculus@3608
   149
    }
icculus@3608
   150
    if (joystick->hats) {
icculus@3608
   151
        SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
icculus@3608
   152
    }
icculus@3608
   153
    if (joystick->balls) {
icculus@3608
   154
        SDL_memset(joystick->balls, 0,
icculus@3608
   155
            joystick->nballs * sizeof(*joystick->balls));
icculus@3608
   156
    }
icculus@3608
   157
    if (joystick->buttons) {
icculus@3608
   158
        SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
icculus@3608
   159
    }
icculus@3608
   160
icculus@3608
   161
    /* Add joystick to list */
icculus@3608
   162
    ++joystick->ref_count;
slouken@7191
   163
    /* Link the joystick in the list */
slouken@7191
   164
    joystick->next = SDL_joysticks;
slouken@7191
   165
    SDL_joysticks = joystick;
slouken@6690
   166
slouken@7191
   167
    SDL_SYS_JoystickUpdate( joystick );
icculus@3608
   168
slouken@1895
   169
    return (joystick);
slouken@0
   170
}
slouken@0
   171
slouken@2713
   172
slouken@2713
   173
/*
slouken@2713
   174
 * Checks to make sure the joystick is valid.
slouken@2713
   175
 */
slouken@2713
   176
int
slouken@6690
   177
SDL_PrivateJoystickValid(SDL_Joystick * joystick)
slouken@0
   178
{
slouken@1895
   179
    int valid;
slouken@0
   180
slouken@6690
   181
    if ( joystick == NULL ) {
slouken@1895
   182
        SDL_SetError("Joystick hasn't been opened yet");
slouken@1895
   183
        valid = 0;
slouken@1895
   184
    } else {
slouken@1895
   185
        valid = 1;
slouken@1895
   186
    }
slouken@7191
   187
slouken@7191
   188
    if ( joystick && joystick->closed )
slouken@7191
   189
    {
slouken@7191
   190
        valid = 0;
slouken@7191
   191
    }
slouken@7191
   192
slouken@1895
   193
    return valid;
slouken@0
   194
}
slouken@0
   195
slouken@0
   196
/*
slouken@0
   197
 * Get the number of multi-dimensional axis controls on a joystick
slouken@0
   198
 */
slouken@1895
   199
int
slouken@1895
   200
SDL_JoystickNumAxes(SDL_Joystick * joystick)
slouken@0
   201
{
slouken@6690
   202
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   203
        return (-1);
slouken@1895
   204
    }
slouken@1895
   205
    return (joystick->naxes);
slouken@0
   206
}
slouken@0
   207
slouken@0
   208
/*
slouken@0
   209
 * Get the number of hats on a joystick
slouken@0
   210
 */
slouken@1895
   211
int
slouken@1895
   212
SDL_JoystickNumHats(SDL_Joystick * joystick)
slouken@0
   213
{
slouken@6690
   214
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   215
        return (-1);
slouken@1895
   216
    }
slouken@1895
   217
    return (joystick->nhats);
slouken@0
   218
}
slouken@0
   219
slouken@0
   220
/*
slouken@0
   221
 * Get the number of trackballs on a joystick
slouken@0
   222
 */
slouken@1895
   223
int
slouken@1895
   224
SDL_JoystickNumBalls(SDL_Joystick * joystick)
slouken@0
   225
{
slouken@6690
   226
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   227
        return (-1);
slouken@1895
   228
    }
slouken@1895
   229
    return (joystick->nballs);
slouken@0
   230
}
slouken@0
   231
slouken@0
   232
/*
slouken@0
   233
 * Get the number of buttons on a joystick
slouken@0
   234
 */
slouken@1895
   235
int
slouken@1895
   236
SDL_JoystickNumButtons(SDL_Joystick * joystick)
slouken@0
   237
{
slouken@6690
   238
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   239
        return (-1);
slouken@1895
   240
    }
slouken@1895
   241
    return (joystick->nbuttons);
slouken@0
   242
}
slouken@0
   243
slouken@0
   244
/*
slouken@0
   245
 * Get the current state of an axis control on a joystick
slouken@0
   246
 */
slouken@1895
   247
Sint16
slouken@1895
   248
SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
slouken@0
   249
{
slouken@1895
   250
    Sint16 state;
slouken@0
   251
slouken@6690
   252
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   253
        return (0);
slouken@1895
   254
    }
slouken@1895
   255
    if (axis < joystick->naxes) {
slouken@1895
   256
        state = joystick->axes[axis];
slouken@1895
   257
    } else {
slouken@1895
   258
        SDL_SetError("Joystick only has %d axes", joystick->naxes);
slouken@1895
   259
        state = 0;
slouken@1895
   260
    }
slouken@1895
   261
    return (state);
slouken@0
   262
}
slouken@0
   263
slouken@0
   264
/*
slouken@0
   265
 * Get the current state of a hat on a joystick
slouken@0
   266
 */
slouken@1895
   267
Uint8
slouken@1895
   268
SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
slouken@0
   269
{
slouken@1895
   270
    Uint8 state;
slouken@0
   271
slouken@6690
   272
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   273
        return (0);
slouken@1895
   274
    }
slouken@1895
   275
    if (hat < joystick->nhats) {
slouken@1895
   276
        state = joystick->hats[hat];
slouken@1895
   277
    } else {
slouken@1895
   278
        SDL_SetError("Joystick only has %d hats", joystick->nhats);
slouken@1895
   279
        state = 0;
slouken@1895
   280
    }
slouken@1895
   281
    return (state);
slouken@0
   282
}
slouken@0
   283
slouken@0
   284
/*
slouken@0
   285
 * Get the ball axis change since the last poll
slouken@0
   286
 */
slouken@1895
   287
int
slouken@1895
   288
SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
slouken@0
   289
{
slouken@1895
   290
    int retval;
slouken@0
   291
slouken@6690
   292
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   293
        return (-1);
slouken@1895
   294
    }
slouken@0
   295
slouken@1895
   296
    retval = 0;
slouken@1895
   297
    if (ball < joystick->nballs) {
slouken@1895
   298
        if (dx) {
slouken@1895
   299
            *dx = joystick->balls[ball].dx;
slouken@1895
   300
        }
slouken@1895
   301
        if (dy) {
slouken@1895
   302
            *dy = joystick->balls[ball].dy;
slouken@1895
   303
        }
slouken@1895
   304
        joystick->balls[ball].dx = 0;
slouken@1895
   305
        joystick->balls[ball].dy = 0;
slouken@1895
   306
    } else {
icculus@7037
   307
        return SDL_SetError("Joystick only has %d balls", joystick->nballs);
slouken@1895
   308
    }
slouken@1895
   309
    return (retval);
slouken@0
   310
}
slouken@0
   311
slouken@0
   312
/*
slouken@0
   313
 * Get the current state of a button on a joystick
slouken@0
   314
 */
slouken@1895
   315
Uint8
slouken@1895
   316
SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
slouken@0
   317
{
slouken@1895
   318
    Uint8 state;
slouken@0
   319
slouken@6690
   320
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@1895
   321
        return (0);
slouken@1895
   322
    }
slouken@1895
   323
    if (button < joystick->nbuttons) {
slouken@1895
   324
        state = joystick->buttons[button];
slouken@1895
   325
    } else {
slouken@1895
   326
        SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
slouken@1895
   327
        state = 0;
slouken@1895
   328
    }
slouken@1895
   329
    return (state);
slouken@0
   330
}
slouken@0
   331
slouken@0
   332
/*
slouken@6690
   333
 * Return if the joystick in question is currently attached to the system,
slouken@6690
   334
 *  \return 0 if not plugged in, 1 if still present.
slouken@6690
   335
 */
slouken@6707
   336
SDL_bool
slouken@6707
   337
SDL_JoystickGetAttached(SDL_Joystick * joystick)
slouken@6690
   338
{
slouken@7191
   339
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6707
   340
        return SDL_FALSE;
slouken@6690
   341
    }
slouken@6690
   342
slouken@7191
   343
    return SDL_SYS_JoystickAttached(joystick);
slouken@6690
   344
}
slouken@6690
   345
slouken@6690
   346
/*
slouken@6690
   347
 * Get the instance id for this opened joystick
slouken@6690
   348
 */
slouken@7191
   349
SDL_JoystickID
slouken@6707
   350
SDL_JoystickInstanceID(SDL_Joystick * joystick)
slouken@6690
   351
{
slouken@7191
   352
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6690
   353
        return (-1);
slouken@6690
   354
    }
slouken@6690
   355
slouken@7191
   356
    return (joystick->instance_id);
slouken@6690
   357
}
slouken@6690
   358
slouken@6690
   359
/*
slouken@6690
   360
 * Get the friendly name of this joystick
slouken@6690
   361
 */
slouken@6690
   362
const char *
slouken@6690
   363
SDL_JoystickName(SDL_Joystick * joystick)
slouken@6690
   364
{
slouken@6690
   365
    if (!SDL_PrivateJoystickValid(joystick)) {
slouken@6690
   366
        return (NULL);
slouken@6690
   367
    }
slouken@7191
   368
slouken@6690
   369
    return (joystick->name);
slouken@6690
   370
}
slouken@6690
   371
slouken@6690
   372
/*
slouken@0
   373
 * Close a joystick previously opened with SDL_JoystickOpen()
slouken@0
   374
 */
slouken@1895
   375
void
slouken@1895
   376
SDL_JoystickClose(SDL_Joystick * joystick)
slouken@0
   377
{
slouken@7191
   378
    SDL_Joystick *joysticklist;
slouken@7191
   379
    SDL_Joystick *joysticklistprev;
slouken@0
   380
slouken@6690
   381
    if (!joystick) {
slouken@1895
   382
        return;
slouken@1895
   383
    }
slouken@0
   384
slouken@1895
   385
    /* First decrement ref count */
slouken@1895
   386
    if (--joystick->ref_count > 0) {
slouken@1895
   387
        return;
slouken@1895
   388
    }
slouken@0
   389
slouken@6712
   390
    if (joystick == SDL_updating_joystick) {
slouken@6712
   391
        return;
slouken@6712
   392
    }
slouken@6712
   393
slouken@1895
   394
    SDL_SYS_JoystickClose(joystick);
slouken@0
   395
slouken@7191
   396
    joysticklist = SDL_joysticks;
slouken@7191
   397
    joysticklistprev = NULL;
slouken@7191
   398
    while ( joysticklist )
slouken@7191
   399
    {
slouken@7191
   400
        if (joystick == joysticklist)
slouken@7191
   401
        {
slouken@7191
   402
            if ( joysticklistprev )
slouken@7191
   403
            {
slouken@7191
   404
                /* unlink this entry */
slouken@7191
   405
                joysticklistprev->next = joysticklist->next;
slouken@7191
   406
            }
slouken@7191
   407
            else
slouken@7191
   408
            {
slouken@7191
   409
                SDL_joysticks = joystick->next;
slouken@7191
   410
            }
slouken@7191
   411
slouken@7191
   412
            break;
slouken@7191
   413
        }
slouken@7191
   414
        joysticklistprev = joysticklist;
slouken@7191
   415
        joysticklist = joysticklist->next;
slouken@7191
   416
    }
slouken@7191
   417
slouken@7191
   418
    if (joystick->name)
slouken@7191
   419
        SDL_free(joystick->name);
slouken@0
   420
slouken@1895
   421
    /* Free the data associated with this joystick */
slouken@1895
   422
    if (joystick->axes) {
slouken@1895
   423
        SDL_free(joystick->axes);
slouken@1895
   424
    }
slouken@1895
   425
    if (joystick->hats) {
slouken@1895
   426
        SDL_free(joystick->hats);
slouken@1895
   427
    }
slouken@1895
   428
    if (joystick->balls) {
slouken@1895
   429
        SDL_free(joystick->balls);
slouken@1895
   430
    }
slouken@1895
   431
    if (joystick->buttons) {
slouken@1895
   432
        SDL_free(joystick->buttons);
slouken@1895
   433
    }
slouken@1895
   434
    SDL_free(joystick);
slouken@0
   435
}
slouken@0
   436
slouken@1895
   437
void
slouken@1895
   438
SDL_JoystickQuit(void)
slouken@0
   439
{
slouken@6712
   440
    /* Make sure we're not getting called in the middle of updating joysticks */
slouken@6712
   441
    SDL_assert(!SDL_updating_joystick);
slouken@6712
   442
slouken@1895
   443
    /* Stop the event polling */
slouken@7191
   444
    while ( SDL_joysticks )
slouken@7191
   445
    {
slouken@7191
   446
        SDL_joysticks->ref_count = 1;
slouken@6690
   447
        SDL_JoystickClose(SDL_joysticks);
slouken@7191
   448
    }
icculus@5856
   449
slouken@1895
   450
    /* Quit the joystick setup */
slouken@1895
   451
    SDL_SYS_JoystickQuit();
slouken@0
   452
}
slouken@0
   453
slouken@0
   454
jorgen@7279
   455
static SDL_bool
jorgen@7279
   456
SDL_PrivateJoystickShouldIgnoreEvent()
jorgen@7279
   457
{
jorgen@7279
   458
    const char *hint;
jorgen@7279
   459
    if (SDL_GetKeyboardFocus() != NULL) {
jorgen@7279
   460
        return SDL_FALSE;
jorgen@7279
   461
    }
jorgen@7279
   462
jorgen@7279
   463
    hint = SDL_GetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS);
jorgen@7279
   464
    if (hint && *hint == '1') {
jorgen@7279
   465
        return SDL_FALSE;
jorgen@7279
   466
    }
jorgen@7279
   467
jorgen@7279
   468
    return SDL_TRUE;
jorgen@7279
   469
}
jorgen@7279
   470
slouken@0
   471
/* These are global for SDL_sysjoystick.c and SDL_events.c */
slouken@0
   472
slouken@1895
   473
int
slouken@1895
   474
SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
slouken@0
   475
{
slouken@1895
   476
    int posted;
slouken@0
   477
slouken@6145
   478
    /* Make sure we're not getting garbage events */
slouken@6145
   479
    if (axis >= joystick->naxes) {
slouken@6145
   480
        return 0;
slouken@6145
   481
    }
slouken@6145
   482
slouken@1895
   483
    /* Update internal joystick state */
slouken@6735
   484
    if (value == joystick->axes[axis]) {
slouken@6735
   485
        return 0;
slouken@6735
   486
    }
slouken@1895
   487
    joystick->axes[axis] = value;
slouken@0
   488
jorgen@7279
   489
    /* We ignore events if we don't have keyboard focus, except for centering
jorgen@7279
   490
     * events.
jorgen@7279
   491
     */
jorgen@7279
   492
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   493
        if (!(joystick->closed && joystick->uncentered)) {
jorgen@7279
   494
            return 0;
jorgen@7279
   495
        }
jorgen@7279
   496
    }
jorgen@7279
   497
slouken@1895
   498
    /* Post the event, if desired */
slouken@1895
   499
    posted = 0;
slouken@1361
   500
#if !SDL_EVENTS_DISABLED
slouken@4429
   501
    if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
slouken@1895
   502
        SDL_Event event;
slouken@1895
   503
        event.type = SDL_JOYAXISMOTION;
slouken@6690
   504
        event.jaxis.which = joystick->instance_id;
slouken@1895
   505
        event.jaxis.axis = axis;
slouken@1895
   506
        event.jaxis.value = value;
slouken@6690
   507
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   508
    }
slouken@1361
   509
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   510
    return (posted);
slouken@0
   511
}
slouken@0
   512
slouken@1895
   513
int
slouken@1895
   514
SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
slouken@0
   515
{
slouken@1895
   516
    int posted;
slouken@0
   517
slouken@6145
   518
    /* Make sure we're not getting garbage events */
slouken@6145
   519
    if (hat >= joystick->nhats) {
slouken@6145
   520
        return 0;
slouken@6145
   521
    }
slouken@6145
   522
slouken@1895
   523
    /* Update internal joystick state */
slouken@1895
   524
    joystick->hats[hat] = value;
slouken@0
   525
jorgen@7279
   526
    /* We ignore events if we don't have keyboard focus, except for centering
jorgen@7279
   527
     * events.
jorgen@7279
   528
     */
jorgen@7279
   529
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   530
        if (!(joystick->closed && joystick->uncentered)) {
jorgen@7279
   531
            return 0;
jorgen@7279
   532
        }
jorgen@7279
   533
    }
jorgen@7279
   534
jorgen@7279
   535
slouken@1895
   536
    /* Post the event, if desired */
slouken@1895
   537
    posted = 0;
slouken@1361
   538
#if !SDL_EVENTS_DISABLED
slouken@4429
   539
    if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
slouken@1895
   540
        SDL_Event event;
slouken@1895
   541
        event.jhat.type = SDL_JOYHATMOTION;
slouken@6690
   542
        event.jhat.which = joystick->instance_id;
slouken@1895
   543
        event.jhat.hat = hat;
slouken@1895
   544
        event.jhat.value = value;
slouken@6690
   545
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   546
    }
slouken@1361
   547
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   548
    return (posted);
slouken@0
   549
}
slouken@0
   550
slouken@1895
   551
int
slouken@1895
   552
SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
slouken@1895
   553
                        Sint16 xrel, Sint16 yrel)
slouken@0
   554
{
slouken@1895
   555
    int posted;
slouken@0
   556
slouken@6145
   557
    /* Make sure we're not getting garbage events */
slouken@6145
   558
    if (ball >= joystick->nballs) {
slouken@6145
   559
        return 0;
slouken@6145
   560
    }
slouken@6145
   561
jorgen@7279
   562
    /* We ignore events if we don't have keyboard focus. */
jorgen@7279
   563
    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
jorgen@7279
   564
        return 0;
jorgen@7279
   565
    }
jorgen@7279
   566
slouken@1895
   567
    /* Update internal mouse state */
slouken@1895
   568
    joystick->balls[ball].dx += xrel;
slouken@1895
   569
    joystick->balls[ball].dy += yrel;
slouken@0
   570
slouken@1895
   571
    /* Post the event, if desired */
slouken@1895
   572
    posted = 0;
slouken@1361
   573
#if !SDL_EVENTS_DISABLED
slouken@4429
   574
    if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
slouken@1895
   575
        SDL_Event event;
slouken@1895
   576
        event.jball.type = SDL_JOYBALLMOTION;
slouken@6690
   577
        event.jball.which = joystick->instance_id;
slouken@1895
   578
        event.jball.ball = ball;
slouken@1895
   579
        event.jball.xrel = xrel;
slouken@1895
   580
        event.jball.yrel = yrel;
slouken@6690
   581
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   582
    }
slouken@1361
   583
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   584
    return (posted);
slouken@0
   585
}
slouken@0
   586
slouken@1895
   587
int
slouken@1895
   588
SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
slouken@0
   589
{
slouken@1895
   590
    int posted;
slouken@1361
   591
#if !SDL_EVENTS_DISABLED
slouken@1895
   592
    SDL_Event event;
slouken@0
   593
slouken@1895
   594
    switch (state) {
slouken@1895
   595
    case SDL_PRESSED:
slouken@1895
   596
        event.type = SDL_JOYBUTTONDOWN;
slouken@1895
   597
        break;
slouken@1895
   598
    case SDL_RELEASED:
slouken@1895
   599
        event.type = SDL_JOYBUTTONUP;
slouken@1895
   600
        break;
slouken@1895
   601
    default:
slouken@1895
   602
        /* Invalid state -- bail */
slouken@1895
   603
        return (0);
slouken@1895
   604
    }
slouken@1361
   605
#endif /* !SDL_EVENTS_DISABLED */
slouken@0
   606
slouken@6145
   607
    /* Make sure we're not getting garbage events */
slouken@6145
   608
    if (button >= joystick->nbuttons) {
slouken@6145
   609
        return 0;
slouken@6145
   610
    }
slouken@6145
   611
jorgen@7279
   612
    /* We ignore events if we don't have keyboard focus, except for button
jorgen@7279
   613
     * release. */
jorgen@7279
   614
    if (SDL_PrivateJoystickShouldIgnoreEvent() && event.type == SDL_JOYBUTTONDOWN) {
jorgen@7279
   615
        return 0;
jorgen@7279
   616
    }
jorgen@7279
   617
slouken@1895
   618
    /* Update internal joystick state */
slouken@1895
   619
    joystick->buttons[button] = state;
slouken@0
   620
slouken@1895
   621
    /* Post the event, if desired */
slouken@1895
   622
    posted = 0;
slouken@1361
   623
#if !SDL_EVENTS_DISABLED
slouken@4429
   624
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@6690
   625
        event.jbutton.which = joystick->instance_id;
slouken@1895
   626
        event.jbutton.button = button;
slouken@1895
   627
        event.jbutton.state = state;
slouken@6690
   628
        posted = SDL_PushEvent(&event) == 1;
slouken@1895
   629
    }
slouken@1361
   630
#endif /* !SDL_EVENTS_DISABLED */
slouken@1895
   631
    return (posted);
slouken@0
   632
}
slouken@0
   633
slouken@1895
   634
void
slouken@1895
   635
SDL_JoystickUpdate(void)
slouken@0
   636
{
slouken@7191
   637
    SDL_Joystick *joystick;
slouken@7191
   638
slouken@7191
   639
    joystick = SDL_joysticks;
slouken@7191
   640
    while ( joystick )
slouken@7191
   641
    {
slouken@7191
   642
        SDL_Joystick *joysticknext;
slouken@7191
   643
        /* save off the next pointer, the Update call may cause a joystick removed event
slouken@7191
   644
         * and cause our joystick pointer to be freed
slouken@7191
   645
         */
slouken@7191
   646
        joysticknext = joystick->next;
slouken@0
   647
slouken@6712
   648
        SDL_updating_joystick = joystick;
slouken@6712
   649
slouken@6690
   650
        SDL_SYS_JoystickUpdate( joystick );
slouken@6690
   651
slouken@7191
   652
        if ( joystick->closed && joystick->uncentered )
slouken@7191
   653
        {
slouken@7191
   654
            int i;
slouken@6690
   655
slouken@6712
   656
            /* Tell the app that everything is centered/unpressed...  */
slouken@6690
   657
            for (i = 0; i < joystick->naxes; i++)
slouken@6690
   658
                SDL_PrivateJoystickAxis(joystick, i, 0);
slouken@6690
   659
slouken@6690
   660
            for (i = 0; i < joystick->nbuttons; i++)
slouken@6690
   661
                SDL_PrivateJoystickButton(joystick, i, 0);
slouken@6690
   662
slouken@6690
   663
            for (i = 0; i < joystick->nhats; i++)
slouken@6690
   664
                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
slouken@6712
   665
jorgen@7279
   666
            joystick->uncentered = 0;
slouken@7191
   667
        }
slouken@6690
   668
slouken@6712
   669
        SDL_updating_joystick = NULL;
slouken@6712
   670
slouken@6712
   671
        /* If the joystick was closed while updating, free it here */
slouken@6712
   672
        if ( joystick->ref_count <= 0 ) {
slouken@6712
   673
            SDL_JoystickClose(joystick);
slouken@6712
   674
        }
slouken@6712
   675
slouken@7191
   676
        joystick = joysticknext;
slouken@7191
   677
    }
slouken@6690
   678
slouken@7191
   679
    /* this needs to happen AFTER walking the joystick list above, so that any
slouken@7191
   680
       dangling hardware data from removed devices can be free'd
slouken@7191
   681
     */
slouken@7191
   682
    SDL_SYS_JoystickDetect();
slouken@0
   683
}
slouken@0
   684
slouken@1895
   685
int
slouken@1895
   686
SDL_JoystickEventState(int state)
slouken@0
   687
{
slouken@1361
   688
#if SDL_EVENTS_DISABLED
slouken@6753
   689
    return SDL_DISABLE;
slouken@0
   690
#else
slouken@4429
   691
    const Uint32 event_list[] = {
slouken@1895
   692
        SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
slouken@6690
   693
        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
slouken@1895
   694
    };
slouken@1895
   695
    unsigned int i;
slouken@0
   696
slouken@1895
   697
    switch (state) {
slouken@1895
   698
    case SDL_QUERY:
slouken@6753
   699
        state = SDL_DISABLE;
slouken@1895
   700
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
   701
            state = SDL_EventState(event_list[i], SDL_QUERY);
slouken@1895
   702
            if (state == SDL_ENABLE) {
slouken@1895
   703
                break;
slouken@1895
   704
            }
slouken@1895
   705
        }
slouken@1895
   706
        break;
slouken@1895
   707
    default:
slouken@1895
   708
        for (i = 0; i < SDL_arraysize(event_list); ++i) {
slouken@1895
   709
            SDL_EventState(event_list[i], state);
slouken@1895
   710
        }
slouken@1895
   711
        break;
slouken@1895
   712
    }
slouken@1895
   713
    return (state);
slouken@1361
   714
#endif /* SDL_EVENTS_DISABLED */
slouken@0
   715
}
slouken@1895
   716
slouken@6690
   717
/* return 1 if you want to run the joystick update loop this frame, used by hotplug support */
slouken@7191
   718
SDL_bool
slouken@6690
   719
SDL_PrivateJoystickNeedsPolling()
slouken@6690
   720
{
slouken@7191
   721
    if (SDL_joysticks != NULL) {
slouken@7191
   722
        return SDL_TRUE;
slouken@7191
   723
    } else {
slouken@7191
   724
        return SDL_SYS_JoystickNeedsPolling();
slouken@7191
   725
    }
slouken@6690
   726
}
slouken@6690
   727
slouken@6690
   728
slouken@6693
   729
/* return the guid for this index */
slouken@6738
   730
SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
slouken@6690
   731
{
slouken@7191
   732
    return SDL_SYS_JoystickGetDeviceGUID( device_index );
slouken@6690
   733
}
slouken@6690
   734
slouken@6693
   735
/* return the guid for this opened device */
slouken@6738
   736
SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6690
   737
{
slouken@7191
   738
    return SDL_SYS_JoystickGetGUID( joystick );
slouken@6690
   739
}
slouken@6690
   740
slouken@6690
   741
/* convert the guid to a printable string */
slouken@6738
   742
void SDL_JoystickGetGUIDString( SDL_JoystickGUID guid, char *pszGUID, int cbGUID )
slouken@6690
   743
{
slouken@7191
   744
    static const char k_rgchHexToASCII[] = "0123456789abcdef";
slouken@7191
   745
    int i;
slouken@6690
   746
icculus@6748
   747
    if ((pszGUID == NULL) || (cbGUID <= 0)) {
icculus@6748
   748
        return;
icculus@6748
   749
    }
icculus@6748
   750
slouken@7191
   751
    for ( i = 0; i < sizeof(guid.data) && i < (cbGUID-1); i++ )
slouken@7191
   752
    {
slouken@7191
   753
        /* each input byte writes 2 ascii chars, and might write a null byte. */
slouken@7191
   754
        /* If we don't have room for next input byte, stop */
slouken@7191
   755
        unsigned char c = guid.data[i];
slouken@6690
   756
slouken@7191
   757
        *pszGUID++ = k_rgchHexToASCII[ c >> 4 ];
slouken@7191
   758
        *pszGUID++ = k_rgchHexToASCII[ c & 0x0F ];
slouken@7191
   759
    }
slouken@7191
   760
    *pszGUID = '\0';
slouken@6690
   761
}
slouken@6690
   762
slouken@6690
   763
slouken@7191
   764
/*-----------------------------------------------------------------------------
slouken@7191
   765
 * Purpose: Returns the 4 bit nibble for a hex character
slouken@7191
   766
 * Input  : c -
slouken@7191
   767
 * Output : unsigned char
slouken@7191
   768
 *-----------------------------------------------------------------------------*/
slouken@6690
   769
static unsigned char nibble( char c )
slouken@6690
   770
{
slouken@7191
   771
    if ( ( c >= '0' ) &&
slouken@7191
   772
        ( c <= '9' ) )
slouken@7191
   773
    {
slouken@7191
   774
        return (unsigned char)(c - '0');
slouken@7191
   775
    }
slouken@6690
   776
slouken@7191
   777
    if ( ( c >= 'A' ) &&
slouken@7191
   778
        ( c <= 'F' ) )
slouken@7191
   779
    {
slouken@7191
   780
        return (unsigned char)(c - 'A' + 0x0a);
slouken@7191
   781
    }
slouken@6690
   782
slouken@7191
   783
    if ( ( c >= 'a' ) &&
slouken@7191
   784
        ( c <= 'f' ) )
slouken@7191
   785
    {
slouken@7191
   786
        return (unsigned char)(c - 'a' + 0x0a);
slouken@7191
   787
    }
slouken@6690
   788
slouken@7191
   789
    /* received an invalid character, and no real way to return an error */
slouken@7191
   790
    /* AssertMsg1( false, "Q_nibble invalid hex character '%c' ", c ); */
slouken@7191
   791
    return 0;
slouken@6690
   792
}
slouken@6690
   793
slouken@6690
   794
slouken@6690
   795
/* convert the string version of a joystick guid to the struct */
slouken@6738
   796
SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
slouken@6690
   797
{
slouken@7191
   798
    SDL_JoystickGUID guid;
slouken@7191
   799
    int maxoutputbytes= sizeof(guid);
slouken@7191
   800
    int len = SDL_strlen( pchGUID );
slouken@7191
   801
    Uint8 *p;
slouken@7191
   802
    int i;
slouken@6690
   803
slouken@7191
   804
    /* Make sure it's even */
slouken@7191
   805
    len = ( len ) & ~0x1;
slouken@6690
   806
slouken@7191
   807
    SDL_memset( &guid, 0x00, sizeof(guid) );
slouken@6690
   808
slouken@7191
   809
    p = (Uint8 *)&guid;
slouken@7191
   810
    for ( i = 0;
slouken@7191
   811
        ( i < len ) && ( ( p - (Uint8 *)&guid ) < maxoutputbytes );
slouken@7191
   812
        i+=2, p++ )
slouken@7191
   813
    {
slouken@7191
   814
        *p = ( nibble( pchGUID[i] ) << 4 ) | nibble( pchGUID[i+1] );
slouken@7191
   815
    }
slouken@6690
   816
slouken@7191
   817
    return guid;
slouken@6690
   818
}
slouken@6690
   819
slouken@6690
   820
slouken@1895
   821
/* vi: set ts=4 sw=4 expandtab: */