[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] Fix curses interaction with keymaps
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH] Fix curses interaction with keymaps |
Date: |
Sat, 6 Mar 2010 23:20:06 +0100 |
User-agent: |
Mutt/1.5.20 (2009-06-14) |
On Sun, Feb 28, 2010 at 09:03:00PM +0100, Samuel Thibault wrote:
> Hello,
>
> The combination of keymap support (-k option) and curses is currently
> very broken. The patch below fixes it by first extending keymap support
> to interpret the shift, ctrl, altgr and addupper keywords in keymaps,
> and to fix curses into properly using keymaps.
>
> Samuel
>
> Signed-off-by: Samuel Thibault <address@hidden>
>
> commit 36f0635cb65e1735a7e231d609da98efcda756c5
> Author: Samuel Thibault <address@hidden>
> Date: Sun Feb 28 20:48:39 2010 +0100
>
> Fix curses with -k option
Thanks, applied.
> diff --git a/curses.c b/curses.c
> index 3ce12b9..4b5beac 100644
> --- a/curses.c
> +++ b/curses.c
> @@ -159,11 +159,10 @@ static void curses_cursor_position(DisplayState *ds,
> int x, int y)
> #include "curses_keys.h"
>
> static kbd_layout_t *kbd_layout = NULL;
> -static int keycode2keysym[CURSES_KEYS];
>
> static void curses_refresh(DisplayState *ds)
> {
> - int chr, nextchr, keysym, keycode;
> + int chr, nextchr, keysym, keycode, keycode_alt;
>
> if (invalidate) {
> clear();
> @@ -204,43 +203,58 @@ static void curses_refresh(DisplayState *ds)
> #endif
>
> keycode = curses2keycode[chr];
> - if (keycode == -1)
> - continue;
> + keycode_alt = 0;
>
> /* alt key */
> if (keycode == 1) {
> nextchr = getch();
>
> if (nextchr != ERR) {
> + chr = nextchr;
> + keycode_alt = ALT;
> keycode = curses2keycode[nextchr];
> nextchr = ERR;
> - if (keycode == -1)
> - continue;
>
> - keycode |= ALT;
> + if (keycode != -1) {
> + keycode |= ALT;
>
> - /* process keys reserved for qemu */
> - if (keycode >= QEMU_KEY_CONSOLE0 &&
> - keycode < QEMU_KEY_CONSOLE0 + 9) {
> - erase();
> - wnoutrefresh(stdscr);
> - console_select(keycode - QEMU_KEY_CONSOLE0);
> + /* process keys reserved for qemu */
> + if (keycode >= QEMU_KEY_CONSOLE0 &&
> + keycode < QEMU_KEY_CONSOLE0 + 9) {
> + erase();
> + wnoutrefresh(stdscr);
> + console_select(keycode - QEMU_KEY_CONSOLE0);
>
> - invalidate = 1;
> - continue;
> + invalidate = 1;
> + continue;
> + }
> }
> }
> }
>
> - if (kbd_layout && !(keycode & GREY)) {
> - keysym = keycode2keysym[keycode & KEY_MASK];
> - if (keysym == -1)
> - keysym = chr;
> + if (kbd_layout) {
> + keysym = -1;
> + if (chr < CURSES_KEYS)
> + keysym = curses2keysym[chr];
> +
> + if (keysym == -1) {
> + if (chr < ' ')
> + keysym = (chr + '@' - 'A' + 'a') | KEYSYM_CNTRL;
> + else
> + keysym = chr;
> + }
>
> - keycode &= ~KEY_MASK;
> - keycode |= keysym2scancode(kbd_layout, keysym);
> + keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK);
> + if (keycode == 0)
> + continue;
> +
> + keycode |= (keysym & ~KEYSYM_MASK) >> 16;
> + keycode |= keycode_alt;
> }
>
> + if (keycode == -1)
> + continue;
> +
> if (is_graphic_console()) {
> /* since terminals don't know about key press and release
> * events, we need to emit both for each key received */
> @@ -250,12 +264,20 @@ static void curses_refresh(DisplayState *ds)
> kbd_put_keycode(CNTRL_CODE);
> if (keycode & ALT)
> kbd_put_keycode(ALT_CODE);
> + if (keycode & ALTGR) {
> + kbd_put_keycode(SCANCODE_EMUL0);
> + kbd_put_keycode(ALT_CODE);
> + }
> if (keycode & GREY)
> kbd_put_keycode(GREY_CODE);
> kbd_put_keycode(keycode & KEY_MASK);
> if (keycode & GREY)
> kbd_put_keycode(GREY_CODE);
> kbd_put_keycode((keycode & KEY_MASK) | KEY_RELEASE);
> + if (keycode & ALTGR) {
> + kbd_put_keycode(SCANCODE_EMUL0);
> + kbd_put_keycode(ALT_CODE | KEY_RELEASE);
> + }
> if (keycode & ALT)
> kbd_put_keycode(ALT_CODE | KEY_RELEASE);
> if (keycode & CNTRL)
> @@ -263,7 +285,7 @@ static void curses_refresh(DisplayState *ds)
> if (keycode & SHIFT)
> kbd_put_keycode(SHIFT_CODE | KEY_RELEASE);
> } else {
> - keysym = curses2keysym[chr];
> + keysym = curses2qemu[chr];
> if (keysym == -1)
> keysym = chr;
>
> @@ -301,8 +323,6 @@ static void curses_setup(void)
>
> static void curses_keyboard_setup(void)
> {
> - int i, keycode, keysym;
> -
> #if defined(__APPLE__)
> /* always use generic keymaps */
> if (!keyboard_layout)
> @@ -313,27 +333,6 @@ static void curses_keyboard_setup(void)
> if (!kbd_layout)
> exit(1);
> }
> -
> - for (i = 0; i < CURSES_KEYS; i ++)
> - keycode2keysym[i] = -1;
> -
> - for (i = 0; i < CURSES_KEYS; i ++) {
> - if (curses2keycode[i] == -1)
> - continue;
> -
> - keycode = curses2keycode[i] & KEY_MASK;
> - if (keycode2keysym[keycode] >= 0)
> - continue;
> -
> - for (keysym = 0; keysym < CURSES_KEYS; keysym ++)
> - if (curses2keycode[keysym] == keycode) {
> - keycode2keysym[keycode] = keysym;
> - break;
> - }
> -
> - if (keysym >= CURSES_KEYS)
> - keycode2keysym[keycode] = i;
> - }
> }
>
> void curses_display_init(DisplayState *ds, int full_screen)
> diff --git a/curses_keys.h b/curses_keys.h
> index 9c1aa7f..36b8b9b 100644
> --- a/curses_keys.h
> +++ b/curses_keys.h
> @@ -28,20 +28,36 @@
>
> #define KEY_RELEASE 0x80
> #define KEY_MASK 0x7f
> -#define SHIFT_CODE 0x2a
> -#define SHIFT 0x0080
> #define GREY_CODE 0xe0
> -#define GREY 0x0100
> +#define GREY SCANCODE_GREY
> +#define SHIFT_CODE 0x2a
> +#define SHIFT SCANCODE_SHIFT
> #define CNTRL_CODE 0x1d
> -#define CNTRL 0x0200
> +#define CNTRL SCANCODE_CTRL
> #define ALT_CODE 0x38
> -#define ALT 0x0400
> +#define ALT SCANCODE_ALT
> +#define ALTGR SCANCODE_ALTGR
> +
> +#define KEYSYM_MASK 0x0ffffff
> +#define KEYSYM_SHIFT (SCANCODE_SHIFT << 16)
> +#define KEYSYM_CNTRL (SCANCODE_CTRL << 16)
> +#define KEYSYM_ALT (SCANCODE_ALT << 16)
> +#define KEYSYM_ALTGR (SCANCODE_ALTGR << 16)
>
> /* curses won't detect a Control + Alt + 1, so use Alt + 1 */
> #define QEMU_KEY_CONSOLE0 (2 | ALT) /* (curses2keycode['1'] | ALT) */
>
> #define CURSES_KEYS KEY_MAX /* KEY_MAX defined in <curses.h> */
>
> +static const int curses2keysym[CURSES_KEYS] = {
> + [0 ... (CURSES_KEYS - 1)] = -1,
> +
> + [0x7f] = KEY_BACKSPACE,
> + ['\r'] = KEY_ENTER,
> + ['\n'] = KEY_ENTER,
> + [KEY_BTAB] = '\t' | KEYSYM_SHIFT,
> +};
> +
> static const int curses2keycode[CURSES_KEYS] = {
> [0 ... (CURSES_KEYS - 1)] = -1,
>
> @@ -225,7 +241,7 @@ static const int curses2keycode[CURSES_KEYS] = {
>
> };
>
> -static const int curses2keysym[CURSES_KEYS] = {
> +static const int curses2qemu[CURSES_KEYS] = {
> [0 ... (CURSES_KEYS - 1)] = -1,
>
> ['\n'] = '\n',
> @@ -449,9 +465,9 @@ static const name2keysym_t name2keysym[] = {
> { "ydiaeresis", 0x0ff },
>
> /* Special keys */
> - { "BackSpace", 0x07f },
> + { "BackSpace", KEY_BACKSPACE },
> { "Tab", '\t' },
> - { "Return", '\n' },
> + { "Return", KEY_ENTER },
> { "Right", KEY_RIGHT },
> { "Left", KEY_LEFT },
> { "Up", KEY_UP },
> diff --git a/keymaps.c b/keymaps.c
> index 6685562..78c7ea3 100644
> --- a/keymaps.c
> +++ b/keymaps.c
> @@ -59,6 +59,29 @@ static void add_to_key_range(struct key_range **krp, int
> code) {
> }
> }
>
> +static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k)
> {
> + if (keysym < MAX_NORMAL_KEYCODE) {
> + //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode);
> + k->keysym2keycode[keysym] = keycode;
> + } else {
> + if (k->extra_count >= MAX_EXTRA_COUNT) {
> + fprintf(stderr,
> + "Warning: Could not assign keysym %s (0x%x) because of
> memory constraints.\n",
> + line, keysym);
> + } else {
> +#if 0
> + fprintf(stderr, "Setting %d: %d,%d\n",
> + k->extra_count, keysym, keycode);
> +#endif
> + k->keysym2keycode_extra[k->extra_count].
> + keysym = keysym;
> + k->keysym2keycode_extra[k->extra_count].
> + keycode = keycode;
> + k->extra_count++;
> + }
> + }
> +}
> +
> static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
> const char *language,
> kbd_layout_t * k)
> @@ -111,27 +134,22 @@ static kbd_layout_t *parse_keyboard_layout(const
> name2keysym_t *table,
> //fprintf(stderr, "keypad keysym %04x keycode %d\n",
> keysym, keycode);
> }
>
> - /* if(keycode&0x80)
> - keycode=(keycode<<8)^0x80e0; */
> - if (keysym < MAX_NORMAL_KEYCODE) {
> - //fprintf(stderr,"Setting keysym %s (%d) to
> %d\n",line,keysym,keycode);
> - k->keysym2keycode[keysym] = keycode;
> - } else {
> - if (k->extra_count >= MAX_EXTRA_COUNT) {
> - fprintf(stderr,
> - "Warning: Could not assign keysym %s (0x%x)
> because of memory constraints.\n",
> - line, keysym);
> - } else {
> -#if 0
> - fprintf(stderr, "Setting %d: %d,%d\n",
> - k->extra_count, keysym, keycode);
> -#endif
> - k->keysym2keycode_extra[k->extra_count].
> - keysym = keysym;
> - k->keysym2keycode_extra[k->extra_count].
> - keycode = keycode;
> - k->extra_count++;
> - }
> + if (rest && strstr(rest, "shift"))
> + keycode |= SCANCODE_SHIFT;
> + if (rest && strstr(rest, "altgr"))
> + keycode |= SCANCODE_ALTGR;
> + if (rest && strstr(rest, "ctrl"))
> + keycode |= SCANCODE_CTRL;
> +
> + add_keysym(line, keysym, keycode, k);
> +
> + if (rest && strstr(rest, "addupper")) {
> + char *c;
> + for (c = line; *c; c++)
> + *c = toupper(*c);
> + keysym = get_keysym(table, line);
> + if (keysym)
> + add_keysym(line, keysym, keycode | SCANCODE_SHIFT,
> k);
> }
> }
> }
> diff --git a/keymaps.h b/keymaps.h
> index 17f6efd..a7600d5 100644
> --- a/keymaps.h
> +++ b/keymaps.h
> @@ -51,6 +51,23 @@ typedef struct {
> struct key_range *numlock_range;
> } kbd_layout_t;
>
> +/* scancode without modifiers */
> +#define SCANCODE_KEYMASK 0xff
> +/* scancode without grey or up bit */
> +#define SCANCODE_KEYCODEMASK 0x7f
> +
> +/* "grey" keys will usually need a 0xe0 prefix */
> +#define SCANCODE_GREY 0x80
> +#define SCANCODE_EMUL0 0xE0
> +/* "up" flag */
> +#define SCANCODE_UP 0x80
> +
> +/* Additional modifiers to use if not catched another way. */
> +#define SCANCODE_SHIFT 0x100
> +#define SCANCODE_CTRL 0x200
> +#define SCANCODE_ALT 0x400
> +#define SCANCODE_ALTGR 0x800
> +
>
> void *init_keyboard_layout(const name2keysym_t *table, const char *language);
> int keysym2scancode(void *kbd_layout, int keysym);
> diff --git a/sdl.c b/sdl.c
> index a9b4323..f26035c 100644
> --- a/sdl.c
> +++ b/sdl.c
> @@ -248,7 +248,7 @@ 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);
> + return keysym2scancode(kbd_layout, keysym) & SCANCODE_KEYMASK;
> }
>
> /* specific keyboard conversions from scan codes */
> @@ -343,9 +343,9 @@ static void reset_keys(void)
> int i;
> for(i = 0; i < 256; i++) {
> if (modifiers_state[i]) {
> - if (i & 0x80)
> - kbd_put_keycode(0xe0);
> - kbd_put_keycode(i | 0x80);
> + if (i & SCANCODE_GREY)
> + kbd_put_keycode(SCANCODE_EMUL0);
> + kbd_put_keycode(i | SCANCODE_UP);
> modifiers_state[i] = 0;
> }
> }
> @@ -359,7 +359,7 @@ static void sdl_process_key(SDL_KeyboardEvent *ev)
> /* specific case */
> v = 0;
> if (ev->type == SDL_KEYUP)
> - v |= 0x80;
> + v |= SCANCODE_UP;
> kbd_put_keycode(0xe1);
> kbd_put_keycode(0x1d | v);
> kbd_put_keycode(0x45 | v);
> @@ -392,17 +392,17 @@ static void sdl_process_key(SDL_KeyboardEvent *ev)
> case 0x3a: /* caps lock */
> /* SDL does not send the key up event, so we generate it */
> kbd_put_keycode(keycode);
> - kbd_put_keycode(keycode | 0x80);
> + kbd_put_keycode(keycode | SCANCODE_UP);
> return;
> }
>
> /* now send the key code */
> - if (keycode & 0x80)
> - kbd_put_keycode(0xe0);
> + if (keycode & SCANCODE_GREY)
> + kbd_put_keycode(SCANCODE_EMUL0);
> if (ev->type == SDL_KEYUP)
> - kbd_put_keycode(keycode | 0x80);
> + kbd_put_keycode(keycode | SCANCODE_UP);
> else
> - kbd_put_keycode(keycode & 0x7f);
> + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
> }
>
> static void sdl_update_caption(void)
> diff --git a/vnc.c b/vnc.c
> index db34b0e..01353a9 100644
> --- a/vnc.c
> +++ b/vnc.c
> @@ -1482,9 +1482,9 @@ static void reset_keys(VncState *vs)
> int i;
> for(i = 0; i < 256; i++) {
> if (vs->modifiers_state[i]) {
> - if (i & 0x80)
> - kbd_put_keycode(0xe0);
> - kbd_put_keycode(i | 0x80);
> + if (i & SCANCODE_GREY)
> + kbd_put_keycode(SCANCODE_EMUL0);
> + kbd_put_keycode(i | SCANCODE_UP);
> vs->modifiers_state[i] = 0;
> }
> }
> @@ -1492,8 +1492,13 @@ static void reset_keys(VncState *vs)
>
> static void press_key(VncState *vs, int keysym)
> {
> - kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) & 0x7f);
> - kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) | 0x80);
> + int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) &
> SCANCODE_KEYMASK;
> + if (keycode & SCANCODE_GREY)
> + kbd_put_keycode(SCANCODE_EMUL0);
> + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
> + if (keycode & SCANCODE_GREY)
> + kbd_put_keycode(SCANCODE_EMUL0);
> + kbd_put_keycode(keycode | SCANCODE_UP);
> }
>
> static void do_key_event(VncState *vs, int down, int keycode, int sym)
> @@ -1566,12 +1571,12 @@ static void do_key_event(VncState *vs, int down, int
> keycode, int sym)
> }
>
> if (is_graphic_console()) {
> - if (keycode & 0x80)
> - kbd_put_keycode(0xe0);
> + if (keycode & SCANCODE_GREY)
> + kbd_put_keycode(SCANCODE_EMUL0);
> if (down)
> - kbd_put_keycode(keycode & 0x7f);
> + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
> else
> - kbd_put_keycode(keycode | 0x80);
> + kbd_put_keycode(keycode | SCANCODE_UP);
> } else {
> /* QEMU console emulation */
> if (down) {
> @@ -1679,7 +1684,7 @@ static void key_event(VncState *vs, int down, uint32_t
> sym)
> lsym = lsym - 'A' + 'a';
> }
>
> - keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF);
> + keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) &
> SCANCODE_KEYMASK;
> do_key_event(vs, down, keycode, sym);
> }
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
address@hidden http://www.aurel32.net
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [Qemu-devel] [PATCH] Fix curses interaction with keymaps,
Aurelien Jarno <=