headless & shell: add headless_input, add seat/focus management to headless_shell... 35/207135/1
authorSung-Jin Park <sj76.park@samsung.com>
Fri, 19 Apr 2019 08:36:28 +0000 (17:36 +0900)
committerSung-Jin Park <sj76.park@samsung.com>
Thu, 30 May 2019 08:32:42 +0000 (17:32 +0900)
Change-Id: I80a03ca0a3ebfc31b4ddbfafe5bbc7bb2e5ed69c
Signed-off-by: Sung-Jin Park <sj76.park@samsung.com>
configure.ac
src/bin/headless/Makefile.am
src/bin/headless/headless_server.c
src/bin/headless/headless_server.h
src/bin/headless/input.c [new file with mode: 0644]
src/bin/headless/shell/shell.c

index 7de0d47..e9ad5f4 100644 (file)
@@ -309,8 +309,8 @@ AC_SUBST(SAMPLES_LIBS)
 # headless server
 HEADLESS_SERVER_REQUIRES="wayland-server capi-system-peripheral-io xdg-shell-unstable-v6-server"
 PKG_CHECK_MODULES(HEADLESS_SERVER, $[HEADLESS_SERVER_REQUIRES])
-HEADLESS_SERVER_CFLAGS="$PEPPER_DIR $HEADLESS_SERVER_CFLAGS"
-HEADLESS_SERVER_LIBS="$PEPPER_LIB $PEPPER_LIBS $HEADLESS_SERVER_LIBS"
+HEADLESS_SERVER_CFLAGS="$PEPPER_DIR $PEPPER_EVDEV_DIR $HEADLESS_SERVER_CFLAGS"
+HEADLESS_SERVER_LIBS="$PEPPER_LIB $PEPPER_LIBS $PEPPER_EVDEV_LIB $PEPPER_EVDEV_LIBS $HEADLESS_SERVER_LIBS"
 
 AC_SUBST(HEADLESS_SERVER_CFLAGS)
 AC_SUBST(HEADLESS_SERVER_LIBS)
index 3803ab0..cf7f936 100644 (file)
@@ -6,6 +6,7 @@ headless_server_CFLAGS = $(HEADLESS_SERVER_CFLAGS)
 headless_server_LDADD  = $(HEADLESS_SERVER_LIBS)
 
 headless_server_SOURCES = headless_server.c \
+                         input.c \
                          output/output_led.c \
                          output/HL_UI_LED_APA102.c \
                          shell/shell.c
index 86a4c5d..7edb780 100644 (file)
@@ -41,10 +41,17 @@ int main(int argc, char *argv[])
        if (!socket_name)
                socket_name = "headless-0";
 
+       if (!getenv("XDG_RUNTIME_DIR"))
+               setenv("XDG_RUNTIME_DIR", "/run", 1);
+
        /* create pepper compositir */
        compositor = pepper_compositor_create(socket_name);
        PEPPER_CHECK(compositor, return EXIT_FAILURE, "Failed to create compositor !");
 
+       /* Init input for headless */
+       ret = headless_input_init(compositor);
+       PEPPER_CHECK(ret, goto end, "headless_input_init() failed\n");
+
        /* Init Output */
        ret = pepper_output_led_init(compositor);
        PEPPER_CHECK(ret, goto end, "pepper_output_led_init() failed.\n");
index 0f4af0f..63b29f4 100644 (file)
@@ -34,6 +34,7 @@ PEPPER_API pepper_bool_t pepper_output_led_init(pepper_compositor_t *compositor)
 PEPPER_API void pepper_output_led_deinit(pepper_compositor_t *compositor);
 
 PEPPER_API pepper_bool_t headless_shell_init(pepper_compositor_t *compositor);
