From 0581f981272aad25c99fcb58208f4291bdec8457 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 4 May 2022 15:34:19 +0900 Subject: [PATCH 01/16] tinyds: Handle ds_seat tinyds now handles ds_seat, but only for pointer. Change-Id: I2b48841e8dcbbe0845d5cb2facd46b78b48eafd7 --- src/examples/tinyds.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/examples/tinyds.c b/src/examples/tinyds.c index 64612a6..0e25462 100644 --- a/src/examples/tinyds.c +++ b/src/examples/tinyds.c @@ -21,6 +21,7 @@ #include #include #include +#include #define TINYDS_UNUSED __attribute__((unused)) @@ -34,6 +35,8 @@ 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; struct wl_listener motion_absolute; @@ -84,6 +87,7 @@ struct tinyds_server struct ds_backend *backend; struct ds_compositor *compositor; struct ds_xdg_shell *xdg_shell; + struct ds_seat *seat; struct tinyds_output output; @@ -115,6 +119,8 @@ static bool server_init(struct tinyds_server *server, static void server_fini(struct tinyds_server *server); static void server_add_view(struct tinyds_server *server, struct ds_xdg_surface *xdg_surface); +static struct tinyds_view *server_view_at(struct tinyds_server *server, + double lx, double ly, double *sx, double *sy); static bool output_init(struct tinyds_output *output, struct tinyds_server *server, struct ds_output *ds_output, int width, int height); @@ -354,11 +360,37 @@ pointer_handle_motion_absolute(struct wl_listener *listener, void *data) { struct tinyds_pointer *pointer; struct ds_event_pointer_motion_absolute *event = data; + struct tinyds_view *view; + double ox, oy, sx, sy; pointer = wl_container_of(listener, pointer, motion_absolute); ds_inf("Pointer(%p) motion absolute: (x %f y %f) time(%d)", pointer, event->x, event->y, event->time_msec); + + ox = event->x * OUTPUT_WIDTH; + oy = event->y * OUTPUT_HEIGHT; + view = server_view_at(pointer->server, ox, oy, &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 @@ -383,6 +415,7 @@ pointer_handle_frame(struct wl_listener *listener, void *data) pointer = wl_container_of(listener, pointer, frame); ds_inf("Pointer(%p) frame", pointer); + ds_seat_pointer_notify_frame(pointer->server->seat); } static void @@ -437,6 +470,7 @@ server_handle_new_input(struct wl_listener *listener, void *data) break; case DS_INPUT_DEVICE_POINTER: server_add_pointer(server, dev); + ds_seat_set_capabilities(server->seat, WL_SEAT_CAPABILITY_POINTER); break; default: ds_err("Unknown type(%d) of ds_input_device", dev_type); @@ -534,6 +568,10 @@ server_init(struct tinyds_server *server, struct wl_display *display) 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; + return true; err: @@ -696,6 +734,34 @@ server_add_view(struct tinyds_server *server, struct ds_xdg_surface *xdg_surface ds_inf("View(%p) added", view); } +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 <= w && ly >= y && ly <= h) { + *sx = lx - x; + *sy = ly - y; + + return view; + } + } + + return NULL; +} + static void view_destroy(struct tinyds_view *view) { -- 2.7.4 From c563346a8a7117f4a4e4b1daf8c1d44fdf4103e2 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 18 May 2022 18:37:26 +0900 Subject: [PATCH 02/16] seat: fix the typo. should handle a proper device type Change-Id: Ifd7196e8f2a803973e1083b3baba7cff07428b20 --- src/libds/seat/seat.c | 8 ++++---- src/libds/seat/seat_touch.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libds/seat/seat.c b/src/libds/seat/seat.c index 542186e..51d5c23 100644 --- a/src/libds/seat/seat.c +++ b/src/libds/seat/seat.c @@ -201,10 +201,10 @@ seat_handle_get_keyboard(struct wl_client *wl_client, return; if (!(seat_client->seat->accumulated_capabilities & - WL_SEAT_CAPABILITY_POINTER)) { + WL_SEAT_CAPABILITY_KEYBOARD)) { #ifdef HAVE_WL_SEAT_ERROR_MISSING_CAPABILITY wl_resource_post_error(resource, WL_SEAT_ERROR_MISSING_CAPABILITY, - "wl_seat.get_pointer called when no " + "wl_seat.get_keyboard called when no " "keyboard capability has existed"); #endif return; @@ -225,10 +225,10 @@ seat_handle_get_touch(struct wl_client *wl_client, return; if (!(seat_client->seat->accumulated_capabilities & - WL_SEAT_CAPABILITY_POINTER)) { + WL_SEAT_CAPABILITY_TOUCH)) { #ifdef HAVE_WL_SEAT_ERROR_MISSING_CAPABILITY wl_resource_post_error(resource, WL_SEAT_ERROR_MISSING_CAPABILITY, - "wl_seat.get_pointer called when no " + "wl_seat.get_touch called when no " "touch capability has existed"); #endif return; diff --git a/src/libds/seat/seat_touch.c b/src/libds/seat/seat_touch.c index 8a02e94..476c6a8 100644 --- a/src/libds/seat/seat_touch.c +++ b/src/libds/seat/seat_touch.c @@ -233,7 +233,7 @@ seat_client_add_touch_resource(struct ds_seat_client *seat_client, struct wl_resource *resource; resource = wl_resource_create(seat_client->wl_client, - &wl_keyboard_interface, version, id); + &wl_touch_interface, version, id); if (!resource) { wl_client_post_no_memory(seat_client->wl_client); return; -- 2.7.4 From 754af62ee9070b524facf7b758f9d76a4c04aa4a Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Wed, 18 May 2022 18:39:54 +0900 Subject: [PATCH 03/16] example: add an executable 'tinyds-tdm-libinput' and handle ds_seat Change-Id: I965563b0f783c2f0ef685d9db34236e985edf9eb --- packaging/libds.spec | 1 + src/clients/simple-tbm.c | 168 +++++++ src/examples/meson.build | 17 + src/examples/tinyds-tdm-libinput.c | 992 +++++++++++++++++++++++++++++++++++++ 4 files changed, 1178 insertions(+) create mode 100644 src/examples/tinyds-tdm-libinput.c diff --git a/packaging/libds.spec b/packaging/libds.spec index 45329fe..2ffdca0 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -102,6 +102,7 @@ ninja -C builddir install %{_bindir}/tdm-backend %{_bindir}/tinyds-tdm %{_bindir}/ds-simple-tbm +%{_bindir}/tinyds-tdm-libinput %files tizen-keyrouter %manifest %{name}.manifest diff --git a/src/clients/simple-tbm.c b/src/clients/simple-tbm.c index f572b60..4fd9847 100644 --- a/src/clients/simple-tbm.c +++ b/src/clients/simple-tbm.c @@ -48,6 +48,7 @@ struct display { struct wl_compositor *compositor; struct xdg_wm_base *wm_base; struct wl_shm *shm; + struct wl_seat *seat; struct wayland_tbm_client *wl_tbm; bool has_xrgb; }; @@ -329,6 +330,168 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = { xdg_wm_base_ping, }; +static void pointer_handle_button(void *data, struct wl_pointer *pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) +{ + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { + fprintf(stderr, "pointer_handle_button: PRESSED\n"); + } + else { + fprintf(stderr, "pointer_handle_button: RELEASED\n"); + } +} + +static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) +{ + fprintf(stderr, "pointer_handle_enter surface_x:%d, surface_y:%d\n", + wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); +} + +static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) +{ + fprintf(stderr, "pointer_handle_leave\n"); +} + +static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) +{ + fprintf(stderr, "pointer_handle_motion surface_x:%d, surface_y:%d\n", + wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); +} + +static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) +{ + fprintf(stderr, "pointer_handle_frame\n"); +} + +static struct wl_pointer_listener pointer_listener = { + .enter = pointer_handle_enter, + .leave = pointer_handle_leave, + .motion = pointer_handle_motion, + .button = pointer_handle_button, + .axis = NULL, + .frame = pointer_handle_frame, + .axis_source = NULL, + .axis_stop = NULL, + .axis_discrete = NULL, +}; + +static void touch_handle_down(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, struct wl_surface *surface, + int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + fprintf(stderr, "touch_handle_down id:%d, x:%d, y:%d\n", + id, wl_fixed_to_int(x), wl_fixed_to_int(y)); +} + +static void touch_handle_up(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) +{ + fprintf(stderr, "touch_handle_up id:%d\n", id); +} + +static void touch_handle_motion(void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + fprintf(stderr, "touch_handle_motion id:%d, x:%d, y:%d\n", + id, wl_fixed_to_int(x), wl_fixed_to_int(y)); +} + +static void touch_handle_frame(void *data, struct wl_touch *wl_touch) +{ + fprintf(stderr, "touch_handle_frame\n"); +} + +static struct wl_touch_listener touch_listener = { + .down = touch_handle_down, + .up = touch_handle_up, + .motion = touch_handle_motion, + .frame = touch_handle_frame, + .cancel = NULL, + .shape = NULL, + .orientation = NULL, +}; + +static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, + uint32_t format, int32_t fd, uint32_t size) +{ + fprintf(stderr, "keyboard_handle_keymap\n"); +} +static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface, struct wl_array *keys) +{ + fprintf(stderr, "keyboard_handle_enter\n"); +} +static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *surface) +{ + fprintf(stderr, "keyboard_handle_leave\n"); +} +static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ + fprintf(stderr, "keyboard_handle_modifiers\n"); +} +static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard, + int32_t rate, int32_t delay) +{ + fprintf(stderr, "keyboard_handle_repeat_info\n"); +} + +static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + fprintf(stderr, "keyboard_handle_key: PRESSED\n"); + } else { + fprintf(stderr, "keyboard_handle_key: RELEASED\n"); + } +} + +static struct wl_keyboard_listener keyboard_listener = { + .keymap = keyboard_handle_keymap, + .enter = keyboard_handle_enter, + .leave = keyboard_handle_leave, + .key = keyboard_handle_key, + .modifiers = keyboard_handle_modifiers, + .repeat_info = keyboard_handle_repeat_info, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) +{ + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + struct wl_keyboard *keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL); + fprintf(stderr, "seat_handle_capabilities: keyboard\n"); + } + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(pointer, &pointer_listener, NULL); + fprintf(stderr, "seat_handle_capabilities: pointer\n"); + } + if ((caps & WL_SEAT_CAPABILITY_TOUCH)) { + struct wl_touch *touch = wl_seat_get_touch(wl_seat); + wl_touch_add_listener(touch, &touch_listener, NULL); + fprintf(stderr, "seat_handle_capabilities: touch\n"); + } +} + +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) +{ + fprintf(stderr, "seat_handle_name name:%s\n", name); +} + +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) @@ -347,6 +510,11 @@ registry_handle_global(void *data, struct wl_registry *registry, d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "wl_seat") == 0) { + d->seat = wl_registry_bind(registry, + id, &wl_seat_interface, 7); + wl_seat_add_listener(d->seat, &seat_listener, d); + fprintf(stderr, "wl_seat bound!\n"); } } diff --git a/src/examples/meson.build b/src/examples/meson.build index 9f2d976..5c5c437 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -65,4 +65,21 @@ if get_option('tizen') install_dir: libds_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, + dependency('pixman-1', required: true), + dependency('threads', required: true), + ], + install_dir: libds_bindir, + install : true + ) endif diff --git a/src/examples/tinyds-tdm-libinput.c b/src/examples/tinyds-tdm-libinput.c new file mode 100644 index 0000000..f4e9319 --- /dev/null +++ b/src/examples/tinyds-tdm-libinput.c @@ -0,0 +1,992 @@ +#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_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 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 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; +}; + +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 tinyds_keyboard +{ + struct ds_input_device *dev; + struct tinyds_server *server; + + struct wl_listener destroy; + struct wl_listener key; +}; + +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); + +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_handle_xdg_surface_map(struct wl_listener *listener, + void *data TINYDS_UNUSED) +{ + struct tinyds_view *view; + + view = wl_container_of(listener, view, xdg_surface_map); + view->mapped = true; +} + +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; +} + +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); + + 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 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) + return false; + + server->new_output.notify = backend_handle_new_output; + ds_backend_add_new_output_listener(server->backend, + &server->new_output); + + 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; + + 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); + + free(kbd); +} + +static void +keyboard_handle_key(struct wl_listener *listener, void *data) +{ + struct tinyds_keyboard *kbd; + struct ds_event_keyboard_key *event = data; + + 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); + //TODO: + //ds_seat_keyboard_notify_key() +} + +static void +server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev) +{ + struct tinyds_keyboard *kbd; + + kbd = calloc(1, sizeof *kbd); + assert(kbd); + + kbd->dev = dev; + kbd->server = server; + + kbd->destroy.notify = keyboard_handle_device_destroy; + ds_input_device_add_destroy_listener(dev, &kbd->destroy); + + kbd->key.notify = keyboard_handle_key; + ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key); + + ds_inf("Keyboard(%p) added", kbd); +} + +static 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); + + 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); + + ds_inf("Pointer(%p) added", pointer); +} -- 2.7.4 From e38d54bf0825e4aa061e6d96ab925daec94b20e6 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Thu, 19 May 2022 10:03:25 +0900 Subject: [PATCH 04/16] libinput: get event time from libinput_event Change-Id: I51c5ef5ca3d3a7b1bd27172617e484303205c46c --- src/libds/backend/libinput/backend.c | 4 ++++ src/libds/backend/libinput/backend.h | 2 ++ src/libds/backend/libinput/keyboard.c | 12 ++++++------ src/libds/backend/libinput/pointer.c | 9 ++++++--- src/libds/backend/libinput/touch.c | 9 ++++++--- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libds/backend/libinput/backend.c b/src/libds/backend/libinput/backend.c index f3ee044..b6dc4f1 100644 --- a/src/libds/backend/libinput/backend.c +++ b/src/libds/backend/libinput/backend.c @@ -225,3 +225,7 @@ libinput_backend_handle_display_destroy(struct wl_listener *listener, wl_container_of(listener, libinput_backend, display_destroy); libinput_backend_destroy(libinput_backend); } + +uint32_t usec_to_msec(uint64_t usec) { + return (uint32_t)(usec / 1000); +} \ No newline at end of file diff --git a/src/libds/backend/libinput/backend.h b/src/libds/backend/libinput/backend.h index 6fa2122..4d1c0ce 100644 --- a/src/libds/backend/libinput/backend.h +++ b/src/libds/backend/libinput/backend.h @@ -34,6 +34,8 @@ struct ds_libinput_input_device struct wl_list link; //ds_libinput_backend.devices }; +uint32_t usec_to_msec(uint64_t usec); + struct ds_libinput_backend * libinput_backend_from_backend(struct ds_backend *backend); diff --git a/src/libds/backend/libinput/keyboard.c b/src/libds/backend/libinput/keyboard.c index 53db0c9..9376f11 100644 --- a/src/libds/backend/libinput/keyboard.c +++ b/src/libds/backend/libinput/keyboard.c @@ -9,6 +9,7 @@ handle_keyboard_key(struct libinput_event *event, uint32_t key; enum libinput_key_state li_state; enum wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED; + struct ds_event_keyboard_key ds_event = {0}; kbevent = libinput_event_get_keyboard_event(event); @@ -24,12 +25,11 @@ handle_keyboard_key(struct libinput_event *event, ds_log(DS_DBG, "Keyboard(%p) key event key:%d, state:%s", kbd, key, (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? "PRESSED":"RELEASED"); - struct ds_event_keyboard_key ds_event = { - .keycode = key, - .state = state, - .time_msec = -1, - .update_state = false, - }; + ds_event.keycode = key; + ds_event.state = state; + ds_event.time_msec = usec_to_msec( + libinput_event_keyboard_get_time_usec(kbevent)); + ds_event.update_state = false; ds_keyboard_notify_key(kbd, &ds_event); } diff --git a/src/libds/backend/libinput/pointer.c b/src/libds/backend/libinput/pointer.c index c118d06..efdbaa7 100644 --- a/src/libds/backend/libinput/pointer.c +++ b/src/libds/backend/libinput/pointer.c @@ -17,7 +17,8 @@ handle_pointer_motion(struct libinput_event *event, ds_log(DS_DBG, "pointer motion event delta_x:%f, delta_y:%f", delta_x, delta_y); ds_event.device = NULL; - ds_event.time_msec = -1; + ds_event.time_msec = usec_to_msec( + libinput_event_pointer_get_time_usec(pevent)); ds_event.delta_x = delta_x; ds_event.delta_y = delta_y; @@ -40,7 +41,8 @@ handle_pointer_motion_abs(struct libinput_event *event, ds_log(DS_DBG, "Pointer(%p) motion abs event x:%f, y:%f", pointer, x, y); ds_event.device = NULL; - ds_event.time_msec = -1; + ds_event.time_msec = usec_to_msec( + libinput_event_pointer_get_time_usec(pevent)); ds_event.x = x; ds_event.y = y; @@ -75,7 +77,8 @@ handle_pointer_button(struct libinput_event *event, (state == DS_BUTTON_PRESSED) ? "PRESSED" : "RELEASED"); ds_event.device = NULL; - ds_event.time_msec = -1; + ds_event.time_msec = usec_to_msec( + libinput_event_pointer_get_time_usec(pevent)); ds_event.button = button; ds_event.state = state; diff --git a/src/libds/backend/libinput/touch.c b/src/libds/backend/libinput/touch.c index 08b7b80..fd94c0b 100644 --- a/src/libds/backend/libinput/touch.c +++ b/src/libds/backend/libinput/touch.c @@ -19,7 +19,8 @@ handle_touch_down(struct libinput_event *event, ds_log(DS_DBG, "touch down event id:%d, x:%f, y:%f", touch_id, x, y); ds_event.device = NULL; - ds_event.time_msec = -1; + ds_event.time_msec = usec_to_msec( + libinput_event_touch_get_time_usec(tevent)); ds_event.id = touch_id; ds_event.x = x; ds_event.y = y; @@ -42,7 +43,8 @@ handle_touch_up(struct libinput_event *event, ds_log(DS_DBG, "touch up event id:%d", touch_id); ds_event.device = NULL; - ds_event.time_msec = -1; + ds_event.time_msec = usec_to_msec( + libinput_event_touch_get_time_usec(tevent)); ds_event.id = touch_id; wl_signal_emit(&touch->events.up, &ds_event); @@ -66,7 +68,8 @@ handle_touch_motion(struct libinput_event *event, ds_log(DS_DBG, "touch motion event id:%d, x:%f, y:%f", touch_id, x, y); ds_event.device = NULL; - ds_event.time_msec = -1; + ds_event.time_msec = usec_to_msec( + libinput_event_touch_get_time_usec(tevent)); ds_event.id = touch_id; ds_event.x = x; ds_event.y = y; -- 2.7.4 From bea3faea6e531643e9a9b037942b2345fef1a225 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 19 May 2022 19:34:06 +0900 Subject: [PATCH 05/16] keyrouter: change the prefix of the internal functions remove the tizen prefix. Change-Id: I060071ea4593d2dca366965b9ad9e94dc9d0c98f --- src/libds-tizen/keyrouter/keyrouter.c | 42 +++++++++++++++--------------- src/libds-tizen/keyrouter/keyrouter.h | 16 ++++++------ src/libds-tizen/keyrouter/keyrouter_grab.c | 16 ++++++------ 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/libds-tizen/keyrouter/keyrouter.c b/src/libds-tizen/keyrouter/keyrouter.c index eaa831a..6b5b220 100644 --- a/src/libds-tizen/keyrouter/keyrouter.c +++ b/src/libds-tizen/keyrouter/keyrouter.c @@ -13,13 +13,13 @@ #include "keyrouter.h" static void -tizen_keyrouter_bind(struct wl_client *client, void *data, uint32_t version, +keyrouter_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); static bool keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, struct wl_client *client, uint32_t mode, uint32_t keycode); static void -tizen_keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter); +keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter); static void keyrouter_handle_display_destroy(struct wl_listener *listener, void *data) @@ -40,7 +40,7 @@ keyrouter_handle_display_destroy(struct wl_listener *listener, void *data) wl_global_destroy(keyrouter->global); - tizen_keyrouter_grab_destroy(keyrouter->keyrouter_grab); + keyrouter_grab_destroy(keyrouter->keyrouter_grab); free(keyrouter); } @@ -55,7 +55,7 @@ ds_tizen_keyrouter_create(struct wl_display *display) return NULL; } - keyrouter->keyrouter_grab = tizen_keyrouter_grab_create(); + keyrouter->keyrouter_grab = keyrouter_grab_create(); if (keyrouter->keyrouter_grab == NULL) { ds_err("Failed to create keyrouter."); free(keyrouter); @@ -63,9 +63,9 @@ ds_tizen_keyrouter_create(struct wl_display *display) } keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface, - 2, keyrouter, tizen_keyrouter_bind); + 2, keyrouter, keyrouter_bind); if (!keyrouter->global) { - tizen_keyrouter_grab_destroy(keyrouter->keyrouter_grab); + keyrouter_grab_destroy(keyrouter->keyrouter_grab); free(keyrouter); return NULL; } @@ -77,7 +77,7 @@ ds_tizen_keyrouter_create(struct wl_display *display) keyrouter->display_destroy.notify = keyrouter_handle_display_destroy; wl_display_add_destroy_listener(display, &keyrouter->display_destroy); - tizen_keyrouter_options_set(keyrouter); + keyrouter_options_set(keyrouter); if (!tizen_security_init()) { ds_inf("tizen_security_init() is not sucessful. keyrouter works without security."); @@ -115,7 +115,7 @@ keyrouter_handle_keygrab_set(struct wl_client *client, return; } - res = tizen_keyrouter_grab_grab_key(keyrouter->keyrouter_grab, + res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, mode, key, (void *)client); if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true) keyrouter_client->grabbed = true; @@ -136,7 +136,7 @@ keyrouter_handle_keygrab_unset(struct wl_client *client, keyrouter = keyrouter_client->keyrouter; /* ungrab TOP POSITION grab first, this grab mode is not check privilege */ - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client); ret = keyrouter_check_privilege(keyrouter_client, @@ -147,13 +147,13 @@ keyrouter_handle_keygrab_unset(struct wl_client *client, return; } - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)client); - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)client); - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client); - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_SHARED, key, (void *)client); tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res); @@ -205,7 +205,7 @@ keyrouter_handle_keygrab_set_list(struct wl_client *client, if (ret == false) { grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; } else { - res = tizen_keyrouter_grab_grab_key(keyrouter->keyrouter_grab, + res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab, grab_data->mode, grab_data->key, (void *)client); if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true) keyrouter_client->grabbed = true; @@ -240,7 +240,7 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *client, } wl_array_for_each(ungrab_data, ungrab_list) { - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client); ret = keyrouter_check_privilege(keyrouter_client, client, @@ -248,16 +248,16 @@ keyrouter_handle_keygrab_unset_list(struct wl_client *client, if (!ret) { ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION; } else { - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)client); - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)client); - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client); - tizen_keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, + keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab, TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)client); ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE; @@ -329,7 +329,7 @@ keyrouter_handle_resource_destory(struct wl_resource *resource) } static void -tizen_keyrouter_bind(struct wl_client *client, void *data, uint32_t version, +keyrouter_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { struct ds_tizen_keyrouter *keyrouter = data; @@ -386,7 +386,7 @@ keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client, } static void -tizen_keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter) +keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter) { FILE *file; int keycode; diff --git a/src/libds-tizen/keyrouter/keyrouter.h b/src/libds-tizen/keyrouter/keyrouter.h index c8dfa0f..ffbb3cd 100644 --- a/src/libds-tizen/keyrouter/keyrouter.h +++ b/src/libds-tizen/keyrouter/keyrouter.h @@ -83,26 +83,26 @@ struct ds_tizen_ungrab_data }; struct ds_tizen_keyrouter_grab * -tizen_keyrouter_grab_create(void); +keyrouter_grab_create(void); void -tizen_keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab); +keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab); int -tizen_keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int type, int keycode, void *data); void -tizen_keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int type, int keycode, void *data); int -tizen_keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode, int pressed, struct wl_list *delivery_list); void -tizen_keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *focus_client); void -tizen_keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *top_client); bool -tizen_keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode); #endif diff --git a/src/libds-tizen/keyrouter/keyrouter_grab.c b/src/libds-tizen/keyrouter/keyrouter_grab.c index 873f4b1..f5467ae 100644 --- a/src/libds-tizen/keyrouter/keyrouter_grab.c +++ b/src/libds-tizen/keyrouter/keyrouter_grab.c @@ -24,7 +24,7 @@ keyrouter_grab_get_grabbed_list(struct ds_tizen_keyrouter_grab *keyrouter_grab, } bool -tizen_keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode) +keyrouter_grab_check_grabbed_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode) { struct wl_list *list; @@ -101,7 +101,7 @@ keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab, } void -tizen_keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *focus_client) { keyrouter_grab->focus_client = focus_client; @@ -113,7 +113,7 @@ tizen_keyrouter_grab_set_focus_client(struct ds_tizen_keyrouter_grab *keyrouter_ } void -tizen_keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *top_client) +keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_grab, void *top_client) { keyrouter_grab->top_client = top_client; @@ -124,7 +124,7 @@ tizen_keyrouter_grab_set_top_client(struct ds_tizen_keyrouter_grab *keyrouter_gr } int -tizen_keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, int keycode, int pressed, struct wl_list *delivery_list) { struct ds_tizen_keyrouter_key_info *info, *delivery; @@ -209,7 +209,7 @@ tizen_keyrouter_grab_key_process(struct ds_tizen_keyrouter_grab *keyrouter_grab, } int -tizen_keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_grab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int type, int keycode, void *data) { struct ds_tizen_keyrouter_key_info *info = NULL; @@ -264,7 +264,7 @@ keyrouter_list_remove_data(struct wl_list *list, void *data) } void -tizen_keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, +keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, int type, int keycode, void *data) { struct wl_list *list; @@ -287,7 +287,7 @@ tizen_keyrouter_grab_ungrab_key(struct ds_tizen_keyrouter_grab *keyrouter_grab, } struct ds_tizen_keyrouter_grab * -tizen_keyrouter_grab_create(void) +keyrouter_grab_create(void) { struct ds_tizen_keyrouter_grab *keyrouter_grab = NULL; int i; @@ -334,7 +334,7 @@ keyrouter_grab_delete_list(struct wl_list *list) } void -tizen_keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab) +keyrouter_grab_destroy(struct ds_tizen_keyrouter_grab *keyrouter_grab) { int i; -- 2.7.4 From 68b858cbaf85f370bcd9241d3ae42d7f58485f41 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Wed, 18 May 2022 14:32:31 +0900 Subject: [PATCH 06/16] fix the build warning Change-Id: I43f5101b85b807abef226169940d4cba5955caa9 --- src/libds-tizen/util/security.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libds-tizen/util/security.c b/src/libds-tizen/util/security.c index 735caf5..ad19027 100644 --- a/src/libds-tizen/util/security.c +++ b/src/libds-tizen/util/security.c @@ -145,18 +145,16 @@ tizen_security_finish(void) #ifdef HAVE_CYNARA if (g_cynara_refcount < 1) { ds_err("%s called without tizen_security_init\n", __FUNCTION__); - return 0; + return; } if (--g_cynara_refcount != 0) - return 1; + return; if (g_cynara) { cynara_finish(g_cynara); g_cynara = NULL; } #endif - - return 1; } -- 2.7.4 From 939403b95d4b122e256c25f4fa9d90b7c3a343e5 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 16 May 2022 17:39:29 +0900 Subject: [PATCH 07/16] shell: implement wl_shell_interface ds_shell and ds_shell_surface are resources which implement the wl_shell_interface and wl_shell_surface_interface. Change-Id: I551324b8f14a3aa77c920cece19e15a12e8d9981 --- include/libds/shell.h | 50 +++++ src/libds/meson.build | 2 + src/libds/shell.c | 175 +++++++++++++++ src/libds/shell.h | 157 ++++++++++++++ src/libds/shell_surface.c | 540 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 924 insertions(+) create mode 100644 include/libds/shell.h create mode 100644 src/libds/shell.c create mode 100644 src/libds/shell.h create mode 100644 src/libds/shell_surface.c diff --git a/include/libds/shell.h b/include/libds/shell.h new file mode 100644 index 0000000..b4fa688 --- /dev/null +++ b/include/libds/shell.h @@ -0,0 +1,50 @@ +#ifndef LIBDS_SHELL_H +#define LIBDS_SHELL_H + +#include +#include + +#include "surface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds_shell; + +struct ds_shell_surface; + +struct ds_shell * +ds_shell_create(struct wl_display *display); + +void +ds_shell_add_destroy_listener(struct ds_shell *shell, + struct wl_listener *listener); + +void +ds_shell_add_new_surface_listener(struct ds_shell *shell, + struct wl_listener *listener); + +void +ds_shell_surface_add_destroy_listener(struct ds_shell_surface *surface, + struct wl_listener *listener); + +void +ds_shell_surface_add_map_listener(struct ds_shell_surface *surface, + struct wl_listener *listener); + +void +ds_shell_surface_add_unmap_listener(struct ds_shell_surface *surface, + struct wl_listener *listener); + +void +ds_shell_surface_ping(struct ds_shell_surface *surface); + +struct ds_surface * +ds_shell_surface_get_surface(struct ds_shell_surface *surface); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libds/meson.build b/src/libds/meson.build index 43bdeae..b59fda2 100644 --- a/src/libds/meson.build +++ b/src/libds/meson.build @@ -26,6 +26,8 @@ libds_files = [ 'seat/seat_pointer.c', 'seat/seat_keyboard.c', 'seat/seat_touch.c', + 'shell.c', + 'shell_surface.c', ] protocols = { diff --git a/src/libds/shell.c b/src/libds/shell.c new file mode 100644 index 0000000..3adb519 --- /dev/null +++ b/src/libds/shell.c @@ -0,0 +1,175 @@ +#include +#include +#include + +#include "libds/log.h" +#include "libds/shell.h" + +#include "shell.h" + +#define WL_SHELL_VERSION 1 +#define SHELL_PING_TIMEOUT 10000 + +static void shell_handle_display_destroy(struct wl_listener *listener, + void *data); +static void shell_bind(struct wl_client *wl_client, void *data, + uint32_t verison, uint32_t id); + +WL_EXPORT struct ds_shell * +ds_shell_create(struct wl_display *display) +{ + struct ds_shell *shell; + + shell = calloc(1, sizeof *shell); + if (!shell) { + return NULL; + } + + shell->global = wl_global_create(display, &wl_shell_interface, + WL_SHELL_VERSION, shell, shell_bind); + if (!shell->global) { + free(shell); + return NULL; + } + + wl_list_init(&shell->clients); + + shell->display_destroy.notify = shell_handle_display_destroy; + wl_display_add_destroy_listener(display, &shell->display_destroy); + + wl_signal_init(&shell->events.destroy); + wl_signal_init(&shell->events.new_surface); + + shell->ping_timeout = SHELL_PING_TIMEOUT; + + ds_inf("Global created: xdg_wm_base shell(%p)", shell); + + return shell; +} + +WL_EXPORT void +ds_shell_add_destroy_listener(struct ds_shell *shell, + struct wl_listener *listener) +{ + wl_signal_add(&shell->events.destroy, listener); +} + +WL_EXPORT void +ds_shell_add_new_surface_listener(struct ds_shell *shell, + struct wl_listener *listener) +{ + wl_signal_add(&shell->events.new_surface, listener); +} + +static void +shell_handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ds_shell *shell; + + shell = wl_container_of(listener, shell, display_destroy); + + ds_inf("Global destroy: xdg_wm_base shell(%p)", shell); + + wl_signal_emit(&shell->events.destroy, shell); + wl_list_remove(&shell->display_destroy.link); + wl_global_destroy(shell->global); + free(shell); +} + +static void +shell_handle_get_shell_surface(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t id, + struct wl_resource *surface_resource) +{ + struct ds_shell_client *client; + struct ds_surface *surface; + + client = wl_resource_get_user_data(resource); + surface = ds_surface_from_resource(surface_resource); + create_shell_surface(client, surface, id); +} + +static const struct wl_shell_interface shell_impl = +{ + .get_shell_surface = shell_handle_get_shell_surface, +}; + +static void +shell_client_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_shell_client *client; + struct ds_shell_surface *shell_surface, *tmp; + + client = wl_resource_get_user_data(resource); + + wl_list_for_each_safe(shell_surface, tmp, &client->shell_surfaces, link) + destroy_shell_surface(shell_surface); + + if (client->ping_timer != NULL) + wl_event_source_remove(client->ping_timer); + + wl_list_remove(&client->link); + free(client); +} + +static int +shell_client_handle_ping_timeout(void *user_data) +{ + struct ds_shell_client *client = user_data; + struct ds_shell_surface *surface; + + wl_list_for_each(surface, &client->shell_surfaces, link) + wl_signal_emit(&surface->events.ping_timeout, surface); + + client->ping_serial = 0; + + return 1; +} + +static void +shell_client_init_ping_timer(struct ds_shell_client *client) +{ + struct wl_display *display; + struct wl_event_loop *loop; + + display = wl_client_get_display(client->wl_client); + loop = wl_display_get_event_loop(display); + client->ping_timer = wl_event_loop_add_timer(loop, + shell_client_handle_ping_timeout, client); + if (client->ping_timer == NULL) + wl_client_post_no_memory(client->wl_client); +} + +static void +shell_bind(struct wl_client *wl_client, void *data, uint32_t version, + uint32_t id) +{ + struct ds_shell *shell = data; + struct ds_shell_client *client; + + client = calloc(1, sizeof *client); + if (client == NULL) { + wl_client_post_no_memory(wl_client); + return; + } + + client->wl_client = wl_client; + client->shell = shell; + + wl_list_init(&client->shell_surfaces); + + client->resource = + wl_resource_create(wl_client, &wl_shell_interface, version, id); + if (client->resource == NULL) { + free(client); + wl_client_post_no_memory(wl_client); + return; + } + + wl_resource_set_implementation(client->resource, &shell_impl, client, + shell_client_handle_resource_destroy); + + wl_list_insert(&shell->clients, &client->link); + + shell_client_init_ping_timer(client); +} diff --git a/src/libds/shell.h b/src/libds/shell.h new file mode 100644 index 0000000..c2306af --- /dev/null +++ b/src/libds/shell.h @@ -0,0 +1,157 @@ +#ifndef DS_SHELL_H +#define DS_SHELL_H + +#include + +#include "libds/output.h" + +#include "surface.h" + +enum ds_shell_surface_role +{ + DS_SHELL_SURFACE_ROLE_NONE, + DS_SHELL_SURFACE_ROLE_TOPLEVEL, + DS_SHELL_SURFACE_ROLE_POPUP, +}; + +struct ds_shell +{ + struct wl_global *global; + + struct wl_list clients; + + struct wl_listener display_destroy; + + struct { + struct wl_signal destroy; + struct wl_signal new_surface; + } events; + + uint32_t ping_timeout; +}; + +struct ds_shell_client +{ + struct ds_shell *shell; + + struct wl_resource *resource; + struct wl_client *wl_client; + struct wl_event_source *ping_timer; + + struct wl_list shell_surfaces; + + struct wl_list link; // ds_shell::clients + + uint32_t ping_serial; +}; + +struct ds_shell_toplevel_state +{ + bool maximized, fullscreen, resizing, activated; + uint32_t tiled; + uint32_t width, height; + uint32_t max_width, max_height; + uint32_t min_width, min_height; +}; + +struct ds_shell_toplevel_requested +{ + bool maximized, minimized, fullscreen; + struct ds_output *fullscreen_output; + struct wl_listener fullscreen_output_destroy; +}; + +struct ds_shell_toplevel +{ + struct ds_shell_surface *base; + bool added; + + struct ds_shell_surface *parent; + struct wl_listener parent_unmap; + + struct ds_shell_toplevel_state current, pending; + struct ds_shell_toplevel_requested requested; + + char *title; + char *app_id; + + struct { + struct wl_signal request_maximize; + struct wl_signal request_fullscreen; + struct wl_signal request_minimize; + struct wl_signal request_move; + struct wl_signal request_resize; + struct wl_signal request_show_window_menu; + struct wl_signal set_parent; + struct wl_signal set_title; + struct wl_signal set_app_id; + } events; +}; + +struct ds_xdg_popup +{ + +}; + +struct ds_shell_surface_state +{ + uint32_t configure_serial; + struct { + int x, y; + int width, height; + } geometry; +}; + +struct ds_shell_surface +{ + struct ds_shell_client *client; + struct ds_surface *surface; + + enum ds_shell_surface_role role; + + union { + struct ds_shell_toplevel *toplevel; + struct ds_xdg_popup *popup; + }; + + struct wl_resource *resource; + + struct wl_event_source *configure_idle; + uint32_t scheduled_serial; + struct wl_list configure_list; + + struct ds_shell_surface_state current, pending; + + struct wl_list link; // ds_shell_client::surfaces + + struct { + struct wl_listener surface_destroy; + struct wl_listener surface_commit; + } listener; + + struct { + struct wl_signal destroy; + struct wl_signal ping_timeout; + struct wl_signal new_popup; + struct wl_signal map; + struct wl_signal unmap; + struct wl_signal configure; + } events; + + bool added, configured, mapped; +}; + +struct ds_shell_surface_configure +{ + struct ds_shell_surface *shell_surface; + struct wl_list link; + uint32_t serial; +}; + +struct ds_shell_surface * +create_shell_surface(struct ds_shell_client *client, struct ds_surface *surface, + uint32_t id); + +void destroy_shell_surface(struct ds_shell_surface *surface); + +#endif diff --git a/src/libds/shell_surface.c b/src/libds/shell_surface.c new file mode 100644 index 0000000..73c498b --- /dev/null +++ b/src/libds/shell_surface.c @@ -0,0 +1,540 @@ +#include +#include +#include + +#include "libds/log.h" + +#include "shell.h" + +static const struct wl_shell_surface_interface shell_surface_impl; + +static void reset_shell_surface(struct ds_shell_surface *shell_surface); +static void shell_surface_handle_surface_destroy(struct wl_listener *listener, + void *data); +static void shell_surface_handle_surface_commit(struct wl_listener *listener, + void *data); +static void shell_surface_handle_resource_destroy(struct wl_resource *resource); +static void shell_surface_configure_destroy(struct ds_shell_surface_configure *configure); +static void surface_send_configure(void *user_data); +static void handle_shell_surface_commit(struct ds_surface *surface); + +WL_EXPORT void +ds_shell_surface_add_destroy_listener(struct ds_shell_surface *shell_surface, + struct wl_listener *listener) +{ + wl_signal_add(&shell_surface->events.destroy, listener); +} + +WL_EXPORT void +ds_shell_surface_add_map_listener(struct ds_shell_surface *shell_surface, + struct wl_listener *listener) +{ + wl_signal_add(&shell_surface->events.map, listener); +} + +WL_EXPORT void +ds_shell_surface_add_unmap_listener(struct ds_shell_surface *shell_surface, + struct wl_listener *listener) +{ + wl_signal_add(&shell_surface->events.unmap, listener); +} + +WL_EXPORT struct ds_surface * +ds_shell_surface_get_surface(struct ds_shell_surface *shell_surface) +{ + return shell_surface->surface; +} + +static const struct ds_surface_role shell_surface_role = +{ + .name = "shell_surface", + .commit = handle_shell_surface_commit, +}; + +struct ds_shell_surface * +create_shell_surface(struct ds_shell_client *client, struct ds_surface *surface, + uint32_t id) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = calloc(1, sizeof *shell_surface); + if (!shell_surface) { + wl_client_post_no_memory(client->wl_client); + return NULL; + } + + shell_surface->client = client; + shell_surface->role = DS_SHELL_SURFACE_ROLE_NONE; + shell_surface->surface = surface; + shell_surface->resource = wl_resource_create(client->wl_client, + &wl_shell_surface_interface, wl_resource_get_version(client->resource), + id); + if (!shell_surface->resource) { + free(shell_surface); + wl_client_post_no_memory(client->wl_client); + return NULL; + } + + if (!ds_surface_set_role(shell_surface->surface, &shell_surface_role, + shell_surface, shell_surface->resource, -1)) { + free(shell_surface); + return NULL; + } + + wl_list_init(&shell_surface->configure_list); + + wl_signal_init(&shell_surface->events.destroy); + wl_signal_init(&shell_surface->events.ping_timeout); + wl_signal_init(&shell_surface->events.new_popup); + wl_signal_init(&shell_surface->events.map); + wl_signal_init(&shell_surface->events.unmap); + wl_signal_init(&shell_surface->events.configure); + + shell_surface->listener.surface_destroy.notify = + shell_surface_handle_surface_destroy; + ds_surface_add_destroy_listener(surface, + &shell_surface->listener.surface_destroy); + + shell_surface->listener.surface_commit.notify = + shell_surface_handle_surface_commit; + ds_surface_add_commit_listener(surface, + &shell_surface->listener.surface_commit); + + wl_resource_set_implementation(shell_surface->resource, &shell_surface_impl, + shell_surface, shell_surface_handle_resource_destroy); + + wl_list_insert(&client->shell_surfaces, &shell_surface->link); + + ds_inf("New shell_surface %p (res %p)", shell_surface, shell_surface->resource); + + return shell_surface; +} + +void +destroy_shell_surface(struct ds_shell_surface *shell_surface) +{ + reset_shell_surface(shell_surface); + + wl_resource_set_user_data(shell_surface->resource, NULL); + + ds_surface_reset_role_data(shell_surface->surface); + + wl_list_remove(&shell_surface->link); + wl_list_remove(&shell_surface->listener.surface_destroy.link); + wl_list_remove(&shell_surface->listener.surface_commit.link); + + free(shell_surface); +} + +static void +unmap_shell_surface(struct ds_shell_surface *shell_surface) +{ + struct ds_shell_surface_configure *configure, *tmp; + + // TODO handle popup + + if (shell_surface->mapped) + wl_signal_emit(&shell_surface->events.unmap, shell_surface); + + switch (shell_surface->role) { + case DS_SHELL_SURFACE_ROLE_TOPLEVEL: + if (shell_surface->toplevel->parent) { + wl_list_remove(&shell_surface->toplevel->parent_unmap.link); + shell_surface->toplevel->parent = NULL; + } + free(shell_surface->toplevel->title); + shell_surface->toplevel->title = NULL; + free(shell_surface->toplevel->app_id); + shell_surface->toplevel->app_id = NULL; + break; + case DS_SHELL_SURFACE_ROLE_POPUP: + // TODO + break; + case DS_SHELL_SURFACE_ROLE_NONE: + assert(false && "not reached"); + } + + wl_list_for_each_safe(configure, tmp, &shell_surface->configure_list, link) + shell_surface_configure_destroy(configure); + + if (shell_surface->configure_idle) { + wl_event_source_remove(shell_surface->configure_idle); + shell_surface->configure_idle = NULL; + } + + shell_surface->configured = false; + shell_surface->mapped = false; +} + +static void +reset_shell_surface(struct ds_shell_surface *shell_surface) +{ + struct ds_shell_toplevel_requested *req; + + if (shell_surface->role != DS_SHELL_SURFACE_ROLE_NONE) + unmap_shell_surface(shell_surface); + + if (shell_surface->added) { + wl_signal_emit(&shell_surface->events.destroy, shell_surface); + shell_surface->added = false; + } + + switch (shell_surface->role) { + case DS_SHELL_SURFACE_ROLE_TOPLEVEL: + req = &shell_surface->toplevel->requested; + if (req->fullscreen_output) + wl_list_remove(&req->fullscreen_output_destroy.link); + free(shell_surface->toplevel); + shell_surface->toplevel = NULL; + break; + case DS_SHELL_SURFACE_ROLE_POPUP: + // TODO + break; + case DS_SHELL_SURFACE_ROLE_NONE: + // This space is intentionally left blank + break; + } + + shell_surface->role = DS_SHELL_SURFACE_ROLE_NONE; +} + +static uint32_t +ds_shell_surface_schedule_configure(struct ds_shell_surface *shell_surface) +{ + struct wl_display *display; + struct wl_event_loop *loop; + + display = wl_client_get_display(shell_surface->client->wl_client); + loop = wl_display_get_event_loop(display); + + if (!shell_surface->configure_idle) { + shell_surface->scheduled_serial = wl_display_next_serial(display); + shell_surface->configure_idle = wl_event_loop_add_idle(loop, + surface_send_configure, shell_surface); + if (!shell_surface->configure_idle) + wl_client_post_no_memory(shell_surface->client->wl_client); + } + + return shell_surface->scheduled_serial; +} + +static void +handle_shell_surface_commit(struct ds_surface *surface) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = ds_surface_get_role_data(surface); + shell_surface->current = shell_surface->pending; + + switch (shell_surface->role) { + case DS_SHELL_SURFACE_ROLE_NONE: + // inert toplevel or popup + break; + case DS_SHELL_SURFACE_ROLE_TOPLEVEL: + if (!shell_surface->toplevel->added) { + ds_shell_surface_schedule_configure(shell_surface); + shell_surface->toplevel->added = true; + } + // TODO + break; + case DS_SHELL_SURFACE_ROLE_POPUP: + // TODO + break; + } + + if (!shell_surface->added) { + shell_surface->added = true; + wl_signal_emit(&shell_surface->client->shell->events.new_surface, shell_surface); + } + + if (shell_surface->configured && + ds_surface_has_buffer(shell_surface->surface) && + !shell_surface->mapped) { + shell_surface->mapped = true; + wl_signal_emit(&shell_surface->events.map, shell_surface); + } +} + +void handle_shell_surface_precommit(struct ds_surface *surface) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = ds_surface_get_role_data(surface); + + // TODO + (void)shell_surface; +} + +void +ds_shell_surface_ping(struct ds_shell_surface *shell_surface) +{ +} + +static void +shell_surface_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_container_of(listener, shell_surface, listener.surface_destroy); + destroy_shell_surface(shell_surface); +} + +static void +shell_surface_handle_surface_commit(struct wl_listener *listener, void *data) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_container_of(listener, shell_surface, listener.surface_commit); + + if (ds_surface_has_buffer(shell_surface->surface) && + !shell_surface->configured) { + wl_resource_post_error(shell_surface->resource, + -1, + "shell_surface has never been configured"); + return; + } + + if (!ds_surface_get_role(shell_surface->surface)) { + wl_resource_post_error(shell_surface->resource, + -1, + "shell_surface must have a role"); + return; + } +} + +static void +shell_surface_handle_resource_destroy(struct wl_resource *resource) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + if (!shell_surface) + return; + + destroy_shell_surface(shell_surface); +} + +static void +shell_surface_configure_destroy(struct ds_shell_surface_configure *configure) +{ + wl_list_remove(&configure->link); + free(configure); +} + +static void +create_shell_surface_toplevel(struct ds_shell_surface *shell_surface) +{ + assert(shell_surface->toplevel == NULL); + + shell_surface->toplevel = calloc(1, sizeof *shell_surface->toplevel); + if (!shell_surface->toplevel) { + wl_resource_post_no_memory(shell_surface->resource); + return; + } + + shell_surface->toplevel->base = shell_surface; + + wl_signal_init(&shell_surface->toplevel->events.request_maximize); + wl_signal_init(&shell_surface->toplevel->events.request_fullscreen); + wl_signal_init(&shell_surface->toplevel->events.request_minimize); + wl_signal_init(&shell_surface->toplevel->events.request_move); + wl_signal_init(&shell_surface->toplevel->events.request_resize); + wl_signal_init(&shell_surface->toplevel->events.request_show_window_menu); + wl_signal_init(&shell_surface->toplevel->events.set_parent); + wl_signal_init(&shell_surface->toplevel->events.set_title); + wl_signal_init(&shell_surface->toplevel->events.set_app_id); + + shell_surface->role = DS_SHELL_SURFACE_ROLE_TOPLEVEL; +} + +static void +shell_surface_handle_pong(struct wl_client *wl_client, + struct wl_resource *resource, uint32_t serial) +{ + struct ds_shell_surface *shell_surface; + struct ds_shell_client *client; + + shell_surface = wl_resource_get_user_data(resource); + + client = shell_surface->client; + if (client->ping_serial != serial) + return; + + wl_event_source_timer_update(client->ping_timer, 0); + client->ping_serial = 0; +} + +static void +shell_surface_handle_move(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + // TODO + (void)shell_surface; +} + +static void +shell_surface_handle_resize(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial, uint32_t edges) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + // TODO + (void)shell_surface; +} + +static void +shell_surface_handle_set_toplevel(struct wl_client *client, struct wl_resource *resource) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + create_shell_surface_toplevel(shell_surface); +} + +static void +shell_surface_handle_set_transient(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *parent_resource, + int32_t x, int32_t y, uint32_t flags) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + // TODO + (void)shell_surface; + ds_err("Not implemented yet."); +} + +static void +shell_surface_handle_set_fullscreen(struct wl_client *client, + struct wl_resource *resource, uint32_t method, uint32_t framerate, + struct wl_resource *output_resource) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + // TODO + (void)shell_surface; + ds_err("Not implemented yet."); +} + +static void +shell_surface_handle_set_popup(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *seat_resource, + uint32_t serial, struct wl_resource *parent_resource, + int32_t x, int32_t y, uint32_t flags) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + // TODO + (void)shell_surface; + ds_err("Not implemented yet."); +} + +static void +shell_surface_handle_set_maximized(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *output_resource) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + shell_surface->toplevel->requested.maximized = true; + wl_signal_emit(&shell_surface->toplevel->events.request_maximize, shell_surface); + ds_shell_surface_schedule_configure(shell_surface); +} + +static void +shell_surface_handle_set_title(struct wl_client *client, + struct wl_resource *resource, const char *title) +{ + struct ds_shell_surface *shell_surface; + char *tmp; + + shell_surface = wl_resource_get_user_data(resource); + tmp = strdup(title); + if (!tmp) { + wl_resource_post_no_memory(resource); + return; + } + + if (shell_surface->toplevel->title) + free(shell_surface->toplevel->title); + + shell_surface->toplevel->title = tmp; + wl_signal_emit(&shell_surface->toplevel->events.set_title, shell_surface); +} + +static void +shell_surface_handle_set_class(struct wl_client *client, + struct wl_resource *resource, const char *clas) +{ + struct ds_shell_surface *shell_surface; + + shell_surface = wl_resource_get_user_data(resource); + + // TODO + (void)shell_surface; + ds_err("Not implemented yet."); +} + +static const struct wl_shell_surface_interface shell_surface_impl = +{ + .pong = shell_surface_handle_pong, + .move = shell_surface_handle_move, + .resize = shell_surface_handle_resize, + .set_toplevel = shell_surface_handle_set_toplevel, + .set_transient = shell_surface_handle_set_transient, + .set_fullscreen = shell_surface_handle_set_fullscreen, + .set_popup = shell_surface_handle_set_popup, + .set_maximized = shell_surface_handle_set_maximized, + .set_title = shell_surface_handle_set_title, + .set_class = shell_surface_handle_set_class, +}; + +static void +surface_send_configure(void *user_data) +{ + struct ds_shell_surface *shell_surface; + struct ds_shell_surface_configure *configure; + uint32_t width, height; + uint32_t edges = 0; + + shell_surface = user_data; + shell_surface->configure_idle = NULL; + + // TDOO: Not sure if shell needs the struct ds_shell_surface_configure. + configure = calloc(1, sizeof *configure); + if (!configure) { + wl_client_post_no_memory(shell_surface->client->wl_client); + return; + } + + wl_list_insert(shell_surface->configure_list.prev, &configure->link); + configure->serial = shell_surface->scheduled_serial; + configure->shell_surface = shell_surface; + + wl_signal_emit(&shell_surface->events.configure, configure); + + edges = (WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_LEFT); // fixed default value + width = shell_surface->current.geometry.width; + height = shell_surface->current.geometry.height; + + wl_shell_surface_send_configure(shell_surface->resource, edges, width, height); + + shell_surface->configured = true; + + // TDOO: Not sure if shell needs the struct ds_shell_surface_configure. + shell_surface_configure_destroy(configure); +} -- 2.7.4 From 024636d86aa5e2c43ba2f6c5b68f751cad237b78 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Thu, 19 May 2022 10:38:44 +0900 Subject: [PATCH 08/16] client: add simple-shm-shell sample This is a simple wayland-client which use wl_shm and wl_shell interface. Change-Id: I3d27d37d56097ab84e46d7c59fc52329b5c9605e --- packaging/libds.spec | 1 + src/clients/meson.build | 12 ++ src/clients/simple-shm-shell.c | 339 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 352 insertions(+) create mode 100644 src/clients/simple-shm-shell.c diff --git a/packaging/libds.spec b/packaging/libds.spec index 2ffdca0..5258295 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -103,6 +103,7 @@ ninja -C builddir install %{_bindir}/tinyds-tdm %{_bindir}/ds-simple-tbm %{_bindir}/tinyds-tdm-libinput +%{_bindir}/ds-simple-shm-shell %files tizen-keyrouter %manifest %{name}.manifest diff --git a/src/clients/meson.build b/src/clients/meson.build index 360c425..009016c 100644 --- a/src/clients/meson.build +++ b/src/clients/meson.build @@ -1,3 +1,15 @@ +simple_shm_shell_files = ['simple-shm-shell.c'] +simple_shm_shell_deps = [ + dependency('wayland-client', required: true), +] + +executable('ds-simple-shm-shell', + simple_shm_shell_files, + dependencies: simple_shm_shell_deps, + install_dir: libds_bindir, + install: true, +) + wayland_tbm_client = dependency('wayland-tbm-client', required: false) libtbm = dependency('libtbm', required: false) diff --git a/src/clients/simple-shm-shell.c b/src/clients/simple-shm-shell.c new file mode 100644 index 0000000..52d9ed2 --- /dev/null +++ b/src/clients/simple-shm-shell.c @@ -0,0 +1,339 @@ +/* +Copyright (C) 2015 - 2016 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: + SooChan Lim + Changyeon Lee + JunKyeong Kim + Boram Park + +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 +#include +#include +#include +#include +#include + +#include + +#define BUF_WIDTH 1920 +#define BUF_HEIGHT 1080 + +#define RETURN_VAL_IF_FAIL(c,v) {\ + if(!((c))){\ + fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\ + return (v);\ + }\ +} + +#define GOTO_IF_FAIL(c,l) {\ + if(!(c)) {\ + fprintf(stderr, "[%s(%d)] '%s' failed.", __func__, __LINE__, #c);\ + goto l;\ + }\ +} + +#define EXIT_IF_FAIL(c) {\ + if(!(c)) {\ + fprintf (stderr, "[%s(%d)] '%s' failed.\n",__func__,__LINE__,#c);\ + exit(0);\ + }\ +} + +struct wl_test_info { + int width; + int height; + int stride; + int format; + int size; + + struct wl_display *display; + struct wl_registry *registry; + + /* global objects */ + struct wl_compositor *compositor; + struct wl_shm *shm; + struct wl_shell *shell; + struct wl_shm_pool *shm_pool; + + /* objects */ + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct wl_buffer *buffer; +}; + +static int +_create_anonymous_file (off_t size) +{ + static const char template[] = + "/shooter-XXXXXX"; + const char *path; + char *name = NULL; + int fd = -1; + int ret = -1; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + GOTO_IF_FAIL(name != NULL, fail); + + strcpy(name, path); + strcat(name, template); + + fd = mkstemp(name); + if (fd >= 0) + unlink(name); + + ret = ftruncate(fd, size); + GOTO_IF_FAIL(ret >= 0, fail); + + free(name); + + return fd; +fail: + if (fd >= 0) + close(fd); + + if (name) + free(name); + + return -1; +} + +static void +_destroy_anonymous_file(int fd) +{ + if (fd < 0) return; + + close(fd); +} + + +static struct wl_test_info * +_create_wl_test_info (void) +{ + struct wl_test_info *test_info = NULL; + + test_info = calloc(1, sizeof(struct wl_test_info)); + RETURN_VAL_IF_FAIL(test_info != NULL, NULL); + + return test_info; +} + +static void +_destroy_wl_test_info (struct wl_test_info *test_info) +{ + if (!test_info) return; + + free(test_info); +} + +static struct wl_shm_pool * +_create_shm_pool(struct wl_shm *shm, int size) +{ + struct wl_shm_pool *shm_pool = NULL; + void *data = NULL; + int fd = -1; + + fd = _create_anonymous_file(size); + GOTO_IF_FAIL(fd >= 0, fail); + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + GOTO_IF_FAIL(data != NULL, fail); + + memset(data, 0xff, size); + munmap(data, size); + + shm_pool = wl_shm_create_pool(shm, fd, size); + GOTO_IF_FAIL(shm_pool != NULL, fail); + + _destroy_anonymous_file(fd); + + return shm_pool; + +fail: + if (fd > 0) + _destroy_anonymous_file(fd); + + return NULL; +} + +void +_destroy_shm_pool(struct wl_shm_pool *shm_pool) +{ + if (!shm_pool) return; + + wl_shm_pool_destroy(shm_pool); +} + +static void +handle_global(void *data, struct wl_registry *registry, uint32_t name, + const char *interface, uint32_t version) +{ + struct wl_test_info *ti = (struct wl_test_info *)data; + + if (strcmp(interface, "wl_compositor") == 0) { + ti->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 3); + if (!ti->compositor) + printf("%s(%d): Error. fail to bind %s.\n", + __func__, __LINE__, interface); + else + printf("%s(%d): bind %s.\n", __func__, __LINE__, interface); + } else if (strcmp(interface, "wl_shm") == 0) { + ti->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); + if (!ti->shm) + printf("%s(%d): Error. fail to bind %s.\n", + __func__, __LINE__, interface); + else + printf("%s(%d): bind %s.\n", __func__, __LINE__, interface); + + ti->shm_pool = _create_shm_pool(ti->shm, ti->size); + if (!ti->shm_pool) + printf("%s(%d): Error. fail to create wl_shm_pool.\n", + __func__, __LINE__); + else + printf("%s(%d): success to create wl_shm_pool.\n", + __func__, __LINE__); + + } else if (strcmp(interface, "wl_shell") == 0) { + ti->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1); + if (!ti->shell) + printf("%s(%d): Error. fail to bind %s.\n", + __func__, __LINE__, interface); + else + printf("%s(%d): bind %s.\n", __func__, __LINE__, interface); + } else { + printf("%s(%d): Not bind %s.\n", __func__, __LINE__, interface); + } +} + +static void +handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + +} + +static const struct wl_registry_listener registry_listener = { + handle_global, + handle_global_remove +}; + +int main (void) +{ + struct wl_test_info *ti = NULL; + int ret = 0; + + /* create test info */ + ti = _create_wl_test_info (); + GOTO_IF_FAIL(ti != NULL, fail); + + /* init */ + ti->width = BUF_WIDTH; + ti->height = BUF_HEIGHT; + ti->stride = ti->width * 4; + ti->format = WL_SHM_FORMAT_XRGB8888; + ti->size = ti->stride * ti->height; + + /* connect display */ + ti->display = wl_display_connect(NULL); + GOTO_IF_FAIL(ti->display != NULL, fail); + + /* get the registry */ + ti->registry = wl_display_get_registry(ti->display); + GOTO_IF_FAIL(ti->registry != NULL, fail); + + /* get the global objects */ + wl_registry_add_listener(ti->registry, ®istry_listener, ti); + wl_display_dispatch(ti->display); + wl_display_roundtrip(ti->display); + + /* check the global objects */ + GOTO_IF_FAIL(ti->compositor != NULL, fail); + GOTO_IF_FAIL(ti->shm != NULL, fail); + GOTO_IF_FAIL(ti->shell != NULL, fail); + GOTO_IF_FAIL(ti->shm_pool != NULL, fail); + + /* create objects */ + ti->surface = wl_compositor_create_surface(ti->compositor); + GOTO_IF_FAIL(ti->surface != NULL, fail); + + ti->shell_surface = wl_shell_get_shell_surface(ti->shell, ti->surface); + GOTO_IF_FAIL(ti->shell_surface != NULL, fail); + + wl_shell_surface_set_toplevel(ti->shell_surface); + + ti->buffer = wl_shm_pool_create_buffer(ti->shm_pool, 0, + ti->width, ti->height, ti->stride, ti->format); + GOTO_IF_FAIL(ti->buffer != NULL, fail); + + wl_surface_attach(ti->surface, ti->buffer, 0, 0); + wl_surface_damage(ti->surface, 0, 0, ti->width, ti->height); + wl_surface_commit(ti->surface); + + wl_display_roundtrip(ti->display); + + /* main loop */ + printf("%s(%d): loop start.\n", __func__, __LINE__); + while (ret >= 0) { + ret = wl_display_dispatch(ti->display); + printf("%s(%d): loop running(ret=%d).\n", __func__, __LINE__, ret); + } + printf("%s(%d): loop end.\n", __func__, __LINE__); + +fail: + /* destory objects */ + if (ti->shell_surface) + wl_shell_surface_destroy(ti->shell_surface); + if (ti->surface) + wl_surface_destroy(ti->surface); + if (ti->buffer) + wl_buffer_destroy(ti->buffer); + + /* destroy global objects */ + if (ti->shell) + wl_shell_destroy(ti->shell); + if (ti->shm_pool) + _destroy_shm_pool(ti->shm_pool); + if (ti->shm) + wl_shm_destroy(ti->shm); + if (ti->compositor) + wl_compositor_destroy(ti->compositor); + + /* destory registry and display */ + if (ti->registry) + wl_registry_destroy(ti->registry); + if (ti->display) + wl_display_disconnect(ti->display); + + /* destroy test_info */ + if (ti) + _destroy_wl_test_info(ti); + + return 0; +} -- 2.7.4 From 57b204030d832866d60c8c10613ebafe2d494796 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 27 May 2022 11:39:45 +0900 Subject: [PATCH 09/16] add review-bot as a reviewer Change-Id: Id353d4198b4dfd5a06daf33b2580110161aa405a --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index d52bfc2..06c492b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,5 +5,5 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @sc1-lim @shiin-lee @joonbum-ko @cyeon-lee @doyoun-kang @gl77-lee @duna-oh @jinbong-lee @jk0430-kim @juns-kim @TizenWS/ws_members +* @sc1-lim @shiin-lee @joonbum-ko @cyeon-lee @doyoun-kang @gl77-lee @duna-oh @jinbong-lee @jk0430-kim @juns-kim @TizenWS/ws_members @review-bot -- 2.7.4 From 73292cd943a431496e4b05f618d7e8529c089ae5 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 2 Jun 2022 13:14:29 +0900 Subject: [PATCH 10/16] security: Remove meaningless double check In the function tizen_security_check_privilege(), it double-checks a g_cynara to see if it exists and then return different value if it doesn't exist which is contradictory. Let's just return false if initializing the cynara has been failed or not been initialized. Change-Id: I24755e5b86c5e1f4bf5cf6333a4d4686a880e942 --- src/libds-tizen/util/security.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/libds-tizen/util/security.c b/src/libds-tizen/util/security.c index ad19027..8544951 100644 --- a/src/libds-tizen/util/security.c +++ b/src/libds-tizen/util/security.c @@ -55,11 +55,6 @@ tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) int len = -1; int ret = -1; - /* If cynara_initialize() has been (retried) and failed, we suppose that cynara is not available. */ - /* Then we return true as if there is no security check available. */ - if (!g_cynara) - return true; - if (!g_cynara) { ds_err("security has not been initialized.\n"); return false; -- 2.7.4 From 7dcf6a1c868fd2c893401c745c461e0e551221d3 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 2 Jun 2022 13:50:54 +0900 Subject: [PATCH 11/16] security: Refactor implementation for cynara No functional changes Change-Id: If95362c31dae167d7d11eef1b1b2847747e0636a --- src/libds-tizen/util.h | 2 +- src/libds-tizen/util/security.c | 180 +++++++++++++++++++++++----------------- 2 files changed, 104 insertions(+), 78 deletions(-) diff --git a/src/libds-tizen/util.h b/src/libds-tizen/util.h index 18ad811..82e178b 100644 --- a/src/libds-tizen/util.h +++ b/src/libds-tizen/util.h @@ -5,7 +5,7 @@ #define MIN(a,b) ((a)<(b)?(a):(b)) -int +bool tizen_security_init(void); void diff --git a/src/libds-tizen/util/security.c b/src/libds-tizen/util/security.c index 8544951..9983e24 100644 --- a/src/libds-tizen/util/security.c +++ b/src/libds-tizen/util/security.c @@ -1,4 +1,3 @@ - #include #include #include @@ -8,20 +7,61 @@ #include "util.h" #ifdef HAVE_CYNARA +#include +#include + #include #include #include #include -#include -#include #define CYNARA_BUFSIZE 128 -static cynara *g_cynara = NULL; -static int g_cynara_refcount = 0; +struct ds_cynara +{ + cynara *handle; + int references; +}; + +static struct ds_cynara ds_cynara; + +static bool ds_cynara_init(void); +static void ds_cynara_finish(void); +static bool ds_cynara_check_privilege(pid_t pid, uid_t uid, + const char *privilege); +#endif + +bool +tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) +{ +#ifdef HAVE_CYNARA + return ds_cynara_check_privilege(pid, uid, privilege); +#else + return true; +#endif +} + +bool +tizen_security_init(void) +{ +#ifdef HAVE_CYNARA + return ds_cynara_init(); +#else + return true; +#endif +} + +void +tizen_security_finish(void) +{ +#ifdef HAVE_CYNARA + ds_cynara_finish(); +#endif +} +#ifdef HAVE_CYNARA static void -__security_log_print(int err, const char *fmt, ...) +print_cynara_error(int err, const char *fmt, ...) { int ret; va_list args; @@ -42,12 +82,56 @@ __security_log_print(int err, const char *fmt, ...) ds_err("%s is failed. (%s)\n", tmp, buf); } -#endif -bool -tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) +static bool +ds_cynara_init(void) +{ + int ret = CYNARA_API_SUCCESS; + int retry_cnt = 0; + + if (++ds_cynara.references != 1) + return true; + + for (retry_cnt = 0; retry_cnt < 5; retry_cnt++) { + ds_dbg("Retry cynara initialize: %d\n", retry_cnt + 1); + + ret = cynara_initialize(&ds_cynara.handle, NULL); + + if (CYNARA_API_SUCCESS == ret) { + ds_dbg("Succeed to initialize cynara !\n"); + return true; + } + + print_cynara_error(ret, "cynara_initialize"); + } + + ds_err("Failed to initialize cynara! (error:%d, retry_cnt=%d)\n", + ret, retry_cnt); + + --ds_cynara.references; + + return false; + +} + +static void +ds_cynara_finish(void) +{ + if (ds_cynara.references < 1) { + ds_err("%s called without ds_cynara_init\n", __FUNCTION__); + return; + } + + if (--ds_cynara.references != 0) + return; + + cynara_finish(ds_cynara.handle); + ds_cynara.handle = NULL; +} + +static bool +ds_cynara_check_privilege(pid_t pid, uid_t uid, const char *privilege) { -#ifdef HAVE_CYNARA bool res = false; char *client_smack = NULL; char *client_session = NULL; @@ -55,8 +139,8 @@ tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) int len = -1; int ret = -1; - if (!g_cynara) { - ds_err("security has not been initialized.\n"); + if (!ds_cynara.handle) { + ds_err("ds_cynara has not been initialized.\n"); return false; } @@ -70,86 +154,28 @@ tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) if (!client_session) goto finish; - ret = cynara_check(g_cynara, client_smack, client_session, - uid_str, privilege); + ret = cynara_check(ds_cynara.handle, client_smack, client_session, + uid_str, privilege); if (ret == CYNARA_API_ACCESS_ALLOWED) res = true; else - __security_log_print(ret, "privilege: %s, client_smack: %s, pid: %d", privilege, client_smack, pid); + print_cynara_error(ret, "privilege: %s, client_smack: %s, pid: %d", + privilege, client_smack, pid); finish: - ds_dbg("Privilege Check For '%s' %s pid:%u uid:%u client_smack:%s(len:%d) client_session:%s ret:%d", + ds_dbg("Privilege Check For '%s' %s pid:%u uid:%u client_smack:%s(len:%d) " + "client_session:%s ret:%d", privilege, res ? "SUCCESS" : "FAIL", pid, uid, client_smack ? client_smack : "N/A", len, client_session ? client_session: "N/A", ret); if (client_session) free(client_session); + if (client_smack) free(client_smack); return res; -#else - return true; -#endif } - -int -tizen_security_init(void) -{ -#ifdef HAVE_CYNARA - int ret = CYNARA_API_SUCCESS; - int retry_cnt = 0; - static bool retried = false; - - if (++g_cynara_refcount != 1) - return g_cynara_refcount; - - if (!g_cynara && false == retried) { - retried = true; - - for (retry_cnt = 0; retry_cnt < 5; retry_cnt++) { - ds_dbg("Retry cynara initialize: %d\n", retry_cnt + 1); - - ret = cynara_initialize(&g_cynara, NULL); - - if (CYNARA_API_SUCCESS == ret) { - ds_dbg("Succeed to initialize cynara !\n"); - return 1; - } - - __security_log_print(ret, "cynara_initialize"); - g_cynara = NULL; - } - } - - ds_err("Failed to initialize _security ! (error:%d, retry_cnt=%d)\n", - ret, retry_cnt); - --g_cynara_refcount; - - return 0; -#else - return 1; #endif -} - -void -tizen_security_finish(void) -{ -#ifdef HAVE_CYNARA - if (g_cynara_refcount < 1) { - ds_err("%s called without tizen_security_init\n", __FUNCTION__); - return; - } - - if (--g_cynara_refcount != 0) - return; - - if (g_cynara) { - cynara_finish(g_cynara); - g_cynara = NULL; - } -#endif -} - -- 2.7.4 From 538346c41a6940903e46c97d822e9f5276b9a896 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 2 Jun 2022 13:53:14 +0900 Subject: [PATCH 12/16] tizen-util: Include an appropriate header Change-Id: I7794e38a4ad2b02116a5a7fe3b02bcf339bbd3a9 --- src/libds-tizen/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libds-tizen/util.h b/src/libds-tizen/util.h index 82e178b..126467c 100644 --- a/src/libds-tizen/util.h +++ b/src/libds-tizen/util.h @@ -1,7 +1,7 @@ #ifndef DS_UTIL_H #define DS_UTIL_H -#include +#include #define MIN(a,b) ((a)<(b)?(a):(b)) -- 2.7.4 From 99694de50a487cdf41eef2c4544719b5b3f74d68 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 2 Jun 2022 14:22:55 +0900 Subject: [PATCH 13/16] security: Enable cynara to be built This patch also removes conditional compilation for cynara. This should be considered again if it gets needed. Change-Id: I7f7447a0f9a0c51b39bd454180b543f9d2b420e2 --- packaging/libds.spec | 3 +++ src/libds-tizen/util/meson.build | 5 +++++ src/libds-tizen/util/security.c | 26 +++++--------------------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/packaging/libds.spec b/packaging/libds.spec index 5258295..ed21c53 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -23,6 +23,9 @@ BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(wayland-tbm-server) BuildRequires: pkgconfig(wayland-tbm-client) BuildRequires: pkgconfig(tizen-dpms-server) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) +BuildRequires: pkgconfig(libsmack) %description Wayland Compositor Library diff --git a/src/libds-tizen/util/meson.build b/src/libds-tizen/util/meson.build index 3d34ab8..0ec6a9d 100644 --- a/src/libds-tizen/util/meson.build +++ b/src/libds-tizen/util/meson.build @@ -1 +1,6 @@ libds_tizen_files += files('security.c') +libds_tizen_deps += [ + dependency('cynara-client', required: true), + dependency('cynara-session', required: true), + dependency('libsmack', required: true) +] diff --git a/src/libds-tizen/util/security.c b/src/libds-tizen/util/security.c index 9983e24..b592577 100644 --- a/src/libds-tizen/util/security.c +++ b/src/libds-tizen/util/security.c @@ -1,20 +1,17 @@ +#include +#include #include #include #include -#include "libds/log.h" - -#include "util.h" - -#ifdef HAVE_CYNARA -#include -#include - #include #include #include #include +#include "libds/log.h" +#include "util.h" + #define CYNARA_BUFSIZE 128 struct ds_cynara @@ -29,37 +26,25 @@ static bool ds_cynara_init(void); static void ds_cynara_finish(void); static bool ds_cynara_check_privilege(pid_t pid, uid_t uid, const char *privilege); -#endif bool tizen_security_check_privilege(pid_t pid, uid_t uid, const char *privilege) { -#ifdef HAVE_CYNARA return ds_cynara_check_privilege(pid, uid, privilege); -#else - return true; -#endif } bool tizen_security_init(void) { -#ifdef HAVE_CYNARA return ds_cynara_init(); -#else - return true; -#endif } void tizen_security_finish(void) { -#ifdef HAVE_CYNARA ds_cynara_finish(); -#endif } -#ifdef HAVE_CYNARA static void print_cynara_error(int err, const char *fmt, ...) { @@ -178,4 +163,3 @@ finish: return res; } -#endif -- 2.7.4 From f090d9ed2f37041cf3d7497a567d1ae7e509b611 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 3 Jun 2022 18:05:12 +0900 Subject: [PATCH 14/16] keyrouter: Fix wrong return value According to implementation of pepper keyrouter which is a reference of libds keyrouter, keyrouter_grab_check_grabbed() is supposed to return true if a list of MODE_EXCLUSIVE is not empty. This error seems to have been introduced by mistake during the migration from pepper. Change-Id: Ibc0d35bb4b7ba2c6381c248ddc0c861c83f6c8c1 --- src/libds-tizen/keyrouter/keyrouter_grab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libds-tizen/keyrouter/keyrouter_grab.c b/src/libds-tizen/keyrouter/keyrouter_grab.c index f5467ae..053b3e8 100644 --- a/src/libds-tizen/keyrouter/keyrouter_grab.c +++ b/src/libds-tizen/keyrouter/keyrouter_grab.c @@ -79,9 +79,9 @@ keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab, switch(type) { case TIZEN_KEYROUTER_MODE_EXCLUSIVE: if (wl_list_empty(list) == false) - ret = false; - else ret = true; + else + ret = false; break; case TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: ret = keyrouter_grab_check_duplicated_data(list, data); -- 2.7.4 From 8a986fd3ccc17f3faaf11ae4ed87a30c0a56ce43 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 3 Jun 2022 18:12:29 +0900 Subject: [PATCH 15/16] keyrouter: Return an appropriate value The return value of keyrouter_grab_check_grabbed() is boolean. So let's make it right. Change-Id: Ic3c5b7fc16cb571633bd8a299cb12a2c3fee1797 --- src/libds-tizen/keyrouter/keyrouter_grab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libds-tizen/keyrouter/keyrouter_grab.c b/src/libds-tizen/keyrouter/keyrouter_grab.c index 053b3e8..a836292 100644 --- a/src/libds-tizen/keyrouter/keyrouter_grab.c +++ b/src/libds-tizen/keyrouter/keyrouter_grab.c @@ -93,7 +93,7 @@ keyrouter_grab_check_grabbed(struct ds_tizen_keyrouter_grab *keyrouter_grab, ret = keyrouter_grab_check_duplicated_data(list, data); break; default: - ret = TIZEN_KEYROUTER_ERROR_INVALID_MODE; + ret = true; break; } -- 2.7.4 From b890aa59286a411d11a1a0b012efbb5290d86844 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 7 Jun 2022 13:29:44 +0900 Subject: [PATCH 16/16] dpms: fix build error Change-Id: I1190b3d14494921bc657ba8d6dd37bc42fd215f9 Signed-off-by: Junkyeong Kim --- include/libds-tizen/dpms.h | 2 +- src/libds-tizen/dpms.c | 15 ++++++++------- src/libds-tizen/meson.build | 2 ++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/libds-tizen/dpms.h b/include/libds-tizen/dpms.h index 3293ae8..10df4c1 100644 --- a/include/libds-tizen/dpms.h +++ b/include/libds-tizen/dpms.h @@ -30,7 +30,7 @@ enum ds_tizen_dpms_error struct ds_tizen_dpms_event { //struct ds_output *output; - ds_tizen_dpms_mode mode; + enum ds_tizen_dpms_mode mode; }; struct ds_tizen_dpms * diff --git a/src/libds-tizen/dpms.c b/src/libds-tizen/dpms.c index c5bcabb..315d6c0 100644 --- a/src/libds-tizen/dpms.c +++ b/src/libds-tizen/dpms.c @@ -3,9 +3,10 @@ #include #include #include "libds/log.h" -#include "libds-tizen/dpms.h" #include "libds/output.h" +#include "libds-tizen/dpms.h" #include "tizen-dpms-server-protocol.h" +#include "util.h" struct ds_tizen_dpms { @@ -53,8 +54,8 @@ ds_tizen_dpms_create(struct wl_display *display) wl_signal_init(&dpms->events.set_dpms); wl_signal_init(&dpms->events.get_dpms); - dpms->display_destroy.notify = dpms_handle_display_destroy; - wl_display_add_destroy_listener(display, &dpms->display_destroy); + dpms->destroy.notify = dpms_handle_display_destroy; + wl_display_add_destroy_listener(display, &dpms->destroy); ds_inf("global create : tizen_dpms_manager(%p)", dpms); @@ -103,12 +104,12 @@ dpms_handle_display_destroy(struct wl_listener *listener, void *data) { struct ds_tizen_dpms *dpms; - dpms = wl_container_of(listener, dpms, display_destroy); + dpms = wl_container_of(listener, dpms, destroy); ds_inf("global destroy : tizen_dpms_manager(%p)", dpms); wl_signal_emit(&dpms->events.destroy, dpms); - wl_list_remove(&dpms->display_destroy.link); + wl_list_remove(&dpms->destroy.link); wl_resource_set_user_data(dpms->res, NULL); wl_global_destroy(dpms->global); free(dpms); @@ -132,8 +133,8 @@ _tizen_dpms_manager_handle_set_dpms(struct wl_client *client, if (mode > DS_TIZEN_DPMS_MODE_OFF) { ds_err("set dpms error : not supported mode(%d)", mode); - tizen_dpms_manager_send_set_state(resource, E_DPMS_MODE_OFF, - E_DPMS_MANAGER_ERROR_INVALID_PARAMETER); + tizen_dpms_manager_send_set_state(resource, DS_TIZEN_DPMS_MODE_OFF, + DS_TIZEN_DPMS_ERROR_INVALID_PARAMETER); return; } diff --git a/src/libds-tizen/meson.build b/src/libds-tizen/meson.build index 0d780a3..6779a72 100644 --- a/src/libds-tizen/meson.build +++ b/src/libds-tizen/meson.build @@ -1,6 +1,7 @@ libds_tizen_files = [ 'pixel_format.c', 'tbm_server.c', + 'dpms.c', ] libds_tizen_deps = [ @@ -8,6 +9,7 @@ libds_tizen_deps = [ dependency('libdrm', required: true), dependency('libtbm', required: true), dependency('wayland-tbm-server', required: true), + dependency('tizen-dpms-server', required: true), ] subdir('allocator') -- 2.7.4