From 0b7b11607617abe39b7f458869a17d84fa78da87 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 8 Aug 2022 15:55:50 +0900 Subject: [PATCH] merge tizends-tdm-libinput code to tinyds-tdm Change-Id: Iac7a17b98776e88eb1a434f7318ed69c7cf839c8 --- examples/meson.build | 19 - examples/tinyds-tdm-libinput.c | 1369 ---------------------------------------- examples/tinyds-tdm.c | 820 +++++++++++++++++++++++- packaging/libds-tizen.spec | 1 - 4 files changed, 805 insertions(+), 1404 deletions(-) delete mode 100644 examples/tinyds-tdm-libinput.c diff --git a/examples/meson.build b/examples/meson.build index ec5c244..3370f26 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -29,25 +29,6 @@ executable('tinyds-tdm', deps_libds_tizen_backend_tdm, deps_libds_tizen_tbm_server, deps_libds_tizen_dpms, - dependency('pixman-1', required: true), - dependency('threads', required: true), - ], - install_dir: libds_tizen_bindir, - install : true -) - -tinyds_tdm_libinput_files = [ - 'tinyds-tdm-libinput.c', - 'pixman-helper.c', - 'pixman-tbm-helper.c', - 'tinyds-tdm-renderer.c', -] - -executable('tinyds-tdm-libinput', - tinyds_tdm_libinput_files, - dependencies: [ - common_deps, - deps_libds_tizen_backend_tdm, deps_libds_tizen_input_devicemgr, deps_libds_tizen_launch, dependency('pixman-1', required: true), diff --git a/examples/tinyds-tdm-libinput.c b/examples/tinyds-tdm-libinput.c deleted file mode 100644 index faf666b..0000000 --- a/examples/tinyds-tdm-libinput.c +++ /dev/null @@ -1,1369 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define USE_TDM_BUFFER_QUEUE - -#ifdef USE_TDM_BUFFER_QUEUE -#include "pixman-tbm-helper.h" -#include "tinyds-tdm-renderer.h" -#else -#include -#endif - -#include "pixman-helper.h" - -#define TINYDS_UNUSED __attribute__((unused)) -struct tinyds_keyboard; -struct tinyds_pointer; - -struct tinyds_output -{ - struct tinyds_server *server; - struct ds_output *ds_output; - struct ds_allocator *allocator; -#ifdef USE_TDM_BUFFER_QUEUE - struct tinyds_renderer renderer; - struct ds_tdm_buffer_queue *buffer_queue; - struct wl_listener buffer_queue_acquirable; -#else - struct ds_swapchain *swapchain; -#endif - struct ds_buffer *front_buffer; - - struct wl_listener output_destroy; - struct wl_listener output_frame; - - int width, height; - - bool drawable; - bool damaged; -}; - -struct tinyds_server -{ - struct ds_tbm_server *tbm_server; - - struct wl_display *display; - - struct ds_backend *backend; - struct ds_backend *input_backend; - struct ds_compositor *compositor; - struct ds_xdg_shell *xdg_shell; - struct ds_seat *seat; - uint32_t seat_caps; - double output_x, output_y; - struct ds_tizen_input_devicemgr *devicemgr; - struct ds_tizen_effect *effect; - struct ds_tizen_splash *splash; - - struct tinyds_output *output; - struct wl_event_source *stdin_source; - - struct wl_list views; - - struct wl_listener new_output; - struct wl_listener new_input; - struct wl_listener new_xdg_surface; - struct wl_listener devicemgr_destroy; - struct wl_listener pointer_warp; - struct wl_listener effect_destroy; - struct wl_listener effect_type_set; - struct wl_listener effect_type_unset; - struct wl_listener new_splash; - struct wl_listener splash_owner; - - struct wl_list keyboards; - struct wl_list pointers; -}; - -struct tinyds_view -{ - struct tinyds_server *server; - - struct tinyds_texture *texture; - struct ds_xdg_surface *xdg_surface; - - struct wl_listener xdg_surface_map; - struct wl_listener xdg_surface_unmap; - struct wl_listener xdg_surface_destroy; - struct wl_listener surface_commit; - struct wl_list link; // tinyds_server::views - - int x, y; - bool mapped; - - pid_t pid; - int effect_type; -}; - -struct tinyds_pointer -{ - struct ds_input_device *dev; - struct tinyds_server *server; - - struct tinyds_view *focused_view; - - struct wl_listener destroy; - struct wl_listener motion; //relative - struct wl_listener button; - struct wl_listener frame; - struct wl_list link; //tinyds_server::pointers -}; - -struct tinyds_keyboard -{ - struct ds_input_device *dev; - struct tinyds_server *server; - - struct wl_listener destroy; - struct wl_listener key; - struct wl_list link; //tinyds_server::keyboards -}; - -struct tinyds_touch -{ - struct ds_input_device *dev; - struct tinyds_server *server; - - struct wl_listener destroy; - struct wl_listener down; - struct wl_listener up; - struct wl_listener motion; -}; - -struct tinyds_server tinyds; - -static bool init_server(struct tinyds_server *server, struct wl_display *display); -static int server_dispatch_stdin(int fd, uint32_t mask, void *data); -static void output_handle_destroy(struct wl_listener *listener, void *data); -static void output_handle_frame(struct wl_listener *listener, void *data); -static void draw_server_with_damage(struct tinyds_server *server); -static void draw_output(struct tinyds_output *output); -static void output_swap_buffer(struct tinyds_output *output, - struct ds_buffer *buffer); -static void view_send_frame_done(struct tinyds_view *view); -#ifdef USE_TDM_BUFFER_QUEUE -static void output_buffer_queue_init(struct tinyds_output *output); -static void output_renderer_init(struct tinyds_output *output); -static void output_draw_with_renderer(struct tinyds_output *output); -#else -static void output_swapchain_init(struct tinyds_output *output, - int width, int height, uint32_t format); -static void output_draw_with_swapchain(struct tinyds_output *output); -static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image); -#endif -static void server_add_keyboard(struct tinyds_server *server, - struct ds_input_device *dev); -static void server_add_pointer(struct tinyds_server *server, - struct ds_input_device *dev); -static void server_add_touch(struct tinyds_server *server, - struct ds_input_device *dev); - -static struct tinyds_view * -server_view_at(struct tinyds_server *server, double lx, double ly, - double *sx, double *sy); - -int -main(void) -{ - struct tinyds_server *server = &tinyds; - struct wl_display *display; - struct wl_event_loop *loop; - const char *socket; - bool res; - - ds_log_init(DS_INF, NULL); - - display = wl_display_create(); - assert(display); - - res = init_server(server, display); - assert(res); - - socket = wl_display_add_socket_auto(display); - assert(socket); - - ds_backend_start(server->backend); - ds_backend_start(server->input_backend); - - setenv("WAYLAND_DISPLAY", socket, true); - - ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket); - - loop = wl_display_get_event_loop(display); - server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO, - WL_EVENT_READABLE, server_dispatch_stdin, server); - - wl_display_run(display); - - wl_display_destroy_clients(display); - wl_display_destroy(display); - - return 0; -} - -static void -view_populate_pid(struct tinyds_view *view) -{ - pid_t pid; - struct wl_client *client = NULL; - struct ds_surface *surface = ds_xdg_surface_get_surface(view->xdg_surface); - - if (surface) - client = wl_resource_get_client(ds_surface_get_wl_resource(surface)); - wl_client_get_credentials(client, &pid, NULL, NULL); - - ds_inf("view pid(%u)", pid); - view->pid = pid; - - view->effect_type = ds_tizen_effect_get_effect_type(view->server->effect, pid); - ds_tizen_effect_unset_effect_type(view->server->effect, pid); - ds_inf("view effect_type(%d)", view->effect_type); -} - -static void -view_handle_xdg_surface_map(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - struct ds_keyboard *keyboard; - struct tinyds_keyboard *kbd; - view = wl_container_of(listener, view, xdg_surface_map); - view->mapped = true; - - view_populate_pid(view); - - wl_list_for_each(kbd, &view->server->keyboards, link) { - keyboard = ds_input_device_get_keyboard(kbd->dev); - if (keyboard != NULL) { - ds_seat_keyboard_notify_enter(view->server->seat, - ds_xdg_surface_get_surface(view->xdg_surface), - keyboard->keycodes, keyboard->num_keycodes, - &keyboard->modifiers); - return; - } - } -} - -static void -view_handle_xdg_surface_unmap(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - - view = wl_container_of(listener, view, xdg_surface_unmap); - view->mapped = false; -} - -static void -view_handle_xdg_surface_destroy(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - struct tinyds_server *server; - - view = wl_container_of(listener, view, xdg_surface_destroy); - server = view->server; - - wl_list_remove(&view->xdg_surface_destroy.link); - wl_list_remove(&view->xdg_surface_map.link); - wl_list_remove(&view->xdg_surface_unmap.link); - wl_list_remove(&view->surface_commit.link); - wl_list_remove(&view->link); - free(view); - - draw_server_with_damage(server); -} - -static void -view_handle_surface_commit(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_view *view; - - view = wl_container_of(listener, view, surface_commit); - draw_server_with_damage(view->server); -} - -static void -server_new_xdg_surface(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct tinyds_view *view; - struct ds_xdg_surface *xdg_surface; - - server = wl_container_of(listener, server, new_xdg_surface); - xdg_surface = data; - - ds_inf("New xdg_surface(%p)", (void *)xdg_surface); - - view = calloc(1, sizeof *view); - assert(view); - - view->server = server; - view->xdg_surface = xdg_surface; - - view->xdg_surface_map.notify = view_handle_xdg_surface_map; - ds_xdg_surface_add_map_listener(xdg_surface, - &view->xdg_surface_map); - - view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap; - ds_xdg_surface_add_unmap_listener(xdg_surface, - &view->xdg_surface_unmap); - - view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy; - ds_xdg_surface_add_destroy_listener(xdg_surface, - &view->xdg_surface_destroy); - - view->surface_commit.notify = view_handle_surface_commit; - ds_surface_add_commit_listener( - ds_xdg_surface_get_surface(xdg_surface), - &view->surface_commit); - - wl_list_insert(server->views.prev, &view->link); - - view->x = rand() % 1000; - view->y = rand() % 500; - - view->pid = 0; - view->effect_type = -1; - - ds_inf("view at (%d, %d)", view->x, view->y); -} - -static void -backend_handle_new_output(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct tinyds_output *output; - struct ds_output *ds_output; - const struct ds_output_mode *mode; - - server = wl_container_of(listener, server, new_output); - ds_output = data; - - ds_inf("New output(%p)", ds_output); - - if (server->output) - return; - - mode = ds_output_get_preferred_mode(ds_output); - ds_output_set_mode(ds_output, mode); - - output = calloc(1, sizeof *output); - if (!output) - return; - - output->server = server; - output->ds_output = ds_output; - output->width = mode->width; - output->height = mode->height; - output->drawable = true; - output->damaged = true; - -#ifdef USE_TDM_BUFFER_QUEUE - output_buffer_queue_init(output); - output_renderer_init(output); -#else - output_swapchain_init(output, mode->width, mode->height, - DRM_FORMAT_XRGB8888); -#endif - - output->output_destroy.notify = output_handle_destroy; - ds_output_add_destroy_listener(ds_output, &output->output_destroy); - - output->output_frame.notify = output_handle_frame; - ds_output_add_frame_listener(ds_output, &output->output_frame); - - ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height); - - server->output = output; - - draw_output(output); -} - -static void -backend_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); - server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD; - break; - case DS_INPUT_DEVICE_TOUCH: - server_add_touch(server, dev); - server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH; - break; - case DS_INPUT_DEVICE_POINTER: - server_add_pointer(server, dev); - server->seat_caps |= WL_SEAT_CAPABILITY_POINTER; - break; - default: - ds_err("Unknown type(%d) of ds_input_device", dev_type); - break; - } - - ds_seat_set_capabilities(server->seat, server->seat_caps); -} - -static void -devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode) -{ - struct ds_tizen_input_devicemgr_keymap_data *data; - - data = calloc(1, sizeof *data); - if (!data) { - ds_err("Failed to alloc memory\n"); - return; - } - - data->name = strdup(name); - data->keycode = keycode; - - wl_list_insert(list, &data->link); -} - -static void -devicemgr_remove_keymap_data(struct wl_list *list, int keycode) -{ - struct ds_tizen_input_devicemgr_keymap_data *data, *tmp; - - wl_list_for_each_safe(data, tmp, list, link) { - if (data->keycode == keycode) { - wl_list_remove(&data->link); - free(data); - } - } -} - -static void -devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr) -{ - struct wl_list keymap_list; - bool res; - - wl_list_init(&keymap_list); - - devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455); - devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456); - devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457); - devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458); - - res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list); - if (!res) - ds_inf("Failed to set keymap"); - - devicemgr_remove_keymap_data(&keymap_list, 455); - devicemgr_remove_keymap_data(&keymap_list, 456); - devicemgr_remove_keymap_data(&keymap_list, 457); - devicemgr_remove_keymap_data(&keymap_list, 458); -} - -static void -devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct tinyds_pointer *pointer; - struct ds_tizen_input_devicemgr_event_pointer_warp *event = data; - double sx = 0.f, sy = 0.f; - struct tinyds_view *view = NULL; - - server = wl_container_of(listener, server, pointer_warp); - - ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface, - event->x, event->y); - - wl_list_for_each(pointer, &server->pointers, link){ - if (!pointer->focused_view) continue; - view = pointer->focused_view; - } - if (!view) return; - - if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) { - ds_inf("Pointer is not on the requested surface"); - return; - } - - server->output_x = view->x + (event->x * server->output->width); - server->output_y = view->y + (event->y * server->output->height); - - server_view_at(server, server->output_x, server->output_y, &sx, &sy); - - ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f", - sx, sy, server->output_x, server->output_y); - - ds_seat_pointer_notify_motion(server->seat, - event->time_msec, sx, sy); -} - -static void -devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) -{ - struct tinyds_server *server = - wl_container_of(listener, server, devicemgr_destroy); - - wl_list_remove(&server->devicemgr_destroy.link); - wl_list_remove(&server->pointer_warp.link); - - server->devicemgr = NULL; -} - -static void -launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) -{ - struct tinyds_server *server = - wl_container_of(listener, server, effect_destroy); - - wl_list_remove(&server->effect_destroy.link); - wl_list_remove(&server->effect_type_set.link); - wl_list_remove(&server->effect_type_unset.link); - wl_list_remove(&server->new_splash.link); - - server->effect = NULL; -} - -static void -launch_effect_handle_type_set(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct ds_tizen_effect_event_type_set *event = data; - struct tinyds_view *view = NULL; - bool existing = false; - - server = wl_container_of(listener, server, effect_type_set); - - ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch"); - - wl_list_for_each(view, &server->views, link) { - if (view->pid == event->pid) { - view->effect_type = event->effect_type; - ds_inf("Launch effect. existing pid"); - existing = true; - } - } - if (existing) { - ds_tizen_effect_unset_effect_type(server->effect, event->pid); - } else { - ds_tizen_effect_set_effect_type(server->effect, event->pid, event->effect_type); - } -} - -static void -launch_effect_handle_type_unset(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct ds_tizen_effect_event_type_unset *event = data; - struct tinyds_view *view = NULL; - - server = wl_container_of(listener, server, effect_type_unset); - - ds_inf("Launch effect. type_unset: pid(%u)", event->pid); - - wl_list_for_each(view, &server->views, link) { - if (view->pid == event->pid) { - view->effect_type = -1; - ds_inf("Launch effect. pid found"); - } - } - ds_tizen_effect_unset_effect_type(server->effect, event->pid); -} - -static void -launch_splash_handle_owner(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct ds_tizen_splash_event_owner *event = data; - struct tinyds_view *view = NULL; - - server = wl_container_of(listener, server, splash_owner); - - ds_inf("Splash owner. pid(%u)", event->pid); - - wl_list_for_each(view, &server->views, link) { - if (view->pid == event->pid) { - if (event->pid == ds_tizen_splash_get_pid(server->splash)) - ;// - else { - ds_tizen_splash_set_pid(server->splash, event->pid); - } - } - } -} - -static void -launch_effect_handle_new_splash(struct wl_listener *listener, void *data) -{ - struct tinyds_server *server; - struct ds_tizen_effect_event_new_splash *event = data; - struct tinyds_view *view = NULL; - - server = wl_container_of(listener, server, new_splash); - - ds_inf("Launch new splash. splash(%p)", event->splash); - if (!event->splash) return; - - server->splash = event->splash; - - // new view for "Launchscreen" - view = calloc(1, sizeof *view); - assert(view); - wl_list_insert(server->views.prev, &view->link); - view->pid = ds_tizen_splash_get_pid(event->splash); - - server->splash_owner.notify = launch_splash_handle_owner; - ds_tizen_splash_add_owner_listener(server->splash, - &server->splash_owner); -} - -static bool -init_server(struct tinyds_server *server, struct wl_display *display) -{ - server->display = display; - - wl_list_init(&server->views); - - if (wl_display_init_shm(display) != 0) - return false; - - server->backend = ds_tdm_backend_create(display); - if (!server->backend) - return false; - - server->input_backend = ds_libinput_backend_create(display); - if (!server->input_backend) { - ds_backend_destroy(server->backend); - return false; - } - - server->new_output.notify = backend_handle_new_output; - ds_backend_add_new_output_listener(server->backend, - &server->new_output); - - wl_list_init(&server->keyboards); - wl_list_init(&server->pointers); - server->new_input.notify = backend_handle_new_input; - ds_backend_add_new_input_listener(server->input_backend, &server->new_input); - - server->compositor = ds_compositor_create(display); - if (!server->compositor) - goto err; - - server->tbm_server = ds_tbm_server_create(display); - if (!server->tbm_server) - goto err; - - server->xdg_shell = ds_xdg_shell_create(display); - if (!server->xdg_shell) - goto err; - - server->new_xdg_surface.notify = server_new_xdg_surface; - ds_xdg_shell_add_new_surface_listener(server->xdg_shell, - &server->new_xdg_surface); - - server->seat = ds_seat_create(display, "seat0" /* arbitrary name */); - if (!server->seat) - goto err; - server->seat_caps = 0; - - server->devicemgr = ds_tizen_input_devicemgr_create( - server->input_backend, server->seat); - if (!server->devicemgr) { - goto err; - } - - devicemgr_set_keymap(server->devicemgr); - - server->devicemgr_destroy.notify = devicemgr_handle_destroy; - ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr, - &server->devicemgr_destroy); - - server->pointer_warp.notify = devicemgr_handle_pointer_warp; - ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr, - &server->pointer_warp); - - server->effect = ds_tizen_effect_create(display); - if (!server->effect) { - goto err; - } - - server->effect_destroy.notify = launch_effect_handle_destroy; - ds_tizen_effect_add_destroy_listener(server->effect, - &server->effect_destroy); - - server->effect_type_set.notify = launch_effect_handle_type_set; - ds_tizen_effect_add_type_set_listener(server->effect, - &server->effect_type_set); - - server->effect_type_unset.notify = launch_effect_handle_type_unset; - ds_tizen_effect_add_type_unset_listener(server->effect, - &server->effect_type_unset); - - server->new_splash.notify = launch_effect_handle_new_splash; - ds_tizen_effect_add_new_splash_listener(server->effect, - &server->new_splash); - - return true; - -err: - ds_backend_destroy(server->backend); - ds_backend_destroy(server->input_backend); - - return false; -} - -static void -output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) -{ - struct tinyds_output *output = - wl_container_of(listener, output, output_destroy); - - wl_list_remove(&output->output_destroy.link); - wl_list_remove(&output->output_frame.link); - - if (output->front_buffer) - ds_buffer_unlock(output->front_buffer); - -#ifdef USE_TDM_BUFFER_QUEUE - fini_renderer(&output->renderer); -#else - if (output->swapchain) - ds_swapchain_destroy(output->swapchain); - - if (output->allocator) - ds_allocator_destroy(output->allocator); -#endif - - wl_display_terminate(output->server->display); - - output->server->output = NULL; - - free(output); -} - -static void -output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED) -{ - struct tinyds_output *output = - wl_container_of(listener, output, output_frame); - - output->drawable = true; - draw_output(output); -} - -static void -draw_server_with_damage(struct tinyds_server *server) -{ - server->output->damaged = true; - draw_output(server->output); -} - -#ifdef USE_TDM_BUFFER_QUEUE -static void -output_handle_buffer_queue_acquirable(struct wl_listener *listener, - void *data TINYDS_UNUSED) -{ - struct tinyds_output *output; - struct ds_buffer *buffer; - - output = wl_container_of(listener, output, buffer_queue_acquirable); - - buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue); - assert(buffer); - - output_swap_buffer(output, buffer); -} - -static void -output_buffer_queue_init(struct tinyds_output *output) -{ - struct ds_tdm_output *tdm_output; - - tdm_output = ds_tdm_output_from_output(output->ds_output); - assert(tdm_output); - - output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output); - assert(output->buffer_queue); - - output->buffer_queue_acquirable.notify = - output_handle_buffer_queue_acquirable; - ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue, - &output->buffer_queue_acquirable); -} - -static void -output_renderer_init(struct tinyds_output *output) -{ - init_renderer(&output->renderer); - - renderer_set_surface_queue(&output->renderer, - ds_tdm_buffer_queue_get_native_queue(output->buffer_queue)); - - renderer_set_bg_color(&output->renderer, 80, 80, 80); -} - -static void -output_draw_with_renderer(struct tinyds_output *output) -{ - struct tinyds_view *view; - - ds_dbg(">> BEGIN UPDATE TEXTURES"); - - wl_list_for_each(view, &output->server->views, link) { - struct ds_buffer *ds_buffer; - struct ds_tbm_client_buffer *tbm_buffer; - tbm_surface_h surface; - - if (!view->mapped) - continue; - - ds_buffer = ds_surface_get_buffer( - ds_xdg_surface_get_surface(view->xdg_surface)); - assert(ds_buffer); - - tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer); - assert(tbm_buffer); - - surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer); - - renderer_add_texture(&output->renderer, surface, view->x, view->y); - - view_send_frame_done(view); - } - - ds_dbg("<< END UPDATE TEXTURES"); - - renderer_draw(&output->renderer); - -} -#else -static void -output_swapchain_init(struct tinyds_output *output, - int width, int height, uint32_t format); - -{ - output->allocator = ds_tbm_allocator_create(); - assert(output->allocator); - - output->swapchain = ds_swapchain_create(output->allocator, - width, height, format); - assert(output->swapchain); -} - -static void -output_draw_with_swapchain(struct tinyds_output *output) -{ - struct tinyds_view *view; - struct ds_buffer *output_buffer; - pixman_image_t *output_image; - - output_buffer = ds_swapchain_acquire(output->swapchain, NULL); - if (!output_buffer) - return; - - output_image = pixman_image_from_buffer(output_buffer, - DS_BUFFER_DATA_PTR_ACCESS_WRITE); - if (!output_image) { - ds_buffer_unlock(output_buffer); - return; - } - - pixman_image_fill_color(output_image, 80, 80, 80); - - wl_list_for_each(view, &output->server->views, link) { - if (!view->mapped) - continue; - draw_view(view, output_image); - } - pixman_image_unref(output_image); - - output_swap_buffer(output, output_buffer); -} - -static void -draw_view(struct tinyds_view *view, pixman_image_t *dst_image) -{ - struct ds_buffer *buffer; - pixman_image_t *src_image; - - buffer = ds_surface_get_buffer( - ds_xdg_surface_get_surface(view->xdg_surface)); - if (!buffer) - return; - - src_image = pixman_image_from_buffer(buffer, - DS_BUFFER_DATA_PTR_ACCESS_READ); - pixman_image_composite32(PIXMAN_OP_OVER, - src_image, - NULL, - dst_image, - 0, 0, 0, 0, - view->x, view->y, - pixman_image_get_width(src_image), - pixman_image_get_height(src_image)); - pixman_image_unref(src_image); - - view_send_frame_done(view); -} -#endif - -static void -draw_output(struct tinyds_output *output) -{ - - if (!output->drawable || !output->damaged) - return; - -#ifdef USE_TDM_BUFFER_QUEUE - output_draw_with_renderer(output); -#else - output_draw_with_swapchain(output); -#endif - - output->drawable = false; - output->damaged = false; -} - -static void -output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer) -{ - ds_output_attach_buffer(output->ds_output, buffer); - ds_output_commit(output->ds_output); - - if (output->front_buffer) - ds_buffer_unlock(output->front_buffer); - output->front_buffer = buffer; -} - -static void -view_send_frame_done(struct tinyds_view *view) -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface), - &now); -} - -static int -server_dispatch_stdin(int fd, uint32_t mask, void *data) -{ - struct tinyds_server *server = data; - - wl_display_terminate(server->display); - - return 1; -} - - -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); - wl_list_remove(&kbd->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; - int nsyms; - bool handled = false; - - kbd = wl_container_of(listener, kbd, key); - - ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), " - "update_state(%d)", kbd->dev, - event->keycode, event->state, event->time_msec, - event->update_state); - - ds_keyboard = ds_input_device_get_keyboard(kbd->dev); - - if (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++) { - handled = server_handle_keybinding(kbd->server, syms[i]); - } - } - } - - if (!handled) { - ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec, - event->keycode, event->state); - } -} - -static void -server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev) -{ - struct tinyds_keyboard *kbd; - struct xkb_context *context; - struct xkb_keymap *keymap; - - kbd = calloc(1, sizeof *kbd); - assert(kbd); - - kbd->dev = dev; - kbd->server = server; - - context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - keymap = xkb_keymap_new_from_names(context, NULL, - XKB_KEYMAP_COMPILE_NO_FLAGS); - - if (!keymap) { - ds_err("Failed to compile keymap"); - xkb_context_unref(context); - } - - ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap); - - xkb_keymap_unref(keymap); - xkb_context_unref(context); - - 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); - - wl_list_insert(&server->keyboards, &kbd->link); - - ds_inf("Keyboard(%p) added", kbd); -} - -static struct tinyds_view * -server_view_at(struct tinyds_server *server, double lx, double ly, - double *sx, double *sy) -{ - struct tinyds_view *view; - struct ds_surface *surface; - struct ds_buffer *buffer; - int x, y, w = 0, h = 0; - - wl_list_for_each(view, &server->views, link) { - surface = ds_xdg_surface_get_surface(view->xdg_surface); - buffer = ds_surface_get_buffer(surface); - ds_buffer_get_size(buffer, &w, &h); - - x = view->x; - y = view->y; - - if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) { - *sx = lx - x; - *sy = ly - y; - - return view; - } - } - - return NULL; -} - -static void -touch_handle_device_destroy(struct wl_listener *listener, void *data) -{ - struct tinyds_touch *touch; - - touch = wl_container_of(listener, touch, destroy); - - ds_inf("Touch(%p) destroyed", touch); - - wl_list_remove(&touch->destroy.link); - wl_list_remove(&touch->down.link); - wl_list_remove(&touch->up.link); - wl_list_remove(&touch->motion.link); - - free(touch); -} - -static void -touch_handle_down(struct wl_listener *listener, void *data) -{ - struct ds_event_touch_down *event = data; - struct tinyds_touch *touch; - struct tinyds_view *view; - struct tinyds_server *server; - double sx = 0.f, sy = 0.f; - - touch = wl_container_of(listener, touch, down); - - server = touch->server; - server->output_x = event->x * server->output->width; - server->output_y = event->y * server->output->height; - - ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f", - touch->dev, event->id, event->x, event->y, server->output_x, server->output_y); - - view = server_view_at(server, server->output_x, server->output_y, &sx, &sy); - - if (view) { - ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface), - event->time_msec, event->id, sx, sy); - } -} - -static void -touch_handle_up(struct wl_listener *listener, void *data) -{ - struct ds_event_touch_up *event = data; - struct tinyds_touch *touch; - - touch = wl_container_of(listener, touch, up); - - ds_inf("Touch(%p) event up: id(%d) time_msec(%d)", - touch->dev, event->id, event->time_msec); - - ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id); -} - -static void -touch_handle_motion(struct wl_listener *listener, void *data) -{ - struct ds_event_touch_motion *event = data; - struct tinyds_touch *touch; - struct tinyds_view *view; - struct tinyds_server *server; - double sx = 0.f, sy = 0.f; - - touch = wl_container_of(listener, touch, motion); - - server = touch->server; - server->output_x = event->x * server->output->width; - server->output_y = event->y * server->output->height; - - ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f", - touch->dev, event->id, event->x, event->y, server->output_x, server->output_y); - - view = server_view_at(server, server->output_x, server->output_y, &sx, &sy); - - if (view) { - ds_seat_touch_notify_motion(server->seat, event->time_msec, - event->id, sx, sy); - } -} - -static void -server_add_touch(struct tinyds_server *server, struct ds_input_device *dev) -{ - struct tinyds_touch *touch; - - touch = calloc(1, sizeof *touch); - assert(touch); - - touch->dev = dev; - touch->server = server; - - touch->destroy.notify = touch_handle_device_destroy; - ds_input_device_add_destroy_listener(dev, &touch->destroy); - - touch->down.notify = touch_handle_down; - ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down); - - touch->up.notify = touch_handle_up; - ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up); - - touch->motion.notify = touch_handle_motion; - ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion); - - ds_inf("Touch(%p) added", touch); -} - -static void -pointer_handle_device_destroy(struct wl_listener *listener, void *data) -{ - struct tinyds_pointer *pointer; - - pointer = wl_container_of(listener, pointer, destroy); - - ds_inf("Pointer(%p) destroyed", pointer); - - wl_list_remove(&pointer->destroy.link); - wl_list_remove(&pointer->motion.link); - wl_list_remove(&pointer->button.link); - wl_list_remove(&pointer->frame.link); - wl_list_remove(&pointer->link); - - free(pointer); -} - -static void -pointer_handle_motion(struct wl_listener *listener, void *data) -{ - struct tinyds_pointer *pointer; - struct ds_event_pointer_motion *event = data; - struct tinyds_view *view; - struct tinyds_server *server; - int ow = 0, oh = 0; - double sx, sy; - - pointer = wl_container_of(listener, pointer, motion); - - server = pointer->server; - if (server->output) { - ow = server->output->width; - oh = server->output->height; - } - - if (server->output_x + event->delta_x >= ow) - server->output_x = ow; - else if(server->output_x + event->delta_x <= 0.f) - server->output_x = 0.f; - else - server->output_x = server->output_x + event->delta_x ; - if (server->output_y + event->delta_y >= oh) - server->output_y = oh; - else if(server->output_y + event->delta_y <= 0.f) - server->output_y = 0.f; - else - server->output_y = server->output_y + event->delta_y ; - - ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f", - pointer, event->delta_x, event->delta_y, server->output_x, server->output_y); - - view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy); - - if (pointer->focused_view != view) { - if (pointer->focused_view) { - ds_inf("Clear pointer focus from view(%p)", pointer->focused_view); - ds_seat_pointer_notify_clear_focus(pointer->server->seat); - pointer->focused_view = NULL; - } - - if (view) { - ds_inf("Set pointer focus to view(%p)", view); - ds_seat_pointer_notify_enter(pointer->server->seat, - ds_xdg_surface_get_surface(view->xdg_surface), sx, sy); - pointer->focused_view = view; - } - } - - if (view) { - ds_seat_pointer_notify_motion(pointer->server->seat, - event->time_msec, sx, sy); - } -} - -static void -pointer_handle_button(struct wl_listener *listener, void *data) -{ - struct tinyds_pointer *pointer; - struct ds_event_pointer_button *event = data; - - pointer = wl_container_of(listener, pointer, button); - - ds_inf("Pointer(%p) button(%d): state(%s) time(%d)", - pointer, event->button, - (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released", - event->time_msec); - - ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state); -} - -static void -pointer_handle_frame(struct wl_listener *listener, void *data) -{ - struct tinyds_pointer *pointer; - - pointer = wl_container_of(listener, pointer, frame); - - ds_inf("Pointer(%p) frame", pointer); - ds_seat_pointer_notify_frame(pointer->server->seat); -} - -static void -server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev) -{ - struct tinyds_pointer *pointer; - - pointer = calloc(1, sizeof *pointer); - assert(pointer); - - pointer->dev = dev; - pointer->server = server; - server->output_x = 200; - server->output_y = 200; - - pointer->destroy.notify = pointer_handle_device_destroy; - ds_input_device_add_destroy_listener(dev, &pointer->destroy); - - pointer->motion.notify = pointer_handle_motion; - ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev), - &pointer->motion); - - pointer->button.notify = pointer_handle_button; - ds_pointer_add_button_listener(ds_input_device_get_pointer(dev), - &pointer->button); - - pointer->frame.notify = pointer_handle_frame; - ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev), - &pointer->frame); - - pointer->focused_view = NULL; - - wl_list_insert(&server->pointers, &pointer->link); - - ds_inf("Pointer(%p) added", pointer); -} diff --git a/examples/tinyds-tdm.c b/examples/tinyds-tdm.c index 98b9a0a..0abb4b0 100644 --- a/examples/tinyds-tdm.c +++ b/examples/tinyds-tdm.c @@ -15,8 +15,18 @@ #include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define USE_TDM_BUFFER_QUEUE @@ -30,6 +40,8 @@ #include "pixman-helper.h" #define TINYDS_UNUSED __attribute__((unused)) +struct tinyds_keyboard; +struct tinyds_pointer; struct tinyds_output { @@ -71,8 +83,15 @@ struct tinyds_server struct wl_display *display; struct ds_backend *backend; + struct ds_backend *input_backend; struct ds_compositor *compositor; struct ds_xdg_shell *xdg_shell; + struct ds_seat *seat; + uint32_t seat_caps; + double output_x, output_y; + struct ds_tizen_input_devicemgr *devicemgr; + struct ds_tizen_effect *effect; + struct ds_tizen_splash *splash; struct tinyds_output *output; struct tinyds_dpms *dpms; @@ -81,7 +100,18 @@ struct tinyds_server struct wl_list views; struct wl_listener new_output; + struct wl_listener new_input; struct wl_listener new_xdg_surface; + struct wl_listener devicemgr_destroy; + struct wl_listener pointer_warp; + struct wl_listener effect_destroy; + struct wl_listener effect_type_set; + struct wl_listener effect_type_unset; + struct wl_listener new_splash; + struct wl_listener splash_owner; + + struct wl_list keyboards; + struct wl_list pointers; }; struct tinyds_view @@ -99,6 +129,44 @@ struct tinyds_view int x, y; bool mapped; + + pid_t pid; + int effect_type; +}; + +struct tinyds_pointer +{ + struct ds_input_device *dev; + struct tinyds_server *server; + + struct tinyds_view *focused_view; + + struct wl_listener destroy; + struct wl_listener motion; //relative + struct wl_listener button; + struct wl_listener frame; + struct wl_list link; //tinyds_server::pointers +}; + +struct tinyds_keyboard +{ + struct ds_input_device *dev; + struct tinyds_server *server; + + struct wl_listener destroy; + struct wl_listener key; + struct wl_list link; //tinyds_server::keyboards +}; + +struct tinyds_touch +{ + struct ds_input_device *dev; + struct tinyds_server *server; + + struct wl_listener destroy; + struct wl_listener down; + struct wl_listener up; + struct wl_listener motion; }; struct tinyds_server tinyds; @@ -125,7 +193,16 @@ static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image); static void dpms_handle_destroy(struct wl_listener *listener, void *data); static void dpms_handle_set_dpms(struct wl_listener *listener, void *data); static void dpms_handle_get_dpms(struct wl_listener *listener, void *data); +static void server_add_keyboard(struct tinyds_server *server, + struct ds_input_device *dev); +static void server_add_pointer(struct tinyds_server *server, + struct ds_input_device *dev); +static void server_add_touch(struct tinyds_server *server, + struct ds_input_device *dev); +static struct tinyds_view * +server_view_at(struct tinyds_server *server, double lx, double ly, + double *sx, double *sy); int main(void) @@ -148,6 +225,7 @@ main(void) assert(socket); ds_backend_start(server->backend); + ds_backend_start(server->input_backend); setenv("WAYLAND_DISPLAY", socket, true); @@ -166,13 +244,47 @@ main(void) } static void +view_populate_pid(struct tinyds_view *view) +{ + pid_t pid; + struct wl_client *client = NULL; + struct ds_surface *surface = ds_xdg_surface_get_surface(view->xdg_surface); + + if (surface) + client = wl_resource_get_client(ds_surface_get_wl_resource(surface)); + wl_client_get_credentials(client, &pid, NULL, NULL); + + ds_inf("view pid(%u)", pid); + view->pid = pid; + + view->effect_type = ds_tizen_effect_get_effect_type(view->server->effect, pid); + ds_tizen_effect_unset_effect_type(view->server->effect, pid); + ds_inf("view effect_type(%d)", view->effect_type); +} + +static void view_handle_xdg_surface_map(struct wl_listener *listener, void *data TINYDS_UNUSED) { struct tinyds_view *view; + struct ds_keyboard *keyboard; + struct tinyds_keyboard *kbd; view = wl_container_of(listener, view, xdg_surface_map); view->mapped = true; + + view_populate_pid(view); + + wl_list_for_each(kbd, &view->server->keyboards, link) { + keyboard = ds_input_device_get_keyboard(kbd->dev); + if (keyboard != NULL) { + ds_seat_keyboard_notify_enter(view->server->seat, + ds_xdg_surface_get_surface(view->xdg_surface), + keyboard->keycodes, keyboard->num_keycodes, + &keyboard->modifiers); + return; + } + } } static void @@ -254,6 +366,11 @@ server_new_xdg_surface(struct wl_listener *listener, void *data) view->x = rand() % 1000; view->y = rand() % 500; + + view->pid = 0; + view->effect_type = -1; + + ds_inf("view at (%d, %d)", view->x, view->y); } static void @@ -300,6 +417,8 @@ backend_handle_new_output(struct wl_listener *listener, void *data) output->output_frame.notify = output_handle_frame; ds_output_add_frame_listener(ds_output, &output->output_frame); + ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height); + server->output = output; draw_output(output); @@ -334,6 +453,247 @@ add_new_dpms(struct tinyds_server *server) return true; } +static void +backend_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); + server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD; + break; + case DS_INPUT_DEVICE_TOUCH: + server_add_touch(server, dev); + server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH; + break; + case DS_INPUT_DEVICE_POINTER: + server_add_pointer(server, dev); + server->seat_caps |= WL_SEAT_CAPABILITY_POINTER; + break; + default: + ds_err("Unknown type(%d) of ds_input_device", dev_type); + break; + } + + ds_seat_set_capabilities(server->seat, server->seat_caps); +} + +static void +devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode) +{ + struct ds_tizen_input_devicemgr_keymap_data *data; + + data = calloc(1, sizeof *data); + if (!data) { + ds_err("Failed to alloc memory\n"); + return; + } + + data->name = strdup(name); + data->keycode = keycode; + + wl_list_insert(list, &data->link); +} + +static void +devicemgr_remove_keymap_data(struct wl_list *list, int keycode) +{ + struct ds_tizen_input_devicemgr_keymap_data *data, *tmp; + + wl_list_for_each_safe(data, tmp, list, link) { + if (data->keycode == keycode) { + wl_list_remove(&data->link); + free(data); + } + } +} + +static void +devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr) +{ + struct wl_list keymap_list; + bool res; + + wl_list_init(&keymap_list); + + devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455); + devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456); + devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457); + devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458); + + res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list); + if (!res) + ds_inf("Failed to set keymap"); + + devicemgr_remove_keymap_data(&keymap_list, 455); + devicemgr_remove_keymap_data(&keymap_list, 456); + devicemgr_remove_keymap_data(&keymap_list, 457); + devicemgr_remove_keymap_data(&keymap_list, 458); +} + +static void +devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct tinyds_pointer *pointer; + struct ds_tizen_input_devicemgr_event_pointer_warp *event = data; + double sx = 0.f, sy = 0.f; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, pointer_warp); + + ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface, + event->x, event->y); + + wl_list_for_each(pointer, &server->pointers, link){ + if (!pointer->focused_view) continue; + view = pointer->focused_view; + } + if (!view) return; + + if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) { + ds_inf("Pointer is not on the requested surface"); + return; + } + + server->output_x = view->x + (event->x * server->output->width); + server->output_y = view->y + (event->y * server->output->height); + + server_view_at(server, server->output_x, server->output_y, &sx, &sy); + + ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f", + sx, sy, server->output_x, server->output_y); + + ds_seat_pointer_notify_motion(server->seat, + event->time_msec, sx, sy); +} + +static void +devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) +{ + struct tinyds_server *server = + wl_container_of(listener, server, devicemgr_destroy); + + wl_list_remove(&server->devicemgr_destroy.link); + wl_list_remove(&server->pointer_warp.link); + + server->devicemgr = NULL; +} + +static void +launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED) +{ + struct tinyds_server *server = + wl_container_of(listener, server, effect_destroy); + + wl_list_remove(&server->effect_destroy.link); + wl_list_remove(&server->effect_type_set.link); + wl_list_remove(&server->effect_type_unset.link); + wl_list_remove(&server->new_splash.link); + + server->effect = NULL; +} + +static void +launch_effect_handle_type_set(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_effect_event_type_set *event = data; + struct tinyds_view *view = NULL; + bool existing = false; + + server = wl_container_of(listener, server, effect_type_set); + + ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch"); + + wl_list_for_each(view, &server->views, link) { + if (view->pid == event->pid) { + view->effect_type = event->effect_type; + ds_inf("Launch effect. existing pid"); + existing = true; + } + } + if (existing) { + ds_tizen_effect_unset_effect_type(server->effect, event->pid); + } else { + ds_tizen_effect_set_effect_type(server->effect, event->pid, event->effect_type); + } +} + +static void +launch_effect_handle_type_unset(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_effect_event_type_unset *event = data; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, effect_type_unset); + + ds_inf("Launch effect. type_unset: pid(%u)", event->pid); + + wl_list_for_each(view, &server->views, link) { + if (view->pid == event->pid) { + view->effect_type = -1; + ds_inf("Launch effect. pid found"); + } + } + ds_tizen_effect_unset_effect_type(server->effect, event->pid); +} + +static void +launch_splash_handle_owner(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_splash_event_owner *event = data; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, splash_owner); + + ds_inf("Splash owner. pid(%u)", event->pid); + + wl_list_for_each(view, &server->views, link) { + if (view->pid == event->pid) { + if (event->pid == ds_tizen_splash_get_pid(server->splash)) + ;// + else { + ds_tizen_splash_set_pid(server->splash, event->pid); + } + } + } +} + +static void +launch_effect_handle_new_splash(struct wl_listener *listener, void *data) +{ + struct tinyds_server *server; + struct ds_tizen_effect_event_new_splash *event = data; + struct tinyds_view *view = NULL; + + server = wl_container_of(listener, server, new_splash); + + ds_inf("Launch new splash. splash(%p)", event->splash); + if (!event->splash) return; + + server->splash = event->splash; + + // new view for "Launchscreen" + view = calloc(1, sizeof *view); + assert(view); + wl_list_insert(server->views.prev, &view->link); + view->pid = ds_tizen_splash_get_pid(event->splash); + + server->splash_owner.notify = launch_splash_handle_owner; + ds_tizen_splash_add_owner_listener(server->splash, + &server->splash_owner); +} + static bool init_server(struct tinyds_server *server, struct wl_display *display) { @@ -348,38 +708,89 @@ init_server(struct tinyds_server *server, struct wl_display *display) if (!server->backend) return false; + server->input_backend = ds_libinput_backend_create(display); + if (!server->input_backend) { + ds_backend_destroy(server->backend); + return false; + } + server->new_output.notify = backend_handle_new_output; ds_backend_add_new_output_listener(server->backend, &server->new_output); + wl_list_init(&server->keyboards); + wl_list_init(&server->pointers); + server->new_input.notify = backend_handle_new_input; + ds_backend_add_new_input_listener(server->input_backend, &server->new_input); + server->compositor = ds_compositor_create(display); - if (!server->compositor) { - ds_backend_destroy(server->backend); - return false; - } + if (!server->compositor) + goto err; server->tbm_server = ds_tbm_server_create(display); - if (!server->tbm_server) { - ds_backend_destroy(server->backend); - return false; - } + if (!server->tbm_server) + goto err; server->xdg_shell = ds_xdg_shell_create(display); - if (!server->xdg_shell) { - ds_backend_destroy(server->backend); - return false; - } + if (!server->xdg_shell) + goto err; server->new_xdg_surface.notify = server_new_xdg_surface; ds_xdg_shell_add_new_surface_listener(server->xdg_shell, &server->new_xdg_surface); - if (!add_new_dpms(server)) { - ds_backend_destroy(server->backend); - return false; + if (!add_new_dpms(server)) + goto err; + + server->seat = ds_seat_create(display, "seat0" /* arbitrary name */); + if (!server->seat) + goto err; + server->seat_caps = 0; + + server->devicemgr = ds_tizen_input_devicemgr_create( + server->input_backend, server->seat); + if (!server->devicemgr) { + goto err; + } + + devicemgr_set_keymap(server->devicemgr); + + server->devicemgr_destroy.notify = devicemgr_handle_destroy; + ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr, + &server->devicemgr_destroy); + + server->pointer_warp.notify = devicemgr_handle_pointer_warp; + ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr, + &server->pointer_warp); + + server->effect = ds_tizen_effect_create(display); + if (!server->effect) { + goto err; } + server->effect_destroy.notify = launch_effect_handle_destroy; + ds_tizen_effect_add_destroy_listener(server->effect, + &server->effect_destroy); + + server->effect_type_set.notify = launch_effect_handle_type_set; + ds_tizen_effect_add_type_set_listener(server->effect, + &server->effect_type_set); + + server->effect_type_unset.notify = launch_effect_handle_type_unset; + ds_tizen_effect_add_type_unset_listener(server->effect, + &server->effect_type_unset); + + server->new_splash.notify = launch_effect_handle_new_splash; + ds_tizen_effect_add_new_splash_listener(server->effect, + &server->new_splash); + return true; + +err: + ds_backend_destroy(server->backend); + ds_backend_destroy(server->input_backend); + + return false; } static void @@ -670,3 +1081,382 @@ dpms_handle_get_dpms(struct wl_listener *listener, void *data) ds_tizen_dpms_send_get_result(dpms->ds_dpms, DS_TIZEN_DPMS_MODE_ON, DS_TIZEN_DPMS_ERROR_NONE); } + +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); + wl_list_remove(&kbd->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; + int nsyms; + bool handled = false; + + kbd = wl_container_of(listener, kbd, key); + + ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), " + "update_state(%d)", kbd->dev, + event->keycode, event->state, event->time_msec, + event->update_state); + + ds_keyboard = ds_input_device_get_keyboard(kbd->dev); + + if (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++) { + handled = server_handle_keybinding(kbd->server, syms[i]); + } + } + } + + if (!handled) { + ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec, + event->keycode, event->state); + } +} + +static void +server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev) +{ + struct tinyds_keyboard *kbd; + struct xkb_context *context; + struct xkb_keymap *keymap; + + kbd = calloc(1, sizeof *kbd); + assert(kbd); + + kbd->dev = dev; + kbd->server = server; + + context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + keymap = xkb_keymap_new_from_names(context, NULL, + XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!keymap) { + ds_err("Failed to compile keymap"); + xkb_context_unref(context); + } + + ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap); + + xkb_keymap_unref(keymap); + xkb_context_unref(context); + + 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); + + wl_list_insert(&server->keyboards, &kbd->link); + + ds_inf("Keyboard(%p) added", kbd); +} + +static struct tinyds_view * +server_view_at(struct tinyds_server *server, double lx, double ly, + double *sx, double *sy) +{ + struct tinyds_view *view; + struct ds_surface *surface; + struct ds_buffer *buffer; + int x, y, w = 0, h = 0; + + wl_list_for_each(view, &server->views, link) { + surface = ds_xdg_surface_get_surface(view->xdg_surface); + buffer = ds_surface_get_buffer(surface); + ds_buffer_get_size(buffer, &w, &h); + + x = view->x; + y = view->y; + + if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) { + *sx = lx - x; + *sy = ly - y; + + return view; + } + } + + return NULL; +} + +static void +touch_handle_device_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_touch *touch; + + touch = wl_container_of(listener, touch, destroy); + + ds_inf("Touch(%p) destroyed", touch); + + wl_list_remove(&touch->destroy.link); + wl_list_remove(&touch->down.link); + wl_list_remove(&touch->up.link); + wl_list_remove(&touch->motion.link); + + free(touch); +} + +static void +touch_handle_down(struct wl_listener *listener, void *data) +{ + struct ds_event_touch_down *event = data; + struct tinyds_touch *touch; + struct tinyds_view *view; + struct tinyds_server *server; + double sx = 0.f, sy = 0.f; + + touch = wl_container_of(listener, touch, down); + + server = touch->server; + server->output_x = event->x * server->output->width; + server->output_y = event->y * server->output->height; + + ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f", + touch->dev, event->id, event->x, event->y, server->output_x, server->output_y); + + view = server_view_at(server, server->output_x, server->output_y, &sx, &sy); + + if (view) { + ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface), + event->time_msec, event->id, sx, sy); + } +} + +static void +touch_handle_up(struct wl_listener *listener, void *data) +{ + struct ds_event_touch_up *event = data; + struct tinyds_touch *touch; + + touch = wl_container_of(listener, touch, up); + + ds_inf("Touch(%p) event up: id(%d) time_msec(%d)", + touch->dev, event->id, event->time_msec); + + ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id); +} + +static void +touch_handle_motion(struct wl_listener *listener, void *data) +{ + struct ds_event_touch_motion *event = data; + struct tinyds_touch *touch; + struct tinyds_view *view; + struct tinyds_server *server; + double sx = 0.f, sy = 0.f; + + touch = wl_container_of(listener, touch, motion); + + server = touch->server; + server->output_x = event->x * server->output->width; + server->output_y = event->y * server->output->height; + + ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f", + touch->dev, event->id, event->x, event->y, server->output_x, server->output_y); + + view = server_view_at(server, server->output_x, server->output_y, &sx, &sy); + + if (view) { + ds_seat_touch_notify_motion(server->seat, event->time_msec, + event->id, sx, sy); + } +} + +static void +server_add_touch(struct tinyds_server *server, struct ds_input_device *dev) +{ + struct tinyds_touch *touch; + + touch = calloc(1, sizeof *touch); + assert(touch); + + touch->dev = dev; + touch->server = server; + + touch->destroy.notify = touch_handle_device_destroy; + ds_input_device_add_destroy_listener(dev, &touch->destroy); + + touch->down.notify = touch_handle_down; + ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down); + + touch->up.notify = touch_handle_up; + ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up); + + touch->motion.notify = touch_handle_motion; + ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion); + + ds_inf("Touch(%p) added", touch); +} + +static void +pointer_handle_device_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_pointer *pointer; + + pointer = wl_container_of(listener, pointer, destroy); + + ds_inf("Pointer(%p) destroyed", pointer); + + wl_list_remove(&pointer->destroy.link); + wl_list_remove(&pointer->motion.link); + wl_list_remove(&pointer->button.link); + wl_list_remove(&pointer->frame.link); + wl_list_remove(&pointer->link); + + free(pointer); +} + +static void +pointer_handle_motion(struct wl_listener *listener, void *data) +{ + struct tinyds_pointer *pointer; + struct ds_event_pointer_motion *event = data; + struct tinyds_view *view; + struct tinyds_server *server; + int ow = 0, oh = 0; + double sx, sy; + + pointer = wl_container_of(listener, pointer, motion); + + server = pointer->server; + if (server->output) { + ow = server->output->width; + oh = server->output->height; + } + + if (server->output_x + event->delta_x >= ow) + server->output_x = ow; + else if(server->output_x + event->delta_x <= 0.f) + server->output_x = 0.f; + else + server->output_x = server->output_x + event->delta_x ; + if (server->output_y + event->delta_y >= oh) + server->output_y = oh; + else if(server->output_y + event->delta_y <= 0.f) + server->output_y = 0.f; + else + server->output_y = server->output_y + event->delta_y ; + + ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f", + pointer, event->delta_x, event->delta_y, server->output_x, server->output_y); + + view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy); + + if (pointer->focused_view != view) { + if (pointer->focused_view) { + ds_inf("Clear pointer focus from view(%p)", pointer->focused_view); + ds_seat_pointer_notify_clear_focus(pointer->server->seat); + pointer->focused_view = NULL; + } + + if (view) { + ds_inf("Set pointer focus to view(%p)", view); + ds_seat_pointer_notify_enter(pointer->server->seat, + ds_xdg_surface_get_surface(view->xdg_surface), sx, sy); + pointer->focused_view = view; + } + } + + if (view) { + ds_seat_pointer_notify_motion(pointer->server->seat, + event->time_msec, sx, sy); + } +} + +static void +pointer_handle_button(struct wl_listener *listener, void *data) +{ + struct tinyds_pointer *pointer; + struct ds_event_pointer_button *event = data; + + pointer = wl_container_of(listener, pointer, button); + + ds_inf("Pointer(%p) button(%d): state(%s) time(%d)", + pointer, event->button, + (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released", + event->time_msec); + + ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state); +} + +static void +pointer_handle_frame(struct wl_listener *listener, void *data) +{ + struct tinyds_pointer *pointer; + + pointer = wl_container_of(listener, pointer, frame); + + ds_inf("Pointer(%p) frame", pointer); + ds_seat_pointer_notify_frame(pointer->server->seat); +} + +static void +server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev) +{ + struct tinyds_pointer *pointer; + + pointer = calloc(1, sizeof *pointer); + assert(pointer); + + pointer->dev = dev; + pointer->server = server; + server->output_x = 200; + server->output_y = 200; + + pointer->destroy.notify = pointer_handle_device_destroy; + ds_input_device_add_destroy_listener(dev, &pointer->destroy); + + pointer->motion.notify = pointer_handle_motion; + ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev), + &pointer->motion); + + pointer->button.notify = pointer_handle_button; + ds_pointer_add_button_listener(ds_input_device_get_pointer(dev), + &pointer->button); + + pointer->frame.notify = pointer_handle_frame; + ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev), + &pointer->frame); + + pointer->focused_view = NULL; + + wl_list_insert(&server->pointers, &pointer->link); + + ds_inf("Pointer(%p) added", pointer); +} diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 1ab1978..ceb30a2 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -338,7 +338,6 @@ ninja -C builddir install %{_includedir}/libds-tizen/input_devicemgr.h %{_libdir}/pkgconfig/libds-tizen-input-devicemgr.pc %{_libdir}/libds-tizen-input-devicemgr.so -%{_bindir}/tinyds-tdm-libinput %{_bindir}/input-generator %files dpms -- 2.7.4