+PEPPER_API pepper_bool_t headless_input_init(pepper_compositor_t *compositor);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/bin/headless/input.c b/src/bin/headless/input.c
new file mode 100644 (file)
index 0000000..cb88ec2
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+* Copyright © 2018 Samsung Electronics co., Ltd. All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+#include <pepper-evdev.h>
+#include <pepper-input-backend.h>
+
+typedef struct
+{
+       pepper_compositor_t *compositor;
+       pepper_evdev_t *evdev;
+       pepper_seat_t *seat;
+
+       pepper_event_listener_t *listener_seat_keyboard_key;
+       pepper_event_listener_t *listener_seat_keyboard_add;
+       pepper_event_listener_t *listener_seat_add;
+       pepper_event_listener_t *listener_input_device_add;
+       pepper_event_listener_t *listener_input_device_remove;
+
+       uint32_t ndevices;
+} headless_input_t;
+
+const static int KEY_INPUT = 0xdeadbeaf;
+
+static void init_event_listeners(headless_input_t *hi);
+static void deinit_event_listeners(headless_input_t *hi);
+
+/* PEPPER_EVENT_KEYBOARD_KEY handler (must be changed to pepper_keyrouter_event_handler) */
+static void
+_handle_keyboard_key(pepper_event_listener_t *listener, pepper_object_t *object, uint32_t id, void *info, void *data)
+{
+       pepper_input_event_t *event;
+       headless_input_t *hi = (headless_input_t *)data;
+       pepper_keyboard_t *keyboard = pepper_seat_get_keyboard(hi->seat);
+
+       event = (pepper_input_event_t *)info;
+       event->key +=8;
+
+       PEPPER_TRACE("[%s] keycode:%d, state=%d\n", __FUNCTION__, event->key, event->state);
+
+       /* send key event to focused client */
+       pepper_view_t *focus_view = pepper_keyboard_get_focus(keyboard);
+       PEPPER_CHECK(focus_view, return, "[%s] No focused view exists.\n", __FUNCTION__);
+       pepper_keyboard_send_key(keyboard, focus_view, event->time, event->key, event->state);
+}
+
+/* seat keyboard add event handler */
+static void
+_handle_seat_keyboard_add(pepper_event_listener_t *listener, pepper_object_t *object, uint32_t id, void *info, void *data)
+{
+       pepper_event_listener_t *h = NULL;
+       pepper_keyboard_t *keyboard = (pepper_keyboard_t *)info;
+       headless_input_t *hi = (headless_input_t *)data;
+
+       PEPPER_TRACE("[%s] keyboard added\n", __FUNCTION__);
+
+       pepper_keyboard_set_keymap_info(keyboard, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP, -1, 0);
+
+       h = pepper_object_add_event_listener((pepper_object_t *)keyboard, PEPPER_EVENT_KEYBOARD_KEY,
+                                                               0, _handle_keyboard_key, hi);
+       PEPPER_CHECK(h, goto end, "Failed to add keyboard key listener.\n");
+       hi->listener_seat_keyboard_key = h;
+
+       return;
+
+end:
+       deinit_event_listeners(hi);
+}
+
+/* compositor input device add event handler */
+static void
+_handle_input_device_add(pepper_event_listener_t *listener, pepper_object_t *object, uint32_t id, void *info, void *data)
+{
+       pepper_input_device_t *device = (pepper_input_device_t *)info;
+       headless_input_t *hi = (headless_input_t *)data;
+
+       /* temporary : only add keyboard device to a seat */
+       if (!(WL_SEAT_CAPABILITY_KEYBOARD & pepper_input_device_get_caps(device)))
+               return;
+
+       PEPPER_TRACE("[%s] input device added.\n", __FUNCTION__);
+
+       if (hi->seat)
+               pepper_seat_add_input_device(hi->seat, device);
+}
+
+/* compositor input device remove event handler */
+static void
+_handle_input_device_remove(pepper_event_listener_t *listener, pepper_object_t *object, uint32_t id, void *info, void *data)
+{
+       pepper_input_device_t *device = (pepper_input_device_t *)info;
+       headless_input_t *hi = (headless_input_t *)data;
+
+       /* temporary : only handle the removal of a keyboard device */
+       if (!(WL_SEAT_CAPABILITY_KEYBOARD & pepper_input_device_get_caps(device)))
+               return;
+
+       PEPPER_TRACE("[%s] input device removed.\n", __FUNCTION__);
+
+       if (hi->seat)
+               pepper_seat_remove_input_device(hi->seat, device);
+}
+
+/* seat add event handler */
+static void
+_handle_seat_add(pepper_event_listener_t *listener, pepper_object_t *object, uint32_t id, void *info, void *data)
+{
+       pepper_event_listener_t *h = NULL;
+       pepper_seat_t *seat = (pepper_seat_t *)info;
+       headless_input_t *hi = (headless_input_t *)data;
+
+       PEPPER_TRACE("[%s] seat added. name:%s\n", __FUNCTION__, pepper_seat_get_name(seat));
+
+       h = pepper_object_add_event_listener((pepper_object_t *)seat, PEPPER_EVENT_SEAT_KEYBOARD_ADD,
+                                                               0, _handle_seat_keyboard_add, hi);
+       PEPPER_CHECK(h, goto end, "Failed to add seat keyboard add listener.\n");
+       hi->listener_seat_keyboard_add = h;
+
+       return;
+
+end:
+       deinit_event_listeners(hi);
+}
+
+static void
+init_event_listeners(headless_input_t *hi)
+{
+       pepper_event_listener_t *h = NULL;
+       pepper_object_t *compositor = (pepper_object_t *)hi->compositor;
+
+       /* register event listeners */
+       h = pepper_object_add_event_listener((pepper_object_t *)compositor,
+                                               PEPPER_EVENT_COMPOSITOR_SEAT_ADD, 0, _handle_seat_add, hi);
+       PEPPER_CHECK(h, goto end, "Failed to add seat add listener.\n");
+       hi->listener_seat_add = h;
+
+       h = pepper_object_add_event_listener((pepper_object_t *)compositor,
+                                               PEPPER_EVENT_COMPOSITOR_INPUT_DEVICE_ADD, 0, _handle_input_device_add, hi);
+       PEPPER_CHECK(h, goto end, "Failed to add input device add listener.\n");
+       hi->listener_input_device_add = h;
+
+       h = pepper_object_add_event_listener((pepper_object_t *)compositor,
+                                               PEPPER_EVENT_COMPOSITOR_INPUT_DEVICE_REMOVE, 0, _handle_input_device_remove, hi);
+       PEPPER_CHECK(h, goto end, "Failed to add input device remove listener.\n");
+       hi->listener_input_device_remove = h;
+
+       return;
+
+end:
+       PEPPER_ERROR("Failed to init listeners");
+       deinit_event_listeners(hi);
+}
+
+static void
+deinit_event_listeners(headless_input_t *hi)
+{
+       pepper_event_listener_remove(hi->listener_seat_keyboard_key);
+       pepper_event_listener_remove(hi->listener_seat_keyboard_add);
+       pepper_event_listener_remove(hi->listener_seat_add);
+       pepper_event_listener_remove(hi->listener_input_device_add);
+       pepper_event_listener_remove(hi->listener_input_device_remove);
+
+       PEPPER_TRACE("[%s] event listeners have been removed.\n");
+}
+
+static void
+input_deinit(headless_input_t *hi)
+{
+       if (hi->seat)
+               pepper_seat_destroy(hi->seat);
+       pepper_evdev_destroy(hi->evdev);
+
+       hi->seat = NULL;
+       hi->evdev = NULL;
+       hi->ndevices = 0;
+}
+
+static pepper_bool_t
+input_init(headless_input_t *hi)
+{
+       uint32_t caps = 0;
+       uint32_t probed = 0;
+
+       const char *seat_name = NULL;
+       pepper_evdev_t *evdev = NULL;
+       pepper_seat_t *seat = NULL;
+
+       seat_name = getenv("XDG_SEAT");
+
+       if (!seat_name)
+               seat_name = "seat0";
+
+       /* create a default seat (seat0) */
+       seat = pepper_compositor_add_seat(hi->compositor, seat_name);
+       PEPPER_CHECK(seat, goto end, "Failed to add seat (%s)!\n", seat_name);
+
+       /* create pepper evdev */
+       evdev = pepper_evdev_create(hi->compositor);
+       PEPPER_CHECK(evdev, goto end, "Failed to create evdev !\n");
+
+       /* probe evdev keyboard device(s) */
+       caps |= WL_SEAT_CAPABILITY_KEYBOARD;
+       probed = pepper_evdev_device_probe(evdev, caps);
+
+       if (!probed)
+               PEPPER_TRACE("No evdev devices have been probed.\n");
+       else
+               PEPPER_TRACE("%d evdev device(s) has been probed.\n", probed);
+
+       hi->evdev = evdev;
+       hi->seat = seat;
+       hi->ndevices = probed;
+
+       return PEPPER_TRUE;
+
+end:
+       if (seat)
+               pepper_seat_destroy(seat);
+       pepper_evdev_destroy(evdev);
+
+       return PEPPER_FALSE;
+}
+
+static void
+headless_input_deinit(void *data)
+{
+       headless_input_t *hi = (headless_input_t*)data;
+
+       if (!hi) return;
+
+       deinit_event_listeners(hi);
+       input_deinit(hi);
+
+       pepper_object_set_user_data((pepper_object_t *)hi->compositor, &KEY_INPUT, NULL, NULL);
+       free(hi);
+}
+
+pepper_bool_t
+headless_input_init(pepper_compositor_t *compositor)
+{
+       headless_input_t *hi = NULL;
+       pepper_bool_t init = PEPPER_FALSE;
+
+       hi = (headless_input_t*)calloc(1, sizeof(headless_input_t));
+       PEPPER_CHECK(hi, goto error, "Failed to alloc for input\n");
+       hi->compositor = compositor;
+
+       init_event_listeners(hi);
+       init = input_init(hi);
+       PEPPER_CHECK(init, goto error, "input_init() failed\n");
+
+       pepper_object_set_user_data((pepper_object_t *)compositor, &KEY_INPUT, NULL, headless_input_deinit);
+
+       return PEPPER_TRUE;
+
+error:
+       headless_input_deinit(hi);
+
+       return PEPPER_FALSE;
+}
index 6f0e405..41e01aa 100644 (file)
 typedef struct {
        pepper_compositor_t *compositor;
        struct wl_global *zxdg_shell;
+
+       pepper_seat_t *seat;
+       pepper_event_listener_t *seat_add_listener;
+       pepper_event_listener_t  *seat_remove_listener;
 }headless_shell_t;
 
 typedef struct {
@@ -422,6 +426,25 @@ zxdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource
                        hs_surface->zxdg_shell_surface,
                        hs_surface->view,
                        psurface);
