Esempio n. 1
0
KeySym
X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group)
{
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    KeySym keysym;

#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    if (data->xkb) {
        int num_groups     = XkbKeyNumGroups(data->xkb, keycode);
        unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
        
        if (num_groups && group >= num_groups) {
        
            int action = XkbOutOfRangeGroupAction(info);
            
            if (action == XkbRedirectIntoRange) {
                if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) {
                    group = 0;
                }
            } else if (action == XkbClampIntoRange) {
                group = num_groups - 1;
            } else {
                group %= num_groups;
            }
        }
        keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
    } else {
        keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
    }
#else
    keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
#endif

    return keysym;
}
/* This function only works for keyboards in US QWERTY layout */
static SDL_Scancode
X11_KeyCodeToSDLScancode(Display *display, KeyCode keycode)
{
    KeySym keysym;
    int i;

#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
#else
    keysym = X11_XKeycodeToKeysym(display, keycode, 0);
#endif
    if (keysym == NoSymbol) {
        return SDL_SCANCODE_UNKNOWN;
    }

    if (keysym >= XK_A && keysym <= XK_Z) {
        return SDL_SCANCODE_A + (keysym - XK_A);
    }

    if (keysym >= XK_0 && keysym <= XK_9) {
        return SDL_SCANCODE_0 + (keysym - XK_0);
    }

    for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
        if (keysym == KeySymToSDLScancode[i].keysym) {
            return KeySymToSDLScancode[i].scancode;
        }
    }
    return SDL_SCANCODE_UNKNOWN;
}
static Uint32
X11_KeyCodeToUcs4(Display *display, KeyCode keycode)
{
    KeySym keysym;

#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
#else
    keysym = X11_XKeycodeToKeysym(display, keycode, 0);
#endif
    if (keysym == NoSymbol) {
        return 0;
    }

    return X11_KeySymToUcs4(keysym);
}
int
X11_InitKeyboard(_THIS)
{
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    int i = 0;
    int j = 0;
    int min_keycode, max_keycode;
    struct {
        SDL_Scancode scancode;
        KeySym keysym;
        int value;
    } fingerprint[] = {
        { SDL_SCANCODE_HOME, XK_Home, 0 },
        { SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
        { SDL_SCANCODE_UP, XK_Up, 0 },
        { SDL_SCANCODE_LEFT, XK_Left, 0 },
        { SDL_SCANCODE_DELETE, XK_Delete, 0 },
        { SDL_SCANCODE_KP_ENTER, XK_KP_Enter, 0 },
    };
    int best_distance;
    int best_index;
    int distance;

    X11_XAutoRepeatOn(data->display);

    /* Try to determine which scancodes are being used based on fingerprint */
    best_distance = SDL_arraysize(fingerprint) + 1;
    best_index = -1;
    X11_XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
    for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
        fingerprint[i].value =
            X11_XKeysymToKeycode(data->display, fingerprint[i].keysym) -
            min_keycode;
    }
    for (i = 0; i < SDL_arraysize(scancode_set); ++i) {
        /* Make sure the scancode set isn't too big */
        if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
            continue;
        }
        distance = 0;
        for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
            if (fingerprint[j].value < 0
                || fingerprint[j].value >= scancode_set[i].table_size) {
                distance += 1;
            } else if (scancode_set[i].table[fingerprint[j].value] != fingerprint[j].scancode) {
                distance += 1;
            }
        }
        if (distance < best_distance) {
            best_distance = distance;
            best_index = i;
        }
    }
    if (best_index >= 0 && best_distance <= 2) {
#ifdef DEBUG_KEYBOARD
        printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", best_index, min_keycode, max_keycode, scancode_set[best_index].table_size);
#endif
        SDL_memcpy(&data->key_layout[min_keycode], scancode_set[best_index].table,
                   sizeof(SDL_Scancode) * scancode_set[best_index].table_size);
    } else {
        SDL_Keycode keymap[SDL_NUM_SCANCODES];

        printf
            ("Keyboard layout unknown, please send the following to the SDL mailing list ([email protected]):\n");

        /* Determine key_layout - only works on US QWERTY layout */
        SDL_GetDefaultKeymap(keymap);
        for (i = min_keycode; i <= max_keycode; ++i) {
            KeySym sym;
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
            sym = X11_XkbKeycodeToKeysym(data->display, i, 0, 0);
#else
            sym = X11_XKeycodeToKeysym(data->display, i, 0);
#endif
            if (sym != NoSymbol) {
                SDL_Scancode scancode;
                printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
                       (unsigned int) sym, X11_XKeysymToString(sym));
                scancode = X11_KeyCodeToSDLScancode(data->display, i);
                data->key_layout[i] = scancode;
                if (scancode == SDL_SCANCODE_UNKNOWN) {
                    printf("scancode not found\n");
                } else {
                    printf("scancode = %d (%s)\n", scancode, SDL_GetScancodeName(scancode));
                }
            }
        }
    }

    X11_UpdateKeymap(_this);

    SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");

#ifdef SDL_USE_IBUS
    SDL_IBus_Init();
#endif

    return 0;
}