Commit abb4f2c9 authored by Gerd Hoffmann's avatar Gerd Hoffmann
Browse files

keymap: consider modifier state when picking a mapping



Pass the modifier state to the keymap lookup function.  In case multiple
keysym -> keycode mappings exist look at the modifier state and prefer
the mapping where the modifier state matches.

Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Reviewed-by: default avatarDaniel P. Berrangé <berrange@redhat.com>
Message-id: 20180222070513.8740-6-kraxel@redhat.com
parent 23ad24e4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -271,7 +271,8 @@ static void curses_refresh(DisplayChangeListener *dcl)
                    keysym = chr;
            }

            keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK);
            keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK,
                                      false, false, false);
            if (keycode == 0)
                continue;

+32 −1
Original line number Diff line number Diff line
@@ -176,8 +176,12 @@ kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
}


int keysym2scancode(kbd_layout_t *k, int keysym)
int keysym2scancode(kbd_layout_t *k, int keysym,
                    bool shift, bool altgr, bool ctrl)
{
    static const uint32_t mask =
        SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL;
    uint32_t mods, i;
    struct keysym2code *keysym2code;

#ifdef XK_ISO_Left_Tab
@@ -193,6 +197,33 @@ int keysym2scancode(kbd_layout_t *k, int keysym)
        return 0;
    }

    if (keysym2code->count == 1) {
        return keysym2code->keycodes[0];
    }

    /*
     * We have multiple keysym -> keycode mappings.
     *
     * Check whenever we find one mapping where the modifier state of
     * the mapping matches the current user interface modifier state.
     * If so, prefer that one.
     */
    mods = 0;
    if (shift) {
        mods |= SCANCODE_SHIFT;
    }
    if (altgr) {
        mods |= SCANCODE_ALTGR;
    }
    if (ctrl) {
        mods |= SCANCODE_CTRL;
    }

    for (i = 0; i < keysym2code->count; i++) {
        if ((keysym2code->keycodes[i] & mask) == mods) {
            return keysym2code->keycodes[i];
        }
    }
    return keysym2code->keycodes[0];
}

+2 −1
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ typedef struct kbd_layout_t kbd_layout_t;

kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
                                   const char *language);
int keysym2scancode(kbd_layout_t *k, int keysym);
int keysym2scancode(kbd_layout_t *k, int keysym,
                    bool shift, bool altgr, bool ctrl);
int keycode_is_keypad(kbd_layout_t *k, int keycode);
int keysym_is_numlock(kbd_layout_t *k, int keysym);

+5 −1
Original line number Diff line number Diff line
@@ -201,6 +201,9 @@ static kbd_layout_t *kbd_layout = NULL;

static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
{
    bool shift = modifiers_state[0x2a] || modifiers_state[0x36];
    bool altgr = modifiers_state[0xb8];
    bool ctrl  = modifiers_state[0x1d] || modifiers_state[0x9d];
    int keysym;
    /* workaround for X11+SDL bug with AltGR */
    keysym = ev->keysym.sym;
@@ -210,7 +213,8 @@ static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
    if (keysym == 92 && ev->keysym.scancode == 133) {
        keysym = 0xa5;
    }
    return keysym2scancode(kbd_layout, keysym) & SCANCODE_KEYMASK;
    return keysym2scancode(kbd_layout, keysym,
                           shift, altgr, ctrl) & SCANCODE_KEYMASK;
}


+7 −2
Original line number Diff line number Diff line
@@ -1734,7 +1734,8 @@ static void reset_keys(VncState *vs)

static void press_key(VncState *vs, int keysym)
{
    int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
    int keycode = keysym2scancode(vs->vd->kbd_layout, keysym,
                                  false, false, false) & SCANCODE_KEYMASK;
    qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
    qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
    qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
@@ -1993,6 +1994,9 @@ static const char *code2name(int keycode)

static void key_event(VncState *vs, int down, uint32_t sym)
{
    bool shift = vs->modifiers_state[0x2a] || vs->modifiers_state[0x36];
    bool altgr = vs->modifiers_state[0xb8];
    bool ctrl  = vs->modifiers_state[0x1d] || vs->modifiers_state[0x9d];
    int keycode;
    int lsym = sym;

@@ -2000,7 +2004,8 @@ static void key_event(VncState *vs, int down, uint32_t sym)
        lsym = lsym - 'A' + 'a';
    }

    keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
    keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF,
                              shift, altgr, ctrl) & SCANCODE_KEYMASK;
    trace_vnc_key_event_map(down, sym, keycode, code2name(keycode));
    do_key_event(vs, down, keycode, sym);
}