src/video/x11/SDL_x11keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 09 May 2010 20:47:22 -0700
changeset 4465 3e69e077cb95
parent 3697 f7b03b6838cb
child 4535 ce811c9247da
permissions -rw-r--r--
Removed multi-mouse / multi-keyboard support in anticipation of a real multi-mouse and multi-touch API.

Plus, this lets me start implementing cursor support.
slouken@1950
     1
/*
slouken@1950
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@1950
     4
slouken@1950
     5
    This library is free software; you can redistribute it and/or
slouken@1950
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1950
     7
    License as published by the Free Software Foundation; either
slouken@1950
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1950
     9
slouken@1950
    10
    This library is distributed in the hope that it will be useful,
slouken@1950
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1950
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1950
    13
    Lesser General Public License for more details.
slouken@1950
    14
slouken@1950
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1950
    16
    License along with this library; if not, write to the Free Software
slouken@1950
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1950
    18
slouken@1950
    19
    Sam Lantinga
slouken@1950
    20
    slouken@libsdl.org
slouken@1950
    21
*/
slouken@1950
    22
#include "SDL_config.h"
slouken@1950
    23
slouken@1950
    24
#include "SDL_x11video.h"
slouken@1950
    25
slouken@1950
    26
#include "../../events/SDL_keyboard_c.h"
slouken@2305
    27
#include "../../events/scancodes_darwin.h"
slouken@2305
    28
#include "../../events/scancodes_xfree86.h"
slouken@1950
    29
bob@2295
    30
#include <X11/keysym.h>
bob@2295
    31
bob@2295
    32
#include "imKStoUCS.h"
bob@2295
    33
slouken@3001
    34
/* *INDENT-OFF* */
slouken@3162
    35
