[mutter/wip/wayland-input: 3/9] wayland: Add keyboard support



commit 746b87817d5731cead81b0a58c3d12b8e8f931ff
Author: Neil Roberts <neil linux intel com>
Date:   Tue Jan 17 19:54:26 2012 +0000

    wayland: Add keyboard support
    
    This adds basic keyboard support to the wayland compositor.
    Auto-repeated key events are filtered out because the Wayland clients
    are expected to generate them themselves. The wayland keyboard input
    focus surface is updated whenever Mutter sees a FocusIn event so that
    it will stay in synch with whatever surface Mutter wants as the focus.

 src/core/display.c                      |   12 +++++
 src/wayland/meta-wayland-input-device.c |   71 +++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-private.h      |   16 ++++---
 src/wayland/meta-wayland.c              |   28 ++++++++++++
 4 files changed, 121 insertions(+), 6 deletions(-)
---
diff --git a/src/core/display.c b/src/core/display.c
index b656ea9..dd5bad9 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -77,6 +77,9 @@
 #include <X11/extensions/Xfixes.h>
 #include <string.h>
 #include <unistd.h>
+#ifdef HAVE_WAYLAND
+#include "meta-wayland-private.h"
+#endif
 
 #define GRAB_OP_IS_WINDOW_SWITCH(g)                     \
         (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL  ||  \
@@ -2164,6 +2167,15 @@ meta_display_handle_event (MetaDisplay *display,
         }
       break;
     case FocusIn:
+#ifdef HAVE_WAYLAND
+      {
+        MetaWaylandCompositor *compositor =
+          meta_wayland_compositor_get_default ();
+        meta_wayland_compositor_set_input_focus (compositor,
+                                                 window);
+      }
+#endif
+      /* fall through */
     case FocusOut:
       if (window)
         {
diff --git a/src/wayland/meta-wayland-input-device.c b/src/wayland/meta-wayland-input-device.c
index 89dcd55..adba30c 100644
--- a/src/wayland/meta-wayland-input-device.c
+++ b/src/wayland/meta-wayland-input-device.c
@@ -25,6 +25,7 @@
 #include <clutter/wayland/clutter-wayland-compositor.h>
 #include <clutter/wayland/clutter-wayland-surface.h>
 #include <stdlib.h>
+#include <string.h>
 #include <linux/input.h>
 #include "meta-wayland-input-device.h"
 #include "meta-wayland-private.h"
@@ -160,6 +161,70 @@ handle_button_event (MetaWaylandInputDevice *input_device,
   device->grab->interface->button (device->grab, event->time, button, state);
 }
 
+static void
+handle_key_event (MetaWaylandInputDevice *input_device,
+                  const ClutterKeyEvent *event)
+{
+  struct wl_input_device *device =
+    (struct wl_input_device *) input_device;
+  gboolean state = event->type == CLUTTER_KEY_PRESS;
+  guint evdev_code;
+
+  /* We can't do anything with the event if we can't get an evdev
+     keycode for it */
+  if (event->device == NULL ||
+      !clutter_input_device_keycode_to_evdev (event->device,
+                                              event->hardware_keycode,
+                                              &evdev_code))
+    return;
+
+  /* We want to ignore events that are sent because of auto-repeat. In
+     the Clutter event stream these appear as a single key press
+     event. We can detect that because the key will already have been
+     pressed */
+  if (state)
+    {
+      uint32_t *end = (void *) ((char *) device->keys.data + device->keys.size);
+      uint32_t *k;
+
+      /* Ignore the event if the key is already down */
+      for (k = device->keys.data; k < end; k++)
+        if (*k == evdev_code)
+          return;
+
+      /* Otherwise add the key to the list of pressed keys */
+      k = wl_array_add (&device->keys, sizeof (*k));
+      *k = evdev_code;
+    }
+  else
+    {
+      uint32_t *end = (void *) ((char *) device->keys.data + device->keys.size);
+      uint32_t *k;
+
+      /* Remove the key from the array */
+      for (k = device->keys.data; k < end; k++)
+        if (*k == evdev_code)
+          {
+            *k = *(end - 1);
+            device->keys.size -= sizeof (*k);
+
+            goto found;
+          }
+
+      g_warning ("unexpected key release event for key 0x%x", evdev_code);
+
+    found:
+      (void) 0;
+    }
+
+  if (device->keyboard_focus_resource)
+    wl_resource_post_event (device->keyboard_focus_resource,
+                            WL_INPUT_DEVICE_KEY,
+                            event->time,
+                            evdev_code,
+                            state);
+}
+
 void
 meta_wayland_input_device_handle_event (MetaWaylandInputDevice *input_device,
                                         const ClutterEvent *event)
@@ -177,6 +242,12 @@ meta_wayland_input_device_handle_event (MetaWaylandInputDevice *input_device,
                            (const ClutterButtonEvent *) event);
       break;
 
+    case CLUTTER_KEY_PRESS:
+    case CLUTTER_KEY_RELEASE:
+      handle_key_event (input_device,
+                        (const ClutterKeyEvent *) event);
+      break;
+
     default:
       break;
     }
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 0e4e2ec..b0896a6 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -28,6 +28,7 @@
 
 #include "window-private.h"
 #include "meta-wayland-input-device.h"
+#include "window-private.h"
 
 typedef struct _MetaWaylandCompositor MetaWaylandCompositor;
 
@@ -133,17 +134,20 @@ struct _MetaWaylandCompositor
   guint32 implicit_grab_button;
 };
 
