From e6ec9ba53a6e349d28dfa1f9dfdbf067e0cfef67 Mon Sep 17 00:00:00 2001
From: Rob Bradford <rob@linux.intel.com>
Date: Tue, 1 May 2012 16:16:43 +0100
Subject: [PATCH] Ecore_Evas (wayland): Complete implementation of key event
 handling

Finish implementing the keyboard event handling by creating the event
structure and posting the event to the loop.

This change pulls in the X keysym header until the keysyms. This can be
switched to libxkbcommon when the keysyms are added to the header files it
ships.

Similarly the code to generate the unicode representation for the keysym can
be replaced with a function call into libxkbcommon when the code to provide
that lands.
---
 src/lib/ecore_wayland/ecore_wl_input.c |  114 ++++++++++++++++++++++++++++++--
 1 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/src/lib/ecore_wayland/ecore_wl_input.c b/src/lib/ecore_wayland/ecore_wl_input.c
index b7e6f95..17833be 100644
--- a/src/lib/ecore_wayland/ecore_wl_input.c
+++ b/src/lib/ecore_wayland/ecore_wl_input.c
@@ -33,6 +33,9 @@
 # define BTN_BACK 0x116
 #endif
 
+/* Required for keysym names - in the future available in libxkbcommon */
+#include <X11/keysym.h>
+
 /* local function prototypes */
 static void _ecore_wl_input_cb_motion(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int sx, int sy);
 static void _ecore_wl_input_cb_button(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int serial, unsigned int timestamp, unsigned int button, unsigned int state);
@@ -236,12 +239,64 @@ _ecore_wl_input_cb_axis(void *data, struct wl_input_device *input_device __UNUSE
    _ecore_wl_input_mouse_wheel_send(input, axis, value, timestamp);
 }
 
+/*
+ * stringify_keysym: 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
+ *
+ */
+static int
+stringify_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 >= XK_BackSpace) &&
+            (symbol <= XK_Clear)) ||
+           (symbol == XK_Return) ||
+           (symbol == XK_Escape) ||
+           (symbol == XK_KP_Space) ||
+           (symbol == XK_KP_Tab) ||
+           (symbol == XK_KP_Enter) ||
+           ((symbol >= XK_KP_Multiply) &&
+            (symbol <= XK_KP_9)) ||
+           (symbol == XK_KP_Equal) ||
+           (symbol == XK_Delete))))))
+    return 0;
+
+  /* if X keysym, convert to ascii by grabbing low 7 bits */
+  if (symbol == XK_KP_Space)
+    c = XK_space & 0x7F; /* patch encoding botch */
+  else if (high_bytes == 0xFF)
+    c = symbol & 0x7F;
+  else
+    c = symbol & 0xFF;
+
+  buffer[0] = c;
+  return 1;
+}
+
 static void 
-_ecore_wl_input_cb_key(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int serial, unsigned int timestamp, unsigned int key, unsigned int state)
+_ecore_wl_input_cb_key(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int serial, unsigned int timestamp, unsigned int keycode, unsigned int state)
 {
    Ecore_Wl_Input *input;
    Ecore_Wl_Window *win;
-   unsigned int keycode = 0;
+   uint32_t keysym, modified_keysym, level = 0;
+   char key[8], keyname[8], string[8];
+   Ecore_Event_Key *e;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
@@ -250,16 +305,61 @@ _ecore_wl_input_cb_key(void *data, struct wl_input_device *input_device __UNUSED
    input->timestamp = timestamp;
    input->display->serial = serial;
    win = input->keyboard_focus;
+
    if ((!win) || (win->keyboard_device != input)) return;
 
    /* FIXME: NB: I believe this should be min_key_code rather than 8, 
     * but weston code has it like this */
-   keycode = key + 8;
+   keycode += 8;
+
+   if ((input->modifiers & XKB_COMMON_SHIFT_MASK) &&
+        (XkbKeyGroupWidth(_ecore_wl_disp->xkb, keycode, 0) > 1))
+      level = 1;
+
+   memset(key, sizeof (key), 0);
+   memset(keyname, sizeof (keyname), 0);
+   memset(string, sizeof (string), 0);
+
+   modified_keysym = XkbKeySymEntry(_ecore_wl_disp->xkb, keycode, level, 0);
+   xkb_keysym_to_string(modified_keysym, key, sizeof (key));
+
+   keysym = XkbKeySymEntry(_ecore_wl_disp->xkb, keycode, 0, 0);
+   xkb_keysym_to_string(keysym, keyname, sizeof (keyname));
 
-   /* if ((input->modifiers & XKB_COMMON_SHIFT_MASK) &&  */
-   /*     (XkbKeyGroupWidth(_ecore_wl_disp->xkb, keycode, 0) > 1))  */
-   /*   level = 1; */
-   /* keysym = XkbKeySymEntry(_ecore_wl_disp->xkb, keycode, level, 0); */
+   /* TODO: Switch over to the libxkbcommon API when it is available */
+   if (!stringify_keysym(modified_keysym, string, sizeof (string)))
+     string[0] = '\0';
+
+   e = malloc (sizeof(Ecore_Event_Key) + strlen (keyname) + strlen(key) +
+               strlen(string) + 3);
+
+   e->keyname = (char *)(e + 1);
+   e->key = e->keyname + strlen(keyname) + 1;
+   e->string = strlen(string) ? e->key + strlen(key) + 1 : NULL;
+   e->compose = e->string;
+
+   strcpy((char *)e->keyname, keyname);
+   strcpy((char *)e->key, key);
+   if (strlen (string))
+     strcpy((char *)e->string, string);
+
+   e->window = win->id;
+   e->event_window = win->id;
+   e->timestamp = timestamp;
+
+   /* The Ecore_Event_Modifiers don't quite match the X mask bits */
+   e->modifiers = 0;
+   if (input->modifiers & XKB_COMMON_SHIFT_MASK)
+     e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
+   if (input->modifiers & XKB_COMMON_CONTROL_MASK)
+     e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
+   if (input->modifiers & XKB_COMMON_MOD1_MASK)
+     e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
+
+   if (state)
+     ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
+   else
+     ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
 
    if (state)
      input->modifiers |= _ecore_wl_disp->xkb->map->modmap[keycode];
-- 
1.7.7.6