static const struct {
slouken@3001
    36
    KeySym keysym;
slouken@3001
    37
    SDLKey sdlkey;
slouken@3001
    38
} KeySymToSDLKey[] = {
slouken@3001
    39
    { XK_Return, SDLK_RETURN },
slouken@3001
    40
    { XK_Escape, SDLK_ESCAPE },
slouken@3001
    41
    { XK_BackSpace, SDLK_BACKSPACE },
slouken@3001
    42
    { XK_Tab, SDLK_TAB },
slouken@3001
    43
    { XK_Caps_Lock, SDLK_CAPSLOCK },
slouken@3001
    44
    { XK_F1, SDLK_F1 },
slouken@3001
    45
    { XK_F2, SDLK_F2 },
slouken@3001
    46
    { XK_F3, SDLK_F3 },
slouken@3001
    47
    { XK_F4, SDLK_F4 },
slouken@3001
    48
    { XK_F5, SDLK_F5 },
slouken@3001
    49
    { XK_F6, SDLK_F6 },
slouken@3001
    50
    { XK_F7, SDLK_F7 },
slouken@3001
    51
    { XK_F8, SDLK_F8 },
slouken@3001
    52
    { XK_F9, SDLK_F9 },
slouken@3001
    53
    { XK_F10, SDLK_F10 },
slouken@3001
    54
    { XK_F11, SDLK_F11 },
slouken@3001
    55
    { XK_F12, SDLK_F12 },
slouken@3001
    56
    { XK_Print, SDLK_PRINTSCREEN },
slouken@3001
    57
    { XK_Scroll_Lock, SDLK_SCROLLLOCK },
slouken@3001
    58
    { XK_Pause, SDLK_PAUSE },
slouken@3001
    59
    { XK_Insert, SDLK_INSERT },
slouken@3001
    60
    { XK_Home, SDLK_HOME },
slouken@3001
    61
    { XK_Prior, SDLK_PAGEUP },
slouken@3001
    62
    { XK_Delete, SDLK_DELETE },
slouken@3001
    63
    { XK_End, SDLK_END },
slouken@3001
    64
    { XK_Next, SDLK_PAGEDOWN },
slouken@3001
    65
    { XK_Right, SDLK_RIGHT },
slouken@3001
    66
    { XK_Left, SDLK_LEFT },
slouken@3001
    67
    { XK_Down, SDLK_DOWN },
slouken@3001
    68
    { XK_Up, SDLK_UP },
slouken@3001
    69
    { XK_Num_Lock, SDLK_NUMLOCKCLEAR },
slouken@3001
    70
    { XK_KP_Divide, SDLK_KP_DIVIDE },
slouken@3001
    71
    { XK_KP_Multiply, SDLK_KP_MULTIPLY },
slouken@3001
    72
    { XK_KP_Subtract, SDLK_KP_MINUS },
slouken@3001
    73
    { XK_KP_Add, SDLK_KP_PLUS },
slouken@3001
    74
    { XK_KP_Enter, SDLK_KP_ENTER },
slouken@3001
    75
    { XK_KP_Delete, SDLK_KP_PERIOD },
slouken@3001
    76
    { XK_KP_End, SDLK_KP_1 },
slouken@3001
    77
    { XK_KP_Down, SDLK_KP_2 },
slouken@3001
    78
    { XK_KP_Next, SDLK_KP_3 },
slouken@3001
    79
    { XK_KP_Left, SDLK_KP_4 },
slouken@3001
    80
    { XK_KP_Begin, SDLK_KP_5 },
slouken@3001
    81
    { XK_KP_Right, SDLK_KP_6 },
slouken@3001
    82
    { XK_KP_Home, SDLK_KP_7 },
slouken@3001
    83
    { XK_KP_Up, SDLK_KP_8 },
slouken@3001
    84
    { XK_KP_Prior, SDLK_KP_9 },
slouken@3001
    85
    { XK_KP_Insert, SDLK_KP_0 },
slouken@3001
    86
    { XK_KP_Decimal, SDLK_KP_PERIOD },
slouken@3001
    87
    { XK_KP_1, SDLK_KP_1 },
slouken@3001
    88
    { XK_KP_2, SDLK_KP_2 },
slouken@3001
    89
    { XK_KP_3, SDLK_KP_3 },
slouken@3001
    90
    { XK_KP_4, SDLK_KP_4 },
slouken@3001
    91
    { XK_KP_5, SDLK_KP_5 },
slouken@3001
    92
    { XK_KP_6, SDLK_KP_6 },
slouken@3001
    93
    { XK_KP_7, SDLK_KP_7 },
slouken@3001
    94
    { XK_KP_8, SDLK_KP_8 },
slouken@3001
    95
    { XK_KP_9, SDLK_KP_9 },
slouken@3001
    96
    { XK_KP_0, SDLK_KP_0 },
slouken@3001
    97
    { XK_KP_Decimal, SDLK_KP_PERIOD },
slouken@3001
    98
    { XK_Hyper_R, SDLK_APPLICATION },
slouken@3001
    99
    { XK_KP_Equal, SDLK_KP_EQUALS },
slouken@3001
   100
    { XK_F13, SDLK_F13 },
slouken@3001
   101
    { XK_F14, SDLK_F14 },
slouken@3001
   102
    { XK_F15, SDLK_F15 },
slouken@3001
   103
    { XK_F16, SDLK_F16 },
slouken@3001
   104
    { XK_F17, SDLK_F17 },
slouken@3001
   105
    { XK_F18, SDLK_F18 },
slouken@3001
   106
    { XK_F19, SDLK_F19 },
slouken@3001
   107
    { XK_F20, SDLK_F20 },
slouken@3001
   108
    { XK_F21, SDLK_F21 },
slouken@3001
   109
    { XK_F22, SDLK_F22 },
slouken@3001
   110
    { XK_F23, SDLK_F23 },
slouken@3001
   111
    { XK_F24, SDLK_F24 },
slouken@3001
   112
    { XK_Execute, SDLK_EXECUTE },
slouken@3001
   113
    { XK_Help, SDLK_HELP },
slouken@3001
   114
    { XK_Menu, SDLK_MENU },
slouken@3001
   115
    { XK_Select, SDLK_SELECT },
slouken@3001
   116
    { XK_Cancel, SDLK_STOP },
slouken@3001
   117
    { XK_Redo, SDLK_AGAIN },
slouken@3001
   118
    { XK_Undo, SDLK_UNDO },
slouken@3001
   119
    { XK_Find, SDLK_FIND },
slouken@3001
   120
    { XK_KP_Separator, SDLK_KP_COMMA },
slouken@3001
   121
    { XK_Sys_Req, SDLK_SYSREQ },
slouken@3001
   122
    { XK_Control_L, SDLK_LCTRL },
slouken@3001
   123
    { XK_Shift_L, SDLK_LSHIFT },
slouken@3001
   124
    { XK_Alt_L, SDLK_LALT },
slouken@3001
   125
    { XK_Meta_L, SDLK_LGUI },
slouken@3001
   126
    { XK_Super_L, SDLK_LGUI },
slouken@3001
   127
    { XK_Control_R, SDLK_RCTRL },
slouken@3001
   128
    { XK_Shift_R, SDLK_RSHIFT },
slouken@3001
   129
    { XK_Alt_R, SDLK_RALT },
slouken@3001
   130
    { XK_Meta_R, SDLK_RGUI },
slouken@3001
   131
    { XK_Super_R, SDLK_RGUI },
slouken@3001
   132
    { XK_Mode_switch, SDLK_MODE },
bob@2295
   133
};
bob@2295
   134