-void                    meta_wayland_init                   (void);
-void                    meta_wayland_finalize               (void);
+void                    meta_wayland_init                       (void);
+void                    meta_wayland_finalize                   (void);
 
 /* We maintain a singleton MetaWaylandCompositor which can be got at via this
  * API after meta_wayland_init() has been called. */
-MetaWaylandCompositor  *meta_wayland_compositor_get_default (void);
+MetaWaylandCompositor  *meta_wayland_compositor_get_default     (void);
+
+void                    meta_wayland_handle_sig_child           (void);
 
-void                    meta_wayland_handle_sig_child       (void);
+MetaWaylandSurface     *meta_wayland_lookup_surface_for_xid     (guint32 xid);
 
-MetaWaylandSurface     *meta_wayland_lookup_surface_for_xid (guint32 xid);
+void                    meta_wayland_compositor_repick          (MetaWaylandCompositor *compositor);
 
-void                    meta_wayland_compositor_repick      (MetaWaylandCompositor *compositor);
+void                    meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
+                                                                 MetaWindow            *window);
 
 #endif /* META_WAYLAND_PRIVATE_H */
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 8bb7506..1a043be 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -360,6 +360,34 @@ meta_wayland_compositor_repick (MetaWaylandCompositor *compositor)
                                     NULL);
 }
 
+void
+meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
+                                         MetaWindow            *window)
+{
+  struct wl_surface *surface = NULL;
+
+  if (window)
+    {
+      MetaWindowActor *window_actor =
+        META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
+      ClutterActor *shaped_texture =
+        meta_window_actor_get_shaped_texture (window_actor);
+
+      if (CLUTTER_WAYLAND_IS_SURFACE (shaped_texture))
+        {
+          ClutterWaylandSurface *surface_actor =
+            CLUTTER_WAYLAND_SURFACE (shaped_texture);
+
+          surface = clutter_wayland_surface_get_surface (surface_actor);
+        }
+    }
+
+  wl_input_device_set_keyboard_focus ((struct wl_input_device *)
+                                      compositor->input_device,
+                                      (struct wl_surface *) surface,
+                                      get_time ());
+}
+
 static void
 surface_actor_destroyed_cb (void *user_data,
                             GObject *old_object)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]