From db289d856aad2a62df2f2175c5995906715e2435 Mon Sep 17 00:00:00 2001 From: Sung-Jin Park Date: Fri, 19 Apr 2019 17:36:28 +0900 Subject: [PATCH] headless & shell: add headless_input, add seat/focus management to headless_shell (temp) Change-Id: I80a03ca0a3ebfc31b4ddbfafe5bbc7bb2e5ed69c Signed-off-by: Sung-Jin Park --- configure.ac | 4 +- src/bin/headless/Makefile.am | 1 + src/bin/headless/headless_server.c | 7 + src/bin/headless/headless_server.h | 1 + src/bin/headless/input.c | 278 +++++++++++++++++++++++++++++++++++++ src/bin/headless/shell/shell.c | 77 ++++++++++ 6 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 src/bin/headless/input.c diff --git a/configure.ac b/configure.ac index 7de0d47..e9ad5f4 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/src/bin/headless/Makefile.am b/src/bin/headless/Makefile.am index 3803ab0..cf7f936 100644 --- a/src/bin/headless/Makefile.am +++ b/src/bin/headless/Makefile.am @@ -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 diff --git a/src/bin/headless/headless_server.c b/src/bin/headless/headless_server.c index 86a4c5d..7edb780 100644 --- a/src/bin/headless/headless_server.c +++ b/src/bin/headless/headless_server.c @@ -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"); diff --git a/src/bin/headless/headless_server.h b/src/bin/headless/headless_server.h index 0f4af0f..63b29f4 100644 --- a/src/bin/headless/headless_server.h +++ b/src/bin/headless/headless_server.h @@ -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 index 0000000..cb88ec2 --- /dev/null +++ b/src/bin/headless/input.c @@ -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 +#include + +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; +} diff --git a/src/bin/headless/shell/shell.c b/src/bin/headless/shell/shell.c index 6f0e405..41e01aa 100644 --- a/src/bin/headless/shell/shell.c +++ b/src/bin/headless/shell/shell.c @@ -31,6 +31,10 @@ 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); -- 2.7.4