slouken@3162
   135
static const struct
bob@2295
   136
{
slouken@3162
   137
    const SDL_scancode const *table;
slouken@2305
   138
    int table_size;
slouken@2305
   139
} scancode_set[] = {
slouken@2308
   140
    { darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
slouken@2308
   141
    { xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
slouken@2825
   142
    { xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
slouken@2308
   143
};
slouken@2308
   144
/* *INDENT-OFF* */
bob@2295
   145
slouken@3001
   146
static SDLKey
slouken@3001
   147
X11_KeyCodeToSDLKey(Display *display, KeyCode keycode)
slouken@3001
   148
{
slouken@3001
   149
    KeySym keysym;
slouken@3001
   150
    unsigned int ucs4;
slouken@3001
   151
    int i;
slouken@3001
   152
slouken@3001
   153
    keysym = XKeycodeToKeysym(display, keycode, 0);
slouken@3001
   154
    if (keysym == NoSymbol) {
slouken@3001
   155
        return SDLK_UNKNOWN;
slouken@3001
   156
    }
slouken@3001
   157
slouken@3001
   158
    ucs4 = X11_KeySymToUcs4(keysym);
slouken@3001
   159
    if (ucs4) {
slouken@3001
   160
        return (SDLKey) ucs4;
slouken@3001
   161
    }
slouken@3001
   162
slouken@3001
   163
    for (i = 0; i < SDL_arraysize(KeySymToSDLKey); ++i) {
slouken@3001
   164
        if (keysym == KeySymToSDLKey[i].keysym) {
slouken@3001
   165
            return KeySymToSDLKey[i].sdlkey;
slouken@3001
   166
        }
slouken@3001
   167
    }
slouken@3001
   168
    return SDLK_UNKNOWN;
slouken@3001
   169
}
slouken@3001
   170
bob@2295
   171
int
slouken@1950
   172
X11_InitKeyboard(_THIS)
slouken@1950
   173
{
slouken@1950
   174
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2305
   175
    int i, j;
slouken@2305
   176
    int min_keycode, max_keycode;
slouken@3001
   177
    struct {
slouken@3001
   178
        SDL_scancode scancode;
slouken@3001
   179
        KeySym keysym;
slouken@3001
   180
        int value;
slouken@3001
   181
    } fingerprint[] = {
slouken@3001
   182
        { SDL_SCANCODE_HOME, XK_Home, 0 },
slouken@3001
   183
        { SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
slouken@3001
   184
        { SDL_SCANCODE_PAGEDOWN, XK_Next, 0 },
slouken@2305
   185
    };
slouken@2305
   186
    SDL_bool fingerprint_detected;
bob@2295
   187
bob@2299
   188
    XAutoRepeatOn(data->display);
bob@2299
   189
slouken@2305
   190
    /* Try to determine which scancodes are being used based on fingerprint */
slouken@2305
   191
    fingerprint_detected = SDL_FALSE;
slouken@2305
   192
    XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
slouken@3001
   193
    for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
slouken@3001
   194
        fingerprint[i].value =
slouken@3001
   195
            XKeysymToKeycode(data->display, fingerprint[i].keysym) -
slouken@2305
   196
            min_keycode;
slouken@2305
   197
    }
slouken@2305
   198
    for (i = 0; i < SDL_arraysize(scancode_set); ++i) {
slouken@2305
   199
        /* Make sure the scancode set isn't too big */
slouken@2305
   200
        if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
slouken@2305
   201
            continue;
slouken@2305
   202
        }
slouken@2305
   203
        for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
slouken@3001
   204
            if (fingerprint[j].value < 0
slouken@3001
   205
                || fingerprint[j].value >= scancode_set[i].table_size) {
slouken@2305
   206
                break;
slouken@2305
   207
            }
slouken@3001
   208
            if (scancode_set[i].table[fingerprint[j].value] !=
slouken@3001
   209
                fingerprint[j].scancode) {
slouken@2305
   210
                break;
slouken@2305
   211
            }
slouken@2305
   212
        }
slouken@2305
   213
        if (j == SDL_arraysize(fingerprint)) {
bob@2323
   214
            /* printf("Using scancode set %d\n", i); */
slouken@2305
   215
            SDL_memcpy(&data->key_layout[min_keycode], scancode_set[i].table,
slouken@2305
   216
                       sizeof(SDL_scancode) * scancode_set[i].table_size);
slouken@2305
   217
            fingerprint_detected = SDL_TRUE;
slouken@2305
   218
            break;
slouken@2305
   219
        }
slouken@2305
   220
    }
bob@2296
   221
slouken@2305
   222
    if (!fingerprint_detected) {
slouken@3001
   223
        SDLKey keymap[SDL_NUM_SCANCODES];
slouken@3001
   224
slouken@2305
   225
        printf
slouken@2305
   226
            ("Keyboard layout unknown, please send the following to the SDL mailing list (sdl@libsdl.org):\n");
slouken@2305
   227
slouken@2305
   228
        /* Determine key_layout - only works on US QWERTY layout */
slouken@3001
   229
        SDL_GetDefaultKeymap(keymap);
slouken@2305
   230
        for (i = min_keycode; i <= max_keycode; ++i) {
slouken@2305
   231
            KeySym sym;
slouken@2305
   232
            sym = XKeycodeToKeysym(data->display, i, 0);
slouken@3001
   233
            if (sym != NoSymbol) {
slouken@3001
   234
                SDLKey key;
icculus@3667
   235
                printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
icculus@3667
   236
                       (unsigned int) sym, XKeysymToString(sym));
slouken@3001
   237
                key = X11_KeyCodeToSDLKey(data->display, i);
slouken@3001
   238
                for (j = 0; j < SDL_arraysize(keymap); ++j) {
slouken@3001
   239
                    if (keymap[j] == key) {
slouken@2305
   240
                        data->key_layout[i] = (SDL_scancode) j;
slouken@2305
   241
                        break;
slouken@2305
   242
                    }
slouken@2305
   243
                }
slouken@3001
   244
                if (j == SDL_arraysize(keymap)) {
slouken@2305
   245
                    printf("scancode not found\n");
slouken@2305
   246
                } else {
slouken@2305
   247
                    printf("scancode = %d (%s)\n", j, SDL_GetScancodeName(j));
slouken@2305
   248
                }
slouken@2305
   249
            }
slouken@2305
   250
        }
slouken@2305
   251
    }
slouken@1950
   252
slouken@2306
   253
    X11_UpdateKeymap(_this);
bob@2295
   254
slouken@2305
   255
    SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
bob@2295
   256
bob@2295
   257
    return 0;
bob@2295
   258
}
bob@2295
   259