+
+       /* temporary focus view set */
+       if (!hs->seat)
+               return;
+
+       pepper_keyboard_t *keyboard = pepper_seat_get_keyboard(hs->seat);
+       PEPPER_CHECK(keyboard, return, "[%s] pepper_keyboard is null !", __FUNCTION__);
+
+       pepper_view_t *focus = pepper_keyboard_get_focus(keyboard);
+
+       if (!focus || focus != hs_surface->view) {
+               if (focus) pepper_keyboard_send_leave(keyboard, focus);
+               pepper_keyboard_set_focus(keyboard, hs_surface->view);
+               pepper_keyboard_send_enter(keyboard, hs_surface->view);
+       }
+
+       /* temporary top view set */
+       pepper_view_stack_top(hs_surface->view, PEPPER_FALSE);
+
        return;
 error:
        if (hs_surface) {
@@ -493,11 +516,64 @@ zxdg_deinit(headless_shell_t *shell)
 }
 
 static void
+_seat_add_callback(pepper_event_listener_t    *listener,
+                                 pepper_object_t            *object,
+                                 uint32_t                    id,
+                                 void                       *info,
+                                 void                       *data)
+{
+       headless_shell_t *shell = (headless_shell_t *)data;
+       shell->seat = (pepper_seat_t *)info;
+
+       if (shell->seat)
+               PEPPER_TRACE("[%s] seat added (name:%s)\n", __FUNCTION__, pepper_seat_get_name(shell->seat));
+       else
+               PEPPER_TRACE("[%s] seat is NULL.\n", __FUNCTION__);
+}
+
+static void
+_seat_remove_callback(pepper_event_listener_t    *listener,
+                                        pepper_object_t            *object,
+                                        uint32_t                    id,
+                                        void                       *info,
+                                        void                       *data)
+{
+       headless_shell_t *shell = (headless_shell_t *)data;
+
+       if (shell->seat)
+               PEPPER_TRACE("[%s] seat removed (name:%s)\n", __FUNCTION__, pepper_seat_get_name(shell->seat));
+       else
+               PEPPER_TRACE("[%s] seat is NULL.\n", __FUNCTION__);
+
+       shell->seat = NULL;
+}
+
+static void
+init_listeners(headless_shell_t *shell)
+{
+       shell->seat_add_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor,
+                                                               PEPPER_EVENT_COMPOSITOR_SEAT_ADD,
+                                                               0, _seat_add_callback, shell);
+
+       shell->seat_remove_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor,
+                                                               PEPPER_EVENT_COMPOSITOR_SEAT_REMOVE,
+                                                               0, _seat_remove_callback, shell);
+}
+
+static void
+deinit_listeners(headless_shell_t *shell)
+{
+       pepper_event_listener_remove(shell->seat_add_listener);
+       pepper_event_listener_remove(shell->seat_remove_listener);
+}
+
+static void
 headless_shell_deinit(void *data)
 {
        headless_shell_t *shell = (headless_shell_t*)data;
        if (!shell) return;
 
+       deinit_listeners(shell);
        zxdg_deinit(shell);
 
        pepper_object_set_user_data((pepper_object_t *)shell->compositor, &KEY_SHELL, NULL, NULL);
@@ -513,6 +589,7 @@ headless_shell_init(pepper_compositor_t *compositor)
        PEPPER_CHECK(shell, goto error, "fail to alloc for shell\n");
        shell->compositor = compositor;
 
+       init_listeners(shell);
        PEPPER_CHECK(zxdg_init(shell), goto error, "zxdg_init() failed\n");
 
        pepper_object_set_user_data((pepper_object_t *)compositor, &KEY_SHELL, NULL, headless_shell_deinit);