seat: Add ds_seat_set_keyboard() 07/278107/1
authorSeunghun Lee <shiin.lee@samsung.com>
Wed, 29 Jun 2022 07:19:52 +0000 (16:19 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:08:59 +0000 (14:08 +0900)
The ds_seat_set_keyboard() enables a seat to refer to a ds_keyboard, so
that the seat reads keymap and repeat info from ds_keyboard and then
sends them to the wayland clients.

Change-Id: Ic20fa041f391d0f8c73c8a6818505525701e3929

include/libds/seat.h
src/keyboard.c
src/keyboard.h [new file with mode: 0644]
src/seat/seat_keyboard.c
src/seat/seat_private.h

index e55fc4c..928861d 100644 (file)
@@ -95,6 +95,8 @@ void ds_seat_set_capabilities(struct ds_seat *seat,
 
 void ds_seat_set_name(struct ds_seat *seat, const char *name);
 
+void ds_seat_set_keyboard(struct ds_seat *seat, struct ds_input_device *device);
+
 void ds_seat_add_destroy_listener(struct ds_seat *seat,
         struct wl_listener *listener);
 
index d122e81..72467ee 100644 (file)
@@ -246,6 +246,10 @@ ds_keyboard_init(struct ds_keyboard *keyboard,
     keyboard->iface = iface;
     keyboard->keymap_fd = -1;
 
+    // Sane defaults
+    keyboard->repeat_info.rate = 25;
+    keyboard->repeat_info.delay = 600;
+
     wl_signal_init(&keyboard->events.destroy);
     wl_signal_init(&keyboard->events.key);
     wl_signal_init(&keyboard->events.modifiers);
@@ -262,6 +266,33 @@ ds_keyboard_destroy(struct ds_keyboard *keyboard)
         free(keyboard);
 }
 
+bool
+ds_keyboard_get_keymap_fd(struct ds_keyboard *keyboard, int *keymap_fd,
+        size_t *keymap_size)
+{
+    if (keyboard->keymap_fd < 0)
+        return false;
+
+    if (keymap_fd)
+        *keymap_fd = keyboard->keymap_fd;
+
+    if (keymap_size)
+        *keymap_size = keyboard->keymap_size;
+
+    return true;
+}
+
+void
+ds_keyboard_get_repeat_info(struct ds_keyboard *keyboard, int32_t *rate,
+        int32_t *delay)
+{
+    if (rate)
+        *rate = keyboard->repeat_info.rate;
+
+    if (delay)
+        *delay = keyboard->repeat_info.delay;
+}
+
 static bool
 keyboard_modifier_update(struct ds_keyboard *keyboard)
 {
diff --git a/src/keyboard.h b/src/keyboard.h
new file mode 100644 (file)
index 0000000..193501d
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef DS_KEYBOARD_H
+#define DS_KEYBOARD_H
+
+#include "libds/keyboard.h"
+
+bool ds_keyboard_get_keymap_fd(struct ds_keyboard *keyboard, int *keymap_fd,
+        size_t *keymap_size);
+
+void ds_keyboard_get_repeat_info(struct ds_keyboard *keyboard, int32_t *rate,
+        int32_t *delay);
+
+#endif
index b022163..4846711 100644 (file)
@@ -4,6 +4,7 @@
 #include <time.h>
 
 #include "libds/log.h"
+#include "keyboard.h"
 #include "seat_private.h"
 
 static const struct ds_keyboard_grab_interface default_keyboard_grab_iface;
@@ -12,10 +13,47 @@ static const struct wl_keyboard_interface keyboard_impl;
 static void
 seat_client_send_keyboard_leave_raw(struct ds_seat_client *seat_client,
         struct ds_surface *surface);
-static void
-seat_keyboard_handle_surface_destroy(struct wl_listener *listener,
+static void seat_client_send_keymap(struct ds_seat_client *seat_client,
+        struct ds_keyboard *ds_keyboard);
+static void seat_client_send_repeat_info(struct ds_seat_client *seat_client,
+        struct ds_keyboard *ds_keyboard);
+static void seat_keyboard_handle_surface_destroy(struct wl_listener *listener,
         void *data);
 static void keyboard_handle_resource_destroy(struct wl_resource *resource);
+static void seat_keyboard_set_keyboard(struct ds_seat_keyboard *keyboard,
+        struct ds_input_device *device);
+static void seat_keyboard_unset_keyboard(struct ds_seat_keyboard *keyboard);
+static void seat_keyboard_handle_keyboard_destroy(struct wl_listener *listener,
+        void *data);
+static void seat_keyboard_handle_keymap(struct wl_listener *listener,
+        void *data);
+static void seat_keyboard_handle_repeat_info(struct wl_listener *listener,
+        void *data);
+
+WL_EXPORT void
+ds_seat_set_keyboard(struct ds_seat *seat, struct ds_input_device *device)
+{
+    struct ds_seat_keyboard *keyboard = &seat->keyboard;
+    struct ds_keyboard *ds_keyboard = NULL;
+
+    if (device) {
+        if (ds_input_device_get_type(device) != DS_INPUT_DEVICE_KEYBOARD) {
+            ds_err("Given device is not a keyboard");
+            return;
+        }
+
+        ds_keyboard = ds_input_device_get_keyboard(device);
+    }
+
+    if (keyboard->ds_keyboard == ds_keyboard)
+        return;
+
+    if (keyboard->ds_keyboard)
+        seat_keyboard_unset_keyboard(keyboard);
+
+    if (ds_keyboard)
+        seat_keyboard_set_keyboard(keyboard, device);
+}
 
 WL_EXPORT void
 ds_seat_keyboard_notify_enter(struct ds_seat *seat,
@@ -293,6 +331,7 @@ seat_client_add_keyboard_resource(struct ds_seat_client *seat_client,
         uint32_t version, uint32_t id)
 {
     struct wl_resource *resource;
+    struct ds_keyboard *ds_keyboard;
 
     resource = wl_resource_create(seat_client->wl_client,
             &wl_keyboard_interface, version, id);
@@ -310,6 +349,13 @@ seat_client_add_keyboard_resource(struct ds_seat_client *seat_client,
         wl_resource_set_user_data(resource, NULL);
         return;
     }
+
+    ds_keyboard = seat_client->seat->keyboard.ds_keyboard;
+    if (!ds_keyboard)
+        return;
+
+    seat_client_send_keymap(seat_client, ds_keyboard);
+    seat_client_send_repeat_info(seat_client, ds_keyboard);
 }
 
 void
@@ -401,6 +447,43 @@ seat_client_send_keyboard_leave_raw(struct ds_seat_client *seat_client,
 }
 
 static void
+seat_client_send_keymap(struct ds_seat_client *seat_client,
+        struct ds_keyboard *ds_keyboard)
+{
+    struct wl_resource *resource;
+    int fd;
+    size_t size;
+
+    if (!ds_keyboard_get_keymap_fd(ds_keyboard, &fd, &size)) {
+        ds_err("Failed to get keymap fd from ds_keyboard(%p)", ds_keyboard);
+        return;
+    }
+
+    wl_resource_for_each(resource, &seat_client->keyboards) {
+        wl_keyboard_send_keymap(resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
+                fd, size);
+    }
+}
+
+static void
+seat_client_send_repeat_info(struct ds_seat_client *seat_client,
+        struct ds_keyboard *ds_keyboard)
+{
+    struct wl_resource *resource;
+    int32_t rate, delay;
+
+    ds_keyboard_get_repeat_info(ds_keyboard, &rate, &delay);
+
+    wl_resource_for_each(resource, &seat_client->keyboards) {
+        if (wl_resource_get_version(resource) <
+                WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
+            continue;
+
+        wl_keyboard_send_repeat_info(resource, rate, delay);
+    }
+}
+
+static void
 seat_keyboard_handle_surface_destroy(struct wl_listener *listener,
         void *data)
 {
@@ -412,3 +495,72 @@ seat_keyboard_handle_surface_destroy(struct wl_listener *listener,
     wl_list_init(&keyboard->surface_destroy.link);
     ds_seat_keyboard_clear_focus(keyboard->seat);
 }
+
+static void
+seat_keyboard_set_keyboard(struct ds_seat_keyboard *keyboard,
+        struct ds_input_device *device)
+{
+    struct ds_seat_client *seat_client;
+
+    keyboard->ds_keyboard = ds_input_device_get_keyboard(device);
+
+    keyboard->keyboard_destroy.notify = seat_keyboard_handle_keyboard_destroy;
+    ds_input_device_add_destroy_listener(device, &keyboard->keyboard_destroy);
+
+    keyboard->keymap.notify = seat_keyboard_handle_keymap;
+    ds_keyboard_add_keymap_listener(keyboard->ds_keyboard, &keyboard->keymap);
+
+    keyboard->repeat_info.notify = seat_keyboard_handle_repeat_info;
+    ds_keyboard_add_repeat_info_listener(keyboard->ds_keyboard,
+            &keyboard->repeat_info);
+
+    wl_list_for_each(seat_client, &keyboard->seat->clients, link) {
+        seat_client_send_keymap(seat_client, keyboard->ds_keyboard);
+        seat_client_send_repeat_info(seat_client, keyboard->ds_keyboard);
+    }
+}
+
+static void
+seat_keyboard_unset_keyboard(struct ds_seat_keyboard *keyboard)
+{
+    wl_list_remove(&keyboard->keyboard_destroy.link);
+    wl_list_remove(&keyboard->keymap.link);
+    wl_list_remove(&keyboard->repeat_info.link);
+
+    keyboard->ds_keyboard = NULL;
+}
+
+static void
+seat_keyboard_handle_keyboard_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_seat_keyboard *keyboard;
+
+    keyboard = wl_container_of(listener, keyboard, keyboard_destroy);
+
+    seat_keyboard_unset_keyboard(keyboard);
+}
+
+static void
+seat_keyboard_handle_keymap(struct wl_listener *listener, void *data)
+{
+    struct ds_seat_keyboard *keyboard;
+    struct ds_seat_client *seat_client;
+
+    keyboard = wl_container_of(listener, keyboard, keymap);
+
+    wl_list_for_each(seat_client, &keyboard->seat->clients, link)
+        seat_client_send_keymap(seat_client, keyboard->ds_keyboard);
+}
+
+static void
+seat_keyboard_handle_repeat_info(struct wl_listener *listener,
+        void *data)
+{
+    struct ds_seat_keyboard *keyboard;
+    struct ds_seat_client *seat_client;
+
+    keyboard = wl_container_of(listener, keyboard, repeat_info);
+
+    wl_list_for_each(seat_client, &keyboard->seat->clients, link)
+        seat_client_send_repeat_info(seat_client, keyboard->ds_keyboard);
+}
index 7a566bb..eeaa6ba 100644 (file)
@@ -57,11 +57,15 @@ struct ds_seat_pointer
 struct ds_seat_keyboard
 {
     struct ds_seat *seat;
+    struct ds_keyboard *ds_keyboard;
 
     struct ds_seat_client *focused_client;
     struct ds_surface *focused_surface;
 
     struct wl_listener surface_destroy;
+    struct wl_listener keyboard_destroy;
+    struct wl_listener keymap;
+    struct wl_listener repeat_info;
 
     struct ds_seat_keyboard_grab *grab;
     struct ds_seat_keyboard_grab *default_grab;