From e38d54bf0825e4aa061e6d96ab925daec94b20e6 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Thu, 19 May 2022 10:03:25 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 09/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 10/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 11/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 12/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 13/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 From 94bded6e661616d177c7a6318a44ae044c3553a7 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 7 Jun 2022 13:31:32 +0900 Subject: [PATCH 14/16] example: add tinyds-tdm-dpms Change-Id: I6845876ee8240eba2d8569bdef5c799bd56ee0ce Signed-off-by: Junkyeong Kim --- packaging/libds.spec | 1 + src/examples/meson.build | 13 + src/examples/tinyds-tdm-dpms.c | 672 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 686 insertions(+) create mode 100644 src/examples/tinyds-tdm-dpms.c diff --git a/packaging/libds.spec b/packaging/libds.spec index ed21c53..aefff95 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -107,6 +107,7 @@ ninja -C builddir install %{_bindir}/ds-simple-tbm %{_bindir}/tinyds-tdm-libinput %{_bindir}/ds-simple-shm-shell +%{_bindir}/tinyds-tdm-dpms %files tizen-keyrouter %manifest %{name}.manifest diff --git a/src/examples/meson.build b/src/examples/meson.build index 5c5c437..aad893e 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -82,4 +82,17 @@ if get_option('tizen') install_dir: libds_bindir, install : true ) + executable('tinyds-tdm-dpms', + 'tinyds-tdm-dpms.c', + 'pixman-helper.c', + 'pixman-tbm-helper.c', + 'tinyds-tdm-renderer.c', + 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-dpms.c b/src/examples/tinyds-tdm-dpms.c new file mode 100644 index 0000000..dc32e8f --- /dev/null +++ b/src/examples/tinyds-tdm-dpms.c @@ -0,0 +1,672 @@ +#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_dpms +{ + struct ds_tizen_dpms *ds_dpms; + struct tinyds_server *server; + + struct wl_listener destroy; + struct wl_listener set_dpms; + struct wl_listener get_dpms; +}; + +struct tinyds_server +{ + struct ds_tbm_server *tbm_server; + + struct wl_display *display; + + struct ds_backend *backend; + struct ds_compositor *compositor; + struct ds_xdg_shell *xdg_shell; + + struct tinyds_output *output; + struct tinyds_dpms *dpms; + struct wl_event_source *stdin_source; + + struct wl_list views; + + struct wl_listener new_output; + 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_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 dpms_handle_destroy(struct wl_listener *listener, void *data); +static void dpms_handle_set_dpms(struct wl_listener *listener, void *data); +static void dpms_handle_get_dpms(struct wl_listener *listener, void *data); + + +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); + + 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 bool +add_new_dpms(struct tinyds_server *server) +{ + struct tinyds_dpms *dpms; + + dpms = calloc(1, sizeof *dpms); + if (!dpms) + return false; + + dpms->ds_dpms = ds_tizen_dpms_create(server->display); + if (!dpms->ds_dpms) + return false; + + dpms->destroy.notify = dpms_handle_destroy; + ds_tizen_dpms_add_destroy_listener(dpms->ds_dpms, &dpms->destroy); + + dpms->set_dpms.notify = dpms_handle_set_dpms; + ds_tizen_dpms_add_set_dpms_listener(dpms->ds_dpms, &dpms->set_dpms); + + dpms->get_dpms.notify = dpms_handle_get_dpms; + ds_tizen_dpms_add_get_dpms_listener(dpms->ds_dpms, &dpms->get_dpms); + + server->dpms = dpms; + + ds_inf("Dpms (%p) added", dpms); + + return true; +} + +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->new_output.notify = backend_handle_new_output; + ds_backend_add_new_output_listener(server->backend, + &server->new_output); + + server->compositor = ds_compositor_create(display); + if (!server->compositor) { + ds_backend_destroy(server->backend); + return false; + } + + server->tbm_server = ds_tbm_server_create(display); + if (!server->tbm_server) { + ds_backend_destroy(server->backend); + return false; + } + + server->xdg_shell = ds_xdg_shell_create(display); + if (!server->xdg_shell) { + ds_backend_destroy(server->backend); + return false; + } + + server->new_xdg_surface.notify = server_new_xdg_surface; + ds_xdg_shell_add_new_surface_listener(server->xdg_shell, + &server->new_xdg_surface); + + if (!add_new_dpms(server)) { + ds_backend_destroy(server->backend); + return false; + } + + return true; +} + +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 +dpms_handle_destroy(struct wl_listener *listener, void *data) +{ + struct tinyds_dpms *dpms; + + dpms = wl_container_of(listener, dpms, destroy); + + ds_inf("Dpms(%p) destroyed", dpms); + + wl_list_remove(&dpms->destroy.link); + wl_list_remove(&dpms->set_dpms.link); + wl_list_remove(&dpms->get_dpms.link); + + free(dpms); +} + +static void +dpms_handle_set_dpms(struct wl_listener *listener, void *data) +{ + struct tinyds_dpms *dpms; + struct ds_tizen_dpms_event *event = data; + + dpms = wl_container_of(listener, dpms, set_dpms); + + ds_inf("Dpms(%p) set dpms : %d", dpms, event->mode); + + //To do + //set dpms mode to output + ds_tizen_dpms_send_set_result(dpms->ds_dpms, event->mode, + DS_TIZEN_DPMS_ERROR_NONE); +} + +static void +dpms_handle_get_dpms(struct wl_listener *listener, void *data) +{ + struct tinyds_dpms *dpms; + + dpms = wl_container_of(listener, dpms, get_dpms); + + ds_inf("Dpms(%p) get dpms", dpms); + + //To do + //get dpms mode from output + ds_tizen_dpms_send_get_result(dpms->ds_dpms, DS_TIZEN_DPMS_MODE_ON, + DS_TIZEN_DPMS_ERROR_NONE); +} \ No newline at end of file -- 2.7.4 From 86d9c43ef128f42ed834dffc0373dd24ddf41884 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 7 Jun 2022 13:34:43 +0900 Subject: [PATCH 15/16] client: add simple-dpms Change-Id: Idf32c869b660f568ab6514d542396c40f32dc6c6 Signed-off-by: Junkyeong Kim --- packaging/libds.spec | 2 + src/clients/meson.build | 10 ++ src/clients/simple-dpms.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 src/clients/simple-dpms.c diff --git a/packaging/libds.spec b/packaging/libds.spec index aefff95..6260ed2 100644 --- a/packaging/libds.spec +++ b/packaging/libds.spec @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(wayland-tbm-server) BuildRequires: pkgconfig(wayland-tbm-client) BuildRequires: pkgconfig(tizen-dpms-server) +BuildRequires: pkgconfig(tizen-dpms-client) BuildRequires: pkgconfig(cynara-client) BuildRequires: pkgconfig(cynara-session) BuildRequires: pkgconfig(libsmack) @@ -108,6 +109,7 @@ ninja -C builddir install %{_bindir}/tinyds-tdm-libinput %{_bindir}/ds-simple-shm-shell %{_bindir}/tinyds-tdm-dpms +%{_bindir}/ds-simple-dpms %files tizen-keyrouter %manifest %{name}.manifest diff --git a/src/clients/meson.build b/src/clients/meson.build index 009016c..6fcd3f8 100644 --- a/src/clients/meson.build +++ b/src/clients/meson.build @@ -55,3 +55,13 @@ executable('ds-simple-tbm', install_dir: libds_bindir, install: true, ) + +executable('ds-simple-dpms', + 'simple-dpms.c', + dependencies: [ + dependency('wayland-client', required: true), + dependency('tizen-dpms-client', required: true), + ], + install_dir: libds_bindir, + install: true, +) diff --git a/src/clients/simple-dpms.c b/src/clients/simple-dpms.c new file mode 100644 index 0000000..9b4d22c --- /dev/null +++ b/src/clients/simple-dpms.c @@ -0,0 +1,239 @@ +/* +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 +#include +#include +#include +#include + +#include +#include +#include + + +struct wl_dpms_info { + char *app_name; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_output *output; + struct tizen_dpms_manager *tz_dpms_mng; + int got_dpms_state; +}; + +void +usage(const char *app_name) +{ + printf("usage: %s \n", app_name); + printf("%s output_num option(set1/get0) state\nex)\n", app_name); + printf("%s 1 0 => set dpms_on\n", app_name); + printf("%s 1 3 => set dpms_off\n", app_name); + printf("%s 0 0 => get state\n", app_name); +} + +static struct wl_dpms_info * +_create_wl_dpms_info (void) +{ + struct wl_dpms_info *test_info = NULL; + + test_info = calloc(1, sizeof(struct wl_dpms_info)); + if (test_info == NULL) { + printf("alloc fail"); + return NULL; + } + + return test_info; +} + +static void +_destroy_wl_dpms_info (struct wl_dpms_info *test_info) +{ + if (!test_info) return; + + if (test_info->app_name) + free(test_info->app_name); + if (test_info->tz_dpms_mng) + tizen_dpms_manager_destroy(test_info->tz_dpms_mng); + if (test_info->registry) + wl_registry_destroy(test_info->registry); + if (test_info->display) + wl_display_disconnect(test_info->display); + + free(test_info); +} + +static void +dpms_handle_set_state(void *data, struct tizen_dpms_manager *tz_dpms, uint32_t mode, uint32_t error) +{ + struct wl_dpms_info *test_info = (struct wl_dpms_info *)data; + printf("dpms_set_state_cb - mode:%d, error:%d\n", mode, error); + test_info->got_dpms_state = 1; +} + +static void +dpms_handle_get_state(void *data, struct tizen_dpms_manager *tz_dpms, uint32_t mode, uint32_t error) +{ + struct wl_dpms_info *test_info = (struct wl_dpms_info *)data; + printf("dpms_get_state_cb - mode:%d, error:%d\n", mode, error); + test_info->got_dpms_state = 1; +} + +static const struct tizen_dpms_manager_listener dpms_listener = { + dpms_handle_set_state, + dpms_handle_get_state +}; + +static void +handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + struct wl_dpms_info *test_info = (struct wl_dpms_info *)data; + + if (strcmp(interface, "wl_output") == 0) { + test_info->output = wl_registry_bind(registry, name, &wl_output_interface, 2); + if (!test_info->output) + printf("bind wl_output fail\n"); + else + printf("bind wl_output\n"); + } else if (strcmp(interface, "tizen_dpms_manager") == 0) { + test_info->tz_dpms_mng = wl_registry_bind(registry, name, &tizen_dpms_manager_interface, 1); + if (!test_info->tz_dpms_mng) + printf("bind tizen_dpms_manager fail\n"); + else { + tizen_dpms_manager_add_listener(test_info->tz_dpms_mng, &dpms_listener, test_info); + printf("bind tizen_dpms_manager\n"); + } + } +} + +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(int argc, char *argv[]) +{ + struct wl_dpms_info *test_info = NULL; + char *opt = NULL; + int option; + char *sta = NULL; + int state = 0; + + test_info = _create_wl_dpms_info(); + if (test_info == NULL) return 0; + + test_info->app_name = strdup(argv[0]); + if (test_info->app_name == NULL) { + printf("alloc fail"); + goto done; + } + if (argc != 3) { + usage(test_info->app_name); + goto done; + } + + opt = strdup(argv[1]); + if (opt == NULL) { + printf("alloc fail"); + goto done; + } + option = opt[0] - '0'; + free(opt); + if (!(option == 0 || option == 1)) { + usage(test_info->app_name); + goto done; + } + + if (option == 1) { + sta = strdup(argv[2]); + if (sta == NULL) { + printf("alloc fail"); + goto done; + } + state = sta [0] - '0'; + free(sta); + if (!(state == 0 || state == 1 || state == 2 || state == 3)) { + usage(test_info->app_name); + goto done; + } + } + + test_info->display = wl_display_connect(NULL); + if (test_info->display == NULL) { + printf("wl_display_connect fail"); + goto done; + } + + test_info->registry = wl_display_get_registry(test_info->display); + if (test_info->registry == NULL) { + printf("wl_display_get_registry fail"); + goto done; + } + + wl_registry_add_listener(test_info->registry, ®istry_listener, test_info); + wl_display_roundtrip(test_info->display); + + if (!test_info->output || !test_info->tz_dpms_mng) { + printf("bind fail\n"); + goto done; + } + + if (option == 1) { + tizen_dpms_manager_set_dpms(test_info->tz_dpms_mng, test_info->output, state); + printf("set dpms %d\n", state); + } else { + tizen_dpms_manager_get_dpms(test_info->tz_dpms_mng, test_info->output); + printf("get dpms\n"); + } + + test_info->got_dpms_state = 0; + while (!test_info->got_dpms_state) { + wl_display_roundtrip(test_info->display); + } + +done: + _destroy_wl_dpms_info(test_info); + + return 0; +} + -- 2.7.4 From dc8d92eacfadc35ebff24b2fc63fccb1b80aab4a Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 7 Jun 2022 13:35:51 +0900 Subject: [PATCH 16/16] dpms: set ds_tizen_dpms enum value by tizen dpms protocol enum value Change-Id: I1f02952b83bfcedfa60cfb045d710b0edb354492 Signed-off-by: Junkyeong Kim --- include/libds-tizen/dpms.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/include/libds-tizen/dpms.h b/include/libds-tizen/dpms.h index 10df4c1..c614e66 100644 --- a/include/libds-tizen/dpms.h +++ b/include/libds-tizen/dpms.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -12,19 +13,19 @@ struct ds_tizen_dpms; enum ds_tizen_dpms_mode { - DS_TIZEN_DPMS_MODE_ON = 0, - DS_TIZEN_DPMS_MODE_STANDBY = 1, - DS_TIZEN_DPMS_MODE_SUSPEND = 2, - DS_TIZEN_DPMS_MODE_OFF = 3, + DS_TIZEN_DPMS_MODE_ON = TIZEN_DPMS_MANAGER_MODE_ON, + DS_TIZEN_DPMS_MODE_STANDBY = TIZEN_DPMS_MANAGER_MODE_STANDBY, + DS_TIZEN_DPMS_MODE_SUSPEND = TIZEN_DPMS_MANAGER_MODE_SUSPEND, + DS_TIZEN_DPMS_MODE_OFF = TIZEN_DPMS_MANAGER_MODE_OFF, }; enum ds_tizen_dpms_error { - DS_TIZEN_DPMS_ERROR_NONE = 0, - DS_TIZEN_DPMS_ERROR_INVALID_PERMISSION = 1, - DS_TIZEN_DPMS_ERROR_INVALID_PARAMETER = 2, - DS_TIZEN_DPMS_ERROR_NOT_SUPPORTED = 3, - DS_TIZEN_DPMS_ERROR_ALREADY_DONE = 4, + DS_TIZEN_DPMS_ERROR_NONE = TIZEN_DPMS_MANAGER_ERROR_NONE, + DS_TIZEN_DPMS_ERROR_INVALID_PERMISSION = TIZEN_DPMS_MANAGER_ERROR_INVALID_PERMISSION, + DS_TIZEN_DPMS_ERROR_INVALID_PARAMETER = TIZEN_DPMS_MANAGER_ERROR_INVALID_PARAMETER, + DS_TIZEN_DPMS_ERROR_NOT_SUPPORTED = TIZEN_DPMS_MANAGER_ERROR_NOT_SUPPORTED, + DS_TIZEN_DPMS_ERROR_ALREADY_DONE = TIZEN_DPMS_MANAGER_ERROR_ALREADY_DONE, }; struct ds_tizen_dpms_event -- 2.7.4