From: Jan Arne Petersen <[email protected]>

Add support for requesting hardware input into an input method.

Signed-off-by: Jan Arne Petersen <[email protected]>
---
 protocol/input-method.xml |   9 ++++
 src/text-backend.c        | 107 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/protocol/input-method.xml b/protocol/input-method.xml
index 61b70c0..3418c0c 100644
--- a/protocol/input-method.xml
+++ b/protocol/input-method.xml
@@ -67,6 +67,15 @@
       <arg name="state" type="uint"/>
       <arg name="modifiers" type="uint"/>
     </request>
+    <request name="grab_keyboard">
+      <description summary="grab hardware keyboard">
+        Allows an input method to receive hardware keyboard input and process
+        key events to generate text events (with pre-edit) over the. This 
allows
+        input methods which compose multiple key events for inputting text
+        like it is done for CJK languages.
+      </description>
+       <arg name="keyboard" type="new_id" interface="wl_keyboard"/>
+    </request>
     <event name="surrounding_text">
       <description summary="surrounding text event">
         The plain surrounding text around the input position. Cursor is the
diff --git a/src/text-backend.c b/src/text-backend.c
index f37a9cf..3799adb 100644
--- a/src/text-backend.c
+++ b/src/text-backend.c
@@ -72,8 +72,12 @@ struct input_method_context {
        struct wl_resource resource;
 
        struct text_model *model;
+       struct input_method *input_method;
 
        struct wl_list link;
+
+       struct wl_resource *keyboard;
+       struct wl_keyboard_grab grab;
 };
 
 struct text_backend {
@@ -92,6 +96,7 @@ struct text_backend {
 
 static void input_method_context_create(struct text_model *model,
                                        struct input_method *input_method);
+static void input_method_context_end_keyboard_grab(struct input_method_context 
*context);
 
 static void input_method_init_seat(struct weston_seat *seat);
 
@@ -102,8 +107,12 @@ deactivate_text_model(struct text_model *text_model,
        struct weston_compositor *ec = text_model->ec;
 
        if (input_method->model == text_model) {
-               if (input_method->context && input_method->input_method_binding)
-                       
input_method_send_deactivate(input_method->input_method_binding, 
&input_method->context->resource);
+               if (input_method->context && 
input_method->input_method_binding) {
+                       
input_method_context_end_keyboard_grab(input_method->context);
+                       
input_method_send_deactivate(input_method->input_method_binding,
+                                                    
&input_method->context->resource);
+               }
+
                wl_list_remove(&input_method->link);
                input_method->model = NULL;
                input_method->context = NULL;
@@ -364,12 +373,84 @@ input_method_context_keysym(struct wl_client *client,
                               sym, state, modifiers);
 }
 
+static void
+unbind_keyboard(struct wl_resource *resource)
+{
+       struct input_method_context *context = resource->data;
+
+       input_method_context_end_keyboard_grab(context);
+       context->keyboard = NULL;
+
+       free(resource);
+}
+
+static void
+input_method_context_grab_key(struct wl_keyboard_grab *grab,
+                             uint32_t time, uint32_t key, uint32_t state_w)
+{
+       struct input_method_context *input_method_context = container_of(grab, 
struct input_method_context, grab);
+       uint32_t serial;
+       
+       if (input_method_context->keyboard) {
+               serial = 
wl_display_next_serial(input_method_context->model->ec->wl_display);
+               wl_keyboard_send_key(input_method_context->keyboard,
+                                    serial, time, key, state_w);
+       }
+}
+
+static void
+input_method_context_grab_modifier(struct wl_keyboard_grab *grab, uint32_t 
serial,
+                                  uint32_t mods_depressed, uint32_t 
mods_latched,
+                                  uint32_t mods_locked, uint32_t group)
+{
+       struct input_method_context *input_method_context = container_of(grab, 
struct input_method_context, grab);
+
+       if (!input_method_context->keyboard)
+               return;
+
+       wl_keyboard_send_modifiers(input_method_context->keyboard,
+                                  serial, mods_depressed, mods_latched,
+                                  mods_locked, group);
+}
+
+static const struct wl_keyboard_grab_interface input_method_context_grab = {
+       input_method_context_grab_key,
+       input_method_context_grab_modifier,
+};
+
+static void
+input_method_context_grab_keyboard(struct wl_client *client,
+                                  struct wl_resource *resource,
+                                  uint32_t id)
+{
+       struct input_method_context *context = resource->data;
+       struct wl_resource *cr;
+       struct weston_seat *seat = context->input_method->seat;
+       struct wl_keyboard *keyboard = seat->seat.keyboard;
+
+       cr = wl_client_add_object(client, &wl_keyboard_interface,
+                                 NULL, id, context);
+       cr->destroy = unbind_keyboard;
+
+       context->keyboard = cr;
+
+       wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
+                               seat->xkb_info.keymap_fd,
+                               seat->xkb_info.keymap_size);
+
+       if (keyboard->grab != &keyboard->default_grab) {
+               wl_keyboard_end_grab(keyboard);
+       }
+       wl_keyboard_start_grab(keyboard, &context->grab);
+}
+
 static const struct input_method_context_interface 
input_method_context_implementation = {
        input_method_context_destroy,
        input_method_context_commit_string,
        input_method_context_preedit_string,
        input_method_context_delete_surrounding_text,
-       input_method_context_keysym
+       input_method_context_keysym,
+       input_method_context_grab_keyboard
 };
 
 static void
@@ -377,6 +458,10 @@ destroy_input_method_context(struct wl_resource *resource)
 {
        struct input_method_context *context = resource->data;
 
+       if (context->keyboard) {
+               wl_resource_destroy(context->keyboard);
+       }
+
        free(context);
 }
 
@@ -389,7 +474,7 @@ input_method_context_create(struct text_model *model,
        if (!input_method->input_method_binding)
                return;
 
-       context = malloc(sizeof *context);
+       context = calloc(1, sizeof *context);
        if (context == NULL)
                return;
 
@@ -402,14 +487,28 @@ input_method_context_create(struct text_model *model,
        wl_signal_init(&context->resource.destroy_signal);
 
        context->model = model;
+       context->input_method = input_method;
        input_method->context = context;
 
+       context->grab.interface = &input_method_context_grab;
+
        wl_client_add_resource(input_method->input_method_binding->client, 
&context->resource);
 
        input_method_send_activate(input_method->input_method_binding, 
&context->resource);
 }
 
 static void
+input_method_context_end_keyboard_grab(struct input_method_context *context)
+{
+       struct wl_keyboard_grab *grab = &context->grab;
+
+       if (grab->keyboard && (grab->keyboard->grab == grab)) {
+               wl_keyboard_end_grab(grab->keyboard);
+       }
+}
+
+
+static void
 unbind_input_method(struct wl_resource *resource)
 {
        struct input_method *input_method = resource->data;
-- 
1.7.11.7

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to