diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-02-22 14:44:42 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-02-22 14:44:42 +0000 |
commit | 0ce9cb913e32d7efed64dc1191a7a490d97cf56e (patch) | |
tree | 6f4031e47f540b0c3e7a6543b860f261a1384433 | |
parent | ff8689611a1d954897d857b28f7ef404e11cfa2c (diff) | |
parent | abb4f2c9655503f14dc55064f29c4f59b07e96ff (diff) |
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180222-pull-request' into staging
ui: reverse keymap improvements.
sdl2: hotkey fix.
opengl: dmabuf fixes.
# gpg: Signature made Thu 22 Feb 2018 10:22:58 GMT
# gpg: using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* remotes/kraxel/tags/ui-20180222-pull-request:
keymap: consider modifier state when picking a mapping
keymap: record multiple keysym -> keycode mappings
keymap: numpad keysyms and keycodes are fixed
keymap: use glib hash for kbd_layout_t
keymap: make struct kbd_layout_t private to ui/keymaps.c
egl-helpers: add alpha channel to texture format
egl-headless: cursor_dmabuf: handle NULL cursor
console/opengl: split up dpy_gl_cursor ops
sdl2: fix hotkey keyup
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | include/ui/console.h | 13 | ||||
-rw-r--r-- | ui/console.c | 18 | ||||
-rw-r--r-- | ui/curses.c | 3 | ||||
-rw-r--r-- | ui/egl-headless.c | 30 | ||||
-rw-r--r-- | ui/egl-helpers.c | 2 | ||||
-rw-r--r-- | ui/keymaps.c | 163 | ||||
-rw-r--r-- | ui/keymaps.h | 30 | ||||
-rw-r--r-- | ui/sdl.c | 6 | ||||
-rw-r--r-- | ui/sdl2.c | 14 | ||||
-rw-r--r-- | ui/trace-events | 2 | ||||
-rw-r--r-- | ui/vnc.c | 9 |
11 files changed, 151 insertions, 139 deletions
diff --git a/include/ui/console.h b/include/ui/console.h index e6b1227bef..f29bacd625 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -230,8 +230,10 @@ typedef struct DisplayChangeListenerOps { void (*dpy_gl_scanout_dmabuf)(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf); void (*dpy_gl_cursor_dmabuf)(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf, - uint32_t pos_x, uint32_t pos_y); + QemuDmaBuf *dmabuf, bool have_hot, + uint32_t hot_x, uint32_t hot_y); + void (*dpy_gl_cursor_position)(DisplayChangeListener *dcl, + uint32_t pos_x, uint32_t pos_y); void (*dpy_gl_release_dmabuf)(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf); void (*dpy_gl_update)(DisplayChangeListener *dcl, @@ -304,9 +306,10 @@ void dpy_gl_scanout_texture(QemuConsole *con, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void dpy_gl_scanout_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); -void dpy_gl_cursor_dmabuf(QemuConsole *con, - QemuDmaBuf *dmabuf, - uint32_t pos_x, uint32_t pos_y); +void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, + bool have_hot, uint32_t hot_x, uint32_t hot_y); +void dpy_gl_cursor_position(QemuConsole *con, + uint32_t pos_x, uint32_t pos_y); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/ui/console.c b/ui/console.c index 36584d039e..e22931a396 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1760,14 +1760,24 @@ void dpy_gl_scanout_dmabuf(QemuConsole *con, con->gl->ops->dpy_gl_scanout_dmabuf(con->gl, dmabuf); } -void dpy_gl_cursor_dmabuf(QemuConsole *con, - QemuDmaBuf *dmabuf, - uint32_t pos_x, uint32_t pos_y) +void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, + bool have_hot, uint32_t hot_x, uint32_t hot_y) { assert(con->gl); if (con->gl->ops->dpy_gl_cursor_dmabuf) { - con->gl->ops->dpy_gl_cursor_dmabuf(con->gl, dmabuf, pos_x, pos_y); + con->gl->ops->dpy_gl_cursor_dmabuf(con->gl, dmabuf, + have_hot, hot_x, hot_y); + } +} + +void dpy_gl_cursor_position(QemuConsole *con, + uint32_t pos_x, uint32_t pos_y) +{ + assert(con->gl); + + if (con->gl->ops->dpy_gl_cursor_position) { + con->gl->ops->dpy_gl_cursor_position(con->gl, pos_x, pos_y); } } diff --git a/ui/curses.c b/ui/curses.c index 479b77bd03..597e47fd4a 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -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; diff --git a/ui/egl-headless.c b/ui/egl-headless.c index 38b3766548..b33e0b21fd 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -84,21 +84,30 @@ static void egl_scanout_dmabuf(DisplayChangeListener *dcl, } static void egl_cursor_dmabuf(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf, - uint32_t pos_x, uint32_t pos_y) + QemuDmaBuf *dmabuf, bool have_hot, + uint32_t hot_x, uint32_t hot_y) { egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); - edpy->pos_x = pos_x; - edpy->pos_y = pos_y; - - egl_dmabuf_import_texture(dmabuf); - if (!dmabuf->texture) { - return; + if (dmabuf) { + egl_dmabuf_import_texture(dmabuf); + if (!dmabuf->texture) { + return; + } + egl_fb_setup_for_tex(&edpy->cursor_fb, dmabuf->width, dmabuf->height, + dmabuf->texture, false); + } else { + egl_fb_destroy(&edpy->cursor_fb); } +} - egl_fb_setup_for_tex(&edpy->cursor_fb, dmabuf->width, dmabuf->height, - dmabuf->texture, false); +static void egl_cursor_position(DisplayChangeListener *dcl, + uint32_t pos_x, uint32_t pos_y) +{ + egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); + + edpy->pos_x = pos_x; + edpy->pos_y = pos_y; } static void egl_release_dmabuf(DisplayChangeListener *dcl, @@ -150,6 +159,7 @@ static const DisplayChangeListenerOps egl_ops = { .dpy_gl_scanout_texture = egl_scanout_texture, .dpy_gl_scanout_dmabuf = egl_scanout_dmabuf, .dpy_gl_cursor_dmabuf = egl_cursor_dmabuf, + .dpy_gl_cursor_position = egl_cursor_position, .dpy_gl_release_dmabuf = egl_release_dmabuf, .dpy_gl_update = egl_scanout_flush, }; diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 5fa60ef4e8..16dc3ded36 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -83,7 +83,7 @@ void egl_fb_setup_new_tex(egl_fb *fb, int width, int height) glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0); egl_fb_setup_for_tex(fb, width, height, texture, true); diff --git a/ui/keymaps.c b/ui/keymaps.c index f9762d1497..43fe604724 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -28,6 +28,15 @@ #include "trace.h" #include "qemu/error-report.h" +struct keysym2code { + uint32_t count; + uint16_t keycodes[4]; +}; + +struct kbd_layout_t { + GHashTable *hash; +}; + static int get_keysym(const name2keysym_t *table, const char *name) { @@ -48,46 +57,26 @@ static int get_keysym(const name2keysym_t *table, } -static void add_to_key_range(struct key_range **krp, int code) { - struct key_range *kr; - for (kr = *krp; kr; kr = kr->next) { - if (code >= kr->start && code <= kr->end) { - break; - } - if (code == kr->start - 1) { - kr->start--; - break; - } - if (code == kr->end + 1) { - kr->end++; - break; - } - } - if (kr == NULL) { - kr = g_malloc0(sizeof(*kr)); - kr->start = kr->end = code; - kr->next = *krp; - *krp = kr; - } -} +static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k) +{ + struct keysym2code *keysym2code; -static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k) { - if (keysym < MAX_NORMAL_KEYCODE) { - trace_keymap_add("normal", keysym, keycode, line); - k->keysym2keycode[keysym] = keycode; - } else { - if (k->extra_count >= MAX_EXTRA_COUNT) { - warn_report("Could not assign keysym %s (0x%x)" - " because of memory constraints.", line, keysym); + keysym2code = g_hash_table_lookup(k->hash, GINT_TO_POINTER(keysym)); + if (keysym2code) { + if (keysym2code->count < ARRAY_SIZE(keysym2code->keycodes)) { + keysym2code->keycodes[keysym2code->count++] = keycode; } else { - trace_keymap_add("extra", keysym, keycode, line); - k->keysym2keycode_extra[k->extra_count]. - keysym = keysym; - k->keysym2keycode_extra[k->extra_count]. - keycode = keycode; - k->extra_count++; + warn_report("more than %zd keycodes for keysym %d", + ARRAY_SIZE(keysym2code->keycodes), keysym); } + return; } + + keysym2code = g_new0(struct keysym2code, 1); + keysym2code->keycodes[0] = keycode; + keysym2code->count = 1; + g_hash_table_replace(k->hash, GINT_TO_POINTER(keysym), keysym2code); + trace_keymap_add(keysym, keycode, line); } static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, @@ -111,6 +100,7 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, if (!k) { k = g_new0(kbd_layout_t, 1); + k->hash = g_hash_table_new(NULL, NULL); } for(;;) { @@ -147,13 +137,6 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, const char *rest = line + offset + 1; int keycode = strtol(rest, NULL, 0); - if (strstr(rest, "numlock")) { - add_to_key_range(&k->keypad_range, keycode); - add_to_key_range(&k->numlock_range, keysym); - /* fprintf(stderr, "keypad keysym %04x keycode %d\n", - keysym, keycode); */ - } - if (strstr(rest, "shift")) { keycode |= SCANCODE_SHIFT; } @@ -186,59 +169,79 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, } -void *init_keyboard_layout(const name2keysym_t *table, const char *language) +kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, + const char *language) { return parse_keyboard_layout(table, language, NULL); } -int keysym2scancode(void *kbd_layout, int keysym) +int keysym2scancode(kbd_layout_t *k, int keysym, + bool shift, bool altgr, bool ctrl) { - kbd_layout_t *k = kbd_layout; - if (keysym < MAX_NORMAL_KEYCODE) { - if (k->keysym2keycode[keysym] == 0) { - trace_keymap_unmapped(keysym); - warn_report("no scancode found for keysym %d", keysym); - } - return k->keysym2keycode[keysym]; - } else { - int i; + static const uint32_t mask = + SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL; + uint32_t mods, i; + struct keysym2code *keysym2code; + #ifdef XK_ISO_Left_Tab - if (keysym == XK_ISO_Left_Tab) { - keysym = XK_Tab; - } + if (keysym == XK_ISO_Left_Tab) { + keysym = XK_Tab; + } #endif - for (i = 0; i < k->extra_count; i++) { - if (k->keysym2keycode_extra[i].keysym == keysym) { - return k->keysym2keycode_extra[i].keycode; - } - } + + keysym2code = g_hash_table_lookup(k->hash, GINT_TO_POINTER(keysym)); + if (!keysym2code) { + trace_keymap_unmapped(keysym); + warn_report("no scancode found for keysym %d", keysym); + return 0; } - return 0; -} -int keycode_is_keypad(void *kbd_layout, int keycode) -{ - kbd_layout_t *k = kbd_layout; - struct key_range *kr; + 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 (kr = k->keypad_range; kr; kr = kr->next) { - if (keycode >= kr->start && keycode <= kr->end) { - return 1; + for (i = 0; i < keysym2code->count; i++) { + if ((keysym2code->keycodes[i] & mask) == mods) { + return keysym2code->keycodes[i]; } } - return 0; + return keysym2code->keycodes[0]; } -int keysym_is_numlock(void *kbd_layout, int keysym) +int keycode_is_keypad(kbd_layout_t *k, int keycode) { - kbd_layout_t *k = kbd_layout; - struct key_range *kr; + if (keycode >= 0x47 && keycode <= 0x53) { + return true; + } + return false; +} - for (kr = k->numlock_range; kr; kr = kr->next) { - if (keysym >= kr->start && keysym <= kr->end) { - return 1; - } +int keysym_is_numlock(kbd_layout_t *k, int keysym) +{ + switch (keysym) { + case 0xffb0 ... 0xffb9: /* KP_0 .. KP_9 */ + case 0xffac: /* KP_Separator */ + case 0xffae: /* KP_Decimal */ + return true; } - return 0; + return false; } diff --git a/ui/keymaps.h b/ui/keymaps.h index 8757465529..0693588225 100644 --- a/ui/keymaps.h +++ b/ui/keymaps.h @@ -32,25 +32,6 @@ typedef struct { int keysym; } name2keysym_t; -struct key_range { - int start; - int end; - struct key_range *next; -}; - -#define MAX_NORMAL_KEYCODE 512 -#define MAX_EXTRA_COUNT 256 -typedef struct { - uint16_t keysym2keycode[MAX_NORMAL_KEYCODE]; - struct { - int keysym; - uint16_t keycode; - } keysym2keycode_extra[MAX_EXTRA_COUNT]; - int extra_count; - struct key_range *keypad_range; - struct key_range *numlock_range; -} kbd_layout_t; - /* scancode without modifiers */ #define SCANCODE_KEYMASK 0xff /* scancode without grey or up bit */ @@ -69,10 +50,13 @@ typedef struct { #define SCANCODE_ALT 0x400 #define SCANCODE_ALTGR 0x800 +typedef struct kbd_layout_t kbd_layout_t; -void *init_keyboard_layout(const name2keysym_t *table, const char *language); -int keysym2scancode(void *kbd_layout, int keysym); -int keycode_is_keypad(void *kbd_layout, int keycode); -int keysym_is_numlock(void *kbd_layout, int keysym); +kbd_layout_t *init_keyboard_layout(const name2keysym_t *table, + const char *language); +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); #endif /* QEMU_KEYMAPS_H */ @@ -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; } @@ -39,7 +39,6 @@ static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ static int gui_saved_grab; static int gui_fullscreen; -static int gui_key_modifier_pressed; static int gui_keysym; static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; static SDL_Cursor *sdl_cursor_normal; @@ -331,8 +330,7 @@ static void handle_keydown(SDL_Event *ev) { int win; struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); - - gui_key_modifier_pressed = get_mod_state(); + int gui_key_modifier_pressed = get_mod_state(); if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repeat) { switch (ev->key.keysym.scancode) { @@ -413,18 +411,12 @@ static void handle_keydown(SDL_Event *ev) static void handle_keyup(SDL_Event *ev) { - int mod_state; struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + int gui_key_modifier_pressed = get_mod_state(); scon->ignore_hotkeys = false; - if (!alt_grab) { - mod_state = (ev->key.keysym.mod & gui_grab_code); - } else { - mod_state = (ev->key.keysym.mod & (gui_grab_code | KMOD_LSHIFT)); - } - if (!mod_state && gui_key_modifier_pressed) { - gui_key_modifier_pressed = 0; + if (!gui_key_modifier_pressed) { gui_keysym = 0; } if (!gui_keysym) { diff --git a/ui/trace-events b/ui/trace-events index 34229e6747..861b68a305 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -78,7 +78,7 @@ qemu_spice_create_update(uint32_t left, uint32_t right, uint32_t top, uint32_t b # ui/keymaps.c keymap_parse(const char *file) "file %s" -keymap_add(const char *type, int sym, int code, const char *line) "%-6s sym=0x%04x code=0x%04x (line: %s)" +keymap_add(int sym, int code, const char *line) "sym=0x%04x code=0x%04x (line: %s)" keymap_unmapped(int sym) "sym=0x%04x" # ui/x_keymap.c @@ -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); } |