Include the currently pressed keys in keyboard focus event.
authorKristian Høgsberg <krh@redhat.com>
Tue, 24 Feb 2009 03:30:29 +0000 (22:30 -0500)
committerKristian Høgsberg <krh@redhat.com>
Tue, 24 Feb 2009 03:30:29 +0000 (22:30 -0500)
connection.c
wayland-client.h
wayland-protocol.c
wayland-system-compositor.c
wayland-util.c
wayland-util.h
window.c

index 112ee4f..b37e940 100644 (file)
@@ -229,6 +229,7 @@ wl_connection_vmarshal(struct wl_connection *connection,
 {
        struct wl_object *object;
        uint32_t args[32], length, *p, size;
+       struct wl_array *array;
        const char *s;
        int i, count;
 
@@ -254,6 +255,16 @@ wl_connection_vmarshal(struct wl_connection *connection,
                        object = va_arg(ap, struct wl_object *);
                        *p++ = object ? object->id : 0;
                        break;
+               case 'a':
+                       array = va_arg(ap, struct wl_array *);
+                       if (array == NULL || array->size == 0) {
+                               *p++ = 0;
+                               break;
+                       }
+                       *p++ = array->size;
+                       memcpy(p, array->data, array->size);
+                       p = (void *) p + array->size;
+                       break;
                default:
                        assert(0);
                        break;
@@ -283,6 +294,7 @@ wl_connection_demarshal(struct wl_connection *connection,
                char *string;
                void *object;
                uint32_t new_id;
+               struct wl_array *array;
        } values[20];
        void *args[20];
        struct wl_object *object;
@@ -344,6 +356,20 @@ wl_connection_demarshal(struct wl_connection *connection,
                                printf("object already exists (%d)\n", *p);
                        p++;
                        break;
+               case 'a':
+                       types[i] = &ffi_type_pointer;
+                       length = *p++;
+                       values[i].array = malloc(length + sizeof *values[i].array);
+                       if (values[i].array == NULL) {
+                               /* FIXME: Send NO_MEMORY */
+                               return;
+                       }
+                       values[i].array->size = length;
+                       values[i].array->alloc = 0;
+                       values[i].array->data = values[i].array + 1;
+                       memcpy(values[i].array->data, p, length);
+                       p += DIV_ROUNDUP(length, sizeof *p);
+                       break;
                default:
                        printf("unknown type\n");
                        break;
@@ -359,6 +385,9 @@ wl_connection_demarshal(struct wl_connection *connection,
                case 's':
                        free(values[i].string);
                        break;
+               case 'a':
+                       free(values[i].array);
+                       break;
                }
        }
 }
index 8e8850a..cb2bd29 100644 (file)
@@ -124,7 +124,8 @@ struct wl_input_device_listener {
                              struct wl_surface *surface);
        void (*keyboard_focus)(void *data,
                               struct wl_input_device *input_device,
-                              struct wl_surface *surface);
+                              struct wl_surface *surface,
+                              struct wl_array *keys);
 };
 
 int
index c542205..464af2b 100644 (file)
@@ -77,7 +77,7 @@ static const struct wl_message input_device_events[] = {
        { "button", "uuiiii" },
        { "key", "uu" },
        { "pointer_focus", "o" },
-       { "keyboard_focus", "o" },
+       { "keyboard_focus", "oa" },
 };
 
 WL_EXPORT const struct wl_interface wl_input_device_interface = {
index d0674ec..5524dbb 100644 (file)
@@ -88,6 +88,7 @@ struct wlsc_input_device {
        struct wlsc_surface *grab_surface;
        struct wlsc_surface *pointer_focus;
        struct wlsc_surface *keyboard_focus;
+       struct wl_array keys;
 };
 
 struct wlsc_compositor {
@@ -870,14 +871,13 @@ wlsc_input_device_set_keyboard_focus(struct wlsc_input_device *device,
            (!surface || device->keyboard_focus->base.client != surface->base.client))
                wl_surface_post_event(&device->keyboard_focus->base,
                                      &device->base,
-                                     WL_INPUT_KEYBOARD_FOCUS, NULL);
+                                     WL_INPUT_KEYBOARD_FOCUS, NULL, NULL);
 
-       /* FIXME: We need to send the currently held down keys in the
-        * keyboard focus event. */
        if (surface)
                wl_surface_post_event(&surface->base,
                                      &device->base,
-                                     WL_INPUT_KEYBOARD_FOCUS, &surface->base);
+                                     WL_INPUT_KEYBOARD_FOCUS,
+                                     &surface->base, &device->keys);
 
        device->keyboard_focus = surface;
 }