slouken@2305
   260
void
slouken@2305
   261
X11_UpdateKeymap(_THIS)
bob@2295
   262
{
bob@2295
   263
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2305
   264
    int i;
slouken@2305
   265
    SDL_scancode scancode;
slouken@2305
   266
    SDLKey keymap[SDL_NUM_SCANCODES];
bob@2295
   267
slouken@3001
   268
    SDL_zero(keymap);
bob@2295
   269
slouken@2305
   270
    for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
slouken@2305
   271
slouken@3001
   272
        /* Make sure this is a valid scancode */
slouken@2305
   273
        scancode = data->key_layout[i];
slouken@3001
   274
        if (scancode == SDL_SCANCODE_UNKNOWN) {
slouken@2305
   275
            continue;
slouken@2305
   276
        }
slouken@2305
   277
slouken@3001
   278
        keymap[scancode] = X11_KeyCodeToSDLKey(data->display, (KeyCode)i);
bob@2295
   279
    }
slouken@4465
   280
    SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
slouken@1950
   281
}
slouken@1950
   282
slouken@1950
   283
void
slouken@1950
   284
X11_QuitKeyboard(_THIS)
slouken@1950
   285
{
slouken@1950
   286
}
slouken@1950
   287
slouken@1950
   288
/* vi: set ts=4 sw=4 expandtab: */