examples/tinyds: Handle ds_keyboard 71/278171/1
authorSeunghun Lee <shiin.lee@samsung.com>
Wed, 20 Apr 2022 02:29:17 +0000 (11:29 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:58:28 +0000 (14:58 +0900)
tinyds now handles ds_keyboard, and it may be terminated by pressing
Alt + Ctrl + Shift + BackSapce.

Change-Id: I6333e2b239f3d7b28e62ca3997180e1428c9c4f7

src/examples/tinyds.c

index a4c1042..cfa55a6 100644 (file)
 #include <libds/swapchain.h>
 #include <libds/compositor.h>
 #include <libds/xdg_shell.h>
+#include <libds/input_device.h>
+#include <libds/keyboard.h>
 
 #define TINYDS_UNUSED   __attribute__((unused))
 
 #define OUTPUT_WIDTH   1280
 #define OUTPUT_HEIGHT  720
 
+struct tinyds_server;
+
+struct tinyds_keyboard
+{
+    struct ds_input_device *dev;
+    struct tinyds_server *server;
+
+    struct wl_listener destroy;
+    struct wl_listener key;
+};
+
 struct tinyds_output
 {
     struct tinyds_server *server;
@@ -54,6 +67,7 @@ struct tinyds_server
     struct wl_list views;
     struct wl_list outputs;
 
+    struct wl_listener new_input;
     struct wl_listener new_xdg_surface;
 };
 
@@ -77,6 +91,7 @@ struct tinyds_server _tinyds;
 
 static bool init_server(struct tinyds_server *server, struct wl_display *display);
 static void fini_server(struct tinyds_server *server);
+static void server_handle_new_input(struct wl_listener *listener, void *data);
 static bool init_output(struct tinyds_output *output, struct tinyds_server *server,
         int width, int height);
 static void fini_output(struct tinyds_output *output);
@@ -240,6 +255,9 @@ init_server(struct tinyds_server *server, struct wl_display *display)
     if (!server->backend)
         return false;
 
+    server->new_input.notify = server_handle_new_input;
+    ds_backend_add_new_input_listener(server->backend, &server->new_input);
+
     server->compositor = ds_compositor_create(display);
     if (!server->compositor) {
         ds_backend_destroy(server->backend);
@@ -439,3 +457,103 @@ view_send_frame_done(struct tinyds_view *view)
     ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
             &now);
 }
+
+static void
+keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
+{
+    struct tinyds_keyboard *kbd;
+
+    kbd = wl_container_of(listener, kbd, destroy);
+
+    ds_inf("Keyboard(%p) destroyed", kbd);
+
+    wl_list_remove(&kbd->destroy.link);
+    wl_list_remove(&kbd->key.link);
+
+    free(kbd);
+}
+
+static bool
+server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
+{
+    switch (sym) {
+        case XKB_KEY_BackSpace:
+            wl_display_terminate(server->display);
+            break;
+        default:
+            return false;
+    }
+
+    return true;
+}
+
+static void
+keyboard_handle_key(struct wl_listener *listener, void *data)
+{
+    struct tinyds_keyboard *kbd;
+    struct ds_event_keyboard_key *event = data;
+    struct ds_keyboard *ds_keyboard;
+    struct xkb_state *xkb_state;
+    const xkb_keysym_t *syms;
+    uint32_t modifiers;
+    int nsyms;
+
+    kbd = wl_container_of(listener, kbd, key);
+
+    ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
+
+    modifiers = ds_keyboard_get_modifiers(ds_keyboard);
+    if ((modifiers & DS_MODIFIER_CTRL) &&
+            (modifiers & DS_MODIFIER_ALT) &&
+            (modifiers & DS_MODIFIER_SHIFT) &&
+            event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+        xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
+        if (xkb_state) {
+            nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
+                    &syms);
+            for (int i = 0; i < nsyms; i++) {
+                server_handle_keybinding(kbd->server, syms[i]);
+            }
+        }
+    }
+}
+
+static void
+server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
+{
+    struct tinyds_keyboard *kbd;
+
+    kbd = calloc(1, sizeof *kbd);
+    assert(kbd);
+
+    kbd->dev = dev;
+    kbd->server = server;
+
+    kbd->destroy.notify = keyboard_handle_device_destroy;
+    ds_input_device_add_destroy_listener(dev, &kbd->destroy);
+
+    kbd->key.notify = keyboard_handle_key;
+    ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
+
+    ds_inf("Keyboard(%p) added", kbd);
+}
+
+static void
+server_handle_new_input(struct wl_listener *listener, void *data)
+{
+    struct tinyds_server *server;
+    struct ds_input_device *dev = data;
+    enum ds_input_device_type dev_type;
+
+    server = wl_container_of(listener, server, new_input);
+
+    dev_type = ds_input_device_get_type(dev);
+    switch (dev_type) {
+        case DS_INPUT_DEVICE_KEYBOARD:
+            server_add_keyboard(server, dev);
+            break;
+        default:
+            ds_err("Unknown type(%d) of ds_input_device", dev_type);
+            break;
+    }
+}