qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]