e_view_client: Add e_view_client_util_mirror_add function 75/318775/1
authorJunkyeong Kim <jk0430.kim@samsung.com>
Thu, 23 Jan 2025 09:20:56 +0000 (18:20 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 23 Jan 2025 11:21:07 +0000 (20:21 +0900)
This function replace e_comp_object_util_mirror_add function.

Change-Id: Ie3ff254accae2e231069b412cafb577a596a7200

src/bin/core/e_view_client.c
src/bin/core/e_view_intern.h
src/include/e_view_client.h

index 1a28ca4ee4ccc5466b55f2de3b598ca45cb906cc..cb6d21f31dace92edccfcd46ff90cc7d71245fbf 100644 (file)
@@ -2,9 +2,15 @@
 #include "e_canvas_intern.h"
 #include "e_view_client_intern.h"
 #include "e_view_intern.h"
+#include "e_view_rect.h"
+#include "e_view_image.h"
 #include "e_comp_object_intern.h"
 #include "e_map_intern.h"
 #include "e_client_intern.h"
+#include "e_comp_intern.h"
+#include "e_compositor_intern.h"
+#include "e_comp_wl_subsurface_intern.h"
+#include "e_utils.h"
 
 E_View_Tree_Impl view_client_tree_impl;
 
@@ -21,23 +27,113 @@ typedef struct _E_View_Client_Effect
    void *data;
 } E_View_Client_Effect;
 
+typedef struct _E_View_Client_Mirror
+{
+   E_View_Image *image;
+   E_View_Client *client;
+   struct wl_listener destroy;
+   struct wl_listener show;
+   struct wl_listener hide;
+   struct wl_list link;
+} E_View_Client_Mirror;
+
+/* convert from the surface coordinates to the buffer coordinates */
+static void
+_e_view_client_map_transform_pos(E_Client *ec, int sx, int sy, int *dx, int *dy)
+{
+   E_Surface *surface;
+   int transform;
+   int bw, bh, tx, ty;
+
+   if (!ec || e_object_is_del(E_OBJECT(ec)) || !(surface = e_surface_try_from_ec(ec)))
+     {
+        *dx = sx;
+        *dy = sy;
+        return;
+     }
+
+   transform = e_comp_wl_output_buffer_transform_get(ec);
+
+   e_pixmap_size_get(ec->pixmap, &bw, &bh);
+
+   /* for subsurface, it should be swap 90 and 270 */
+   if (e_comp_wl_subsurface_check(ec))
+     switch (transform)
+       {
+        case WL_OUTPUT_TRANSFORM_90:          transform = WL_OUTPUT_TRANSFORM_270;         break;
+        case WL_OUTPUT_TRANSFORM_270:         transform = WL_OUTPUT_TRANSFORM_90;          break;
+        case WL_OUTPUT_TRANSFORM_FLIPPED_90:  transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; break;
+        case WL_OUTPUT_TRANSFORM_FLIPPED_270: transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;  break;
+        default: break;
+       }
+
+   switch (transform)
+     {
+      case WL_OUTPUT_TRANSFORM_NORMAL:
+      default:                              tx = sx,      ty = sy;      break;
+      case WL_OUTPUT_TRANSFORM_90:          tx = sy,      ty = bw - sx; break;
+      case WL_OUTPUT_TRANSFORM_180:         tx = bw - sx, ty = bh - sy; break;
+      case WL_OUTPUT_TRANSFORM_270:         tx = bh - sy, ty = sx;      break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED:     tx = bw - sx, ty = sy;      break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:  tx = sy,      ty = sx;      break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_180: tx = sx,      ty = bh - sy; break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270: tx = bh - sy, ty = bw - sx; break;
+     }
+
+   tx *= e_surface_buffer_scale_get(surface);
+   ty *= e_surface_buffer_scale_get(surface);
+
+   *dx = tx;
+   *dy = ty;
+}
+
+static void
+_e_view_client_map_transform_rect(E_Client *ec, int sx, int sy, int sw, int sh, int *dx, int *dy, int *dw, int *dh)
+{
+   int x1 = sx;
+   int y1 = sy;
+   int x2 = sx + sw;
+   int y2 = sy + sh;
+   int mx, my;
+
+   _e_view_client_map_transform_pos(ec, x1, y1, &x1, &y1);
+   _e_view_client_map_transform_pos(ec, x2, y2, &x2, &y2);
+
+   mx = MIN(x1, x2);
+   my = MIN(y1, y2);
+
+   if (dx) *dx = mx;
+   if (dy) *dy = my;
+   if (dw) *dw = MAX(x1, x2) - mx;
+   if (dh) *dh = MAX(y1, y2) - my;
+}
+
 static void
 _view_client_handle_destroy(E_View *view)
 {
    E_View_Client *client = e_view_client_from_view(view);
+   E_View_Client_Mirror *mirror, *mirror_tmp;
 
    e_view_data_del(&client->view, "E_Client");
 
+   if (!wl_list_empty(&client->mirror))
+     {
+        wl_list_for_each_safe(mirror, mirror_tmp, &client->mirror, link)
+          {
+             e_view_destroy(e_view_image_view_get(mirror->image));
+          }
+     }
+
    if (client->effect)
      {
         wl_list_remove(&client->effect_destroy.link);
         client->effect_destroy.notify = NULL;
         e_view_destroy(client->effect);
-        free(client->effect);
+        E_FREE(client->effect);
         client->effect = NULL;
      }
 
-   free(client);
+   E_FREE(client);
 }
 
 static void
