From 454dd218d9bd2da0a7e8a74e4b785c794e68e541 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Tue, 7 Mar 2023 20:56:50 +0900 Subject: [PATCH] implement the wtz_screen protocol Change-Id: I258fe058b18b2889cc0dbadd862623425b8c05ba --- configure.ac | 2 +- packaging/enlightenment.spec | 1 + src/bin/e_comp_canvas.c | 8 +- src/bin/e_desk.c | 88 +++++++++++++++++ src/bin/e_desk.h | 2 + src/bin/e_zone.c | 231 +++++++++++++++++++++++++++++++++++++++++++ src/bin/e_zone.h | 11 +++ 7 files changed, 337 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index eeabf92..2f9c2c9 100755 --- a/configure.ac +++ b/configure.ac @@ -370,7 +370,7 @@ AC_MSG_RESULT([${have_shm_open}]) AC_SUBST(SHM_OPEN_LIBS) if test "x${e_cv_want_wayland_only}" != "xno" || test "x${e_cv_want_wayland_clients}" != "xno";then - PKG_CHECK_MODULES([WAYLAND], [wayland-server >= 1.8.0 xkbcommon uuid xdg-shell-unstable-v5-server xdg-shell-unstable-v6-server tizen-remote-surface-server scaler-server screenshooter-server tizen-extension-server tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server linux-explicit-synchronization-unstable-v1-server wtz-foreign-server], + PKG_CHECK_MODULES([WAYLAND], [wayland-server >= 1.8.0 xkbcommon uuid xdg-shell-unstable-v5-server xdg-shell-unstable-v6-server tizen-remote-surface-server scaler-server screenshooter-server tizen-extension-server tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server linux-explicit-synchronization-unstable-v1-server wtz-foreign-server wtz-screen-server], [ have_wayland=yes AC_DEFINE_UNQUOTED([HAVE_WAYLAND],[1],[enable wayland support]) diff --git a/packaging/enlightenment.spec b/packaging/enlightenment.spec index 302c74a..4d72d74 100644 --- a/packaging/enlightenment.spec +++ b/packaging/enlightenment.spec @@ -61,6 +61,7 @@ BuildRequires: pkgconfig(egl) BuildRequires: pkgconfig(linux-explicit-synchronization-unstable-v1-server) BuildRequires: pkgconfig(tizen-hwc-server) BuildRequires: pkgconfig(wtz-foreign-server) +BuildRequires: pkgconfig(wtz-screen-server) Requires: libwayland-extension-server # for gtest/gmock diff --git a/src/bin/e_comp_canvas.c b/src/bin/e_comp_canvas.c index 76c43ce..83d3c58 100644 --- a/src/bin/e_comp_canvas.c +++ b/src/bin/e_comp_canvas.c @@ -180,13 +180,12 @@ e_comp_canvas_init(int w, int h) EINA_LIST_FOREACH(screens, l, scr) { - E_Zone *zone = e_zone_new(scr->screen, scr->escreen, - scr->x, scr->y, scr->w, scr->h); + E_Zone *zone = e_zone_screen_new(scr->screen, scr->w, scr->h); if (scr->id) zone->output_id = strdup(scr->id); } } else - e_zone_new(0, 0, 0, 0, e_comp->w, e_comp->h); + e_zone_screen_new(0, e_comp->w, e_comp->h); E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_MOVE_RESIZE, _e_comp_cb_zone_change, NULL); E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD, _e_comp_cb_zone_change, NULL); @@ -392,8 +391,7 @@ e_comp_canvas_update(void) } else { - zone = e_zone_new(scr->screen, scr->escreen, - scr->x, scr->y, scr->w, scr->h); + zone = e_zone_screen_new(scr->screen, scr->w, scr->h); if (scr->id) zone->output_id = strdup(scr->id); printf("@@@ NEW ZONE = %p\n", zone); diff --git a/src/bin/e_desk.c b/src/bin/e_desk.c index 5545a7e..e677e38 100644 --- a/src/bin/e_desk.c +++ b/src/bin/e_desk.c @@ -1,5 +1,6 @@ #include "e.h" #include "e_policy_wl.h" +#include /* E_Desk is a child object of E_Zone. A desk is essentially a background * and an associated set of client windows. Each zone can have an arbitrary @@ -2244,3 +2245,90 @@ e_desk_desk_group_info_print(E_Desk *desk) } } } + +static void +_e_desk_splitscreen_region_cb_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +_e_desk_splitscreen_region_cb_assign_appid(struct wl_client *client, + struct wl_resource *resource, const char *appid) +{ + E_Desk_Group *edg; + + if (!(edg = wl_resource_get_user_data(resource))) return; + + // TODO: copy the appid string to the E_Desk_Group.... + // call the E_DESK_GROUP_HOOK_ASSIGN_APPID hook + if (!e_desk_group_hook_call(edg, E_DESK_GROUP_HOOK_SET_APPID)) + { + ERR("e_desk_zoom_set: fail get eout"); + return; + } +} + +static const struct wtz_splitscreen_region_interface + _e_desk_splitscreen_region_interface = +{ + _e_desk_splitscreen_region_cb_destroy, + _e_desk_splitscreen_region_cb_assign_appid, +}; + +static void +_e_desk_splitscreen_region_cb_resource_destroy(struct wl_resource *resource) +{ + E_Desk *desk; + E_Desk_Group *edg; + + if (!(edg = wl_resource_get_user_data(resource))) return; + if (!edg->desk) return; + + desk = edg->desk; + + desk->ss_region_resources = + eina_list_remove(desk->ss_region_resources, resource); +} + +EINTERN Eina_Bool +e_desk_splitscreen_regions_all_generate(E_Desk *desk, struct wl_client *client, + struct wl_resource *ss_res, uint32_t id) +{ + E_Desk_Group *edg; + struct wl_resource *ss_region_res; + Eina_List *l; + int i; + + E_OBJECT_CHECK_RETURN(desk, EINA_FALSE); + E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, EINA_FALSE); + + for (i = (E_DESK_GROUP_LAYER_COUNT - 1); i >= 0; i--) + { + EINA_LIST_FOREACH(desk->desk_group.list[i], l, edg) + { + ss_region_res = wl_resource_create(client, + &wtz_splitscreen_region_interface, 1, id); + if (!ss_region_res) + { + wl_resource_post_no_memory(ss_res); + return EINA_FALSE; + } + + wl_resource_set_implementation(ss_region_res, + &_e_desk_splitscreen_region_interface, edg, + _e_desk_splitscreen_region_cb_resource_destroy); + + desk->ss_region_resources = eina_list_append( + desk->ss_region_resources, ss_region_res); + + // send the splitscreen_region sresources + wtz_splitscreen_send_region(ss_res, + ss_region_res, edg->name, + edg->x, edg->y, edg->w, edg->h); + } + } + + return EINA_TRUE; +} diff --git a/src/bin/e_desk.h b/src/bin/e_desk.h index e751f33..3bb62aa 100644 --- a/src/bin/e_desk.h +++ b/src/bin/e_desk.h @@ -94,6 +94,7 @@ struct _E_Desk } desk_group; Eina_List *iconified_list; + Eina_List *ss_region_resources; // splitscreen_region resourses }; struct _E_Event_Desk @@ -179,6 +180,7 @@ E_API void e_desk_visible_client_iconified_list_remove(E_Desk *desk, E_Client *e E_API void e_desk_visible_client_iconified_list_remove_all(E_Desk *desk); E_API Eina_List * e_desk_visible_client_iconified_list_get(E_Desk *desk); +EINTERN Eina_Bool e_desk_splitscreen_regions_all_generate(E_Desk *desk, struct wl_client *client, struct wl_resource *ss_res, uint32_t id); extern E_API int E_EVENT_DESK_SHOW; extern E_API int E_EVENT_DESK_BEFORE_SHOW; diff --git a/src/bin/e_zone.c b/src/bin/e_zone.c index 4ca4828..67d5763 100644 --- a/src/bin/e_zone.c +++ b/src/bin/e_zone.c @@ -1,5 +1,8 @@ #include "e.h" +#include +#include + /* E_Zone is a child object of E_Comp. There is one zone per screen * in a xinerama setup. Each zone has one or more desktops. */ @@ -53,6 +56,8 @@ static int _e_zone_hooks_walking = 0; static Eina_Inlist *_e_zone_hooks[] = { [E_ZONE_HOOK_DISPLAY_STATE_CHANGE] = NULL, + [E_ZONE_HOOK_SPLISCREEN_ACTIVATE] = NULL, + [E_ZONE_HOOK_SPLISCREEN_DEACTIVATE] = NULL, }; @@ -1416,6 +1421,9 @@ _e_zone_object_del_attach(void *o) ev->zone = zone; e_object_ref(E_OBJECT(ev->zone)); ecore_event_add(E_EVENT_ZONE_DEL, ev, _e_zone_event_generic_free, NULL); + + if (zone->global) + wl_global_destroy(zone->global); } static E_Zone_Edge @@ -1546,3 +1554,226 @@ e_zone_hook_del(E_Zone_Hook *zh) else _e_zone_hooks_delete++; } + +static void +_e_zone_screen_capability_add(struct wl_resource *resource, + struct wl_array *capabilities, uint32_t cap) +{ + uint32_t *c; + + c = wl_array_add(capabilities, sizeof(*c)); + if (c) + *c = cap; + else + wl_resource_post_no_memory(resource); +} + +static void +_e_zone_splitscreen_cb_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +_e_zone_splitscreen_cb_activate(struct wl_client *client, + struct wl_resource *resource) +{ + E_Zone *zone; + + if (!(zone = wl_resource_get_user_data(resource))) return; + + // call the hook for activating the splitscreen in this zone + _e_zone_hook_call(E_ZONE_HOOK_SPLISCREEN_ACTIVATE, zone); +} + +static void +_e_zone_splitscreen_cb_deactivate(struct wl_client *client, + struct wl_resource *resource) +{ + E_Zone *zone; + + if (!(zone = wl_resource_get_user_data(resource))) return; + + // call the hook for deactivating the splitscreen in this zone + _e_zone_hook_call(E_ZONE_HOOK_SPLISCREEN_DEACTIVATE, zone); +} + +static const struct wtz_splitscreen_interface _e_zone_splitscreen_interface = +{ + _e_zone_splitscreen_cb_destroy, + _e_zone_splitscreen_cb_activate, + _e_zone_splitscreen_cb_deactivate, +}; + +static void +_e_zone_splitscreen_cb_resource_destroy(struct wl_resource *resource) +{ + // TODO: +} + +static void +_e_zone_screen_cb_destroy(struct wl_client *client EINA_UNUSED, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +_e_zone_screen_cb_get_splitscreen(struct wl_client *client, + struct wl_resource *resource, uint32_t id) +{ + E_Zone *zone; + E_Desk *desk; + struct wl_resource *ss_res; + + if (!(zone = wl_resource_get_user_data(resource))) return; + + if (!zone->splitscreen_enabled) + { + ELOGF("E_Zone", "Screen dose not support Splitscreen.", NULL); + wl_resource_post_error(resource, WTZ_SCREEN_ERROR_NOT_SUPPORTED, + "%d: wtz_screen@%d has no splitscreen capability", + id, wl_resource_get_id(resource)); + return; + } + + ss_res = wl_resource_create(client, + &wtz_splitscreen_interface, 1, id); + if (!ss_res) + { + wl_resource_post_no_memory(resource); + return; + } + + wl_resource_set_implementation(ss_res, + &_e_zone_splitscreen_interface, zone, + _e_zone_splitscreen_cb_resource_destroy); + + // The splitscreen_regions are the e_desk_groups associated with this + // E_Zone(E_Desk) and these are already created by the e20 module with the + // specifc policy. So e20 sends the splitscreen_regions associated with each + // e_desk_group. + desk = e_desk_current_get(zone); + if (e_desk_splitscreen_regions_all_generate(desk, client, ss_res, id)) + { + ELOGF("E_Zone", "e_desk_splitscreen_regions_all_generate() failed.", + NULL); + return; + + } + + ELOGF("E_Zone", "Create a splitscreen resource. zone_id:%d", NULL, zone->id); +} + +static void +_e_zone_screen_cb_set_client_side_decoration(struct wl_client *client, + struct wl_resource *resource, uint32_t enable) +{ + E_Zone *zone; + + if (!(zone = wl_resource_get_user_data(resource))) return; + + if (zone->csd_enabled != enable) zone->csd_enabled = enable; + + // TODO: The currunt ecs(wtz_surface) in this zone(wtz_screen) can support + // client-side decoration. Therefore, do something(?) for them to get + // the client-side decoration. - [soolim] + +} + +static const struct wtz_screen_interface _e_zone_screen_interface = +{ + _e_zone_screen_cb_destroy, + _e_zone_screen_cb_get_splitscreen, + _e_zone_screen_cb_set_client_side_decoration, +}; + +static void +_e_zone_screen_cb_unbind(struct wl_resource *resource) +{ + E_Zone *zone; + + if (!(zone = wl_resource_get_user_data(resource))) return; + + zone->resources = eina_list_remove(zone->resources, resource); +} + +static void +_e_zone_screen_cb_bind(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + E_Zone *zone; + struct wl_resource *resource; + struct wl_array capabilities; + + if (!(zone = data)) return; + + resource = + wl_resource_create(client, &wtz_screen_interface, version, id); + if (!resource) + { + wl_client_post_no_memory(client); + return; + } + + zone->resources = eina_list_append(zone->resources, resource); + + wl_resource_set_implementation(resource, &_e_zone_screen_interface, zone, + _e_zone_screen_cb_unbind); + wl_resource_set_user_data(resource, zone); + + // send the size of the screen + // [TODO] calculate the size with base output resolution. + wtz_screen_send_size(resource, zone->w, zone->h); + + // send the name of the screen + wtz_screen_send_name(resource, zone->name); + + // send the capabilities of the screen + wl_array_init(&capabilities); + if (zone->splitscreen_enabled) + _e_zone_screen_capability_add(resource, &capabilities, + WTZ_SCREEN_CAPABILITY_SPLITSCREEN); + if (zone->csd_enabled) + _e_zone_screen_capability_add(resource, &capabilities, + WTZ_SCREEN_CAPABILITY_CLIENT_SIDE_DECORATION); + wtz_screen_send_capabilities(resource, &capabilities); + + ELOGF("E_Zone", "Bound wtz_screen zone->id: %d Size: %dx%d", NULL, + zone->id, zone->w, zone->h); +} + +EINTERN E_Zone * +e_zone_screen_new(int num, int w, int h) +{ + E_Zone *zone; + + zone = e_zone_new(num, num, 0, 0, w, h); + EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL); + + zone->global = + wl_global_create(e_comp_wl->wl.disp, &wtz_screen_interface, + 1, zone, _e_zone_screen_cb_bind); + EINA_SAFETY_ON_NULL_RETURN_VAL(zone->global, NULL); + + return zone; +} + +E_API Eina_Bool +e_zone_screen_splitscreen_enable(E_Zone *zone) +{ + E_OBJECT_CHECK_RETURN(zone, EINA_FALSE); + E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE); + + if (zone->splitscreen_enabled) + { + ELOGF("E_Zone", "Splitscreen is already enabled. zone_id:%d", NULL, + zone->id); + return EINA_TRUE; + } + + zone->splitscreen_enabled = EINA_TRUE; + + return EINA_TRUE; +} diff --git a/src/bin/e_zone.h b/src/bin/e_zone.h index d6d7343..f956a24 100644 --- a/src/bin/e_zone.h +++ b/src/bin/e_zone.h @@ -53,6 +53,8 @@ typedef struct _E_Zone_Hook E_Zone_Hook; typedef enum _E_Zone_Hook_Point { E_ZONE_HOOK_DISPLAY_STATE_CHANGE, + E_ZONE_HOOK_SPLISCREEN_ACTIVATE, + E_ZONE_HOOK_SPLISCREEN_DEACTIVATE, E_ZONE_HOOK_LAST } E_Zone_Hook_Point; @@ -151,6 +153,11 @@ struct _E_Zone E_Zone_Display_State display_state; char *output_id; // same id we get from e_comp_screen so look it up there + + struct wl_global *global; // wtz_screen global resource + Eina_List *resources; // binding resources of wtz_screen global resource + Eina_Bool splitscreen_enabled; // splitscreen capability + Eina_Bool csd_enabled; // client side decoration capablitiy }; struct _E_Event_Zone_Generic @@ -247,6 +254,10 @@ E_API void e_zone_orientation_force_update_del(E_Zone *zone, E_Client *clie E_API E_Zone_Hook *e_zone_hook_add(E_Zone_Hook_Point hookpoint, E_Zone_Hook_Cb func, const void *data); E_API void e_zone_hook_del(E_Zone_Hook *zh); +// e_zone_screen api for supporting wtz_screen protocol +EINTERN E_Zone *e_zone_screen_new(int num, int w, int h); +E_API Eina_Bool e_zone_screen_splitscreen_enable(E_Zone *zone); + extern E_API int E_EVENT_ZONE_DESK_COUNT_SET; extern E_API int E_EVENT_ZONE_MOVE_RESIZE; extern E_API int E_EVENT_ZONE_ADD; -- 2.7.4