Add support for Dynamic Keymap changes in Wayland Clients.
authorChris Michael <cp.michael@samsung.com>
Fri, 26 Apr 2013 11:06:42 +0000 (12:06 +0100)
committerChris Michael <cp.michael@samsung.com>
Fri, 26 Apr 2013 12:48:46 +0000 (13:48 +0100)
Now, if you change E's keyboard layout, then Wayland Clients will also
dynamically change to the new keymap.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/bin/e_comp_wl.c

index bb8a654..5a71c73 100644 (file)
@@ -8,6 +8,7 @@ static void _e_comp_wl_cb_bind(struct wl_client *client, void *data EINA_UNUSED,
 static Eina_Bool _e_comp_wl_cb_read(void *data EINA_UNUSED, Ecore_Fd_Handler *hdl EINA_UNUSED);
 static Eina_Bool _e_comp_wl_cb_idle(void *data EINA_UNUSED);
 static Eina_Bool _e_comp_wl_cb_module_idle(void *data EINA_UNUSED);
+static Eina_Bool _e_comp_wl_cb_keymap_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED);
 
 /* compositor interface prototypes */
 static void _e_comp_wl_cb_surface_create(struct wl_client *client, struct wl_resource *resource, unsigned int id);
@@ -186,6 +187,11 @@ e_comp_wl_init(void)
         goto err;
      }
 
+   /* setup keymap_change event handler */
+   _e_wl_comp->kbd_handler = 
+     ecore_event_handler_add(ECORE_X_EVENT_XKB_STATE_NOTIFY, 
+                             _e_comp_wl_cb_keymap_changed, NULL);
+
    /* add an idler for deferred shell module loading */
    _module_idler = ecore_idler_add(_e_comp_wl_cb_module_idle, NULL);
 
@@ -216,6 +222,10 @@ e_comp_wl_init(void)
    return EINA_TRUE;
 
 err:
+   /* remove kbd handler */
+   if (_e_wl_comp->kbd_handler) 
+     ecore_event_handler_del(_e_wl_comp->kbd_handler);
+
    /* remove the module idler */
    if (_module_idler) ecore_idler_del(_module_idler);
 
@@ -348,8 +358,11 @@ _e_comp_wl_cb_read(void *data EINA_UNUSED, Ecore_Fd_Handler *hdl EINA_UNUSED)
 static Eina_Bool 
 _e_comp_wl_cb_idle(void *data EINA_UNUSED)
 {
-   /* flush any clients before we idle */
-   wl_display_flush_clients(_e_wl_comp->wl.display);
+   if (_e_wl_comp->wl.display)
+     {
+        /* flush any clients before we idle */
+        wl_display_flush_clients(_e_wl_comp->wl.display);
+     }
 
    return ECORE_CALLBACK_RENEW;
 }
@@ -387,6 +400,71 @@ _e_comp_wl_cb_module_idle(void *data EINA_UNUSED)
    return ECORE_CALLBACK_RENEW;
 }
 
+static Eina_Bool 
+_e_comp_wl_cb_keymap_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+   struct xkb_keymap *keymap;
+
+   printf("Kbd Changed\n");
+
+   /* try to fetch the keymap */
+   if (!(keymap = _e_comp_wl_input_keymap_get())) 
+     return ECORE_CALLBACK_PASS_ON;
+
+   /* destroy keyboard */
+   if (_e_wl_comp->input->xkb.info)
+     {
+        /* if we have a keymap, unreference it */
+        if (_e_wl_comp->input->xkb.info->keymap)
+          xkb_map_unref(_e_wl_comp->input->xkb.info->keymap);
+
+        /* if we have a keymap mmap'd area, unmap it */
+        if (_e_wl_comp->input->xkb.info->area)
+          munmap(_e_wl_comp->input->xkb.info->area, 
+                 _e_wl_comp->input->xkb.info->size);
+
+        /* if we created an fd for keyboard input, close it */
+        if (_e_wl_comp->input->xkb.info->fd) 
+          close(_e_wl_comp->input->xkb.info->fd);
+
+        /* free the allocated keyboard info structure */
+        E_FREE(_e_wl_comp->input->xkb.info);
+     }
+
+   /* unreference the xkb state we created */
+   if (_e_wl_comp->input->xkb.state) 
+     xkb_state_unref(_e_wl_comp->input->xkb.state);
+
+   /* unreference the xkb context we created */
+   if (_e_wl_comp->xkb.context)
+     xkb_context_unref(_e_wl_comp->xkb.context);
+
+   /* create the xkb context */
+   _e_wl_comp->xkb.context = xkb_context_new(0);
+
+   /* try to fetch the keymap */
+//   if ((keymap = _e_comp_wl_input_keymap_get()))
+     {
+        /* try to create new keyboard info */
+        _e_wl_comp->input->xkb.info = 
+          _e_comp_wl_input_keyboard_info_get(keymap);
+
+        /* create new xkb state */
+        _e_wl_comp->input->xkb.state = xkb_state_new(keymap);
+
+        /* unreference the keymap */
+        xkb_map_unref(keymap);
+     }
+
+   /* send the current keymap to the keyboard object */
+   wl_keyboard_send_keymap(_e_wl_comp->input->wl.keyboard_resource, 
+                           WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, 
+                           _e_wl_comp->input->xkb.info->fd, 
+                           _e_wl_comp->input->xkb.info->size);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
 /* compositor interface functions */
 static void 
 _e_comp_wl_cb_surface_create(struct wl_client *client, struct wl_resource *resource, unsigned int id)
@@ -709,10 +787,16 @@ _e_comp_wl_input_cb_unbind(struct wl_resource *resource)
 static struct xkb_keymap *
 _e_comp_wl_input_keymap_get(void)
 {
+   E_Config_XKB_Layout *kbd_layout;
    struct xkb_rule_names names;
 
    memset(&names, 0, sizeof(names));
 
+   kbd_layout = e_xkb_layout_get();
+
+   names.model = strdup(kbd_layout->model);
+   names.layout = strdup(kbd_layout->name);
+
    /* if we are running under X11, try to get the xkb rule names atom */
    if (getenv("DISPLAY"))
      {
@@ -730,11 +814,6 @@ _e_comp_wl_input_keymap_get(void)
          * 
          */
 
-        /* E_Config_XKB_Layout *kbd_layout; */
-        /* kbd_layout = e_xkb_layout_get(); */
-        /* names.model = strdup(kbd_layout->model); */
-        /* names.layout = strdup(kbd_layout->name); */
-
         root = ecore_x_window_root_first_get();
         rules = ecore_x_atom_get("_XKB_RULES_NAMES");
         ecore_x_window_prop_property_get(root, rules, ECORE_X_ATOM_STRING, 
@@ -744,9 +823,9 @@ _e_comp_wl_input_keymap_get(void)
           {
              names.rules = strdup((const char *)data);
              data += strlen((const char *)data) + 1;
-             names.model = strdup((const char *)data);
-             data += strlen((const char *)data) + 1;
-             names.layout = strdup((const char *)data);
+             /* names.model = strdup((const char *)data); */
+             /* data += strlen((const char *)data) + 1; */
+             /* names.layout = strdup((const char *)data); */
 //             free(data);
           }
      }
@@ -914,6 +993,8 @@ _e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *r
         /* update the keyboard focus in the data device */
         wl_data_device_set_keyboard_focus(&input->wl.seat);
      }
+
+   input->wl.keyboard_resource = kbd;
 }
 
 static void