backend/wayland: Support ds_keyboard 67/278167/1
authorSeunghun Lee <shiin.lee@samsung.com>
Mon, 18 Apr 2022 01:33:19 +0000 (10:33 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:58:26 +0000 (14:58 +0900)
Change-Id: Ifadcdd2649fd8c7d3d912b107c2d531801cb189e

src/libds/backend/wayland/backend.h
src/libds/backend/wayland/seat.c
src/libds/util.h
src/libds/util/time.c

index 12e594a..c35f7d1 100644 (file)
@@ -5,6 +5,7 @@
 #include "libds/interfaces/output.h"
 #include "libds/interfaces/input_device.h"
 #include "libds/interfaces/pointer.h"
+#include "libds/interfaces/keyboard.h"
 
 struct ds_wl_backend_server
 {
@@ -103,6 +104,13 @@ struct ds_wl_pointer
     struct wl_pointer *wl_pointer;
 };
 
+struct ds_wl_keyboard
+{
+    struct ds_keyboard base;
+
+    struct wl_keyboard *wl_keyboard;
+};
+
 struct ds_wl_backend *
 wl_backend_from_backend(struct ds_backend *backend);
 
index c569947..966bf77 100644 (file)
@@ -3,11 +3,14 @@
 #include <stdlib.h>
 #include <string.h>
 #include <alloca.h>
+#include <sys/mman.h>
 #include <wayland-client.h>
+#include <xkbcommon/xkbcommon.h>
 
 #include "libds/log.h"
 #include "libds/pointer.h"
 
+#include "util.h"
 #include "backend.h"
 
 #ifdef MIN
@@ -25,6 +28,7 @@ static struct ds_input_device *
 create_wl_input_device(struct ds_wl_seat *seat,
         enum ds_input_device_type type);
 static struct ds_pointer *create_wl_pointer(struct ds_wl_seat *seat);
+static struct ds_keyboard *create_wl_keyboard(struct ds_wl_seat *seat);
 
 struct ds_wl_seat *
 create_wl_seat(struct ds_wl_backend *backend, uint32_t id,
@@ -151,6 +155,10 @@ seat_update_capabilities(struct ds_wl_seat *seat, enum wl_seat_capability caps)
 
         seat->keyboard_dev = create_wl_input_device(seat,
                 DS_INPUT_DEVICE_KEYBOARD);
+        seat->keyboard_dev->keyboard = create_wl_keyboard(seat);
+
+        wl_signal_emit(&seat->backend->base.events.new_input,
+                seat->keyboard_dev);
     }
     else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) &&
             seat->keyboard_dev != NULL) {
@@ -405,3 +413,191 @@ create_wl_pointer(struct ds_wl_seat *seat)
 
     return &pointer->base;
 }