@@ -1051,6 +1051,10 @@ notify_key(struct wlsc_input_device *device,
           uint32_t key, uint32_t state)
 {
        struct wlsc_compositor *ec = device->ec;
+       uint32_t *k, *end;
+
+       if (!ec->vt_active)
+               return;
 
        switch (key | ec->meta_state) {
        case KEY_EJECTCD | META_DOWN:
@@ -1083,8 +1087,16 @@ notify_key(struct wlsc_input_device *device,
                return;
        }
 
-       if (!ec->vt_active)
-               return;
+       end = device->keys.data + device->keys.size;
+       for (k = device->keys.data; k < end; k++) {
+               if (*k == key)
+                       *k = *--end;
+       }
+       device->keys.size = (void *) end - device->keys.data;
+       if (state) {
+               k = wl_array_add(&device->keys, sizeof *k);
+               *k = key;
+       }
 
        if (device->keyboard_focus != NULL)
                wl_surface_post_event(&device->keyboard_focus->base,
index 4fae435..a5ab8be 100644 (file)
@@ -137,3 +137,47 @@ wl_list_empty(struct wl_list *list)
 {
        return list->next == list;
 }
+
+void
+wl_array_init(struct wl_array *array)
+{
+       memset(array, 0, sizeof *array);
+}
+
+void
+wl_array_release(struct wl_array *array)
+{
+       free(array->data);
+}
+
+void *
+wl_array_add(struct wl_array *array, int size)
+{
+       int alloc;
+       void *data, *p;
+
+       if (array->alloc > 0)
+               alloc = array->alloc;
+       else
+               alloc = 16;
+
+       while (alloc < array->size + size)
+               alloc *= 2;
+
+       if (array->alloc < alloc) {
+               if (array->alloc > 0)
+                       data = realloc(array->data, alloc);
+               else
+                       data = malloc(alloc);
+
+               if (data == NULL)
+                       return 0;
+               array->data = data;
+               array->alloc = alloc;
+       }
+
+       p = array->data + array->size;
+       array->size += size;
+
+       return p;
+}
index ffb6f6d..9da870c 100644 (file)
@@ -82,5 +82,14 @@ void wl_list_remove(struct wl_list *elm);
 int wl_list_length(struct wl_list *list);
 int wl_list_empty(struct wl_list *list);
 
+struct wl_array {
+       uint32_t size;
+       uint32_t alloc;
+       void *data;
+};
+
+void wl_array_init(struct wl_array *array);
+void wl_array_release(struct wl_array *array);
+void *wl_array_add(struct wl_array *array, int size);
 
 #endif
index b306a23..9c29b62 100644 (file)
--- a/window.c
+++ b/window.c
@@ -33,6 +33,7 @@
 #include <cairo-drm.h>
 
 #include <linux/input.h>
+#include "wayland-util.h"
 #include "wayland-client.h"
 #include "wayland-glib.h"
 
@@ -490,7 +491,8 @@ window_handle_pointer_focus(void *data,
 static void
 window_handle_keyboard_focus(void *data,
                             struct wl_input_device *input_device,
-                            struct wl_surface *surface)
+                            struct wl_surface *surface,
+                            struct wl_array *keys)
 {
        struct window *window = data;