implement the wtz_screen protocol 27/293227/2
authorSooChan Lim <sc1.lim@samsung.com>
Tue, 7 Mar 2023 11:56:50 +0000 (20:56 +0900)
committerJunseok Kim <juns.kim@samsung.com>
Tue, 23 May 2023 04:13:41 +0000 (13:13 +0900)
Change-Id: I258fe058b18b2889cc0dbadd862623425b8c05ba

configure.ac
packaging/enlightenment.spec
src/bin/e_comp_canvas.c
src/bin/e_desk.c
src/bin/e_desk.h
src/bin/e_zone.c
src/bin/e_zone.h

index 4066b4acfaea0544ef7031397f2c41febd7dc9b5..05eb211639ace0f0c24dd9f4ce1cc30f64c65552 100755 (executable)
@@ -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 relative-pointer-unstable-v1-server pointer-constraints-unstable-v1-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 relative-pointer-unstable-v1-server pointer-constraints-unstable-v1-server wtz-screen-server],
     [
       have_wayland=yes
       AC_DEFINE_UNQUOTED([HAVE_WAYLAND],[1],[enable wayland support])
index 89f0a238ffd03e904c857adddec4e0fc77a892c7..1a381bed0d12ce112ebb1a5b796ae3dafdfac0d6 100644 (file)
@@ -63,6 +63,7 @@ BuildRequires:  pkgconfig(tizen-hwc-server)
 BuildRequires:  pkgconfig(wtz-foreign-server)
 BuildRequires:  pkgconfig(pointer-constraints-unstable-v1-server)
 BuildRequires:  pkgconfig(relative-pointer-unstable-v1-server)
+BuildRequires:  pkgconfig(wtz-screen-server)
 Requires:       libwayland-extension-server
 
 # for gtest/gmock
index 76c43cefa2c47d89f33fe96225a76870e999fa00..83d3c5817f3627a6439899c6167da043d2754d36 100644 (file)
@@ -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);
index e9839bde9fa373e1e8e3b339e3de7b99a28efc32..65f863dca674a980bdf1e1659f7ca980123fd67d 100644 (file)
@@ -1,5 +1,6 @@
 #include "e.h"
 #include "e_policy_wl.h"
+#include <wtz-screen-server-protocol.h>
 
 /* 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
@@ -2267,3 +2268,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;
+}
index e751f335924f84e38c4ff5752d438748c48fad33..3bb62aa7f709a9a5374001657c35667cd7640373 100644 (file)
@@ -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;
index 2017dce0ceabe0e4656da00bb5a6874cbe2c0130..cd213a55cb11175694c7c028be1dd4eaa503d45f 100644 (file)
@@ -1,5 +1,8 @@
 #include "e.h"
 
+#include <wayland-server.h>
+#include <wtz-screen-server-protocol.h>
+
 /* 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.
  */
@@ -54,6 +57,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,
 };
 
 
@@ -1610,6 +1615,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
@@ -1740,3 +1748,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;
+}
index 50e56d24dfc84a09fb36c464b204fcf1a0e33087..3fe1a903bd75c6cc3ca7c9a17c23d103a0cfdabb 100644 (file)
@@ -55,6 +55,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;
 
@@ -154,6 +156,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
+
    Eina_List *obstacles;
 };
 
@@ -264,6 +271,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;