+
+static const struct ds_keyboard_interface keyboard_iface;
+
+static struct ds_wl_keyboard *
+get_wl_keyboard_from_keyboard(struct ds_keyboard *ds_keyboard)
+{
+    assert(ds_keyboard->iface == &keyboard_iface);
+    return (struct ds_wl_keyboard *)ds_keyboard;
+}
+
+static void
+keyboard_iface_destroy(struct ds_keyboard *ds_keyboard)
+{
+    struct ds_wl_keyboard *keyboard;
+
+    keyboard = get_wl_keyboard_from_keyboard(ds_keyboard);
+
+    wl_keyboard_release(keyboard->wl_keyboard);
+
+    free(keyboard);
+}
+
+static const struct ds_keyboard_interface keyboard_iface = {
+    .destroy = keyboard_iface_destroy,
+};
+
+static void
+keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
+        uint32_t format, int fd, uint32_t size)
+{
+    struct ds_wl_seat *seat = data;
+    struct xkb_context *context;
+    struct xkb_keymap *keymap;
+    char *map_str;
+
+    ds_dbg("wl_keyboard: keymap");
+
+    if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+        map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+        if (map_str == MAP_FAILED) {
+            ds_log_errno(DS_ERR, "mmap failed");
+            goto end;
+        }
+
+        context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+        keymap = xkb_keymap_new_from_string(context, map_str,
+                XKB_KEYMAP_FORMAT_TEXT_V1, 0);
+        munmap(map_str, size);
+
+        if (!keymap) {
+            ds_err("Failed to compile keymap");
+            goto end;
+        }
+
+        ds_keyboard_set_keymap(seat->keyboard_dev->keyboard, keymap);
+
+        xkb_keymap_unref(keymap);
+        xkb_context_unref(context);
+    }
+
+    // TODO More case?
+
+end:
+    close(fd);
+}
+
+static void
+keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
+        uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
+{
+    struct ds_wl_seat *seat = data;
+    uint32_t *keycode_ptr;
+    uint32_t time;
+
+    ds_dbg("wl_keyboard: enter");
+
+    time = get_current_time_msec();
+
+    wl_array_for_each(keycode_ptr, keys) {
+        struct ds_event_keyboard_key event = {
+            .keycode = *keycode_ptr,
+            .state = WL_KEYBOARD_KEY_STATE_PRESSED,
+            .time_msec = time,
+            .update_state = false,
+        };
+
+        ds_keyboard_notify_key(seat->keyboard_dev->keyboard, &event);
+    }
+}
+
+static void
+keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
+        uint32_t serial, struct wl_surface *surface)
+{
+    struct ds_wl_seat *seat = data;
+    struct ds_keyboard *keyboard = seat->keyboard_dev->keyboard;
+    uint32_t *pressed;
+    uint32_t time, keycode;
+    size_t num_keycodes;
+
+    ds_dbg("wl_keyboard: leave");
+
+    time = get_current_time_msec();
+
+    num_keycodes = keyboard->num_keycodes;
+    pressed = alloca(num_keycodes + 1);
+    memcpy(pressed, keyboard->keycodes, num_keycodes * sizeof(uint32_t));
+
+    for (size_t i = 0; i < num_keycodes; i++) {
+        keycode = pressed[i];
+
+        struct ds_event_keyboard_key event = {
+            .keycode = keycode,
+            .state = WL_KEYBOARD_KEY_STATE_RELEASED,
+            .time_msec = time,
+            .update_state = false,
+        };
+
+        ds_keyboard_notify_key(keyboard, &event);
+    }
+}
+
+static void
+keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
+        uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
+{
+    struct ds_wl_seat *seat = data;
+
+    ds_dbg("wl_keyboard: key");
+
+    struct ds_event_keyboard_key event = {
+        .keycode = key,
+        .state = state,
+        .time_msec = time,
+        .update_state = false,
+    };
+
+    ds_keyboard_notify_key(seat->keyboard_dev->keyboard, &event);
+}
+
+static void
+keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
+        uint32_t serial_in, uint32_t mods_depressed, uint32_t mods_latched,
+        uint32_t mods_locked, uint32_t group)
+{
+    struct ds_wl_seat *seat = data;
+
+    ds_dbg("wl_keyboard: modifiers");
+
+    ds_keyboard_notify_modifiers(seat->keyboard_dev->keyboard,
+            mods_depressed, mods_latched, mods_locked, group);
+}
+
+static void
+keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
+        int32_t rate, int32_t delay)
+{
+    ds_dbg("wl_keyboard: repeat_info");
+
+    // This space is intentionally left blank
+}
+
+static const struct wl_keyboard_listener wl_keyboard_listener = {
+    .keymap = keyboard_handle_keymap,
+    .enter = keyboard_handle_enter,
+    .leave = keyboard_handle_leave,
+    .key = keyboard_handle_key,
+    .modifiers = keyboard_handle_modifiers,
+    .repeat_info = keyboard_handle_repeat_info,
+};
+
+static struct ds_keyboard *
+create_wl_keyboard(struct ds_wl_seat *seat)
+{
+    struct ds_wl_keyboard *keyboard;
+
+    keyboard = calloc(1, sizeof *keyboard);
+    if (!keyboard)
+        return NULL;
+
+    ds_keyboard_init(&keyboard->base, &keyboard_iface);
+
+    keyboard->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat);
+    wl_keyboard_add_listener(keyboard->wl_keyboard,
+            &wl_keyboard_listener, seat);
+
+    return &keyboard->base;
+}
index 1c9326a..4603544 100644 (file)
@@ -7,6 +7,9 @@
 int64_t
 timespec_to_msec(const struct timespec *a);
 
+uint32_t
+get_current_time_msec(void);
+
 int
 allocate_shm_file(size_t size);
 
index afb0e89..2461cb7 100644 (file)
@@ -8,3 +8,12 @@ timespec_to_msec(const struct timespec *a)
 {
     return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
 }
+
+uint32_t
+get_current_time_msec(void)
+{
+    struct timespec now;
+
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    return timespec_to_msec(&now);
+}