@@ -47,10 +143,57 @@ _view_client_effect_destroy(struct wl_listener *listener, void *data)
 
    wl_list_remove(&client->effect_destroy.link);
    client->effect_destroy.notify = NULL;
-   free(client->effect);
+   E_FREE(client->effect);
    client->effect = NULL;
 }
 
+static void
+_view_client_mirror_destroy(struct wl_listener *listener, void *data)
+{
+   E_View_Client_Mirror *mirror = wl_container_of(listener, mirror, destroy);
+   E_Comp_Object *cw;
+   E_View *view;
+
+   wl_list_remove(&mirror->link);
+   wl_list_remove(&mirror->destroy.link);
+   wl_list_remove(&mirror->show.link);
+   wl_list_remove(&mirror->hide.link);
+
+   cw = evas_object_smart_data_get(mirror->client->view.eo);
+   view = e_view_image_view_get(mirror->image);
+
+   if (cw)
+     cw->obj_mirror = eina_list_remove(cw->obj_mirror, view->eo);
+
+   E_FREE(mirror);
+}
+
+static void
+_view_client_mirror_show(struct wl_listener *listener, void *data)
+{
+   E_View_Client_Mirror *mirror = wl_container_of(listener, mirror, show);
+   E_Comp_Object *cw;
+
+   cw = evas_object_smart_data_get(mirror->client->view.eo);
+   if (!cw) return;
+
+   cw->force_visible++;
+   if (e_comp_hwc_is_configured() && !e_comp_is_on_overlay(cw->ec))
+     e_comp_hwc_client_end(cw->ec, __FUNCTION__);
+}
+
+static void
+_view_client_mirror_hide(struct wl_listener *listener, void *data)
+{
+   E_View_Client_Mirror *mirror = wl_container_of(listener, mirror, hide);
+   E_Comp_Object *cw;
+
+   cw = evas_object_smart_data_get(mirror->client->view.eo);
+   if (!cw) return;
+
+   cw->force_visible--;
+}
+
 static E_View_Client *
 _view_client_from_tree(E_View_Tree *tree)
 {
@@ -103,6 +246,7 @@ e_view_client_create(E_Client *ec, E_View_Tree *parent)
    client->height = 1;
 
    wl_signal_init(&client->events.resize);
+   wl_list_init(&client->mirror);
 
    e_view_init(&client->view, E_VIEW_TYPE_CLIENT, (E_View_Impl*)&view_client_impl, ec->frame, parent);
 
@@ -270,7 +414,7 @@ e_view_client_effect_object_get(E_View_Client *client)
         if (effect->eo == eo)
           return effect;
         e_view_destroy(effect);
-        free(effect);
+        E_FREE(effect);
      }
 
    effect = E_NEW(E_View, 1);
@@ -300,7 +444,7 @@ _view_client_effect_end(void *data, Evas_Object *obj EINA_UNUSED, const char *em
    E_View_Client *client = effect_data->client;
 
    effect_data->cb(effect_data->data, client, emission, source);
-   free(effect_data);
+   E_FREE(effect_data);
 }
 
 E_API bool
@@ -321,7 +465,7 @@ e_view_client_effect_start(E_View_Client *client, E_View_Client_Signal_Cb end_cb
    ret = e_comp_object_effect_start(client->view.eo, _view_client_effect_end, effect_data);
    if (ret == false)
      {
-        free(effect_data);
+        E_FREE(effect_data);
         return ret;
      }
 
@@ -344,7 +488,7 @@ e_view_client_effect_stop(E_View_Client *client,E_View_Client_Signal_Cb end_cb)
    ret = e_comp_object_effect_stop(client->view.eo, _view_client_effect_end);
    if (ret == true)
      {
-        free(effect_data);
+        E_FREE(effect_data);
         client->effect_data = NULL;
      }
 
@@ -1023,3 +1167,120 @@ e_view_client_native_usable_get(E_View_Client *client)
 
    return e_comp_object_native_usable_get(client->view.eo);
 }
