#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;
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
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)
{
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);
if (effect->eo == eo)
return effect;
e_view_destroy(effect);
- free(effect);
+ E_FREE(effect);
}
effect = E_NEW(E_View, 1);
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
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;
}
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;
}
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;
+}