* Re: [Qemu-devel][PATCH] Re: AltGr keystrokes
2006-08-02 1:46 ` Anthony Liguori
2006-08-02 22:52 ` Edu
@ 2006-08-08 22:51 ` Edu
1 sibling, 0 replies; 5+ messages in thread
From: Edu @ 2006-08-08 22:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 305 bytes --]
Hi,
Attached patch, in addition to Anthony's, improves VNC keyboard
support for AltGr and extended characters.
I've only modified Spanish "es" keymap, but should be trivial to
update other keymaps in a similar manner.
This is my first patch submission, so please be lenient :)
Regards,
Eduardo Felipe
[-- Attachment #2: vnc-keyboard.diff --]
[-- Type: application/octet-stream, Size: 14970 bytes --]
--- qemu-old/keymaps/es Sun Dec 12 18:56:30 2004
+++ qemu-new/keymaps/es Tue Aug 08 23:41:55 2006
@@ -103,3 +103,58 @@
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr
+
+
+# Dead keys
+aacute 0x1e dead_acute
+Aacute 0x1e dead_acute shift
+eacute 0x12 dead_acute
+Eacute 0x12 dead_acute shift
+iacute 0x17 dead_acute
+Iacute 0x17 dead_acute shift
+oacute 0x18 dead_acute
+Oacute 0x18 dead_acute shift
+uacute 0x16 dead_acute
+Uacute 0x16 dead_acute shift
+yacute 0x15 dead_acute
+Yacute 0x15 dead_acute shift
+
+agrave 0x1e dead_grave
+Agrave 0x1e dead_grave shift
+egrave 0x12 dead_grave
+Egrave 0x12 dead_grave shift
+igrave 0x17 dead_grave
+Igrave 0x17 dead_grave shift
+ograve 0x18 dead_grave
+Ograve 0x18 dead_grave shift
+ugrave 0x16 dead_grave
+Ugrave 0x16 dead_grave shift
+
+adiaeresis 0x1e dead_diaeresis
+Adiaeresis 0x1e dead_diaeresis shift
+ediaeresis 0x12 dead_diaeresis
+Ediaeresis 0x12 dead_diaeresis shift
+idiaeresis 0x17 dead_diaeresis
+Idiaeresis 0x17 dead_diaeresis shift
+odiaeresis 0x18 dead_diaeresis
+Odiaeresis 0x18 dead_diaeresis shift
+udiaeresis 0x16 dead_diaeresis
+Udiaeresis 0x16 dead_diaeresis shift
+ydiaeresis 0x15 dead_diaeresis
+
+acircumflex 0x1e dead_circumflex
+Acircumflex 0x1e dead_circumflex shift
+ecircumflex 0x12 dead_circumflex
+Ecircumflex 0x12 dead_circumflex shift
+icircumflex 0x17 dead_circumflex
+Icircumflex 0x17 dead_circumflex shift
+ocircumflex 0x18 dead_circumflex
+Ocircumflex 0x18 dead_circumflex shift
+ucircumflex 0x16 dead_circumflex
+Ucircumflex 0x16 dead_circumflex shift
+
+acute 0x39 dead_acute
+grave 0x39 dead_grave
+diaeresis 0x39 dead_diaeresis
+asciicircum 0x39 dead_circumflex
+
--- qemu-old/keymaps.c Sun Apr 30 23:28:35 2006
+++ qemu-new/keymaps.c Tue Aug 08 23:39:58 2006
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+
static int get_keysym(const char *name)
{
name2keysym_t *p;
@@ -32,13 +33,26 @@
return 0;
}
+
+#define KEYMOD_SHIFT 0x01
+#define KEYMOD_CTRL 0x02
+#define KEYMOD_ALT 0x04
+#define KEYMOD_DEAD 0x08
+
#define MAX_NORMAL_KEYCODE 512
#define MAX_EXTRA_COUNT 256
+
typedef struct {
- uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
+ uint16_t keycode;
+ uint8_t keymod;
+ int deadsym;
+} keydata_t;
+
+typedef struct {
+ keydata_t keysym2keycode[MAX_NORMAL_KEYCODE];
struct {
int keysym;
- uint16_t keycode;
+ keydata_t kdata;
} keysym2keycode_extra[MAX_EXTRA_COUNT];
int extra_count;
} kbd_layout_t;
@@ -50,6 +64,7 @@
char file_name[1024];
char line[1024];
int len;
+ int upper;
snprintf(file_name, sizeof(file_name),
"%s/keymaps/%s", bios_dir, language);
@@ -82,17 +97,61 @@
if (*end_of_keysym) {
int keysym;
*end_of_keysym = 0;
+ uint8_t keymod;
+ int deadsym;
+
+ keymod = 0;
+ deadsym = 0;
+ upper = 0;
+redo:
+ if (upper==1){
+ char *c;
+ for(c=line;*c;c++)
+ *c=toupper(*c);
+ keymod |= KEYMOD_SHIFT;
+ upper++;
+ }
keysym = get_keysym(line);
if (keysym == 0) {
// fprintf(stderr, "Warning: unknown keysym %s\n", line);
} else {
const char *rest = end_of_keysym + 1;
int keycode = strtol(rest, NULL, 0);
+ char *modifier;
+ modifier = strtok (rest," ");
+ modifier = strtok (NULL," ");
+ while ( modifier != NULL) {
+ if (!strcmp(modifier, "shift")) {
+ keymod |= KEYMOD_SHIFT;
+ } else
+ if (!strcmp(modifier, "addupper")) {
+ upper++;
+ } else
+ if (!strcmp(modifier, "ctrl")) {
+ keymod |= KEYMOD_CTRL;
+ } else
+ if (!strcmp(modifier, "alt")) {
+ keymod |= KEYMOD_ALT;
+ } else
+ if (!strcmp(modifier, "altgr")) {
+ keymod |= KEYMOD_CTRL | KEYMOD_ALT;
+ } else
+ if (!strncmp(modifier, "dead_",5)) {
+ keymod |= KEYMOD_DEAD;
+ deadsym = get_keysym(modifier);
+ }
+ modifier = strtok (NULL," ");
+ }
/* 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;
+ k->keysym2keycode[keysym].
+ keycode = keycode;
+ k->keysym2keycode[keysym].
+ keymod = keymod;
+ k->keysym2keycode[keysym].
+ deadsym = deadsym;
} else {
if (k->extra_count >= MAX_EXTRA_COUNT) {
fprintf(stderr,
@@ -105,11 +164,18 @@
#endif
k->keysym2keycode_extra[k->extra_count].
keysym = keysym;
- k->keysym2keycode_extra[k->extra_count].
+ k->keysym2keycode_extra[k->extra_count].kdata.
keycode = keycode;
+ k->keysym2keycode_extra[k->extra_count].kdata.
+ keymod = keymod;
+ k->keysym2keycode_extra[k->extra_count].kdata.
+ deadsym = deadsym;
+
k->extra_count++;
}
}
+ if (upper==1)
+ goto redo;
}
}
}
@@ -123,14 +189,11 @@
return parse_keyboard_layout(language, 0);
}
-static int keysym2scancode(void *kbd_layout, int keysym)
+static keydata_t *find_keysym(void *kbd_layout, int keysym)
{
kbd_layout_t *k = kbd_layout;
if (keysym < MAX_NORMAL_KEYCODE) {
- if (k->keysym2keycode[keysym] == 0)
- fprintf(stderr, "Warning: no scancode found for keysym %d\n",
- keysym);
- return k->keysym2keycode[keysym];
+ return &k->keysym2keycode[keysym];
} else {
int i;
#ifdef XK_ISO_Left_Tab
@@ -138,8 +201,9 @@
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;
+ if (k->keysym2keycode_extra[i].keysym == keysym) {
+ return &k->keysym2keycode_extra[i].kdata;
}
- return 0;
+ }
+ return NULL;
}
--- qemu-old/sdl.c Tue Jun 13 14:03:53 2006
+++ qemu-new/sdl.c Tue Aug 08 23:40:08 2006
@@ -104,7 +104,11 @@
keysym = ev->keysym.sym;
if (keysym == 0 && ev->keysym.scancode == 113)
keysym = SDLK_MODE;
- return keysym2scancode(kbd_layout, keysym);
+ keydata_t *eventdata = find_keysym(kbd_layout, keysym);
+ if (eventdata==NULL)
+ return 0;
+ else
+ return eventdata->keycode;
}
/* specific keyboard conversions from scan codes */
--- qemu-old/vnc.c Tue Jun 13 18:35:24 2006
+++ qemu-new/vnc.c Tue Aug 08 23:41:37 2006
@@ -31,6 +31,23 @@
#include "vnc_keysym.h"
#include "keymaps.c"
+
+static uint8_t modifiers_state[2][256];
+
+typedef struct {
+ int left;
+ int right;
+ int bit;
+} modifier_t;
+
+static modifier_t test_modifier[]={
+ {0x2a, 0x36, KEYMOD_SHIFT},
+ {0x1d, 0x9d, KEYMOD_CTRL},
+ {0x38, 0xb8, KEYMOD_ALT},
+ {0,0,0},
+};
+
+
typedef struct Buffer
{
size_t capacity;
@@ -699,12 +716,9 @@
}
}
-static void do_key_event(VncState *vs, int down, uint32_t sym)
-{
- int keycode;
-
- keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
+static void do_keycode(int keycode, int down)
+{
if (keycode & 0x80)
kbd_put_keycode(0xe0);
if (down)
@@ -713,11 +727,88 @@
kbd_put_keycode(keycode | 0x80);
}
+static void do_modifier(int keycode, int down, int level)
+{
+ do_keycode(keycode,down);
+ modifiers_state[level][keycode] = down;
+ if (level==0) {
+ modifiers_state[1][keycode] = down;
+ }
+}
+
+static void set_modifiers(uint8_t reqstate,int down,int full)
+{
+ modifier_t *m;
+ for(m=test_modifier; m->bit; m++) {
+ int requested = reqstate & m->bit;
+ /* Release unwanted modifiers */
+ if (!down || full) {
+ if (modifiers_state[1][m->left] && !requested)
+ do_modifier(m->left,0,1);
+ if (modifiers_state[1][m->right] && !requested)
+ do_modifier(m->right,0,1);
+ }
+ /* Press desired modifiers */
+ if (down || full) {
+ int already_set = modifiers_state[1][m->left] | modifiers_state[1][m->right];
+ if (!already_set && requested)
+ do_modifier(m->left,1,1);
+ }
+ }
+}
+
+static void restore_modifiers()
+{
+ /* Restore modifiers from reference */
+ modifier_t *m;
+ for(m=test_modifier; m->bit; m++) {
+ if (modifiers_state[0][m->left] != modifiers_state[1][m->left])
+ do_modifier(m->left,modifiers_state[0][m->left],0);
+ if (modifiers_state[0][m->right] != modifiers_state[1][m->right])
+ do_modifier(m->right,modifiers_state[0][m->right],0);
+ }
+}
+
static void key_event(VncState *vs, int down, uint32_t sym)
{
- if (sym >= 'A' && sym <= 'Z')
- sym = sym - 'A' + 'a';
- do_key_event(vs, down, sym);
+ keydata_t *eventdata;
+ eventdata = find_keysym(vs->kbd_layout, sym & 0xFFFF);
+ if (eventdata==NULL)
+ return;
+ switch(eventdata->keycode) {
+ case 0x2a: /* Left Shift */
+ case 0x36: /* Right Shift */
+ case 0x1d: /* Left CTRL */
+ case 0x9d: /* Right CTRL */
+ case 0x38: /* Left ALT */
+ case 0xb8: /* Right ALT */
+ do_modifier(eventdata->keycode, down, 0);
+ return;
+ case 0x3a: /* caps lock */
+ /* TODO: handle properly caps lock + shift combinations */
+ return;
+ break;
+ }
+
+ if (down) {
+ /* Send deadkey */
+ if (eventdata->keymod & KEYMOD_DEAD) {
+ keydata_t *deaddata;
+ deaddata = find_keysym(vs->kbd_layout, eventdata->deadsym);
+ if (deaddata!=NULL) {
+ set_modifiers(deaddata->keymod,0,1);
+ do_keycode(deaddata->keycode,1);
+ do_keycode(deaddata->keycode,0);
+ restore_modifiers();
+ }
+ }
+ set_modifiers(eventdata->keymod,1,0);
+ }
+
+ do_keycode(eventdata->keycode,down);
+
+ if (!down)
+ restore_modifiers();
}
static void framebuffer_update_request(VncState *vs, int incremental,
--- qemu-old/vnc_keysym.h Sun Apr 30 23:28:36 2006
+++ qemu-new/vnc_keysym.h Tue Aug 08 23:39:35 2006
@@ -247,6 +247,33 @@
{"F14", 0xffcb}, /* XK_F14 */
{"F15", 0xffcc}, /* XK_F15 */
{"Sys_Req", 0xff15}, /* XK_Sys_Req */
+{"KP_Space", 0xff80}, /* XK_KP_Space */
+{"KP_Tab", 0xff89}, /* XK_KP_Tab */
+{"KP_Enter", 0xff8d}, /* XK_KP_Enter */
+{"KP_F1", 0xff91}, /* XK_KP_F1 */
+{"KP_F2", 0xff92}, /* XK_KP_F2 */
+{"KP_F3", 0xff93}, /* XK_KP_F3 */
+{"KP_F4", 0xff94}, /* XK_KP_F4 */
+{"KP_Home", 0xff95}, /* XK_KP_Home */
+{"KP_Left", 0xff96}, /* XK_KP_Left */
+{"KP_Up", 0xff97}, /* XK_KP_Up */
+{"KP_Right", 0xff98}, /* XK_KP_Right */
+{"KP_Down", 0xff99}, /* XK_KP_Down */
+{"KP_Prior", 0xff9a}, /* XK_KP_Prior */
+{"KP_Page_Up", 0xff9a}, /* XK_KP_Page_Up */
+{"KP_Next", 0xff9b}, /* XK_KP_Next */
+{"KP_Page_Down", 0xff9b}, /* XK_KP_Page_Down */
+{"KP_End", 0xff9c}, /* XK_KP_End */
+{"KP_Begin", 0xff9d}, /* XK_KP_Begin */
+{"KP_Insert", 0xff9e}, /* XK_KP_Insert */
+{"KP_Delete", 0xff9f}, /* XK_KP_Delete */
+{"KP_Equal", 0xffbd}, /* XK_KP_Equal */
+{"KP_Multiply", 0xffaa}, /* XK_KP_Multiply */
+{"KP_Add", 0xffab}, /* XK_KP_Add */
+{"KP_Separator", 0xffac}, /* XK_KP_Separator */
+{"KP_Subtract", 0xffad}, /* XK_KP_Subtract */
+{"KP_Decimal", 0xffae}, /* XK_KP_Decimal */
+{"KP_Divide", 0xffaf}, /* XK_KP_Divide */
{"KP_0", 0xffb0}, /* XK_KP_0 */
{"KP_1", 0xffb1}, /* XK_KP_1 */
{"KP_2", 0xffb2}, /* XK_KP_2 */
@@ -257,13 +284,6 @@
{"KP_7", 0xffb7}, /* XK_KP_7 */
{"KP_8", 0xffb8}, /* XK_KP_8 */
{"KP_9", 0xffb9}, /* XK_KP_9 */
-{"KP_Add", 0xffab}, /* XK_KP_Add */
-{"KP_Decimal", 0xffae}, /* XK_KP_Decimal */
-{"KP_Divide", 0xffaf}, /* XK_KP_Divide */
-{"KP_Enter", 0xff8d}, /* XK_KP_Enter */
-{"KP_Equal", 0xffbd}, /* XK_KP_Equal */
-{"KP_Multiply", 0xffaa}, /* XK_KP_Multiply */
-{"KP_Subtract", 0xffad}, /* XK_KP_Subtract */
{"help", 0xff6a}, /* XK_Help */
{"Menu", 0xff67}, /* XK_Menu */
{"Print", 0xff61}, /* XK_Print */
@@ -271,5 +291,27 @@
{"Num_Lock", 0xff7f}, /* XK_Num_Lock */
{"Pause", 0xff13}, /* XK_Pause */
{"Escape", 0xff1b}, /* XK_Escape */
+
+/* dead keys */
+{"dead_grave", 0xfe50}, /* XK_dead_grave */
+{"dead_acute", 0xfe51}, /* XK_dead_acute */
+{"dead_circumflex", 0xfe52}, /* XK_dead_circumflex */
+{"dead_tilde", 0xfe53}, /* XK_dead_tilde */
+{"dead_macron", 0xfe54}, /* XK_dead_macron */
+{"dead_breve", 0xfe55}, /* XK_dead_breve */
+{"dead_abovedot", 0xfe56}, /* XK_dead_abovedot */
+{"dead_diaeresis", 0xfe57}, /* XK_dead_diaeresis */
+{"dead_abovering", 0xfe58}, /* XK_dead_abovering */
+{"dead_doubleacute", 0xfe59}, /* XK_dead_doubleacute */
+{"dead_caron", 0xfe5a}, /* XK_dead_caron */
+{"dead_cedilla", 0xfe5b}, /* XK_dead_cedilla */
+{"dead_ogonek", 0xfe5c}, /* XK_dead_ogonek */
+{"dead_iota", 0xfe5d}, /* XK_dead_iota */
+{"dead_voiced_sound", 0xfe5e}, /* XK_dead_voiced_sound */
+{"dead_semivoiced_sound", 0xfe5f}, /* XK_dead_semivoiced_sound */
+{"dead_belowdot", 0xfe60}, /* XK_dead_belowdot */
+{"dead_hook", 0xfe61}, /* XK_dead_hook */
+{"dead_horn", 0xfe62}, /* XK_dead_horn */
+
{0,0},
};
^ permalink raw reply [flat|nested] 5+ messages in thread