+
+E_API E_View *
+e_view_client_util_mirror_add(E_View_Client *client)
+{
+   E_View_Client_Mirror *mirror = NULL;
+   E_View_Image *image = NULL;
+   E_View *view = NULL;
+   int w, h, tw, th;
+   unsigned int *pix = NULL;
+   bool argb = false;
+   E_Comp_Object *cw;
+
+   if (client == NULL) return NULL;
+
+   mirror = E_NEW(E_View_Client_Mirror, 1);
+   if (!mirror) return NULL;
+
+   cw = evas_object_smart_data_get(client->view.eo);
+   if ((!cw) || (e_util_strcmp(evas_object_type_get(client->view.eo), "e_comp_object")))
+     cw = NULL;
+
+   if (!cw)
+     cw = e_view_data_get(e_view_client_view_get(client), "comp_mirror");
+   if (!cw)
+     {
+        image = e_view_image_filled_create(client->view.parent);
+        e_view_image_colorspace_set(image, E_VIEW_COLORSPACE_ARGB8888);
+        e_view_image_smooth_scale_set(image, e_comp_config_get()->smooth_windows);
+        e_view_image_alpha_set(image, true);
+        e_view_image_source_set(image, e_view_client_view_get(client));
+
+        mirror->image = image;
+        wl_list_insert(client->mirror.prev, &mirror->link);
+
+        return e_view_image_view_get(image);
+     }
+
+   if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h)))
+     {
+        E_FREE(mirror);
+        return NULL;
+     }
+
+   if (cw->external_content)
+     {
+        ERR("%p of client %p is external content.", client->view.eo, cw->ec);
+        E_FREE(mirror);
+        return NULL;
+     }
+
+   image = e_view_image_filled_create(client->view.parent);
+   e_view_image_colorspace_set(image, E_VIEW_COLORSPACE_ARGB8888);
+   e_view_image_smooth_scale_set(image, e_comp_config_get()->smooth_windows);
+   view = e_view_image_view_get(image);
+   cw->obj_mirror = eina_list_append(cw->obj_mirror, view->eo);
+
+   mirror->image = image;
+   mirror->client = client;
+   wl_list_insert(client->mirror.prev, &mirror->link);
+
+   mirror->destroy.notify = _view_client_mirror_destroy;
+   e_view_event_listener_add(view, E_VIEW_DESTROY, &mirror->destroy);
+   mirror->show.notify = _view_client_mirror_show;
+   e_view_event_listener_add(view, E_VIEW_DESTROY, &mirror->show);
+   mirror->hide.notify = _view_client_mirror_hide;
+   e_view_event_listener_add(view, E_VIEW_DESTROY, &mirror->hide);
+
+   e_view_data_set(view, "E_Client_Mirror", cw->ec);
+   e_view_data_set(view, "comp_mirror", cw->ec);
+
+   e_view_image_alpha_set(image, evas_object_image_alpha_get(cw->obj));
+   _e_view_client_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
+
+   e_view_image_size_set(image, tw, th);
+
+   if (cw->ec->shaped)
+     pix = evas_object_image_data_get(cw->obj, 0);
+   else
+     {
+        if (cw->native)
+          {
+             if (cw->ns)
+               evas_object_image_native_surface_set(view->eo, cw->ns);
+             else
+               {
+                  Evas_Native_Surface ns;
+                  memset(&ns, 0, sizeof(Evas_Native_Surface));
+                  if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
+                    evas_object_image_native_surface_set(view->eo, &ns);
+               }
+          }
+        else
+          {
+             /* FIXME: legacy code, please refer to commit 5e6831187a1 */
+             argb = e_pixmap_image_is_argb(cw->ec->pixmap);
+             if ((argb) &&
+                 (e_pixmap_image_exists(cw->ec->pixmap)))
+               pix = e_pixmap_image_data_get(cw->ec->pixmap);
+             else
+               pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
+          }
+     }
+
+   if (pix)
+     {
+        Eina_Bool dirty;
+
+        dirty = evas_object_image_pixels_dirty_get(cw->obj);
+        e_view_image_pixels_dirty_set(image, dirty);
+        e_view_image_data_set(image, pix);
+        evas_object_image_data_set(cw->obj, pix);
+        if (dirty)
+          e_view_image_data_update_add(image, 0, 0, tw, th);
+     }
+
+   return view;
+}
index abe4d8e3072160c586756ccbbe7516fda6e19e86..00944a9ec0d8e1967706f5862ebd6086eb818881 100644 (file)
@@ -82,6 +82,7 @@ struct _E_View_Client
    E_View *content;
    E_View *effect;
    struct wl_listener effect_destroy;
+   struct wl_list mirror;
    E_View_Tree tree;
    void *effect_data;
 
index 737549ab4c763b860fb99d37826fea366b98cdda..c4458516d372bbba5e1cd7195509786bdb361d96 100644 (file)
@@ -62,6 +62,8 @@ void e_view_client_hide(E_View_Client *client);
 void e_view_client_effect_params_set(E_View_Client *client, int id, int *params, unsigned int count);
 bool e_view_client_effect_hiding_set(E_View_Client *client, bool hiding);
 bool e_view_client_native_usable_get(E_View_Client *client);
+
+E_View *e_view_client_util_mirror_add(E_View_Client *client);
 #ifdef  __cplusplus
 }
 #endif