diff --git a/clutter/evdev/clutter-xkb-utils.c b/clutter/evdev/clutter-xkb-utils.c index f0c3b5859..c6f798071 100644 --- a/clutter/evdev/clutter-xkb-utils.c +++ b/clutter/evdev/clutter-xkb-utils.c @@ -20,11 +20,66 @@ * Authors: * Kristian Høgsberg + * Damien Lespiau */ #include "clutter-keysyms.h" #include "clutter-xkb-utils.h" +/* + * print_key_sym: Translate a symbol to its printable form if any + * @symbol: the symbol to translate + * @buffer: the buffer where to put the translated string + * @len: size of the buffer + * + * Translates @symbol into a printable representation in @buffer, if possible. + * + * Return value: The number of bytes of the translated string, 0 if the + * symbol can't be printed + * + * Note: The code is derived from libX11's src/KeyBind.c + * Copyright 1985, 1987, 1998 The Open Group + * + * Note: This code works for Latin-1 symbols. clutter_keysym_to_unicode() + * does the work for the other keysyms. + */ +static int +print_keysym (uint32_t symbol, + char *buffer, + int len) +{ + unsigned long high_bytes; + unsigned char c; + + high_bytes = symbol >> 8; + if (!(len && + ((high_bytes == 0) || + ((high_bytes == 0xFF) && + (((symbol >= CLUTTER_KEY_BackSpace) && + (symbol <= CLUTTER_KEY_Clear)) || + (symbol == CLUTTER_KEY_Return) || + (symbol == CLUTTER_KEY_Escape) || + (symbol == CLUTTER_KEY_KP_Space) || + (symbol == CLUTTER_KEY_KP_Tab) || + (symbol == CLUTTER_KEY_KP_Enter) || + ((symbol >= CLUTTER_KEY_KP_Multiply) && + (symbol <= CLUTTER_KEY_KP_9)) || + (symbol == CLUTTER_KEY_KP_Equal) || + (symbol == CLUTTER_KEY_Delete)))))) + return 0; + + /* if X keysym, convert to ascii by grabbing low 7 bits */ + if (symbol == CLUTTER_KEY_KP_Space) + c = CLUTTER_KEY_space & 0x7F; /* patch encoding botch */ + else if (high_bytes == 0xFF) + c = symbol & 0x7F; + else + c = symbol & 0xFF; + + buffer[0] = c; + return 1; +} + /* * _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent * @device: a ClutterInputDevice @@ -77,7 +132,21 @@ _clutter_key_event_new_from_evdev (ClutterInputDevice *device, event->key.modifier_state = *modifier_state; event->key.hardware_keycode = key; event->key.keyval = sym; - event->key.unicode_value = sym; + + /* unicode_value is the printable representation */ + n = print_keysym (sym, buffer, sizeof (buffer)); + + if (n == 0) + { + /* not printable */ + event->key.unicode_value = (gunichar) '\0'; + } + else + { + event->key.unicode_value = g_utf8_get_char_validated (buffer, n); + if (event->key.unicode_value == -1 || event->key.unicode_value == -2) + event->key.unicode_value = (gunichar) '\0'; + } return event; }