e_comp_object: add e_comp_object_content_type_set_listener_add
[platform/upstream/enlightenment.git] / src / bin / e_comp_object.c
1 #include "e_comp_object_intern.h"
2 #include "e_bindings_intern.h"
3 #include "e_utils_intern.h"
4 #ifdef REFACTOR_DESK_AREA
5 #else
6 #include "e_comp_canvas_intern.h"
7 #endif
8 #include "e_comp_cfdata_intern.h"
9 #include "e_comp_wl_subsurface_intern.h"
10 #include "e_comp_wl_tbm_intern.h"
11 #include "e_comp_intern.h"
12 #include "e_pixmap_intern.h"
13 #include "e_map_intern.h"
14 #include "e_hwc_window_intern.h"
15 #include "e_hwc_windows_intern.h"
16 #include "e_policy_visibility_intern.h"
17 #include "e_client_video_intern.h"
18 #include "e_client_intern.h"
19 #include "e_zone_intern.h"
20 #include "e_theme_intern.h"
21 #include "e_config_intern.h"
22
23 /* data keys:
24
25    = keys that return objects =
26    - E_Client: the client associated with the object (E_Client*)
27    - comp_smart_obj: cw->smart_obj (Evas_Object*)
28    - comp_obj: cw (E_Comp_Object*)
29
30    = keys that are bool flags =
31    - client_restack: client needs a protocol-level restack
32    - comp_override: object is triggering a nocomp override to force compositing
33    - comp_ref: object has a ref from visibility animations
34    - comp_showing: object is currently running its show animation
35    - comp_hiding: object is currently running its hiding animation
36    - comp_object: object is a compositor-created object
37    - comp_object_skip: object has a name which prohibits theme shadows
38    - comp_object-to_del: list of objects which will be deleted when this object is deleted
39    - comp_mirror: object is the result of e_comp_object_util_mirror_add()
40    - effect_running: object is animating by external module
41 */
42
43 #define UPDATE_MAX 512 // same as evas
44 #define FAILURE_MAX 2 // seems reasonable
45 #define SMART_NAME     "e_comp_object"
46 #define INPUT_OBJ_SMART_NAME "input_object"
47
48 /* for non-util functions */
49 #define API_ENTRY      E_Comp_Object *cw; \
50                        cw = evas_object_smart_data_get(obj); \
51                        if ((!obj) || (!cw) || (e_util_strcmp(evas_object_type_get(obj), SMART_NAME))) return
52
53 /* for util functions (obj may or may not be E_Comp_Object */
54 #define SOFT_ENTRY(...)      E_Comp_Object *cw; \
55                        if (!obj) \
56                          { \
57                             CRI("YOU PASSED NULL! ARGH!"); \
58                             return __VA_ARGS__; \
59                          } \
60                        cw = evas_object_smart_data_get(obj); \
61                        if ((!cw) || (e_util_strcmp(evas_object_type_get(obj), SMART_NAME))) \
62                          cw = NULL
63 #define INTERNAL_ENTRY E_Comp_Object *cw; cw = evas_object_smart_data_get(obj); if (!cw) return;
64
65 /* enable for lots of client size info in console output */
66 #if 1
67 # define e_util_size_debug_set(x, y)
68 #endif
69
70 /* enable along with display-specific damage INF calls to enable render tracing
71  * SLOW!
72  */
73 #if 0
74 #define RENDER_DEBUG(...) INF(__VA_ARGS__)
75 #else
76 #define RENDER_DEBUG(...)
77 #endif
78
79 typedef struct _E_Input_Rect_Data
80 {
81    Eina_Rectangle rect;
82    Evas_Object *obj;
83 } E_Input_Rect_Data;
84
85 typedef struct _E_Input_Rect_Smart_Data
86 {
87    Eina_List *input_rect_data_list;
88    E_Comp_Object *cw;
89 } E_Input_Rect_Smart_Data;
90
91 struct E_Comp_Object_Mover
92 {
93    EINA_INLIST;
94    E_Comp_Object_Mover_Cb func;
95    const char *sig;
96    void *data;
97    int pri;
98 };
99
100 static Eina_Inlist *_e_comp_object_movers = NULL;
101 static Evas_Smart *_e_comp_smart = NULL;
102 static Evas_Smart *_e_comp_input_obj_smart = NULL;
103
104 static int _e_comp_object_hooks_delete = 0;
105 static int _e_comp_object_hooks_walking = 0;
106
107 static Eina_Inlist *_e_comp_object_hooks[] =
108 {
109    [E_COMP_OBJECT_HOOK_EFFECT_START] = NULL,
110    [E_COMP_OBJECT_HOOK_EFFECT_END] = NULL,
111    [E_COMP_OBJECT_HOOK_RESTACK] = NULL,
112    [E_COMP_OBJECT_HOOK_OBJECT_SETUP] = NULL,
113    [E_COMP_OBJECT_HOOK_LAYER_SET] = NULL,
114    [E_COMP_OBJECT_HOOK_MASK_OBJECT_SET] = NULL,
115    [E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET] = NULL,
116    [E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET] = NULL,
117 };
118
119 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
120 static int _e_comp_object_intercept_hooks_delete = 0;
121 static int _e_comp_object_intercept_hooks_walking = 0;
122
123 static Eina_Inlist *_e_comp_object_intercept_hooks[] =
124 {
125    [E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER] = NULL,
126    [E_COMP_OBJECT_INTERCEPT_HOOK_HIDE] = NULL,
127 };
128 #endif
129
130 static Eina_Bool _damage_trace = EINA_FALSE;
131 static Eina_List *_damage_trace_objs = NULL;
132 static Eina_List *_damage_trace_post_objs = NULL;
133
134 /* sekrit functionzzz */
135 EINTERN void e_client_focused_set(E_Client *ec);
136
137 /* emitted every time a new noteworthy comp object is added */
138 EINTERN int E_EVENT_COMP_OBJECT_ADD = -1;
139
140 /* ecore event define */
141 EINTERN int E_EVENT_COMP_OBJECT_IMG_RENDER = -1;
142 EINTERN int E_EVENT_COMP_OBJECT_EFFECT_START = -1;
143 EINTERN int E_EVENT_COMP_OBJECT_EFFECT_END = -1;
144
145 static void           _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect);
146 static Eina_Bool      _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj);
147 static void           _e_comp_object_dim_update(E_Comp_Object *cw);
148 static void           _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror);
149 #ifdef REFACTOR_DESK_AREA
150 #else
151 static void _e_comp_object_lower(E_Comp_Object *cw, Evas_Object *obj);
152 static void _e_comp_object_raise(Evas_Object *obj);
153 static void  _e_comp_object_layer_set(Evas_Object *obj, short layer);
154 static void _e_comp_object_stack_above(Evas_Object *obj, Evas_Object *target);
155 static void _e_comp_object_stack_below(Evas_Object *obj, Evas_Object *target);
156 static void _e_comp_object_transform_obj_stack_update(Evas_Object *obj);
157 #endif
158
159 static E_Client       *dim_client = NULL;
160
161 static void
162 _e_comp_object_hooks_clean(void)
163 {
164    Eina_Inlist *l;
165    E_Comp_Object_Hook *ch;
166    unsigned int x;
167
168    for (x = 0; x < E_COMP_OBJECT_HOOK_LAST; x++)
169      EINA_INLIST_FOREACH_SAFE(_e_comp_object_hooks[x], l, ch)
170        {
171           if (!ch->delete_me) continue;
172           _e_comp_object_hooks[x] = eina_inlist_remove(_e_comp_object_hooks[x], EINA_INLIST_GET(ch));
173           free(ch);
174        }
175 }
176
177 static Eina_Bool
178 _e_comp_object_hook_call(E_Comp_Object_Hook_Point hookpoint, E_Client *ec)
179 {
180    E_Comp_Object_Hook *ch;
181    Eina_Bool ret = EINA_TRUE;
182
183    if (e_object_is_del(E_OBJECT(ec)))
184      {
185         if ((hookpoint != E_COMP_OBJECT_HOOK_EFFECT_START) &&
186             (hookpoint != E_COMP_OBJECT_HOOK_EFFECT_END) &&
187             (hookpoint != E_COMP_OBJECT_HOOK_OBJECT_SETUP) &&
188             (hookpoint != E_COMP_OBJECT_HOOK_LAYER_SET) &&
189             (hookpoint != E_COMP_OBJECT_HOOK_RESTACK) &&
190             (hookpoint != E_COMP_OBJECT_HOOK_MASK_OBJECT_SET) &&
191             (hookpoint != E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET) &&
192             (hookpoint != E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET)
193             )
194           {
195              return ret;
196           }
197      }
198    e_object_ref(E_OBJECT(ec));
199    _e_comp_object_hooks_walking++;
200    EINA_INLIST_FOREACH(_e_comp_object_hooks[hookpoint], ch)
201      {
202         if (ch->delete_me) continue;
203         if (!(ch->func(ch->data, ec)))
204           {
205              ret = EINA_FALSE;
206              break;
207           }
208      }
209    _e_comp_object_hooks_walking--;
210    if ((_e_comp_object_hooks_walking == 0) && (_e_comp_object_hooks_delete > 0))
211      _e_comp_object_hooks_clean();
212
213    e_object_unref(E_OBJECT(ec));
214
215    return ret;
216 }
217
218 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
219 static void
220 _e_comp_object_intercept_hooks_clean(void)
221 {
222    Eina_Inlist *l;
223    E_Comp_Object_Intercept_Hook *ch;
224    unsigned int x;
225
226    for (x = 0; x < E_COMP_OBJECT_INTERCEPT_HOOK_LAST; x++)
227      EINA_INLIST_FOREACH_SAFE(_e_comp_object_intercept_hooks[x], l, ch)
228        {
229           if (!ch->delete_me) continue;
230           _e_comp_object_intercept_hooks[x] = eina_inlist_remove(_e_comp_object_intercept_hooks[x], EINA_INLIST_GET(ch));
231           free(ch);
232        }
233 }
234
235 static Eina_Bool
236 _e_comp_object_intercept_hook_call(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Client *ec)
237 {
238    E_Comp_Object_Intercept_Hook *ch;
239    Eina_Bool ret = EINA_TRUE;
240
241    if (e_object_is_del(E_OBJECT(ec))) return ret;
242    e_object_ref(E_OBJECT(ec));
243    _e_comp_object_intercept_hooks_walking++;
244    EINA_INLIST_FOREACH(_e_comp_object_intercept_hooks[hookpoint], ch)
245      {
246         if (ch->delete_me) continue;
247         if (!(ch->func(ch->data, ec)))
248           {
249              ret = EINA_FALSE;
250              break;
251           }
252      }
253    _e_comp_object_intercept_hooks_walking--;
254    if ((_e_comp_object_intercept_hooks_walking == 0) && (_e_comp_object_intercept_hooks_delete > 0))
255      _e_comp_object_intercept_hooks_clean();
256
257    e_object_unref(E_OBJECT(ec));
258
259    return ret;
260 }
261 #endif
262
263 static void
264 _e_comp_object_event_free(void *d EINA_UNUSED, void *event)
265 {
266    E_Event_Comp_Object *ev = event;
267    E_Client *ec;
268
269    ec = evas_object_data_get(ev->comp_object, "E_Client");
270    if (ec)
271      {
272         UNREFD(ec, 1);
273         e_object_unref(E_OBJECT(ec));
274      }
275    evas_object_unref(ev->comp_object);
276    free(ev);
277 }
278
279 static void
280 _e_comp_object_event_add(Evas_Object *obj)
281 {
282    E_Event_Comp_Object *ev;
283    E_Client *ec;
284
285    if (stopping) return;
286    ev = E_NEW(E_Event_Comp_Object, 1);
287    EINA_SAFETY_ON_NULL_RETURN(ev);
288
289    evas_object_ref(obj);
290    ev->comp_object = obj;
291    ec = evas_object_data_get(ev->comp_object, "E_Client");
292    if (ec)
293      {
294         REFD(ec, 1);
295         e_object_ref(E_OBJECT(ec));
296      }
297    ecore_event_add(E_EVENT_COMP_OBJECT_ADD, ev, _e_comp_object_event_free, NULL);
298 }
299
300 static void
301 _e_comp_object_simple_free(void *d EINA_UNUSED, void *event)
302 {
303    E_Event_Comp_Object *ev = event;
304    E_Client *ec;
305
306    ec = evas_object_data_get(ev->comp_object, "E_Client");
307    if (ec)
308      {
309         UNREFD(ec, 1);
310         e_object_unref(E_OBJECT(ec));
311      }
312    evas_object_unref(ev->comp_object);
313    free(ev);
314 }
315
316 static void
317 _e_comp_object_event_simple(Evas_Object *obj, int type)
318 {
319    E_Event_Comp_Object *ev;
320    E_Client *ec;
321
322    ev = E_NEW(E_Event_Comp_Object, 1);
323    if (!ev) return;
324
325    evas_object_ref(obj);
326    ev->comp_object = obj;
327    ec = evas_object_data_get(ev->comp_object, "E_Client");
328    if (ec)
329      {
330         REFD(ec, 1);
331         e_object_ref(E_OBJECT(ec));
332      }
333    ecore_event_add(type, ev, (Ecore_End_Cb)_e_comp_object_simple_free, NULL);
334 }
335 /////////////////////////////////////
336
337 static void
338 _e_comp_object_cb_mirror_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
339 {
340    E_Comp_Object *cw = data;
341
342    cw->obj_mirror = eina_list_remove(cw->obj_mirror, obj);
343 }
344
345 static void
346 _e_comp_object_cb_mirror_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
347 {
348    E_Comp_Object *cw = data;
349
350    if ((!cw->force_visible) && (!e_object_is_del(E_OBJECT(cw->ec))))
351      evas_object_smart_callback_call(cw->smart_obj, "visibility_force", cw->ec);
352    cw->force_visible++;
353
354    if (e_comp->hwc && !e_comp_is_on_overlay(cw->ec))
355      e_comp_hwc_client_end(cw->ec, __FUNCTION__);
356 }
357
358 static void
359 _e_comp_object_cb_mirror_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
360 {
361    E_Comp_Object *cw = data;
362
363    cw->force_visible--;
364    if ((!cw->force_visible) && (!e_object_is_del(E_OBJECT(cw->ec))))
365      evas_object_smart_callback_call(cw->smart_obj, "visibility_normal", cw->ec);
366 }
367
368 /////////////////////////////////////
369
370 #ifdef REFACTOR_DESK_AREA
371 EINTERN void
372 e_comp_object_transform_obj_stack_update(Evas_Object *obj)
373 #else
374 static void
375 _e_comp_object_transform_obj_stack_update(Evas_Object *obj)
376 #endif
377 {
378    int layer = 0;
379    API_ENTRY;
380    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
381    if (cw->ec->input_only) return;
382
383    layer = evas_object_layer_get(obj);
384
385    if (cw->transform_bg_obj)
386      {
387         if (layer != evas_object_layer_get(cw->transform_bg_obj))
388           {
389              evas_object_layer_set(cw->transform_bg_obj, layer);
390           }
391
392         evas_object_stack_below(cw->transform_bg_obj, obj);
393      }
394
395    if (cw->transform_tranp_obj)
396      {
397         if (layer != evas_object_layer_get(cw->transform_tranp_obj))
398           {
399              evas_object_layer_set(cw->transform_tranp_obj, layer);
400           }
401
402         evas_object_stack_below(cw->transform_tranp_obj, obj);
403      }
404 }
405
406 static E_Map *
407 _e_comp_object_transform_obj_map_new(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
408 {
409    E_Map *map;
410    int i;
411    int x, y;
412
413    map = e_map_new();
414    if (!map) return NULL;
415
416    e_map_util_points_populate_from_object_full(map, obj, 0);
417    e_map_util_points_color_set(map, 255, 255, 255, 255);
418
419    for (i = 0 ; i < 4 ; ++i)
420      {
421         x = 0;
422         y = 0;
423
424         e_util_transform_vertices_pos_round_get(vertices, i, &x, &y, 0, 0);
425         e_map_point_coord_set(map, i, x, y, 1.0);
426      }
427
428    return map;
429 }
430
431 static void
432 _e_comp_object_transform_obj_map_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
433 {
434    if (!obj) return;
435
436    if (vertices)
437      {
438         E_Map *map = _e_comp_object_transform_obj_map_new(obj, vertices);
439         if (map)
440           {
441              e_comp_object_map_set(obj, map);
442              e_comp_object_map_enable_set(obj, EINA_TRUE);
443
444              e_map_free(map);
445           }
446      }
447    else
448      {
449         evas_object_map_enable_set(obj, EINA_FALSE);
450      }
451 }
452
453 static void
454 _e_comp_object_transform_obj_map_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
455 {
456    if (!obj) return;
457
458    if (vertices)
459      {
460         E_Map *map = _e_comp_object_transform_obj_map_new(obj, vertices);
461         if (map)
462           {
463              e_map_util_zoom(map, zoom.zoom_x, zoom.zoom_y, zoom.cx, zoom.cy);
464
465              e_comp_object_map_set(obj, map);
466              e_comp_object_map_enable_set(obj, EINA_TRUE);
467
468              e_map_free(map);
469           }
470      }
471    else
472      {
473         evas_object_map_enable_set(obj, EINA_FALSE);
474      }
475 }
476 /////////////////////////////////////
477
478 static inline Eina_Bool
479 _e_comp_shaped_check(int w, int h, const Eina_Rectangle *rects, int num)
480 {
481    if (num > 1) return EINA_TRUE;
482    if ((rects[0].x == 0) && (rects[0].y == 0) &&
483        ((int)rects[0].w == w) && ((int)rects[0].h == h))
484      return EINA_FALSE;
485    return EINA_TRUE;
486 }
487
488 /////////////////////////////////////
489
490 /* add a client to the layer-client list */
491 #ifdef REFACTOR_DESK_AREA
492 #else
493 static void
494 _e_comp_object_layers_add(E_Comp_Object *cw, E_Comp_Object *above, E_Comp_Object *below, Eina_Bool prepend)
495 {
496    g_rec_mutex_lock(&e_comp->ec_list_mutex);
497
498    if (above)
499     e_comp->layers[above->layer].clients = eina_inlist_append_relative(e_comp->layers[above->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(above->ec));
500    else if (below)
501      e_comp->layers[below->layer].clients = eina_inlist_prepend_relative(e_comp->layers[below->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(below->ec));
502    if ((!above) && (!below))
503      {
504         if (prepend)
505           e_comp->layers[cw->layer].clients = eina_inlist_prepend(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
506         else //this is either the layer object or a tough actin tinactin^W^W^Wfast stacking client
507           e_comp->layers[cw->layer].clients = eina_inlist_append(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
508      }
509    e_comp->layers[cw->layer].clients_count++;
510
511    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
512 }
513
514 static void
515 _e_comp_object_layers_remove(E_Comp_Object *cw)
516 {
517    g_rec_mutex_lock(&e_comp->ec_list_mutex);
518
519    if (cw->ec && e_comp->layers[cw->layer].clients)
520      {
521         e_comp->layers[cw->layer].clients = eina_inlist_remove(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
522         e_comp->layers[cw->layer].clients_count--;
523      }
524
525    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
526 }
527 #endif
528
529 /////////////////////////////////////
530 static void
531 _e_comp_object_alpha_set(E_Comp_Object *cw)
532 {
533    Eina_Bool alpha = cw->ec->argb;
534
535    if ((cw->external_content) &&
536        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
537      {
538         return;
539      }
540
541    if (cw->blanked || cw->ns || cw->ec->shaped) alpha = EINA_TRUE;
542    if (cw->user_alpha_set) alpha = cw->user_alpha;
543
544    evas_object_image_alpha_set(cw->obj, alpha);
545 }
546
547 static void
548 _e_comp_object_shadow(E_Comp_Object *cw)
549 {
550    if (e_client_util_shadow_state_get(cw->ec))
551      edje_object_signal_emit(cw->frame_object ?: cw->shobj, "e,state,shadow,on", "e");
552    else
553      edje_object_signal_emit(cw->frame_object ?: cw->shobj, "e,state,shadow,off", "e");
554    if (cw->frame_object)
555      edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
556    evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
557 }
558
559 /* convert from the surface coordinates to the buffer coordinates */
560 static void
561 _e_comp_object_map_transform_pos(E_Client *ec, int sx, int sy, int *dx, int *dy)
562 {
563    E_Comp_Wl_Buffer_Viewport *vp;
564    E_Comp_Wl_Client_Data *cdata;
565    int transform;
566    int bw, bh, tx, ty;
567
568   cdata = e_client_cdata_get(ec);
569
570    if (!ec || !cdata || e_object_is_del(E_OBJECT(ec)))
571      {
572         *dx = sx;
573         *dy = sy;
574         return;
575      }
576
577    vp = &cdata->scaler.buffer_viewport;
578    transform = e_comp_wl_output_buffer_transform_get(ec);
579
580    e_pixmap_size_get(ec->pixmap, &bw, &bh);
581
582    /* for subsurface, it should be swap 90 and 270 */
583    if (e_comp_wl_subsurface_check(ec))
584      switch (transform)
585        {
586         case WL_OUTPUT_TRANSFORM_90:          transform = WL_OUTPUT_TRANSFORM_270;         break;
587         case WL_OUTPUT_TRANSFORM_270:         transform = WL_OUTPUT_TRANSFORM_90;          break;
588         case WL_OUTPUT_TRANSFORM_FLIPPED_90:  transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; break;
589         case WL_OUTPUT_TRANSFORM_FLIPPED_270: transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;  break;
590         default: break;
591        }
592
593    switch (transform)
594      {
595       case WL_OUTPUT_TRANSFORM_NORMAL:
596       default:                              tx = sx,      ty = sy;      break;
597       case WL_OUTPUT_TRANSFORM_90:          tx = sy,      ty = bw - sx; break;
598       case WL_OUTPUT_TRANSFORM_180:         tx = bw - sx, ty = bh - sy; break;
599       case WL_OUTPUT_TRANSFORM_270:         tx = bh - sy, ty = sx;      break;
600       case WL_OUTPUT_TRANSFORM_FLIPPED:     tx = bw - sx, ty = sy;      break;
601       case WL_OUTPUT_TRANSFORM_FLIPPED_90:  tx = sy,      ty = sx;      break;
602       case WL_OUTPUT_TRANSFORM_FLIPPED_180: tx = sx,      ty = bh - sy; break;
603       case WL_OUTPUT_TRANSFORM_FLIPPED_270: tx = bh - sy, ty = bw - sx; break;
604      }
605
606    tx *= vp->buffer.scale;
607    ty *= vp->buffer.scale;
608
609    *dx = tx;
610    *dy = ty;
611 }
612
613 static void
614 _e_comp_object_map_transform_rect(E_Client *ec, int sx, int sy, int sw, int sh, int *dx, int *dy, int *dw, int *dh)
615 {
616    int x1 = sx;
617    int y1 = sy;
618    int x2 = sx + sw;
619    int y2 = sy + sh;
620    int mx, my;
621
622    _e_comp_object_map_transform_pos(ec, x1, y1, &x1, &y1);
623    _e_comp_object_map_transform_pos(ec, x2, y2, &x2, &y2);
624
625    mx = MIN(x1, x2);
626    my = MIN(y1, y2);
627
628    if (dx) *dx = mx;
629    if (dy) *dy = my;
630    if (dw) *dw = MAX(x1, x2) - mx;
631    if (dh) *dh = MAX(y1, y2) - my;
632 }
633
634 static void
635 _e_comp_object_map_damage_transform_rect(E_Client *ec, E_Map *m, int sx, int sy, int sw, int sh,
636                                          int *dx, int *dy, int *dw, int *dh)
637 {
638    E_Util_Transform_Rect rect = {sx, sy, sw, sh};
639    E_Util_Transform_Rect_Vertex sv, dv;
640    int bw, bh;
641    int i;
642
643    e_pixmap_size_get(ec->pixmap, &bw, &bh);
644
645    sv = e_util_transform_rect_to_vertices(&rect);
646
647    for (i = 0; i < 4; i++)
648      {
649         double x = 0.0, y = 0.0;
650
651         e_map_coords_get(m, sv.vertices[i].vertex[0], sv.vertices[i].vertex[1], &x, &y, 0);
652
653         /* if evas decide coordinate is outside of map, it returns (0, 0)
654            in this case, full damage is added.
655          */
656         if ((i != 0) && (x == 0.0) && (y == 0.0))
657           goto full;
658
659         dv.vertices[i].vertex[0] = x;
660         dv.vertices[i].vertex[1] = y;
661         dv.vertices[i].vertex[2] = 1.0;
662         dv.vertices[i].vertex[3] = 1.0;
663      }
664
665    rect = e_util_transform_vertices_to_rect(&dv);
666
667    if (dx) *dx = rect.x;
668    if (dy) *dy = rect.y;
669    if (dw) *dw = rect.w;
670    if (dh) *dh = rect.h;
671
672    return;
673
674 full:
675    if (dx) *dx = 0;
676    if (dy) *dy = 0;
677    if (dw) *dw = bw;
678    if (dh) *dh = bh;
679
680    return;
681 }
682
683 static E_Map *
684 _e_comp_object_map_damage_transform_get(E_Client *ec)
685 {
686    E_Map *m;
687    E_Map *m2 = NULL;
688    int bw, bh;
689    int i;
690
691    if (!e_client_transform_core_enable_get(ec))
692      return NULL;
693
694    m = e_client_map_get(ec);
695    if (!m)
696      return NULL;
697
698    e_pixmap_size_get(ec->pixmap, &bw, &bh);
699    if ((bw == 0) || (bh == 0))
700      {
701         e_map_free(m);
702         return NULL;
703      }
704
705    m2 = e_map_new();
706    if (!m2)
707      {
708         e_map_free(m);
709         return NULL;
710      }
711
712    e_map_point_coord_set(m2, 0, 0, 0, 0);
713    e_map_point_coord_set(m2, 1, bw, 0, 0);
714    e_map_point_coord_set(m2, 2, bw, bh, 0);
715    e_map_point_coord_set(m2, 3, 0, bh, 0);
716
717    for (i = 0; i < 4; i++)
718      {
719         int map_x, map_y;
720
721         e_map_point_coord_get(m, i, &map_x, &map_y, NULL);
722         e_map_point_image_uv_set(m2, i, map_x, map_y);
723      }
724
725    e_map_free(m);
726    return m2;
727 }
728
729 /////////////////////////////////////
730
731 /* handle evas mouse-in events on client object */
732 static void
733 _e_comp_object_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
734 {
735    Evas_Event_Mouse_In *ev = event_info;
736    E_Comp_Object *cw = data;
737
738    e_client_mouse_in(cw->ec, ev->output.x, ev->output.y);
739 }
740
741 /* handle evas mouse-out events on client object */
742 static void
743 _e_comp_object_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
744 {
745    Evas_Event_Mouse_Out *ev = event_info;
746    E_Comp_Object *cw = data;
747
748    e_client_mouse_out(cw->ec, ev->output.x, ev->output.y);
749 }
750
751 /* handle evas mouse wheel events on client object */
752 static void
753 _e_comp_object_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
754 {
755    Evas_Event_Mouse_Wheel *ev = event_info;
756    E_Comp_Object *cw = data;
757    E_Binding_Event_Wheel ev2;
758
759    if (!cw->ec) return;
760    if (e_client_action_get()) return;
761    e_bindings_evas_event_mouse_wheel_convert(ev, &ev2);
762    e_client_mouse_wheel(cw->ec, &ev->output, &ev2);
763 }
764
765 /* handle evas mouse down events on client object */
766 static void
767 _e_comp_object_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
768 {
769    Evas_Event_Mouse_Down *ev = event_info;
770    E_Comp_Object *cw = data;
771    E_Binding_Event_Mouse_Button ev2;
772
773    if (!cw->ec) return;
774    if (e_client_action_get()) return;
775    e_bindings_evas_event_mouse_down_button_convert(ev, &ev2);
776    e_client_mouse_down(cw->ec, ev->button, &ev->output, &ev2);
777 }
778
779 /* handle evas mouse up events on client object */
780 static void
781 _e_comp_object_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
782 {
783    Evas_Event_Mouse_Up *ev = event_info;
784    E_Comp_Object *cw = data;
785    E_Binding_Event_Mouse_Button ev2;
786
787    if (!cw->ec) return;
788    if (e_client_action_get() && (e_client_action_get() != cw->ec)) return;
789    e_bindings_evas_event_mouse_up_button_convert(ev, &ev2);
790    e_client_mouse_up(cw->ec, ev->button, &ev->output, &ev2);
791 }
792
793 /* handle evas mouse movement events on client object */
794 static void
795 _e_comp_object_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
796 {
797    Evas_Event_Mouse_Move *ev = event_info;
798    E_Comp_Object *cw = data;
799
800    if (!cw->ec) return;
801    if (e_client_action_get() && (e_client_action_get() != cw->ec)) return;
802    e_client_mouse_move(cw->ec, &ev->cur.output);
803 }
804 /////////////////////////////////////
805
806 /* helper function for checking compositor themes based on user-defined matches */
807 static Eina_Bool
808 _e_comp_object_shadow_client_match(const E_Client *ec, E_Comp_Match *m)
809 {
810    if (((m->title) && (!ec->netwm.name)) ||
811        ((ec->netwm.name) && (m->title) && (!e_util_glob_match(ec->netwm.name, m->title))))
812      return EINA_FALSE;
813 #if defined(__cplusplus) || defined(c_plusplus)
814    if (((m->clas) && (!ec->icccm.cpp_class)) ||
815        ((ec->icccm.cpp_class) && (m->clas) && (!e_util_glob_match(ec->icccm.cpp_class, m->clas))))
816      return EINA_FALSE;
817 #else
818    if (((m->clas) && (!ec->icccm.class)) ||
819        ((ec->icccm.class) && (m->clas) && (!e_util_glob_match(ec->icccm.class, m->clas))))
820      return EINA_FALSE;
821 #endif
822
823   if (((m->role) && (!ec->icccm.window_role)) ||
824        ((ec->icccm.window_role) && (m->role) && (!e_util_glob_match(ec->icccm.window_role, m->role))))
825      return EINA_FALSE;
826    if (m->primary_type)
827      {
828         if (ec->netwm.type)
829           {
830              if ((int)ec->netwm.type != m->primary_type)
831                return EINA_FALSE;
832           }
833         else if (m->primary_type != E_WINDOW_TYPE_REAL_UNKNOWN)
834           return EINA_FALSE;
835      }
836   if (m->borderless != 0)
837     {
838        int borderless = 0;
839
840        if (e_client_util_borderless(ec))
841          borderless = 1;
842        if (!(((m->borderless == -1) && (!borderless)) ||
843              ((m->borderless == 1) && (borderless))))
844          return EINA_FALSE;
845     }
846   if (m->dialog != 0)
847     {
848        int dialog = 0;
849
850        if (((ec->icccm.transient_for != 0) ||
851             (ec->dialog)))
852          dialog = 1;
853        if (!(((m->dialog == -1) && (!dialog)) ||
854              ((m->dialog == 1) && (dialog))))
855          return EINA_FALSE;
856     }
857   if (m->accepts_focus != 0)
858     {
859        int accepts_focus = 0;
860
861        if (ec->icccm.accepts_focus)
862          accepts_focus = 1;
863        if (!(((m->accepts_focus == -1) && (!accepts_focus)) ||
864              ((m->accepts_focus == 1) && (accepts_focus))))
865          return EINA_FALSE;
866     }
867   if (m->vkbd != 0)
868     {
869        int vkbd = 0;
870
871        if (ec->vkbd.vkbd)
872          vkbd = 1;
873        if (!(((m->vkbd == -1) && (!vkbd)) ||
874              ((m->vkbd == 1) && (vkbd))))
875          return EINA_FALSE;
876     }
877   if (m->argb != 0)
878     {
879        if (!(((m->argb == -1) && (!ec->argb)) ||
880              ((m->argb == 1) && (ec->argb))))
881          return EINA_FALSE;
882     }
883   if (m->fullscreen != 0)
884     {
885        int fullscreen = ec->fullscreen;
886
887        if (!(((m->fullscreen == -1) && (!fullscreen)) ||
888              ((m->fullscreen == 1) && (fullscreen))))
889          return EINA_FALSE;
890     }
891   if (m->modal != 0)
892     {
893        if (!(m->modal == -1))
894          return EINA_FALSE;
895     }
896   return EINA_TRUE;
897 }
898
899 /* function for setting up a client's compositor frame theme (cw->shobj) */
900 static Eina_Bool
901 _e_comp_object_shadow_setup(E_Comp_Object *cw)
902 {
903    int ok = 0;
904    char buf[4096];
905    Eina_List *list = NULL, *l;
906    E_Input_Rect_Data *input_rect_data;
907    E_Input_Rect_Smart_Data *input_rect_sd;
908    E_Comp_Match *m;
909    Eina_Stringshare *reshadow_group = NULL;
910    Eina_Bool focus = EINA_FALSE, skip = EINA_FALSE, fast = EINA_FALSE, reshadow = EINA_FALSE, no_shadow = EINA_FALSE, pass_event_flag = EINA_FALSE;
911    Eina_Stringshare *name, *title;
912    E_Comp_Config *conf = e_comp_config_get();
913
914    edje_object_file_get(cw->shobj, NULL, &reshadow_group);
915    /* match correct client type */
916    list = cw->ec->override ? conf->match.overrides : conf->match.borders;
917    name = cw->ec->icccm.name;
918    title = cw->ec->icccm.title;
919    skip = (cw->ec->override ? conf->match.disable_overrides : conf->match.disable_borders) || (title && (!strncmp(title, "noshadow", 8)));
920    fast = cw->ec->override ? conf->fast_overrides : conf->fast_borders;
921
922    /* skipping here is mostly a hack for systray because I hate it */
923    if (!skip)
924      {
925         EINA_LIST_FOREACH(list, l, m)
926           {
927              if (((m->name) && (!name)) ||
928                  ((name) && (m->name) && (!e_util_glob_match(name, m->name))))
929                continue;
930              if (!_e_comp_object_shadow_client_match(cw->ec, m)) continue;
931
932              focus = m->focus;
933              no_shadow = m->no_shadow;
934              if (m->shadow_style)
935                {
936                   /* fast effects are just themes with "/fast" appended and shorter effect times */
937                   if (fast)
938                     {
939                        snprintf(buf, sizeof(buf), "e/comp/frame/%s/fast", m->shadow_style);
940                        reshadow = ok = !e_util_strcmp(reshadow_group, buf);
941                        if (!ok)
942                          ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
943                     }
944                   /* default to non-fast style if fast not available */
945                   if (!ok)
946                     {
947                        snprintf(buf, sizeof(buf), "e/comp/frame/%s", m->shadow_style);
948                        reshadow = ok = !e_util_strcmp(reshadow_group, buf);
949                        if (!ok)
950                          ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
951                     }
952                   if (ok && m->visibility_effect)
953                     eina_stringshare_refplace(&cw->visibility_effect, m->visibility_effect);
954                   if (ok) break;
955                }
956           }
957      }
958    while (!ok)
959      {
960         if (skip || (cw->ec->e.state.video))
961           {
962              reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/none");
963              if (!ok)
964                ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/none");
965           }
966         if (ok) break;
967         if (conf->shadow_style)
968           {
969              if (fast)
970                {
971                   snprintf(buf, sizeof(buf), "e/comp/frame/%s/fast", conf->shadow_style);
972                   reshadow = ok = !e_util_strcmp(reshadow_group, buf);
973                   if (!ok)
974                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
975                }
976              if (!ok)
977                {
978                   snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
979                   reshadow = ok = !e_util_strcmp(reshadow_group, buf);
980                   if (!ok)
981                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
982                }
983           }
984         if (!ok)
985           {
986              if (fast)
987                {
988                   reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/default/fast");
989                   if (!ok)
990                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/default/fast");
991                }
992              if (!ok)
993                {
994                   reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/default");
995                   if (!ok)
996                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/default");
997                }
998           }
999         break;
1000      }
1001    /* reshadow means this entire function call has been a no-op since we're re-setting the current style */
1002    if (reshadow)
1003      {
1004         ;
1005      }
1006    if (cw->ec->override)
1007      {
1008         if ((!cw->ec->shaped) && (!no_shadow) && (!cw->ec->argb))
1009           edje_object_signal_emit(cw->shobj, "e,state,shadow,on", "e");
1010         else
1011           edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
1012         evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
1013      }
1014    else
1015      {
1016         if (no_shadow)
1017           {
1018              edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
1019              evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
1020           }
1021         else
1022           _e_comp_object_shadow(cw);
1023      }
1024
1025    if (focus || cw->ec->focused || cw->ec->override)
1026      e_comp_object_signal_emit(cw->smart_obj, "e,state,focused", "e");
1027    else
1028      e_comp_object_signal_emit(cw->smart_obj, "e,state,unfocused", "e");
1029    if (cw->ec->sticky)
1030      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
1031    if (cw->ec->hung)
1032      e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
1033    /* visibility must always be enabled for re_manage clients to prevent
1034     * pop-in animations every time the user sees a persistent client again;
1035     * applying visibility for iconic clients prevents the client from getting
1036     * stuck as hidden
1037     */
1038    if (cw->visible || cw->ec->re_manage)
1039      e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
1040    else
1041      e_comp_object_signal_emit(cw->smart_obj, "e,state,hidden", "e");
1042
1043    /* breaks animation counter */
1044    if (cw->frame_object)
1045      {
1046         edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
1047         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
1048         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
1049         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
1050         no_shadow = 1;
1051      }
1052    else
1053      {
1054         no_shadow = 1;
1055         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->obj);
1056      }
1057    if (cw->input_obj)
1058      {
1059         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
1060         if (input_rect_sd)
1061           {
1062              EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
1063                {
1064                   if (input_rect_data->obj)
1065                     {
1066                        pass_event_flag = EINA_TRUE;
1067                        break;
1068                     }
1069                }
1070           }
1071      }
1072    if (cw->indicator.obj)
1073      {
1074         Evas_Object *indicator;
1075         indicator = edje_object_part_swallow_get(cw->shobj, "e.swallow.indicator");
1076         if (indicator != cw->indicator.obj)
1077           {
1078              edje_object_part_unswallow(cw->shobj, indicator);
1079              edje_object_part_swallow(cw->shobj, "e.swallow.indicator", cw->indicator.obj);
1080              e_comp_object_indicator_size_set(cw->smart_obj, cw->indicator.w, cw->indicator.h);
1081           }
1082      }
1083
1084    evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
1085    evas_object_pass_events_set(cw->obj, pass_event_flag);
1086
1087    return EINA_TRUE;
1088 }
1089
1090 /////////////////////////////////////////////
1091
1092 static void
1093 _e_comp_object_animating_begin(E_Comp_Object *cw)
1094 {
1095    cw->animating++;
1096    if (cw->animating == 1)
1097      {
1098         e_comp->animating++;
1099         REFD(cw->ec, 2);
1100         e_object_ref(E_OBJECT(cw->ec));
1101      }
1102 }
1103
1104 static Eina_Bool
1105 _e_comp_object_animating_end(E_Comp_Object *cw)
1106 {
1107    if (cw->animating)
1108      {
1109         cw->animating--;
1110         if (!cw->animating)
1111           {
1112              if (cw->ec)
1113                {
1114                   if (cw->ec->launching)
1115                     {
1116                        if (!cw->ec->extra_animating)
1117                          {
1118                             ELOGF("COMP", "Un-Set launching flag..", cw->ec);
1119                             cw->ec->launching = EINA_FALSE;
1120                             if (cw->ec->first_mapped)
1121                               {
1122                                  ELOGF("LAUNCH", "SHOW real win", cw->ec);
1123                                  e_comp_object_signal_emit(cw->ec->frame, "e,action,launch_real,done", "e");
1124                               }
1125
1126                             e_comp_object_signal_emit(cw->ec->frame, "e,action,launch,done", "e");
1127                          }
1128                     }
1129                }
1130              e_comp->animating--;
1131              cw->showing = cw->hiding = 0;
1132              UNREFD(cw->ec, 2);
1133              if (e_comp->animating == 0)
1134                e_comp_visibility_calculation_set(EINA_TRUE);
1135              /* remove ref from animation start, account for possibility of deletion from unref */
1136              return !!e_object_unref(E_OBJECT(cw->ec));
1137           }
1138      }
1139    return EINA_TRUE;
1140 }
1141
1142 /* handle the end of a compositor animation */
1143 static void
1144 _e_comp_object_done_defer(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source EINA_UNUSED)
1145 {
1146    E_Comp_Object *cw = data;
1147
1148    /* visible clients which have never been sized are a bug */
1149    if ((!cw->ec->new_client) && (!cw->ec->changes.size) && ((cw->w < 0) || (cw->h < 0)) && (!strcmp(emission, "e,action,show,done")))
1150      CRI("ACK! ec:%p", cw->ec);
1151    if (!_e_comp_object_animating_end(cw)) return;
1152    if (cw->animating) return;
1153    /* hide only after animation finishes to guarantee a full run of the animation */
1154    if (!cw->defer_hide) return;
1155    if ((!strcmp(emission, "e,action,hide,done")) ||
1156        (!strcmp(emission, "e,action,done")) ||
1157        ((cw->ec->iconic) && (!strcmp(emission, "e,action,show,done"))))
1158      {
1159         ELOGF("COMP", "defer hide emission:%s", cw->ec, emission);
1160         evas_object_hide(cw->smart_obj);
1161      }
1162 }
1163
1164 /* run a visibility compositor effect if available, return false if object is dead */
1165 static Eina_Bool
1166 _e_comp_object_effect_visibility_start(E_Comp_Object *cw, Eina_Bool state)
1167 {
1168    E_Zone *zone;
1169    int x, y;
1170    int zw = 0, zh = 0;
1171
1172    if ((!cw->visibility_effect) || (!e_comp_object_effect_allowed_get(cw->smart_obj))) return EINA_TRUE;;
1173    if (!cw->effect_running)
1174      _e_comp_object_animating_begin(cw);
1175    if (!e_comp_object_effect_stop(cw->smart_obj, _e_comp_object_done_defer))
1176      return _e_comp_object_animating_end(cw);
1177    if (!e_comp_object_effect_set(cw->smart_obj, cw->visibility_effect))
1178      return _e_comp_object_animating_end(cw);
1179
1180    evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
1181    x -= cw->x;
1182    y -= cw->y;
1183    zone = e_comp_zone_find_by_ec(cw->ec);
1184    if (zone)
1185      zw = zone->w, zh = zone->h;
1186    else
1187      {
1188         E_Zone *zone;
1189
1190         zone = e_comp_object_util_zone_get(cw->smart_obj);
1191         if (!zone) zone = e_zone_current_get();
1192         if (zone)
1193           {
1194              zw = zone->w;
1195              zh = zone->h;
1196           }
1197      }
1198    e_comp_object_effect_params_set(cw->smart_obj, 1, (int[]){cw->x, cw->y,
1199       cw->w, cw->h, zw, zh, x, y}, 8);
1200    e_comp_object_effect_params_set(cw->smart_obj, 0, (int[]){state}, 1);
1201    e_comp_object_effect_start(cw->smart_obj, _e_comp_object_done_defer, cw);
1202    return EINA_TRUE;
1203 }
1204 /////////////////////////////////////////////
1205
1206 /* create necessary objects for clients that e manages */
1207 static void
1208 _e_comp_object_mouse_event_callback_set(E_Comp_Object *cw)
1209 {
1210    if (cw->set_mouse_callbacks) return;
1211    if (!cw->smart_obj) return;
1212
1213    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_cb_mouse_in, cw);
1214    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_cb_mouse_out, cw);
1215    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_DOWN, _e_comp_object_cb_mouse_down, cw);
1216    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_cb_mouse_up, cw);
1217    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_MOVE, _e_comp_object_cb_mouse_move, cw);
1218    evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_WHEEL, _e_comp_object_cb_mouse_wheel, cw);
1219
1220    cw->set_mouse_callbacks = EINA_TRUE;
1221 }
1222
1223 static void
1224 _e_comp_object_mouse_event_callback_unset(E_Comp_Object *cw)
1225 {
1226    if (!cw->set_mouse_callbacks) return;
1227    if (!cw->smart_obj) return;
1228
1229    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_cb_mouse_in);
1230    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_cb_mouse_out);
1231    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_DOWN, _e_comp_object_cb_mouse_down);
1232    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_cb_mouse_up);
1233    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_MOVE, _e_comp_object_cb_mouse_move);
1234    evas_object_event_callback_del(cw->smart_obj, EVAS_CALLBACK_MOUSE_WHEEL, _e_comp_object_cb_mouse_wheel);
1235
1236    cw->set_mouse_callbacks = EINA_FALSE;
1237 }
1238
1239 static void
1240 _e_comp_object_setup(E_Comp_Object *cw)
1241 {
1242    cw->clip = evas_object_rectangle_add(e_comp->evas);
1243    evas_object_move(cw->clip, -9999, -9999);
1244    evas_object_resize(cw->clip, 999999, 999999);
1245    evas_object_smart_member_add(cw->clip, cw->smart_obj);
1246    cw->effect_obj = edje_object_add(e_comp->evas);
1247    evas_object_move(cw->effect_obj, cw->x, cw->y);
1248    evas_object_clip_set(cw->effect_obj, cw->clip);
1249    evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
1250    e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none");
1251    cw->shobj = edje_object_add(e_comp->evas);
1252    evas_object_data_set(cw->shobj, "comp_smart_obj", cw->smart_obj);
1253    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
1254    edje_object_signal_callback_add(cw->shobj, "e,action,*,done", "e", _e_comp_object_done_defer, cw);
1255
1256    /* name objects appropriately for nicer printing when using e_comp_util_wins_print() */
1257    if (cw->ec->override)
1258      {
1259         evas_object_name_set(cw->shobj, "cw->shobj::WINDOW");
1260         evas_object_name_set(cw->effect_obj, "cw->effect_obj::WINDOW");
1261         evas_object_name_set(cw->clip, "cw->clip::WINDOW");
1262      }
1263    else if (!cw->ec->input_only)
1264      {
1265         evas_object_name_set(cw->shobj, "cw->shobj::CLIENT");
1266         evas_object_name_set(cw->effect_obj, "cw->effect_obj::CLIENT");
1267         evas_object_name_set(cw->clip, "cw->clip::CLIENT");
1268      }
1269    cw->real_hid = !cw->ec->input_only;
1270    if (!cw->ec->input_only)
1271      {
1272         e_util_size_debug_set(cw->effect_obj, 1);
1273         _e_comp_object_mouse_event_callback_set(cw);
1274      }
1275
1276    cw->default_input_obj = evas_object_rectangle_add(e_comp->evas);
1277    evas_object_name_set(cw->default_input_obj, "cw->default_input_obj");
1278    evas_object_move(cw->default_input_obj, cw->x, cw->y);
1279    evas_object_resize(cw->default_input_obj, cw->w, cw->h);
1280    evas_object_color_set(cw->default_input_obj, 0, 0, 0, 0);
1281    evas_object_smart_member_add(cw->default_input_obj, cw->smart_obj);
1282
1283    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_OBJECT_SETUP, cw->ec);
1284 }
1285
1286 /////////////////////////////////////////////
1287
1288 /* for fast path evas rendering; only called during render */
1289 static void
1290 _e_comp_object_pixels_get(void *data, Evas_Object *obj EINA_UNUSED)
1291 {
1292    E_Comp_Object *cw = data;
1293    E_Client *ec = cw->ec;
1294    int pw, ph;
1295    int bx, by, bxx, byy;
1296
1297    if (e_object_is_del(E_OBJECT(ec))) return;
1298    if (cw->external_content) return;
1299    if (!e_pixmap_size_get(ec->pixmap, &pw, &ph)) return;
1300    e_pixmap_image_opaque_get(cw->ec->pixmap, &bx, &by, &bxx, &byy);
1301    if (bxx && byy)
1302      {
1303         bxx = pw - (bx + bxx), byy = ph - (by + byy);
1304         evas_object_image_border_set(cw->obj, bx, bxx, by, byy);
1305      }
1306    else if (cw->client_inset.calc && (!cw->frame_object)) //CSD
1307      {
1308         bx = -cw->client_inset.l + 4, by = -cw->client_inset.t + 4;
1309         bxx = -cw->client_inset.r, byy = -cw->client_inset.b;
1310      }
1311    else
1312      {
1313         bx = by = bxx = byy = 0;
1314         evas_object_image_border_set(cw->obj, bx, bxx, by, byy);
1315      }
1316    {
1317       Edje_Message_Int_Set *msg;
1318       Edje_Message_Int msg2;
1319       Eina_Bool id = (bx || by || bxx || byy);
1320
1321       msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int) * 3));
1322       msg->count = 4;
1323       msg->val[0] = bx;
1324       msg->val[1] = by;
1325       msg->val[2] = bxx;
1326       msg->val[3] = byy;
1327       edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 1, msg);
1328       msg2.val = id;
1329       edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT, 0, &msg2);
1330    }
1331    if (cw->native)
1332      {
1333         E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
1334         e_comp_client_post_update_add(cw->ec);
1335      }
1336    else if (e_comp_object_render(ec->frame))
1337      {
1338         /* apply shape mask if necessary */
1339         if ((!cw->native) && (ec->shaped))
1340           e_comp_object_shape_apply(ec->frame);
1341      }
1342    /* shaped clients get precise mouse events to handle transparent pixels */
1343    evas_object_precise_is_inside_set(cw->obj, ec->shaped);
1344
1345    /* queue another render if client is still dirty; cannot refresh here. */
1346    if (e_pixmap_dirty_get(ec->pixmap) && e_pixmap_size_get(ec->pixmap, &pw, &ph))
1347      e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1348
1349    if (cw->render_trace)
1350      {
1351         _e_comp_object_event_simple(ec->frame, E_EVENT_COMP_OBJECT_IMG_RENDER);
1352      }
1353 }
1354
1355
1356 static void
1357 _e_comp_object_pixels_noti(void *data, Evas_Object *obj EINA_UNUSED)
1358 {
1359    E_Comp_Object *cw = data;
1360    E_Client *ec = cw->ec;
1361
1362    if (e_object_is_del(E_OBJECT(ec))) return;
1363    if (cw->external_content) return;
1364    if (!e_comp->hwc) return;
1365
1366    e_comp_client_render_list_add(cw->ec);
1367
1368    if (!ec->hwc_window) return;
1369
1370    e_hwc_windows_rendered_window_add(ec->hwc_window);
1371 }
1372
1373 /////////////////////////////////////////////
1374
1375 static void
1376 _e_comp_intercept_move(void *data, Evas_Object *obj, int x, int y)
1377 {
1378    E_Comp_Object *cw = data;
1379    int ix, iy, fx, fy;
1380
1381    if (cw->render_update_lock.lock)
1382      {
1383         cw->render_update_lock.pending_move_x = x;
1384         cw->render_update_lock.pending_move_y = y;
1385         cw->render_update_lock.pending_move_set = EINA_TRUE;
1386         return;
1387      }
1388
1389    if ((e_pixmap_type_get(cw->ec->pixmap) != E_PIXMAP_TYPE_EXT_OBJECT) &&
1390        (e_pixmap_usable_get(cw->ec->pixmap)) &&
1391        (cw->external_content))
1392      {
1393         /* delay to move until the external content is unset */
1394         cw->ec->changes.pos = 1;
1395         EC_CHANGED(cw->ec);
1396         return;
1397      }
1398
1399    if (cw->ec->move_after_resize)
1400      {
1401         if ((x != cw->ec->x) || (y != cw->ec->y))
1402           {
1403              if (!cw->ec->is_cursor)
1404                ELOGF("COMP", "Set Pos to (%d,%d). current ec_pos(%d,%d)", cw->ec, x, y, cw->ec->x, cw->ec->y);
1405              e_client_pos_set(cw->ec, x, y);
1406              cw->ec->changes.pos = 1;
1407              EC_CHANGED(cw->ec);
1408           }
1409         return;
1410      }
1411
1412    if ((cw->ec->resize_mode == E_POINTER_RESIZE_NONE) &&
1413        (cw->ec->manage_resize.resize_obj))
1414      {
1415         e_client_pos_set(cw->ec, x, y);
1416         cw->ec->client.x = x + cw->client_inset.l;
1417         cw->ec->client.y = y + cw->client_inset.t;
1418         e_policy_visibility_client_defer_move(cw->ec);
1419         return;
1420      }
1421
1422    /* if frame_object does not exist, client_inset indicates CSD.
1423     * this means that ec->client matches cw->x/y, the opposite
1424     * of SSD.
1425     */
1426    fx = (!cw->frame_object) * cw->client_inset.l;
1427    fy = (!cw->frame_object) * cw->client_inset.t;
1428    if ((cw->x == x + fx) && (cw->y == y + fy))
1429      {
1430         if ((cw->ec->x != x) || (cw->ec->y != y))
1431           {
1432              /* handle case where client tries to move to position and back very quickly */
1433              e_client_pos_set(cw->ec, x, y);
1434              cw->ec->client.x = x + cw->client_inset.l;
1435              cw->ec->client.y = y + cw->client_inset.t;
1436           }
1437         return;
1438      }
1439    if (!cw->ec->maximize_override)
1440      {
1441         /* prevent moving in some directions while directionally maximized */
1442         if ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1443           y = cw->y;
1444         if ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1445           x = cw->x;
1446      }
1447    ix = x + cw->client_inset.l;
1448    iy = y + cw->client_inset.t;
1449    if (cw->ec->maximized && (!cw->ec->maximize_override) && ((cw->ec->x != x) || (cw->ec->y != y)) &&
1450        ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_VERTICAL) &&
1451        ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_HORIZONTAL))
1452      {
1453         /* prevent moving at all if move isn't allowed in current maximize state */
1454         if ((!e_config->allow_manip) && ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
1455         /* queue unmaximize if we are allowing move and update unmaximize geometry */
1456
1457         E_Zone *zone;
1458         zone = e_comp_zone_find_by_ec(cw->ec);
1459         if (!zone) return;
1460
1461         cw->ec->changes.need_unmaximize = 1;
1462         cw->ec->saved.x = ix - zone->x;
1463         cw->ec->saved.y = iy - zone->y;
1464         cw->ec->saved.w = cw->ec->client.w;
1465         cw->ec->saved.h = cw->ec->client.h;
1466         EC_CHANGED(cw->ec);
1467         return;
1468      }
1469    /* only update during resize if triggered by resize */
1470    if (e_client_util_resizing_get(cw->ec) && (!cw->force_move)) return;
1471    /* delay to move while surface waits paired commit serial*/
1472    if (e_client_pending_geometry_has(cw->ec))
1473      {
1474         /* do nothing while waiting paired commit serial*/
1475         return;
1476      }
1477
1478    e_client_pos_set(cw->ec, x, y);
1479    if (cw->ec->new_client)
1480      {
1481         /* don't actually do anything until first client idler loop */
1482         cw->ec->placed = ((!cw->ec->dialog) && (!cw->ec->parent));
1483         cw->ec->changes.pos = 1;
1484         EC_CHANGED(cw->ec);
1485      }
1486    else
1487      {
1488         /* only update xy position of client to avoid invalid
1489          * first damage region if it is not a new_client. */
1490         cw->ec->client.x = ix;
1491         cw->ec->client.y = iy;
1492
1493         /* flip SSD->CSD */
1494         if (!cw->frame_object)
1495           x = ix, y = iy;
1496         evas_object_move(obj, x, y);
1497      }
1498 }
1499
1500 static void
1501 _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
1502 {
1503    E_Comp_Object *cw = data;
1504    int pw = 0, ph = 0, fw, fh, iw, ih, prev_w, prev_h, x, y;
1505    E_Zone *zone;
1506
1507    if (cw->render_update_lock.lock)
1508      {
1509         cw->render_update_lock.pending_resize_w = w;
1510         cw->render_update_lock.pending_resize_h = h;
1511         cw->render_update_lock.pending_resize_set = EINA_TRUE;
1512         return;
1513      }
1514
1515    if (!e_util_strcmp("input_panel_surface", cw->ec->icccm.window_role))
1516      {
1517         e_client_size_set(cw->ec, w, h);
1518         evas_object_resize(obj, w, h);
1519         return;
1520      }
1521
1522    /* if frame_object does not exist, client_inset indicates CSD.
1523     * this means that ec->client matches cw->w/h, the opposite
1524     * of SSD.
1525     */
1526    fw = (!cw->frame_object) * (-cw->client_inset.l - cw->client_inset.r);
1527    fh = (!cw->frame_object) * (-cw->client_inset.t - cw->client_inset.b);
1528    if ((cw->w == w + fw) && (cw->h == h + fh))
1529      {
1530         if (((cw->ec->w != w) || (cw->ec->h != h)) ||
1531             (cw->ec->client.w != w - cw->client_inset.l - cw->client_inset.r) ||
1532             (cw->ec->client.h != h - cw->client_inset.t - cw->client_inset.b))
1533           {
1534              /* handle case where client tries to resize itself and back very quickly */
1535              e_client_size_set(cw->ec, w, h);
1536              cw->ec->client.w = w - cw->client_inset.l - cw->client_inset.r;
1537              cw->ec->client.h = h - cw->client_inset.t - cw->client_inset.b;
1538              evas_object_smart_callback_call(obj, "client_resize", NULL);
1539           }
1540         return;
1541      }
1542    /* guarantee that fullscreen is fullscreen */
1543    zone = e_comp_zone_find_by_ec(cw->ec);
1544    if (!zone) return;
1545    if (cw->ec->fullscreen && ((w != zone->w) || (h != zone->h)))
1546      {
1547         if (!e_client_transform_core_enable_get(cw->ec))
1548           return;
1549      }
1550    /* calculate client size */
1551    iw = w - cw->client_inset.l - cw->client_inset.r;
1552    ih = h - cw->client_inset.t - cw->client_inset.b;
1553    if (cw->ec->maximized && (!cw->ec->maximize_override) && ((cw->ec->w != w) || (cw->ec->h != h)))
1554      {
1555         /* prevent resizing while maximized depending on direction and config */
1556         if ((!e_config->allow_manip) && ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
1557
1558         Eina_Bool reject = EINA_FALSE;
1559         if (cw->ec->maximized & E_MAXIMIZE_VERTICAL)
1560           {
1561              if (cw->ec->client.h != ih)
1562                {
1563                   cw->ec->saved.h = ih;
1564                   cw->ec->saved.y = cw->ec->client.y - zone->y;
1565                   reject = cw->ec->changes.need_unmaximize = 1;
1566                }
1567           }
1568         if (cw->ec->maximized & E_MAXIMIZE_HORIZONTAL)
1569           {
1570              if (cw->ec->client.w != iw)
1571                {
1572                   cw->ec->saved.w = iw;
1573                   cw->ec->saved.x = cw->ec->client.x - zone->x;
1574                   reject = cw->ec->changes.need_unmaximize = 1;
1575                }
1576           }
1577         if (reject)
1578           {
1579              EC_CHANGED(cw->ec);
1580              return;
1581           }
1582      }
1583    if (cw->ec->new_client || (!cw->ec->visible) || (!cw->effect_obj))
1584      {
1585         /* do nothing until client idler loops */
1586         if ((cw->ec->w != w) || (cw->ec->h != h))
1587           {
1588              e_client_size_set(cw->ec, w, h);
1589              cw->ec->changes.size = 1;
1590              EC_CHANGED(cw->ec);
1591           }
1592         return;
1593      }
1594    if (e_client_pending_geometry_has(cw->ec))
1595      {
1596         /* do nothing while waiting paired commit serial*/
1597         return;
1598      }
1599
1600    e_client_size_set(cw->ec, w, h);
1601
1602    cw->ec->client.w = iw;
1603    cw->ec->client.h = ih;
1604    if ((cw->ec->client.w < 0) || (cw->ec->client.h < 0)) CRI("WTF. ec:%p", cw->ec);
1605
1606    /* The size of non-compositing window can be changed, so there is a
1607     * need to check that cw is H/W composited if cw is not redirected.
1608     * And of course we have to change size of evas object of H/W composited cw,
1609     * otherwise cw can't receive input events even if it is shown on the screen.
1610     */
1611    Eina_Bool redirected = cw->redirected;
1612    if (!redirected)
1613      redirected = e_comp_is_on_overlay(cw->ec);
1614
1615    if ((!cw->ec->input_only) && (redirected) &&
1616        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
1617        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE) &&
1618        (e_pixmap_dirty_get(cw->ec->pixmap) ||
1619        (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))))
1620      return;
1621
1622    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE ||
1623        cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE)
1624      pw = w, ph = h;
1625    prev_w = cw->w, prev_h = cw->h;
1626    e_comp_object_frame_wh_adjust(obj, 0, 0, &fw, &fh);
1627    /* check shading and clamp to pixmap size for regular clients */
1628    if ((!cw->ec->input_only) && (!cw->ec->override) &&
1629        (((w - fw != pw) || (h - fh != ph))))
1630      {
1631         //INF("CALLBACK: REQ(%dx%d) != CUR(%dx%d)", w - fw, h - fh, pw, ph);
1632         evas_object_smart_callback_call(obj, "client_resize", NULL);
1633         /* flip for CSD */
1634         if (cw->frame_object || cw->ec->input_only)
1635           e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
1636         else
1637           w = pw, h = ph;
1638         if ((cw->w == w) && (cw->h == h))
1639           {
1640              /* going to be a noop resize which won't trigger smart resize */
1641              RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
1642              if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
1643           }
1644         evas_object_resize(obj, w, h);
1645      }
1646    else
1647      {
1648         evas_object_smart_callback_call(obj, "client_resize", NULL);
1649
1650         /* flip for CSD */
1651         if ((!cw->frame_object) && (!cw->ec->input_only))
1652           w = pw, h = ph;
1653         /* "just do it" for overrides */
1654         evas_object_resize(obj, w, h);
1655      }
1656    if (!cw->ec->override)
1657      {
1658         /* shape probably changed for non-overrides */
1659         if (cw->ec->shaped)
1660           EC_CHANGED(cw->ec);
1661      }
1662
1663    /* this fixes positioning jiggles when using a resize mode
1664     * which also changes the client's position
1665     */
1666    cw->force_move = 1;
1667    if (cw->frame_object)
1668      x = cw->x, y = cw->y;
1669    else
1670      x = cw->ec->x, y = cw->ec->y;
1671    switch (cw->ec->resize_mode)
1672      {
1673       case E_POINTER_RESIZE_BL:
1674       case E_POINTER_RESIZE_L:
1675         evas_object_move(obj, x + prev_w - cw->w, y);
1676         break;
1677       case E_POINTER_RESIZE_TL:
1678         evas_object_move(obj, x + prev_w - cw->w, y + prev_h - cw->h);
1679         break;
1680       case E_POINTER_RESIZE_T:
1681       case E_POINTER_RESIZE_TR:
1682         evas_object_move(obj, x, y + prev_h - cw->h);
1683         break;
1684       default:
1685         break;
1686      }
1687    cw->force_move = 0;
1688 }
1689
1690 static void
1691 _e_comp_intercept_layer_set(void *data, Evas_Object *obj, int layer)
1692 {
1693 #ifdef REFACTOR_DESK_AREA
1694    E_Comp_Object *cw = data;
1695    E_Comp_Object_Data_Set_Layer layer_set_data;
1696
1697    layer_set_data.cw = cw;
1698    layer_set_data.layer = layer;
1699
1700    wl_signal_emit_mutable(&cw->events.set_layer, &layer_set_data);
1701
1702    if (cw->visible)
1703      {
1704         e_comp_render_queue();
1705         e_comp_object_transform_obj_stack_update(obj);
1706      }
1707
1708 #else
1709    E_Comp_Object *cw = data;
1710    E_Comp_Wl_Client_Data *child_cdata;
1711    unsigned int l = e_comp_canvas_layer_map(layer);
1712    int oldraise;
1713
1714    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
1715      {
1716         /* doing a compositor effect, follow directions */
1717         _e_comp_object_layer_set(obj, layer);
1718         if (layer == cw->ec->layer) //trying to put layer back
1719           {
1720              E_Client *ec;
1721
1722              /* if ec->layer and layer are the same but the client is not belong to the given(l)
1723                  that means, layer is changed during layer_pending. in this case, need to update layer inlist*/
1724              if (cw->layer != l) goto layer_set;
1725
1726              if (cw->visible)
1727                {
1728                   e_comp_render_queue();
1729                }
1730              ec = e_client_above_get(cw->ec);
1731              /* skip subsurface: stacking subsurface is handled by e_comp_wl */
1732              while ((ec) && (e_comp_wl_subsurface_check(ec)))
1733                ec = e_client_above_get(ec);
1734              if (ec && (evas_object_layer_get(ec->frame) != evas_object_layer_get(obj)))
1735                {
1736                   ec = e_client_below_get(cw->ec);
1737                   /* skip subsurface: stacking subsurface is handled by e_comp_wl */
1738                   while ((ec) && (e_comp_wl_subsurface_check(ec)))
1739                     ec = e_client_below_get(ec);
1740                   if (ec && (evas_object_layer_get(ec->frame) == evas_object_layer_get(cw->smart_obj)))
1741                     {
1742                        evas_object_stack_above(obj, ec->frame);
1743                        return;
1744                     }
1745                   ec = NULL;
1746                }
1747              if (ec && (cw->ec->parent == ec))
1748                {
1749                   if (e_client_transient_policy_get(cw->ec) == E_TRANSIENT_ABOVE)
1750                     evas_object_stack_above(obj, ec->frame);
1751                   else
1752                     evas_object_stack_below(obj, ec->frame);
1753                }
1754              else
1755                evas_object_stack_below(obj, ec ? ec->frame : e_comp->layers[cw->layer].obj);
1756           }
1757         return;
1758      }
1759
1760 layer_set:
1761    if (cw->layer == l) return;
1762    if (e_comp_canvas_client_layer_map(layer) == 9999)
1763      return; //invalid layer for clients not doing comp effects
1764    if (cw->ec->fullscreen)
1765      {
1766         cw->ec->saved.layer = layer;
1767         return;
1768      }
1769    oldraise = e_config->transient.raise;
1770
1771    /* clamp to valid client layer */
1772    layer = e_comp_canvas_client_layer_map_nearest(layer);
1773    cw->ec->layer = layer;
1774    if (e_config->transient.layer)
1775      {
1776         E_Client *child;
1777         Eina_List *list = eina_list_clone(cw->ec->transients);
1778
1779         /* We need to set raise to one, else the child wont
1780          * follow to the new layer. It should be like this,
1781          * even if the user usually doesn't want to raise
1782          * the transients.
1783          */
1784         e_config->transient.raise = 1;
1785         EINA_LIST_FREE(list, child)
1786           {
1787              child_cdata = e_client_cdata_get(child);
1788              if (child_cdata && !child_cdata->mapped)
1789                {
1790                   ELOGF("COMP", "LAYER_SET CHILD. BUT not mapped. skip. child(ec:%p, win:0x%08zx)", cw->ec, child, e_client_util_win_get(child));
1791                   continue;
1792                }
1793              e_client_layer_set(child, layer);
1794           }
1795      }
1796
1797    e_config->transient.raise = oldraise;
1798
1799    _e_comp_object_layers_remove(cw);
1800    cw->layer = e_comp_canvas_layer_map(layer);
1801    _e_comp_object_layers_add(cw, NULL, NULL, 0);
1802    //if (cw->ec->new_client)
1803      //INF("CLIENT STACKED %p: %u", cw->ec, layer);
1804    _e_comp_object_layer_set(obj, layer);
1805    if (!e_comp->layers[cw->layer].obj) return; //this is a layer marker
1806    evas_object_stack_below(obj, e_comp->layers[cw->layer].obj);
1807    if (evas_object_below_get(obj) == e_comp->layers[cw->layer].obj)
1808      {
1809         /* can't stack a client above its own layer marker */
1810         CRI("STACKING ERROR!!! ec:%p (cw->layer:%d, ec->layer:%d)", cw->ec, cw->layer, cw->ec->layer);
1811      }
1812    if (!cw->visible) return;
1813    e_comp_render_queue();
1814    _e_comp_object_transform_obj_stack_update(obj);
1815 #endif
1816 }
1817
1818 #ifdef REFACTOR_DESK_AREA
1819 #else
1820 typedef void (*E_Comp_Object_Stack_Func)(Evas_Object *obj, Evas_Object *stack);
1821 #endif
1822
1823 #ifdef REFACTOR_DESK_AREA
1824 EINTERN void
1825 e_comp_object_raise(Evas_Object *obj)
1826 #else
1827 static void
1828 _e_comp_object_raise(Evas_Object *obj)
1829 #endif
1830 {
1831    evas_object_raise(obj);
1832
1833    if (evas_object_smart_smart_get(obj))
1834      {
1835         E_Client *ec = e_comp_object_client_get(obj);
1836         if (ec)
1837           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1838      }
1839 }
1840
1841 #ifdef REFACTOR_DESK_AREA
1842 EINTERN void
1843 e_comp_object_lower(E_Comp_Object *cw, Evas_Object *obj)
1844 #else
1845 static void
1846 _e_comp_object_lower(E_Comp_Object *cw, Evas_Object *obj)
1847 #endif
1848 {
1849    evas_object_lower(obj);
1850
1851    if (evas_object_smart_smart_get(obj))
1852      {
1853         E_Client *ec = e_comp_object_client_get(obj);
1854         if (ec)
1855           {
1856              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1857 #ifdef REFACTOR_DESK_AREA
1858              wl_signal_emit_mutable(&cw->events.lower_done, NULL);
1859 #else
1860              wl_signal_emit_mutable(&cw->events.lower, NULL);
1861 #endif
1862           }
1863      }
1864 }
1865
1866 #ifdef REFACTOR_DESK_AREA
1867 EINTERN void
1868 e_comp_object_stack_above(Evas_Object *obj, Evas_Object *target)
1869 #else
1870 static void
1871 _e_comp_object_stack_above(Evas_Object *obj, Evas_Object *target)
1872 #endif
1873 {
1874    evas_object_stack_above(obj, target);
1875
1876    if (evas_object_smart_smart_get(obj))
1877      {
1878         E_Client *ec = e_comp_object_client_get(obj);
1879         if (ec)
1880           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1881      }
1882 }
1883
1884 #ifdef REFACTOR_DESK_AREA
1885 EINTERN void
1886 e_comp_object_stack_below(Evas_Object *obj, Evas_Object *target)
1887 #else
1888 static void
1889 _e_comp_object_stack_below(Evas_Object *obj, Evas_Object *target)
1890 #endif
1891 {
1892    evas_object_stack_below(obj, target);
1893
1894    if (evas_object_smart_smart_get(obj))
1895      {
1896         E_Client *ec = e_comp_object_client_get(obj);
1897         if (ec)
1898           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1899      }
1900 }
1901
1902 #ifdef REFACTOR_DESK_AREA
1903 EINTERN void
1904 e_comp_object_layer_set(Evas_Object *obj, short layer)
1905 #else
1906 static void
1907 _e_comp_object_layer_set(Evas_Object *obj, short layer)
1908 #endif
1909 {
1910    evas_object_layer_set(obj, layer);
1911
1912    if (evas_object_smart_smart_get(obj))
1913      {
1914         E_Client *ec = e_comp_object_client_get(obj);
1915         if (ec)
1916           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_LAYER_SET, ec);
1917      }
1918 }
1919
1920 #ifdef REFACTOR_DESK_AREA
1921 #else
1922 static Eina_Bool
1923 _e_comp_object_is_pending(E_Client *ec)
1924 {
1925    E_Client *topmost;
1926
1927    if (!ec) return EINA_FALSE;
1928
1929    topmost = e_comp_wl_topmost_parent_get(ec);
1930
1931    return (topmost) ? topmost->layer_pending : EINA_FALSE;
1932 }
1933
1934 static void
1935 _e_comp_intercept_stack_helper(E_Comp_Object *cw, Evas_Object *stack, E_Comp_Object_Stack_Func stack_cb)
1936 {
1937    E_Comp_Object *cw2 = NULL;
1938    E_Client *ecstack;
1939    short layer;
1940    Evas_Object *o = stack;
1941 #ifdef REFACTOR_DESK_AREA
1942    Eina_Bool raising = stack_cb == e_comp_object_stack_above;
1943 #else
1944    Eina_Bool raising = stack_cb == _e_comp_object_stack_above;
1945 #endif
1946
1947    /* We should consider topmost's layer_pending for subsurface */
1948    if ((cw->ec->layer_block) || _e_comp_object_is_pending(cw->ec))
1949      {
1950         if (_e_comp_object_is_pending(cw->ec))
1951           e_comp_object_layer_update(cw->smart_obj,
1952                                      raising? stack : NULL,
1953                                      raising? NULL : stack);
1954
1955         /* obey compositor effects! */
1956         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
1957           evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
1958         stack_cb(cw->smart_obj, stack);
1959         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
1960           evas_object_data_del(cw->smart_obj, "client_restack");
1961         return;
1962      }
1963
1964    cw2 = evas_object_data_get(o, "comp_obj");
1965
1966    /* assume someone knew what they were doing during client init */
1967    if (cw->ec->new_client)
1968      layer = cw->ec->layer;
1969    else if ((cw2) && _e_comp_object_is_pending(cw2->ec))
1970      layer = cw2->ec->layer;
1971    else
1972      layer = evas_object_layer_get(stack);
1973    ecstack = e_client_below_get(cw->ec);
1974    if (layer != e_comp_canvas_layer_map_to(cw->layer))
1975      {
1976         evas_object_layer_set(cw->smart_obj, layer);
1977         /* we got our layer wrangled, return now! */
1978         if (layer != e_comp_canvas_layer_map_to(cw->layer)) return;
1979      }
1980
1981    /* check if we're stacking below another client */
1982    while (!cw2)
1983      {
1984         /* check for non-client layer object */
1985         if (!e_util_strcmp(evas_object_name_get(o), "layer_obj"))
1986           break;
1987         /* find an existing client to use for layering
1988          * by walking up the object stack
1989          *
1990          * this is guaranteed to be pretty quick since we'll either:
1991          * - run out of client layers
1992          * - find a stacking client
1993          */
1994         o = evas_object_above_get(o);
1995         if ((!o) || (o == cw->smart_obj)) break;
1996         if (evas_object_layer_get(o) != layer)
1997           {
1998              /* reached the top client layer somehow
1999               * use top client object
2000               */
2001              o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR)].obj;
2002           }
2003         if (!o)
2004           /* top client layer window hasn't been stacked yet. this probably shouldn't happen?
2005            * return here since the top client layer window
2006            */
2007           {
2008              E_Client *ec;
2009
2010              ec = e_client_top_get();
2011              if (ec)
2012                o = ec->frame;
2013              //else //wat
2014           }
2015         if (o) cw2 = evas_object_data_get(o, "comp_obj");
2016      }
2017
2018    if (cw2 && cw->layer != cw2->layer)
2019      return;
2020
2021    /* remove existing layers */
2022    _e_comp_object_layers_remove(cw);
2023    if (cw2)
2024      {
2025         if (o == stack) //if stacking above, cw2 is above; else cw2 is below
2026           _e_comp_object_layers_add(cw, raising ? cw2 : NULL, raising ? NULL : cw2, 0);
2027         else if (o == cw->smart_obj) //prepend (lower) if not stacking above
2028           _e_comp_object_layers_add(cw, NULL, NULL, !raising);
2029         else //if no stacking objects found, either raise or lower
2030           _e_comp_object_layers_add(cw, raising ? NULL : cw2, raising ? cw2 : NULL, 0);
2031      }
2032    else
2033      _e_comp_object_layers_add(cw, NULL, NULL, 0);
2034
2035    /* find new object for stacking if cw2 is on state of layer_pending */
2036    if ((cw2) && _e_comp_object_is_pending(cw2->ec))
2037      {
2038         E_Client *new_stack = NULL, *current_ec = NULL;
2039         current_ec = cw2->ec;
2040         if (raising)
2041           {
2042              while ((new_stack = e_client_below_get(current_ec)))
2043                {
2044                   current_ec = new_stack;
2045                   if (new_stack == cw->ec) continue;
2046                   if (new_stack->layer != cw2->ec->layer) break;
2047                   if (!_e_comp_object_is_pending(new_stack)) break;
2048                }
2049              if ((new_stack) && (new_stack->layer == cw2->ec->layer))
2050                stack = new_stack->frame;
2051              else
2052                {
2053                   /* stack it above layer object */
2054                   int below_layer;
2055                   below_layer = (cw2->layer <= 0)? 0 : cw2->layer - 1 ;
2056                   stack = e_comp->layers[below_layer].obj;
2057                }
2058           }
2059         else
2060           {
2061              while ((new_stack = e_client_above_get(current_ec)))
2062                {
2063                   current_ec = new_stack;
2064                   if (new_stack == cw->ec) continue;
2065                   if (new_stack->layer != cw2->ec->layer) break;
2066                   if (!_e_comp_object_is_pending(new_stack)) break;
2067                }
2068              if ((new_stack) && (new_stack->layer == cw2->ec->layer))
2069                stack = new_stack->frame;
2070              else
2071                stack = e_comp->layers[cw2->layer].obj;
2072           }
2073      }
2074
2075    /* set restack if stacking has changed */
2076    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
2077      evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
2078    stack_cb(cw->smart_obj, stack);
2079    if (e_comp->layers[cw->layer].obj)
2080      if (evas_object_below_get(cw->smart_obj) == e_comp->layers[cw->layer].obj)
2081        {
2082           CRI("STACKING ERROR!!! ec:%p (cw->layer:%d, ec->layer:%d)", cw->ec, cw->layer, cw->ec->layer);
2083        }
2084    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
2085      evas_object_data_del(cw->smart_obj, "client_restack");
2086    if (!cw->visible) return;
2087    e_comp_render_queue();
2088 }
2089 #endif
2090
2091 static void
2092 _e_comp_intercept_stack_above(void *data, Evas_Object *obj, Evas_Object *above)
2093 {
2094    EINA_SAFETY_ON_TRUE_RETURN(obj == above);
2095
2096    TRACE_DS_BEGIN(COMP:INTERCEPT STACK ABOVE);
2097
2098 #ifdef REFACTOR_DESK_AREA
2099    E_Comp_Object *cw = data;
2100    E_Comp_Object_Data_Stack_Above stack_above_data;
2101
2102    stack_above_data.cw = cw;
2103    stack_above_data.above_obj = above;
2104
2105    wl_signal_emit_mutable(&cw->events.stack_above, &stack_above_data);
2106 #else
2107    if (evas_object_below_get(obj) == above)
2108      {
2109         e_comp_object_layer_update(obj, above, NULL);
2110         return;
2111      }
2112
2113    _e_comp_intercept_stack_helper(data, above, _e_comp_object_stack_above);
2114
2115    _e_comp_object_transform_obj_stack_update(obj);
2116    _e_comp_object_transform_obj_stack_update(above);
2117 #endif
2118
2119    TRACE_DS_END();
2120 }
2121
2122 static void
2123 _e_comp_intercept_stack_below(void *data, Evas_Object *obj, Evas_Object *below)
2124 {
2125    EINA_SAFETY_ON_TRUE_RETURN(obj == below);
2126
2127    TRACE_DS_BEGIN(COMP:INTERCEPT STACK BELOW);
2128
2129 #ifdef REFACTOR_DESK_AREA
2130    E_Comp_Object *cw = data;
2131    E_Comp_Object_Data_Stack_Below stack_below_data;
2132
2133    stack_below_data.cw = cw;
2134    stack_below_data.below_obj = below;
2135
2136    wl_signal_emit_mutable(&cw->events.stack_below, &stack_below_data);
2137
2138    if (!cw->visible)
2139      e_comp_render_queue();
2140 #else
2141    if (evas_object_above_get(obj) == below)
2142      {
2143         e_comp_object_layer_update(obj, NULL, below);
2144         return;
2145      }
2146
2147    _e_comp_intercept_stack_helper(data, below, _e_comp_object_stack_below);
2148
2149    if (evas_object_smart_smart_get(obj))
2150      _e_comp_object_transform_obj_stack_update(obj);
2151    if (evas_object_smart_smart_get(below))
2152      _e_comp_object_transform_obj_stack_update(below);
2153 #endif
2154
2155    TRACE_DS_END();
2156 }
2157
2158 static void
2159 _e_comp_intercept_lower(void *data, Evas_Object *obj)
2160 {
2161    E_Comp_Object *cw = data;
2162
2163 #ifdef REFACTOR_DESK_AREA
2164 #else
2165    Evas_Object *o;
2166 #endif
2167
2168    TRACE_DS_BEGIN(COMP:INTERCEPT LOWER);
2169
2170 #ifdef REFACTOR_DESK_AREA
2171    wl_signal_emit_mutable(&cw->events.lower, cw);
2172 #else
2173    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
2174      {
2175         if (cw->ec->layer_pending)
2176           e_comp_object_layer_update(obj, NULL, obj);
2177
2178 #ifdef REFACTOR_DESK_AREA
2179         e_comp_object_lower(cw, obj);
2180 #else
2181         _e_comp_object_lower(cw, obj);
2182 #endif
2183         goto end;
2184      }
2185    if (!EINA_INLIST_GET(cw->ec)->prev) goto end; //already lowest on layer
2186    o = evas_object_below_get(obj);
2187    _e_comp_object_layers_remove(cw);
2188    /* prepend to client list since this client should be the first item now */
2189    _e_comp_object_layers_add(cw, NULL, NULL, 1);
2190    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) goto end; //already at bottom!
2191    evas_object_data_set(obj, "client_restack", (void*)1);
2192 #ifdef REFACTOR_DESK_AREA
2193    e_comp_object_lower(cw, obj);
2194 #else
2195    _e_comp_object_lower(cw, obj);
2196 #endif
2197    evas_object_data_del(obj, "client_restack");
2198    if (!cw->visible) goto end;
2199    e_comp_render_queue();
2200 #ifdef REFACTOR_DESK_AREA
2201    e_comp_object_transform_obj_stack_update(obj);
2202 #else
2203    _e_comp_object_transform_obj_stack_update(obj);
2204 #endif
2205
2206 end:
2207 #endif
2208    TRACE_DS_END();
2209 }
2210
2211 static void
2212 _e_comp_intercept_raise(void *data, Evas_Object *obj)
2213 {
2214    E_Comp_Object *cw = data;
2215 #ifdef REFACTOR_DESK_AREA
2216 #else
2217    Evas_Object *o;
2218    Evas_Object *op;
2219 #endif
2220
2221    TRACE_DS_BEGIN(COMP:INTERCEPT RAISE);
2222
2223 #ifdef REFACTOR_DESK_AREA
2224    wl_signal_emit_mutable(&cw->events.raise, cw);
2225 #else
2226    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
2227      {
2228         if (cw->ec->layer_pending)
2229           {
2230              int obj_layer = evas_object_layer_get(obj);
2231              if (cw->ec->layer != obj_layer)
2232                e_comp_object_layer_update(obj, NULL, NULL);
2233           }
2234 #ifdef REFACTOR_DESK_AREA
2235         e_comp_object_raise(obj);
2236 #else
2237         _e_comp_object_raise(obj);
2238 #endif
2239         goto end;
2240      }
2241    if (!EINA_INLIST_GET(cw->ec)->next) goto end;//already highest on layer
2242    o = evas_object_above_get(obj);
2243    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) goto end; //already at top!
2244
2245    /* still stack below override below the layer marker */
2246    for (op = o = e_comp->layers[cw->layer].obj;
2247         o && o != e_comp->layers[cw->layer - 1].obj;
2248         op = o, o = evas_object_below_get(o))
2249      {
2250         if (evas_object_smart_smart_get(o))
2251           {
2252              E_Client *ec;
2253
2254              ec = e_comp_object_client_get(o);
2255              if (ec && (!ec->override)) break;
2256           }
2257      }
2258 #ifdef REFACTOR_DESK_AREA
2259    e_comp_object_stack_below(obj, op);
2260 #else
2261    _e_comp_object_stack_below(obj, op);
2262 #endif
2263    e_client_focus_defer_set(cw->ec);
2264
2265    if (!cw->visible) goto end;
2266    e_comp_render_queue();
2267 #ifdef REFACTOR_DESK_AREA
2268    e_comp_object_transform_obj_stack_update(obj);
2269 #else
2270    _e_comp_object_transform_obj_stack_update(obj);
2271 #endif
2272
2273 end:
2274 #endif
2275    TRACE_DS_END();
2276 }
2277
2278 static void
2279 _e_comp_intercept_hide(void *data, Evas_Object *obj)
2280 {
2281    E_Comp_Object *cw = data;
2282
2283 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2284    if( !_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_HIDE, cw->ec))
2285      {
2286         ELOGF("COMP", "Hide. intercepted", cw->ec);
2287         return;
2288      }
2289 #endif
2290
2291    if (cw->ec->launching == EINA_TRUE)
2292      {
2293         ELOGF("COMP", "Hide. Cancel launching flag", cw->ec);
2294         cw->ec->launching = EINA_FALSE;
2295      }
2296
2297    if (cw->ec->hidden)
2298      {
2299         /* hidden flag = just do it */
2300         ELOGF("COMP", "Hide hidden evas_object:%p", cw->ec, obj);
2301         evas_object_hide(obj);
2302
2303         wl_signal_emit_mutable(&cw->events.hide, NULL);
2304
2305         return;
2306      }
2307
2308    if (cw->ec->input_only)
2309      {
2310         /* input_only = who cares */
2311         ELOGF("COMP", "Hide input_only evas_object:%p", cw->ec, obj);
2312         evas_object_hide(obj);
2313
2314         wl_signal_emit_mutable(&cw->events.hide, NULL);
2315
2316         return;
2317      }
2318    /* already hidden or currently animating */
2319    if ((!cw->visible) || (cw->animating && cw->hiding && (!cw->ec->iconic)))
2320      {
2321         ELOGF("COMP", "Hide. but already hidden or currently animating", cw->ec);
2322         return;
2323      }
2324
2325    /* don't try hiding during shutdown */
2326    cw->defer_hide |= stopping;
2327    if (!cw->defer_hide)
2328      {
2329         if ((!cw->ec->iconic) && (!cw->ec->override))
2330           /* unset delete requested so the client doesn't break */
2331           cw->ec->delete_requested = 0;
2332         if ((!cw->animating) || (!cw->hiding) || cw->ec->iconic)
2333           {
2334              ELOGF("COMP", "Hide. but after iconify or hide animation, cw->animating:%d, cw->hiding:%d, iconic:%d",
2335                    cw->ec, cw->animating, cw->hiding, cw->ec->iconic);
2336
2337              if (cw->ec->iconic)
2338                e_comp_object_signal_emit(obj, "e,action,iconify", "e");
2339              else
2340                {
2341                   e_comp_object_signal_emit(obj, "e,state,hidden", "e");
2342                   if (!cw->showing)
2343                     _e_comp_object_animating_begin(cw);
2344                   if (!_e_comp_object_effect_visibility_start(cw, 0)) return;
2345                }
2346              evas_object_smart_callback_call(obj, "hiding", cw->ec);
2347              cw->defer_hide = !!cw->animating;
2348              if (!cw->animating)
2349                e_comp_object_effect_set(obj, NULL);
2350           }
2351      }
2352    if (cw->animating) return;
2353    /* if we have no animations running, go ahead and hide */
2354    cw->defer_hide = 0;
2355    ELOGF("COMP", "Hide normal object:%p", cw->ec, obj);
2356    evas_object_hide(obj);
2357
2358    wl_signal_emit_mutable(&cw->events.hide, NULL);
2359 }
2360
2361 static void
2362 _e_comp_intercept_show_helper(E_Comp_Object *cw)
2363 {
2364    E_Client *ec = cw->ec;
2365    int w = 0, h = 0;
2366
2367    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
2368
2369    if (ec->show_pending.count > 0)
2370      {
2371         ELOGF("COMP", "show_helper. Show PENDING!!! show_pending:%d", ec, ec->show_pending.count);
2372         ec->show_pending.running = EINA_TRUE;
2373         return;
2374      }
2375
2376 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2377    if (!_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, ec))
2378      {
2379         ELOGF("COMP", "show_helper. intercepted", cw->ec);
2380         return;
2381      }
2382 #endif
2383
2384    ELOGF("COMP", "show_helper. cw(v:%d,a:%d,dh:%d,ct:%d,u:%p,s(%d,%d)), ec(i:%d(%d,%d),o:%d,g:%d,n:%d)", ec,
2385          cw->visible, cw->animating, cw->defer_hide, cw->content_type, cw->updates, cw->w, cw->h,
2386          ec->iconic, ec->exp_iconify.by_client, ec->exp_iconify.type, ec->input_only, ec->ignored, ec->new_client);
2387
2388    if (ec->sticky)
2389      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
2390    if (cw->visible)
2391      {
2392         if (ec->iconic && cw->animating)
2393           {
2394              /* triggered during iconify animation */
2395              e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
2396              cw->defer_hide = 0;
2397           }
2398         ELOGF("COMP", "show_helper. return. already cw->visible", ec);
2399         return;
2400      }
2401    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE ||
2402        cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE)
2403      {
2404         evas_object_move(cw->smart_obj, ec->x, ec->y);
2405         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2406         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2407
2408         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2409           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2410
2411         cw->real_hid = 0;
2412         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2413         evas_object_show(cw->smart_obj);
2414
2415         if (!ec->iconic)
2416           e_client_focus_defer_set(ec);
2417
2418         return;
2419      }
2420    if ((!cw->updates) && (!ec->input_only) && (!ec->ignored))
2421      {
2422         int pw, ph;
2423
2424         pw = ec->client.w, ph = ec->client.h;
2425         if ((!pw) || (!ph))
2426           if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
2427             {
2428                ec->changes.visible = !ec->hidden;
2429                ec->visible = 1;
2430                EC_CHANGED(ec);
2431                ELOGF("COMP", "show_helper. return. no pixmap size", ec);
2432                return;
2433             }
2434
2435         cw->updates = eina_tiler_new(pw, ph);
2436         if (!cw->updates)
2437           {
2438              ec->changes.visible = !ec->hidden;
2439              ec->visible = 1;
2440              EC_CHANGED(ec);
2441              ELOGF("COMP", "show_helper. return. no cw->updates", ec);
2442              return;
2443           }
2444      }
2445    if (cw->updates)
2446      eina_tiler_tile_size_set(cw->updates, 1, 1);
2447    if (ec->new_client)
2448      {
2449         /* ignore until client idler first run */
2450         ec->changes.visible = !ec->hidden;
2451         ec->visible = 1;
2452         EC_CHANGED(ec);
2453         ELOGF("COMP", "show_helper. return. new_client", ec);
2454         return;
2455      }
2456    if (ec->input_only)
2457      {
2458         /* who cares */
2459         cw->real_hid = 0;
2460         evas_object_move(cw->smart_obj, ec->x, ec->y);
2461         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2462         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2463         evas_object_show(cw->smart_obj);
2464         return;
2465      }
2466    if (ec->netwm.type == E_WINDOW_TYPE_DND && !e_comp_wl->drag_client)
2467      {
2468         /* start_drag not received */
2469         ec->changes.visible = 1;
2470         ec->visible = 1;
2471         EC_CHANGED(ec);
2472         ELOGF("COMP", "show_helper. return. start_drag not received yet", ec);
2473         return;
2474      }
2475    /* re-set geometry */
2476    evas_object_move(cw->smart_obj, ec->x, ec->y);
2477    /* force resize in case it hasn't happened yet, or just to update size */
2478    evas_object_resize(cw->smart_obj, ec->w, ec->h);
2479    if ((cw->w < 1) || (cw->h < 1))
2480      {
2481         /* if resize didn't go through, try again */
2482         ec->visible = ec->changes.visible = 1;
2483         EC_CHANGED(ec);
2484         ELOGF("COMP", "show_helper. return. cw_size(%d,%d)", ec, cw->w, cw->h);
2485         return;
2486      }
2487    /* if pixmap not available, clear pixmap since we're going to fetch it again */
2488    if (!e_pixmap_size_get(ec->pixmap, &w, &h))
2489      e_pixmap_clear(ec->pixmap);
2490
2491    if (cw->real_hid && w && h)
2492      {
2493         cw->real_hid = 0;
2494         /* force comp theming in case it didn't happen already */
2495         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2496         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2497           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2498      }
2499
2500    /* only do the show if show is allowed */
2501    if (!cw->real_hid)
2502      {
2503         if (ec->internal) //internal clients render when they feel like it
2504           e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2505
2506         if (!e_client_is_iconified_by_client(ec)||
2507             e_policy_visibility_client_is_uniconic(ec))
2508           {
2509              ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2510              evas_object_show(cw->smart_obj);
2511
2512              /* if comp object is shown in idle enterer before(E_CLIENT_HOOK_EVAL_FETCH),
2513                 it is rendered in idle callback without native surface and
2514                 compositor shows an empty frame if other objects aren't shown
2515                 because job callback of e_comp called at the next loop.
2516                 it causes a visual defect when windows are switched.
2517               */
2518              if (cw->redirected)
2519                {
2520                   e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2521                   e_comp_object_dirty(cw->smart_obj);
2522                   e_comp_object_render(cw->smart_obj);
2523                }
2524           }
2525      }
2526
2527    wl_signal_emit_mutable(&cw->events.show, NULL);
2528 }
2529
2530 static void
2531 _e_comp_intercept_show(void *data, Evas_Object *obj EINA_UNUSED)
2532 {
2533    E_Comp_Object *cw = data;
2534    E_Client *ec = cw->ec;
2535    Eina_List *l;
2536    E_Input_Rect_Data *input_rect_data;
2537    E_Input_Rect_Smart_Data *input_rect_sd;
2538    int tw, th;
2539
2540    if (ec->ignored) return;
2541
2542    if (cw->effect_obj)
2543      {
2544         //INF("SHOW2 %p", ec);
2545         _e_comp_intercept_show_helper(cw);
2546         return;
2547      }
2548    //INF("SHOW %p", ec);
2549    if (ec->input_only)
2550      {
2551         cw->effect_obj = evas_object_rectangle_add(e_comp->evas);
2552         evas_object_color_set(cw->effect_obj, 0, 0, 0, 0);
2553         evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
2554         evas_object_name_set(cw->effect_obj, "cw->effect_obj::input_only");
2555      }
2556    else
2557      {
2558         if ((!cw->obj) && (cw->external_content))
2559           {
2560              ERR("cw->obj for external content is not created! ec:%p", cw->ec);
2561              return;
2562           }
2563
2564         _e_comp_object_setup(cw);
2565         if (!cw->obj)
2566           {
2567              cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
2568              cw->obj = evas_object_image_filled_add(e_comp->evas);
2569              evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
2570              e_util_size_debug_set(cw->obj, 1);
2571              evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
2572              evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
2573              evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
2574              evas_object_name_set(cw->obj, "cw->obj");
2575              evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
2576           }
2577         _e_comp_object_alpha_set(cw);
2578
2579         cw->redirected = 1;
2580         evas_object_color_set(cw->clip, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity);
2581      }
2582
2583    _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
2584    evas_object_geometry_set(cw->effect_obj, cw->x, cw->y, tw, th);
2585    if (cw->input_obj)
2586      {
2587         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2588         if (input_rect_sd)
2589           {
2590              EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2591                {
2592                   if (input_rect_data->obj)
2593                     {
2594                        evas_object_geometry_set(input_rect_data->obj,
2595                          cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2596                          cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2597                          input_rect_data->rect.w, input_rect_data->rect.h);
2598                     }
2599                }
2600           }
2601      }
2602
2603    if (cw->mask.obj)
2604      evas_object_resize(cw->mask.obj, cw->w, cw->h);
2605
2606    _e_comp_intercept_show_helper(cw);
2607 }
2608
2609 static void
2610 _e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus)
2611 {
2612    E_Comp_Object *cw = data;
2613    E_Client *ec;
2614
2615    ec = cw->ec;
2616    /* note: this is here as it seems there are enough apps that do not even
2617     * expect us to emulate a look of focus but not actually set x input
2618     * focus as we do - so simply abort any focus set on such windows */
2619    /* be strict about accepting focus hint */
2620    /* be strict about accepting focus hint */
2621    if ((!ec->icccm.accepts_focus) &&
2622        (!ec->icccm.take_focus))
2623      {
2624         if (!focus)
2625           {
2626              if (e_client_focused_get() == ec)
2627                 e_client_focused_set(NULL);
2628
2629              ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2630              evas_object_focus_set(obj, focus);
2631           }
2632         return;
2633      }
2634    if (focus && ec->lock_focus_out) return;
2635    if (e_object_is_del(E_OBJECT(ec)) && focus)
2636      CRI("CAN'T FOCUS DELETED CLIENT! ec:%p", ec);
2637
2638    /* filter focus setting based on current state */
2639    if (focus)
2640      {
2641         if (ec->focused)
2642           {
2643              ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2644              evas_object_focus_set(obj, focus);
2645              return;
2646           }
2647         if ((ec->iconic) && (!ec->deskshow))
2648           {
2649              if (!e_policy_visibility_client_is_uniconify_render_running(ec))
2650                {
2651                   /* don't focus an iconified window. that's silly! */
2652                   ELOGF("FOCUS", "Do uniconify to set focus", ec);
2653                   e_client_uniconify(ec);
2654                   e_client_focus_latest_set(ec);
2655                   return;
2656                }
2657           }
2658         if (!ec->visible)
2659           {
2660              return;
2661           }
2662      }
2663
2664    if (focus)
2665      {
2666         if (!cw->visible)
2667           {
2668              /* not yet visible, wait till the next time... */
2669              ec->want_focus = !ec->hidden;
2670              if (ec->want_focus)
2671                EC_CHANGED(ec);
2672              return;
2673           }
2674         e_client_focused_set(ec);
2675      }
2676    else
2677      {
2678         if (e_client_focused_get() == ec)
2679           e_client_focused_set(NULL);
2680      }
2681
2682    if (focus)
2683      ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2684    else
2685      ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2686
2687    evas_object_focus_set(obj, focus);
2688 }
2689
2690 static void
2691 _e_comp_intercept_color_set(void *data, Evas_Object *obj, int r, int g, int b, int a)
2692 {
2693    E_Comp_Object *cw = data;
2694
2695    if (cw->transparent.set)
2696      {
2697         cw->transparent.user_r = r;
2698         cw->transparent.user_g = g;
2699         cw->transparent.user_b = b;
2700         cw->transparent.user_a = a;
2701
2702         ELOGF("COMP", "Transparent user_color(%d,%d,%d,%d)",
2703               cw->ec,
2704               cw->transparent.user_r,
2705               cw->transparent.user_g,
2706               cw->transparent.user_b,
2707               cw->transparent.user_a);
2708      }
2709    else
2710      {
2711         evas_object_color_set(obj, r, g, b, a);
2712      }
2713 }
2714 ////////////////////////////////////////////////////
2715
2716 static void
2717 _e_comp_object_frame_recalc(E_Comp_Object *cw)
2718 {
2719    int w, h, ox, oy, ow, oh;
2720    Eina_List *l;
2721    Eina_Bool pass_event_flag = EINA_FALSE;
2722    E_Input_Rect_Data *input_rect_data;
2723    E_Input_Rect_Smart_Data *input_rect_sd;
2724
2725    if (cw->frame_object)
2726      {
2727         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
2728         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
2729         /* set a fixed size, force edje calc, check size difference */
2730         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
2731         edje_object_message_signal_process(cw->frame_object);
2732         edje_object_calc_force(cw->frame_object);
2733         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
2734         cw->client_inset.l = ox;
2735         cw->client_inset.r = MAX(w, 50) - (ox + ow);
2736         cw->client_inset.t = oy;
2737         cw->client_inset.b = MAX(h, 50) - (oy + oh);
2738         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
2739         evas_object_resize(cw->frame_object, w, h);
2740
2741         if (cw->input_obj)
2742           {
2743              input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2744              if (input_rect_sd)
2745                {
2746                   EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2747                     {
2748                        if (input_rect_data->obj)
2749                          {
2750                             pass_event_flag = EINA_TRUE;
2751                             break;
2752                          }
2753                     }
2754                }
2755           }
2756         evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
2757         evas_object_pass_events_set(cw->obj, pass_event_flag);
2758      }
2759    else
2760      {
2761         cw->client_inset.l = 0;
2762         cw->client_inset.r = 0;
2763         cw->client_inset.t = 0;
2764         cw->client_inset.b = 0;
2765      }
2766    cw->client_inset.calc = !!cw->frame_object;
2767 }
2768
2769 static void
2770 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2771 {
2772    E_Comp_Object *cw = data;
2773    E_Zone *zone;
2774    int w, h, pw, ph;
2775
2776    /* - get current size
2777     * - calc new size
2778     * - readjust for new frame size
2779     */
2780
2781    w = cw->ec->w, h = cw->ec->h;
2782    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
2783
2784    _e_comp_object_frame_recalc(cw);
2785
2786    if (!cw->ec->fullscreen)
2787      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
2788
2789    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2790    if (cw->ec->fullscreen)
2791      {
2792         zone = e_comp_zone_find_by_ec(cw->ec);
2793         if (!zone) return;
2794         evas_object_resize(cw->ec->frame, zone->w, zone->h);
2795      }
2796    else if (cw->ec->new_client)
2797      {
2798         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
2799         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
2800         evas_object_resize(cw->ec->frame, w, h);
2801      }
2802    else if ((w != cw->ec->w) || (h != cw->ec->h))
2803      evas_object_resize(cw->ec->frame, w, h);
2804 }
2805
2806 static void
2807 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2808 {
2809    E_Comp_Object *cw = data;
2810
2811    _e_comp_object_shadow_setup(cw);
2812    if (cw->frame_object)
2813      {
2814         _e_comp_object_shadow(cw);
2815         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2816         _e_comp_object_frame_recalc(cw);
2817         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2818      }
2819 }
2820
2821 static void
2822 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2823 {
2824    E_Comp_Object *cw = data;
2825
2826    if (_e_comp_object_shadow_setup(cw))
2827      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2828    if (cw->frame_object)
2829      {
2830         _e_comp_object_shadow(cw);
2831         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2832         _e_comp_object_frame_recalc(cw);
2833         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2834      }
2835 }
2836
2837 static void
2838 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2839 {
2840    E_Comp_Object *cw = data;
2841
2842    if (cw->frame_object)
2843      {
2844         _e_comp_object_shadow(cw);
2845         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2846         _e_comp_object_frame_recalc(cw);
2847         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2848      }
2849 }
2850
2851 static void
2852 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2853 {
2854    E_Comp_Object *cw = data;
2855
2856    if (_e_comp_object_shadow_setup(cw))
2857      {
2858         EC_CHANGED(cw->ec);
2859         cw->ec->changes.size = 1;
2860      }
2861    if (cw->frame_object)
2862      {
2863         _e_comp_object_shadow(cw);
2864         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
2865         _e_comp_object_frame_recalc(cw);
2866         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2867      }
2868 }
2869
2870 static void
2871 _e_comp_smart_cb_sticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2872 {
2873    e_comp_object_signal_emit(obj, "e,state,sticky", "e");
2874 }
2875
2876 static void
2877 _e_comp_smart_cb_unsticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2878 {
2879    e_comp_object_signal_emit(obj, "e,state,unsticky", "e");
2880 }
2881
2882 static void
2883 _e_comp_smart_cb_unhung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2884 {
2885    E_Comp_Object *cw = data;
2886
2887    if (!cw->ec) return; //NYI
2888    e_comp_object_signal_emit(cw->smart_obj, "e,state,unhung", "e");
2889 }
2890
2891 static void
2892 _e_comp_smart_cb_hung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2893 {
2894    E_Comp_Object *cw = data;
2895
2896    if (!cw->ec) return; //NYI
2897    e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
2898 }
2899
2900 static void
2901 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2902 {
2903    e_comp_object_signal_emit(obj, "e,state,focused", "e");
2904 }
2905
2906 static void
2907 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2908 {
2909    E_Comp_Object *cw = data;
2910
2911    if (!e_object_is_del(E_OBJECT(cw->ec)))
2912      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
2913 }
2914
2915 static void
2916 _e_comp_input_obj_smart_add(Evas_Object *obj)
2917 {
2918    E_Input_Rect_Smart_Data *input_rect_sd;
2919    input_rect_sd = E_NEW(E_Input_Rect_Smart_Data, 1);
2920
2921    if (!input_rect_sd) return;
2922    evas_object_smart_data_set(obj, input_rect_sd);
2923 }
2924
2925 static void
2926 _e_comp_input_obj_smart_del(Evas_Object *obj)
2927 {
2928    E_Input_Rect_Smart_Data *input_rect_sd;
2929    E_Input_Rect_Data *input_rect_data;
2930
2931    input_rect_sd = evas_object_smart_data_get(obj);
2932    if (!input_rect_sd) return;
2933
2934    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
2935      {
2936         if (input_rect_data->obj)
2937           {
2938              evas_object_smart_member_del(input_rect_data->obj);
2939              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
2940           }
2941         E_FREE(input_rect_data);
2942      }
2943    E_FREE(input_rect_sd);
2944 }
2945
2946 static void
2947 _e_comp_input_obj_smart_move(Evas_Object *obj, int x, int y)
2948 {
2949    E_Input_Rect_Smart_Data *input_rect_sd;
2950    E_Input_Rect_Data *input_rect_data;
2951    Eina_List *l;
2952    E_Comp_Object *cw;
2953
2954    input_rect_sd = evas_object_smart_data_get(obj);
2955    if (!input_rect_sd) return;
2956
2957    cw = input_rect_sd->cw;
2958    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2959      {
2960         if (input_rect_data->obj)
2961           {
2962              evas_object_geometry_set(input_rect_data->obj,
2963                x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2964                y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2965                input_rect_data->rect.w, input_rect_data->rect.h);
2966           }
2967      }
2968 }
2969
2970 static void
2971 _e_comp_input_obj_smart_resize(Evas_Object *obj, int w, int h)
2972 {
2973    E_Input_Rect_Smart_Data *input_rect_sd;
2974    E_Input_Rect_Data *input_rect_data;
2975    Eina_List *l;
2976    E_Comp_Object *cw;
2977
2978    input_rect_sd = evas_object_smart_data_get(obj);
2979    if (!input_rect_sd) return;
2980
2981    cw = input_rect_sd->cw;
2982    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2983      {
2984         if (input_rect_data->obj)
2985           {
2986              evas_object_geometry_set(input_rect_data->obj,
2987                cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2988                cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2989                input_rect_data->rect.w, input_rect_data->rect.h);
2990           }
2991      }
2992 }
2993
2994 static void
2995 _e_comp_input_obj_smart_show(Evas_Object *obj)
2996 {
2997    E_Input_Rect_Smart_Data *input_rect_sd;
2998    E_Input_Rect_Data *input_rect_data;
2999    Eina_List *l;
3000
3001    input_rect_sd = evas_object_smart_data_get(obj);
3002    if (!input_rect_sd) return;
3003
3004    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3005      {
3006         if (input_rect_data->obj)
3007           {
3008              evas_object_show(input_rect_data->obj);
3009           }
3010      }
3011 }
3012
3013 static void
3014 _e_comp_input_obj_smart_hide(Evas_Object *obj)
3015 {
3016    E_Input_Rect_Smart_Data *input_rect_sd;
3017    E_Input_Rect_Data *input_rect_data;
3018    Eina_List *l;
3019
3020    input_rect_sd = evas_object_smart_data_get(obj);
3021    if (!input_rect_sd) return;
3022
3023    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3024      {
3025         if (input_rect_data->obj)
3026           {
3027              evas_object_hide(input_rect_data->obj);
3028           }
3029      }
3030 }
3031
3032 static void
3033 _e_comp_input_obj_smart_init(void)
3034 {
3035    if (_e_comp_input_obj_smart) return;
3036    {
3037       static const Evas_Smart_Class sc =
3038       {
3039          INPUT_OBJ_SMART_NAME,
3040          EVAS_SMART_CLASS_VERSION,
3041          _e_comp_input_obj_smart_add,
3042          _e_comp_input_obj_smart_del,
3043          _e_comp_input_obj_smart_move,
3044          _e_comp_input_obj_smart_resize,
3045          _e_comp_input_obj_smart_show,
3046          _e_comp_input_obj_smart_hide,
3047          NULL,
3048          NULL,
3049          NULL,
3050          NULL,
3051          NULL,
3052          NULL,
3053
3054          NULL,
3055          NULL,
3056          NULL,
3057          NULL
3058       };
3059       _e_comp_input_obj_smart = evas_smart_class_new(&sc);
3060    }
3061 }
3062
3063
3064 static void
3065 _e_comp_smart_add(Evas_Object *obj)
3066 {
3067    E_Comp_Object *cw;
3068
3069    cw = E_NEW(E_Comp_Object, 1);
3070    EINA_SAFETY_ON_NULL_RETURN(cw);
3071
3072    wl_signal_init(&cw->events.lower);
3073 #ifdef REFACTOR_DESK_AREA
3074    wl_signal_init(&cw->events.lower_done);
3075    wl_signal_init(&cw->events.raise);
3076 #endif
3077    wl_signal_init(&cw->events.show);
3078    wl_signal_init(&cw->events.hide);
3079 #ifdef REFACTOR_DESK_AREA
3080    wl_signal_init(&cw->events.set_layer);
3081    wl_signal_init(&cw->events.stack_above);
3082    wl_signal_init(&cw->events.stack_below);
3083 #endif
3084    wl_signal_init(&cw->events.image_filter_set);
3085    wl_signal_init(&cw->events.render_op_set);
3086    wl_signal_init(&cw->events.content_type_set);
3087
3088    cw->smart_obj = obj;
3089    cw->x = cw->y = cw->w = cw->h = -1;
3090    evas_object_smart_data_set(obj, cw);
3091    cw->opacity = 255.0;
3092    cw->external_content = 0;
3093    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
3094    cw->transform_bg_color.r = 0;
3095    cw->transform_bg_color.g = 0;
3096    cw->transform_bg_color.b = 0;
3097    cw->transform_bg_color.a = 255;
3098    evas_object_data_set(obj, "comp_obj", cw);
3099    evas_object_move(obj, -1, -1);
3100    /* intercept ALL the callbacks! */
3101    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
3102    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
3103    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
3104    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
3105    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
3106    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
3107    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
3108    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
3109    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
3110    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
3111    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_color_set, cw);
3112
3113    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
3114    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
3115    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
3116    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
3117
3118    evas_object_smart_callback_add(obj, "stick", _e_comp_smart_cb_sticky, cw);
3119    evas_object_smart_callback_add(obj, "unstick", _e_comp_smart_cb_unsticky, cw);
3120
3121    evas_object_smart_callback_add(obj, "hung", _e_comp_smart_cb_hung, cw);
3122    evas_object_smart_callback_add(obj, "unhung", _e_comp_smart_cb_unhung, cw);
3123
3124    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
3125
3126    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
3127    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
3128 }
3129
3130 static void
3131 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3132 {
3133    INTERNAL_ENTRY;
3134    evas_object_color_set(cw->clip, r, g, b, a);
3135    evas_object_smart_callback_call(obj, "color_set", NULL);
3136 }
3137
3138
3139 static void
3140 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3141 {
3142    INTERNAL_ENTRY;
3143    evas_object_clip_set(cw->clip, clip);
3144 }
3145
3146 static void
3147 _e_comp_smart_clip_unset(Evas_Object *obj)
3148 {
3149    INTERNAL_ENTRY;
3150    evas_object_clip_unset(cw->clip);
3151 }
3152
3153 static void
3154 _e_comp_smart_hide(Evas_Object *obj)
3155 {
3156    TRACE_DS_BEGIN(COMP:SMART HIDE);
3157
3158    INTERNAL_ENTRY;
3159    cw->visible = 0;
3160    cw->hiding = 0;
3161    evas_object_hide(cw->clip);
3162    if (cw->input_obj) evas_object_hide(cw->input_obj);
3163    evas_object_hide(cw->effect_obj);
3164    if (cw->default_input_obj) evas_object_hide(cw->default_input_obj);
3165    if (cw->transform_bg_obj) evas_object_hide(cw->transform_bg_obj);
3166    if (cw->transform_tranp_obj) evas_object_hide(cw->transform_tranp_obj);
3167    if (stopping)
3168      {
3169         TRACE_DS_END();
3170         return;
3171      }
3172
3173    /* unset native surface if current displaying buffer was destroied */
3174    if (!cw->buffer_destroy_listener.notify)
3175      {
3176         Evas_Native_Surface *ns;
3177         ns = evas_object_image_native_surface_get(cw->obj);
3178         if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
3179           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
3180      }
3181
3182    if (!cw->ec->input_only)
3183      {
3184         edje_object_freeze(cw->effect_obj);
3185         edje_object_freeze(cw->shobj);
3186         edje_object_play_set(cw->shobj, 0);
3187         if (cw->frame_object)
3188           edje_object_play_set(cw->frame_object, 0);
3189      }
3190
3191    e_comp_render_queue(); //force nocomp recheck
3192
3193    TRACE_DS_END();
3194 }
3195
3196 static void
3197 _e_comp_smart_show(Evas_Object *obj)
3198 {
3199    E_Client *tmp;
3200    Eina_List *l;
3201
3202    INTERNAL_ENTRY;
3203    cw->defer_hide = 0;
3204    cw->visible = 1;
3205    if ((cw->w < 0) || (cw->h < 0))
3206      CRI("ACK! ec:%p", cw->ec);
3207
3208    TRACE_DS_BEGIN(COMP:SMART SHOW);
3209
3210    e_comp_object_map_update(obj);
3211
3212    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
3213      evas_object_show(tmp->frame);
3214
3215    evas_object_show(cw->clip);
3216    if (cw->input_obj) evas_object_show(cw->input_obj);
3217    if (!cw->ec->input_only)
3218      {
3219         edje_object_thaw(cw->effect_obj);
3220         edje_object_thaw(cw->shobj);
3221         edje_object_play_set(cw->shobj, 1);
3222         if (cw->frame_object)
3223           edje_object_play_set(cw->frame_object, 1);
3224      }
3225    evas_object_show(cw->effect_obj);
3226    if (cw->mask.obj) evas_object_show(cw->mask.obj);
3227    if (cw->transform_bg_obj) evas_object_show(cw->transform_bg_obj);
3228    if (cw->transform_tranp_obj) evas_object_show(cw->transform_tranp_obj);
3229    if (cw->default_input_obj) evas_object_show(cw->default_input_obj);
3230    e_comp_render_queue();
3231    if (cw->ec->input_only)
3232      {
3233         TRACE_DS_END();
3234         return;
3235      }
3236    if (cw->ec->iconic && (!cw->ec->new_client))
3237      {
3238         if (e_client_is_iconified_by_client(cw->ec))
3239           {
3240              ELOGF("COMP", "Set launching flag..", cw->ec);
3241              cw->ec->launching = EINA_TRUE;
3242           }
3243
3244         e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
3245      }
3246    else if (!cw->showing) /* if set, client was ec->hidden during show animation */
3247      {
3248         cw->showing = 1;
3249         ELOGF("COMP", "Set launching flag..", cw->ec);
3250         cw->ec->launching = EINA_TRUE;
3251
3252         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
3253         _e_comp_object_animating_begin(cw);
3254         if (!_e_comp_object_effect_visibility_start(cw, 1))
3255           {
3256              TRACE_DS_END();
3257              return;
3258           }
3259      }
3260    /* ensure some random effect doesn't lock the client offscreen */
3261    if (!cw->animating)
3262      {
3263         cw->showing = 0;
3264         e_comp_object_effect_set(obj, NULL);
3265      }
3266
3267    _e_comp_object_dim_update(cw);
3268
3269    TRACE_DS_END();
3270 }
3271
3272 static void
3273 _e_comp_smart_del(Evas_Object *obj)
3274 {
3275    Eina_List *l;
3276
3277    INTERNAL_ENTRY;
3278
3279    if (cw->buffer_destroy_listener.notify)
3280      {
3281         wl_list_remove(&cw->buffer_destroy_listener.link);
3282         cw->buffer_destroy_listener.notify = NULL;
3283      }
3284
3285    if (cw->tbm_surface)
3286      {
3287         tbm_surface_internal_unref(cw->tbm_surface);
3288         cw->tbm_surface = NULL;
3289      }
3290
3291    if (cw->render_update_lock.buffer_ref.buffer)
3292      {
3293         ELOGF("COMP", "Clear buffer_ref of render_update_lock:%d",
3294               cw->ec, cw->render_update_lock.lock);
3295         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
3296      }
3297
3298    e_comp_object_render_update_del(cw->smart_obj);
3299    E_FREE_FUNC(cw->updates, eina_tiler_free);
3300    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
3301    free(cw->ns);
3302
3303    if (cw->obj_mirror)
3304      {
3305         Evas_Object *o;
3306
3307         EINA_LIST_FREE(cw->obj_mirror, o)
3308           {
3309              evas_object_image_data_set(o, NULL);
3310              evas_object_freeze_events_set(o, 1);
3311              evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
3312              evas_object_del(o);
3313           }
3314      }
3315 #ifdef REFACTOR_DESK_AREA
3316 #else
3317    _e_comp_object_layers_remove(cw);
3318 #endif
3319    l = evas_object_data_get(obj, "comp_object-to_del");
3320    E_FREE_LIST(l, evas_object_del);
3321    _e_comp_object_mouse_event_callback_unset(cw);
3322    evas_object_del(cw->clip);
3323    evas_object_del(cw->obj);
3324    evas_object_del(cw->shobj);
3325    evas_object_del(cw->effect_obj);
3326    evas_object_del(cw->frame_object);
3327    evas_object_del(cw->input_obj);
3328    evas_object_del(cw->mask.obj);
3329    if (cw->dim.mask_obj) evas_object_del(cw->dim.mask_obj);
3330    evas_object_del(cw->transform_bg_obj);
3331    evas_object_del(cw->transform_tranp_obj);
3332    evas_object_del(cw->default_input_obj);
3333    eina_stringshare_del(cw->frame_theme);
3334    eina_stringshare_del(cw->frame_name);
3335    if (cw->animating)
3336      {
3337         cw->animating = 0;
3338         e_comp->animating--;
3339         UNREFD(cw->ec, 2);
3340         e_object_unref(E_OBJECT(cw->ec));
3341      }
3342    cw->ec->frame = NULL;
3343    free(cw);
3344 }
3345
3346 static void
3347 _e_comp_smart_move(Evas_Object *obj, int x, int y)
3348 {
3349    INTERNAL_ENTRY;
3350
3351    cw->x = x, cw->y = y;
3352    evas_object_move(cw->effect_obj, x, y);
3353    evas_object_move(cw->default_input_obj, x, y);
3354    if (cw->input_obj) evas_object_move(cw->input_obj, x, y);
3355
3356    e_comp_object_map_update(obj);
3357 }
3358
3359 static void
3360 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
3361 {
3362    Eina_Bool first = EINA_FALSE;
3363    int tw, th;
3364
3365    INTERNAL_ENTRY;
3366
3367    if (!cw->effect_obj) CRI("ACK! ec:%p", cw->ec);
3368
3369    TRACE_DS_BEGIN(COMP:SMART RESIZE);
3370
3371    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
3372
3373    if (cw->w != w || cw->h != h)
3374      e_comp_object_map_update(obj);
3375
3376    first = ((cw->w < 1) || (cw->h < 1));
3377    cw->w = w, cw->h = h;
3378
3379    int ww, hh, pw, ph;
3380
3381    if (cw->frame_object)
3382      e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
3383    else
3384      ww = w, hh = h;
3385    /* verify pixmap:object size */
3386    if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
3387      {
3388         if ((ww != pw) || (hh != ph))
3389           ELOGF("COMP", "CW RSZ: %dx%d || PX: %dx%d.", cw->ec, ww, hh, pw, ph);
3390      }
3391    evas_object_resize(cw->effect_obj, tw, th);
3392    evas_object_resize(cw->default_input_obj, w, h);
3393    if (cw->input_obj)
3394      evas_object_resize(cw->input_obj, w, h);
3395    if (cw->mask.obj)
3396      evas_object_resize(cw->mask.obj, w, h);
3397    /* resize render update tiler */
3398    if (!first)
3399      {
3400         RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
3401         cw->updates_full = 0;
3402         if (cw->updates) eina_tiler_clear(cw->updates);
3403      }
3404    else
3405      {
3406         RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3407         if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3408      }
3409
3410    if (!cw->visible)
3411      {
3412         TRACE_DS_END();
3413         return;
3414      }
3415    e_comp_render_queue();
3416
3417    TRACE_DS_END();
3418 }
3419
3420 static void
3421 _e_comp_smart_init(void)
3422 {
3423    if (_e_comp_smart) return;
3424    {
3425       static const Evas_Smart_Class sc =
3426       {
3427          SMART_NAME,
3428          EVAS_SMART_CLASS_VERSION,
3429          _e_comp_smart_add,
3430          _e_comp_smart_del,
3431          _e_comp_smart_move,
3432          _e_comp_smart_resize,
3433          _e_comp_smart_show,
3434          _e_comp_smart_hide,
3435          _e_comp_smart_color_set,
3436          _e_comp_smart_clip_set,
3437          _e_comp_smart_clip_unset,
3438          NULL,
3439          NULL,
3440          NULL,
3441
3442          NULL,
3443          NULL,
3444          NULL,
3445          NULL
3446       };
3447       _e_comp_smart = evas_smart_class_new(&sc);
3448    }
3449 }
3450
3451 EINTERN void
3452 e_comp_object_init(void)
3453 {
3454    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
3455    E_EVENT_COMP_OBJECT_IMG_RENDER = ecore_event_type_new();
3456    E_EVENT_COMP_OBJECT_EFFECT_START = ecore_event_type_new();
3457    E_EVENT_COMP_OBJECT_EFFECT_END = ecore_event_type_new();
3458 }
3459
3460 EINTERN void
3461 e_comp_object_shutdown(void)
3462 {
3463
3464 }
3465
3466 EINTERN Eina_Bool
3467 e_comp_object_mirror_visibility_check(Evas_Object *obj)
3468 {
3469    API_ENTRY EINA_FALSE;
3470    return !!cw->force_visible;
3471 }
3472 /////////////////////////////////////////////////////////
3473
3474 static void
3475 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3476 {
3477    Eina_List *l;
3478    Eina_Bool comp_object;
3479
3480    comp_object = !!evas_object_data_get(obj, "comp_object");
3481    if (comp_object)
3482      {
3483         Evas_Object *o;
3484
3485         o = edje_object_part_swallow_get(obj, "e.swallow.content");
3486         evas_object_del(o);
3487         e_comp_render_queue();
3488      }
3489    l = evas_object_data_get(obj, "comp_object-to_del");
3490    E_FREE_LIST(l, evas_object_del);
3491 }
3492
3493 static void
3494 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3495 {
3496    if (e_comp_util_object_is_above_nocomp(obj) &&
3497        (!evas_object_data_get(obj, "comp_override")))
3498      {
3499         evas_object_data_set(obj, "comp_override", (void*)1);
3500         e_comp_override_add();
3501      }
3502 }
3503
3504 static void
3505 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
3506 {
3507    Eina_Bool ref = EINA_TRUE;
3508    if (evas_object_visible_get(obj))
3509      {
3510         void *d;
3511
3512         d = evas_object_data_del(obj, "comp_hiding");
3513         if (d)
3514           /* currently trying to hide */
3515           ref = EINA_FALSE;
3516         else
3517           /* already visible */
3518           return;
3519      }
3520
3521    evas_object_show(obj);
3522    if (ref)
3523      {
3524         evas_object_ref(obj);
3525         evas_object_data_set(obj, "comp_ref", (void*)1);
3526      }
3527    edje_object_signal_emit(obj, "e,state,visible", "e");
3528    evas_object_data_set(obj, "comp_showing", (void*)1);
3529    if (e_comp_util_object_is_above_nocomp(obj))
3530      {
3531         evas_object_data_set(obj, "comp_override", (void*)1);
3532         e_comp_override_add();
3533      }
3534 }
3535
3536 static void
3537 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
3538 {
3539    if (!evas_object_visible_get(obj)) return;
3540    /* already hiding */
3541    if (evas_object_data_get(obj, "comp_hiding")) return;
3542    if (!evas_object_data_del(obj, "comp_showing"))
3543      {
3544         evas_object_ref(obj);
3545         evas_object_data_set(obj, "comp_ref", (void*)1);
3546      }
3547    edje_object_signal_emit(obj, "e,state,hidden", "e");
3548    evas_object_data_set(obj, "comp_hiding", (void*)1);
3549
3550    if (evas_object_data_del(obj, "comp_override"))
3551      e_comp_override_timed_pop();
3552 }
3553
3554 static void
3555 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
3556 {
3557    if (!e_util_strcmp(emission, "e,action,hide,done"))
3558      {
3559         if (!evas_object_data_del(obj, "comp_hiding")) return;
3560         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
3561         evas_object_hide(obj);
3562         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
3563      }
3564    else
3565      evas_object_data_del(obj, "comp_showing");
3566    if (evas_object_data_del(obj, "comp_ref"))
3567      evas_object_unref(obj);
3568 }
3569
3570 static void
3571 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3572 {
3573    if (data)
3574      {
3575         int w, h;
3576
3577         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3578      }
3579 }
3580
3581 E_API E_Comp_Object_Hook *
3582 e_comp_object_hook_add(E_Comp_Object_Hook_Point hookpoint, E_Comp_Object_Hook_Cb func, const void *data)
3583 {
3584    E_Comp_Object_Hook *ch;
3585
3586    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_HOOK_LAST, NULL);
3587    ch = E_NEW(E_Comp_Object_Hook, 1);
3588    if (!ch) return NULL;
3589    ch->hookpoint = hookpoint;
3590    ch->func = func;
3591    ch->data = (void*)data;
3592    _e_comp_object_hooks[hookpoint] = eina_inlist_append(_e_comp_object_hooks[hookpoint], EINA_INLIST_GET(ch));
3593    return ch;
3594 }
3595
3596 E_API void
3597 e_comp_object_hook_del(E_Comp_Object_Hook *ch)
3598 {
3599    ch->delete_me = 1;
3600    if (_e_comp_object_hooks_walking == 0)
3601      {
3602         _e_comp_object_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3603         free(ch);
3604      }
3605    else
3606      _e_comp_object_hooks_delete++;
3607 }
3608
3609 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
3610 E_API E_Comp_Object_Intercept_Hook *
3611 e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data)
3612 {
3613    E_Comp_Object_Intercept_Hook *ch;
3614
3615    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_INTERCEPT_HOOK_LAST, NULL);
3616    ch = E_NEW(E_Comp_Object_Intercept_Hook, 1);
3617    if (!ch) return NULL;
3618    ch->hookpoint = hookpoint;
3619    ch->func = func;
3620    ch->data = (void*)data;
3621    _e_comp_object_intercept_hooks[hookpoint] = eina_inlist_append(_e_comp_object_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3622    return ch;
3623 }
3624
3625 E_API void
3626 e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch)
3627 {
3628    ch->delete_me = 1;
3629    if (_e_comp_object_intercept_hooks_walking == 0)
3630      {
3631         _e_comp_object_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3632         free(ch);
3633      }
3634    else
3635      _e_comp_object_intercept_hooks_delete++;
3636 }
3637 #endif
3638
3639 E_API Evas_Object *
3640 e_comp_object_util_add(Evas_Object *obj)
3641 {
3642    Evas_Object *o;
3643    const char *name;
3644    E_Comp_Config *conf = e_comp_config_get();
3645    Eina_Bool skip = EINA_FALSE;
3646    char buf[1024];
3647    int ok = 0;
3648    int x, y, w, h;
3649    Eina_Bool vis;
3650
3651    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
3652
3653    name = evas_object_name_get(obj);
3654    vis = evas_object_visible_get(obj);
3655    o = edje_object_add(e_comp->evas);
3656    evas_object_data_set(o, "comp_object", (void*)1);
3657    if (name)
3658      skip = (!strncmp(name, "noshadow", 8));
3659    if (skip)
3660      evas_object_data_set(o, "comp_object_skip", (void*)1);
3661
3662    if (conf->shadow_style)
3663      {
3664         snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
3665         ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3666      }
3667    if (!ok)
3668      e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default");
3669    if (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow")))
3670      edje_object_signal_emit(o, "e,state,shadow,on", "e");
3671    else
3672      edje_object_signal_emit(o, "e,state,shadow,off", "e");
3673
3674    evas_object_geometry_get(obj, &x, &y, &w, &h);
3675    evas_object_geometry_set(o, x, y, w, h);
3676    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
3677
3678    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, NULL);
3679
3680    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, NULL);
3681    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, NULL);
3682    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, NULL);
3683    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3684    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, NULL);
3685    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, NULL);
3686
3687    e_comp_object_signal_emit(o, "e,state,hidden", "e");
3688
3689    edje_object_part_swallow(o, "e.swallow.content", obj);
3690
3691    _e_comp_object_event_add(o);
3692
3693    if (vis)
3694      evas_object_show(o);
3695
3696    return o;
3697 }
3698
3699 /* utility functions for deleting objects when their "owner" is deleted */
3700 EINTERN void
3701 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
3702 {
3703    Eina_List *l;
3704
3705    SOFT_ENTRY();
3706    EINA_SAFETY_ON_NULL_RETURN(to_del);
3707    l = evas_object_data_get(obj, "comp_object-to_del");
3708    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
3709    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
3710    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3711 }
3712
3713 EINTERN void
3714 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3715 {
3716    Eina_List *l;
3717
3718    SOFT_ENTRY();
3719    EINA_SAFETY_ON_NULL_RETURN(to_del);
3720    l = evas_object_data_get(obj, "comp_object-to_del");
3721    if (l)
3722      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3723 }
3724
3725 /////////////////////////////////////////////////////////
3726
3727 EINTERN Evas_Object *
3728 e_comp_object_client_add(E_Client *ec)
3729 {
3730    Evas_Object *o;
3731    E_Comp_Object *cw;
3732
3733    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3734    if (ec->frame) return NULL;
3735    _e_comp_smart_init();
3736    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3737    cw = evas_object_smart_data_get(o);
3738    if (!cw) return NULL;
3739    evas_object_data_set(o, "E_Client", ec);
3740    cw->ec = ec;
3741    ec->frame = o;
3742    evas_object_data_set(o, "comp_object", (void*)1);
3743
3744    _e_comp_object_event_add(o);
3745
3746    return o;
3747 }
3748
3749 /* utility functions for getting client inset */
3750 E_API void
3751 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3752 {
3753    API_ENTRY;
3754    if (!cw->client_inset.calc)
3755      {
3756         if (ax) *ax = x;
3757         if (ay) *ay = y;
3758         return;
3759      }
3760    if (ax) *ax = x - cw->client_inset.l;
3761    if (ay) *ay = y - cw->client_inset.t;
3762 }
3763
3764 E_API void
3765 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3766 {
3767    API_ENTRY;
3768    if (!cw->client_inset.calc)
3769      {
3770         if (ax) *ax = x;
3771         if (ay) *ay = y;
3772         return;
3773      }
3774    if (ax) *ax = x + cw->client_inset.l;
3775    if (ay) *ay = y + cw->client_inset.t;
3776 }
3777
3778 E_API void
3779 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3780 {
3781    API_ENTRY;
3782    if (!cw->client_inset.calc)
3783      {
3784         if (aw) *aw = w;
3785         if (ah) *ah = h;
3786         return;
3787      }
3788    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
3789    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
3790 }
3791
3792 E_API void
3793 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3794 {
3795    API_ENTRY;
3796    if (!cw->client_inset.calc)
3797      {
3798         if (aw) *aw = w;
3799         if (ah) *ah = h;
3800         return;
3801      }
3802    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
3803    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
3804 }
3805
3806 E_API E_Client *
3807 e_comp_object_client_get(Evas_Object *obj)
3808 {
3809    Evas_Object *o;
3810
3811    SOFT_ENTRY(NULL);
3812    /* FIXME: remove this when eo is used */
3813    o = evas_object_data_get(obj, "comp_smart_obj");
3814    if (o)
3815      return e_comp_object_client_get(o);
3816    return cw ? cw->ec : NULL;
3817 }
3818
3819 EINTERN void
3820 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3821 {
3822    API_ENTRY;
3823    if (cw->frame_extends)
3824      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
3825    else
3826      {
3827         if (x) *x = 0;
3828         if (y) *y = 0;
3829         if (w) *w  = cw->ec->w;
3830         if (h) *h  = cw->ec->h;
3831      }
3832 }
3833
3834 EINTERN E_Zone *
3835 e_comp_object_util_zone_get(Evas_Object *obj)
3836 {
3837    E_Zone *zone = NULL;
3838
3839    SOFT_ENTRY(NULL);
3840    if (cw)
3841      zone = e_comp_zone_find_by_ec(cw->ec);
3842    if (!zone)
3843      {
3844         int x, y;
3845
3846         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3847         zone = e_comp_zone_xy_get(x, y);
3848      }
3849    return zone;
3850 }
3851
3852 EINTERN void
3853 e_comp_object_util_center(Evas_Object *obj)
3854 {
3855    int x, y, w, h, ow, oh;
3856    E_Zone *zone;
3857
3858    SOFT_ENTRY();
3859
3860    zone = e_comp_object_util_zone_get(obj);
3861    EINA_SAFETY_ON_NULL_RETURN(zone);
3862    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
3863    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3864      ow = cw->ec->w, oh = cw->ec->h;
3865    else
3866      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3867    x = x + (w - ow) / 2;
3868    y = y + (h - oh) / 2;
3869    evas_object_move(obj, x, y);
3870 }
3871
3872 EINTERN void
3873 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
3874 {
3875    int x, y, w, h, ow, oh;
3876
3877    SOFT_ENTRY();
3878    EINA_SAFETY_ON_NULL_RETURN(on);
3879    evas_object_geometry_get(on, &x, &y, &w, &h);
3880    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3881      ow = cw->ec->w, oh = cw->ec->h;
3882    else
3883      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3884    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
3885 }
3886
3887 EINTERN void
3888 e_comp_object_util_fullscreen(Evas_Object *obj)
3889 {
3890    SOFT_ENTRY();
3891
3892    if (cw)
3893      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
3894    else
3895      {
3896         evas_object_move(obj, 0, 0);
3897         evas_object_resize(obj, e_comp->w, e_comp->h);
3898      }
3899 }
3900
3901 EINTERN void
3902 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
3903 {
3904    E_Zone *zone;
3905    int zx, zy, zw, zh;
3906    int ow, oh;
3907    SOFT_ENTRY();
3908
3909    if (cw)
3910      ow = cw->w, oh = cw->h;
3911    else
3912      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3913    zone = e_comp_object_util_zone_get(obj);
3914    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
3915    if (x) *x = zx + (zw - ow) / 2;
3916    if (y) *y = zy + (zh - oh) / 2;
3917 }
3918
3919 EINTERN void
3920 e_comp_object_input_objs_del(Evas_Object *obj)
3921 {
3922    API_ENTRY;
3923    E_Input_Rect_Data *input_rect_data;
3924    E_Input_Rect_Smart_Data *input_rect_sd;
3925
3926    if (!cw->input_obj)
3927      return;
3928
3929    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
3930    if (!input_rect_sd) return;
3931
3932    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
3933      {
3934         if (input_rect_data->obj)
3935           {
3936              evas_object_smart_member_del(input_rect_data->obj);
3937              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
3938           }
3939         E_FREE(input_rect_data);
3940      }
3941 }
3942
3943 E_API void
3944 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
3945 {
3946    API_ENTRY;
3947    E_Input_Rect_Data *input_rect_data = NULL;
3948    E_Input_Rect_Smart_Data *input_rect_sd;
3949    int client_w, client_h;
3950
3951    if (cw->ec->client.w)
3952      client_w = cw->ec->client.w;
3953    else
3954      client_w = cw->ec->w;
3955
3956    if (cw->ec->client.h)
3957      client_h = cw->ec->client.h;
3958    else
3959      client_h = cw->ec->h;
3960
3961    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
3962
3963    if (!cw->input_obj)
3964      {
3965         _e_comp_input_obj_smart_init();
3966         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
3967         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
3968         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
3969
3970         if (input_rect_sd)
3971           input_rect_sd->cw = cw;
3972      }
3973
3974    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
3975    if (input_rect_sd)
3976      {
3977         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
3978         if (input_rect_data)
3979           {
3980              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
3981              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
3982           }
3983      }
3984
3985    if ((input_rect_data) &&
3986        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
3987      {
3988         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
3989         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
3990         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
3991         evas_object_clip_set(input_rect_data->obj, cw->clip);
3992         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
3993         evas_object_geometry_set(input_rect_data->obj,
3994           cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l) + x,
3995           cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t) + y, w, h);
3996         evas_object_pass_events_set(cw->default_input_obj, 1);
3997         evas_object_pass_events_set(cw->obj, 1);
3998         if (cw->visible)
3999           {
4000              evas_object_show(input_rect_data->obj);
4001              evas_object_show(cw->input_obj);
4002           }
4003      }
4004    else
4005      {
4006         evas_object_smart_member_del(cw->input_obj);
4007         E_FREE_FUNC(cw->input_obj, evas_object_del);
4008         evas_object_pass_events_set(cw->default_input_obj, 0);
4009         evas_object_pass_events_set(cw->obj, 0);
4010      }
4011 }
4012
4013 E_API void
4014 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4015 {
4016    API_ENTRY;
4017    E_Input_Rect_Smart_Data *input_rect_sd;
4018    E_Input_Rect_Data *input_rect_data;
4019    Eina_List *l;
4020
4021    if (!cw->input_obj) return;
4022
4023    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4024    if (input_rect_sd)
4025      {
4026         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4027           {
4028              *list = eina_list_append(*list, &input_rect_data->rect);
4029           }
4030      }
4031 }
4032
4033 EINTERN void
4034 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4035 {
4036    API_ENTRY;
4037    if (l) *l = cw->client_inset.l;
4038    if (r) *r = cw->client_inset.r;
4039    if (t) *t = cw->client_inset.t;
4040    if (b) *b = cw->client_inset.b;
4041 }
4042
4043 /* set geometry for CSD */
4044 EINTERN void
4045 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4046 {
4047    Eina_Bool calc;
4048    int tx, ty, tw, th;
4049
4050    API_ENTRY;
4051    if (cw->frame_object)
4052      CRI("ACK! ec:%p", cw->ec);
4053    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4054        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4055    calc = cw->client_inset.calc;
4056    cw->client_inset.calc = l || r || t || b;
4057    eina_stringshare_replace(&cw->frame_theme, "borderless");
4058    if (cw->client_inset.calc)
4059      {
4060         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4061         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4062         e_client_size_set(cw->ec, tw, th);
4063      }
4064    else if (cw->ec->maximized || cw->ec->fullscreen)
4065      {
4066         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4067         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4068      }
4069    if (!cw->ec->new_client)
4070      {
4071         if (calc && cw->client_inset.calc)
4072           {
4073              tx = cw->ec->x - (l - cw->client_inset.l);
4074              ty = cw->ec->y - (t - cw->client_inset.t);
4075              e_client_pos_set(cw->ec, tx, ty);
4076           }
4077         cw->ec->changes.pos = cw->ec->changes.size = 1;
4078         EC_CHANGED(cw->ec);
4079      }
4080    cw->client_inset.l = l;
4081    cw->client_inset.r = r;
4082    cw->client_inset.t = t;
4083    cw->client_inset.b = b;
4084 }
4085
4086 EINTERN Eina_Bool
4087 e_comp_object_frame_allowed(Evas_Object *obj)
4088 {
4089    API_ENTRY EINA_FALSE;
4090    return (cw->frame_object || (!cw->client_inset.calc));
4091 }
4092
4093 EINTERN Eina_Bool
4094 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
4095 {
4096    API_ENTRY EINA_FALSE;
4097    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4098    eina_stringshare_replace(&cw->frame_name, name);
4099    if (cw->frame_object)
4100      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4101    return EINA_TRUE;
4102 }
4103
4104 EINTERN Eina_Bool
4105 e_comp_object_frame_exists(Evas_Object *obj)
4106 {
4107    API_ENTRY EINA_FALSE;
4108    return !!cw->frame_object;
4109 }
4110
4111 EINTERN Eina_Bool
4112 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4113 {
4114    Evas_Object *o, *pbg;
4115    char buf[4096];
4116    int ok;
4117    Eina_Stringshare *theme;
4118
4119    API_ENTRY EINA_FALSE;
4120
4121    if (!e_util_strcmp(cw->frame_theme, name))
4122     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4123    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4124      return _e_comp_object_shadow_setup(cw);
4125    pbg = cw->frame_object;
4126    theme = eina_stringshare_add(name);
4127
4128    if (cw->frame_object)
4129      {
4130         int w, h;
4131
4132         w = cw->ec->w, h = cw->ec->h;
4133         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4134         if ((cw->ec->w != w) || (cw->ec->h != h))
4135           {
4136              cw->ec->changes.size = 1;
4137              EC_CHANGED(cw->ec);
4138           }
4139         E_FREE_FUNC(cw->frame_object, evas_object_del);
4140         if (!name) goto reshadow;
4141      }
4142    o = edje_object_add(e_comp->evas);
4143    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4144    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4145    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4146      {
4147         cw->frame_object = NULL;
4148         evas_object_del(o);
4149         eina_stringshare_del(cw->frame_theme);
4150         cw->frame_theme = theme;
4151         goto reshadow;
4152      }
4153    if (!ok)
4154      {
4155         if (theme != e_config->theme_default_border_style)
4156           {
4157              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4158              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4159           }
4160         if (!ok)
4161           {
4162              ok = e_theme_edje_object_set(o, "base/theme/border",
4163                                           "e/widgets/border/default/border");
4164              if (ok && (theme == e_config->theme_default_border_style))
4165                {
4166                   /* Reset default border style to default */
4167                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4168                   e_config_save_queue();
4169                }
4170           }
4171      }
4172
4173    if (ok)
4174      {
4175         cw->frame_object = o;
4176         eina_stringshare_del(cw->frame_theme);
4177         cw->frame_theme = theme;
4178         evas_object_name_set(o, "cw->frame_object");
4179
4180         if (cw->frame_name)
4181           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4182
4183         if (!pbg)
4184           {
4185              cw->ec->changes.icon = 1;
4186              EC_CHANGED(cw->ec);
4187           }
4188      }
4189    else
4190      {
4191         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4192         evas_object_del(o);
4193      }
4194 reshadow:
4195    if (cw->shobj)
4196      _e_comp_object_shadow_setup(cw);
4197    do
4198      {
4199         int old_x, old_y, new_x = 0, new_y = 0;
4200
4201         old_x = cw->x, old_y = cw->y;
4202
4203         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4204         if (pbg)
4205           new_x = cw->ec->x, new_y = cw->ec->y;
4206         else if (cw->ec->placed || (!cw->ec->new_client))
4207           {
4208              /* if no previous frame:
4209               * - reapply client_inset
4210               * - clamp to zone
4211               */
4212              int x, y;
4213
4214              if (cw->ec->changes.size)
4215                {
4216                   x = cw->ec->x;
4217                   y = cw->ec->y;
4218                }
4219              else
4220                {
4221                   E_Zone *zone;
4222                   zone = e_comp_zone_find_by_ec(cw->ec);
4223                   if (!zone) break;
4224
4225                   x = cw->ec->client.x, y = cw->ec->client.y;
4226                   x = MAX(zone->x, cw->ec->client.x - cw->client_inset.l);
4227                   y = MAX(zone->y, cw->ec->client.y - cw->client_inset.t);
4228                }
4229              new_x = x, new_y = y;
4230           }
4231
4232         if (old_x != new_x || old_y != new_y)
4233           {
4234              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4235              cw->y = cw->x = -99999;
4236              evas_object_move(obj, new_x, new_y);
4237           }
4238      } while (0);
4239
4240    if (cw->ec->maximized)
4241      {
4242         cw->ec->changes.need_maximize = 1;
4243         EC_CHANGED(cw->ec);
4244      }
4245    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4246    if (cw->frame_object)
4247      {
4248         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4249      }
4250    else
4251      cw->frame_extends = 0;
4252    evas_object_del(pbg);
4253    return EINA_TRUE;
4254 }
4255
4256 E_API void
4257 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4258 {
4259    E_Comp_Object_Mover *prov;
4260
4261    API_ENTRY;
4262    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4263    edje_object_signal_emit(cw->shobj, sig, src);
4264    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4265    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4266        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4267      return;
4268    /* start with highest priority callback first */
4269    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4270      {
4271         if (!e_util_glob_match(sig, prov->sig)) continue;
4272         if (prov->func(prov->data, obj, sig)) break;
4273      }
4274 }
4275
4276 E_API void
4277 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4278 {
4279    /* FIXME: at some point I guess this should use eo to inherit
4280     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4281     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4282     */
4283    API_ENTRY;
4284    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4285 }
4286
4287 E_API void
4288 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4289 {
4290    API_ENTRY;
4291    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4292 }
4293
4294 E_API void
4295 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4296 {
4297    API_ENTRY;
4298    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4299 }
4300
4301 E_API void
4302 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4303 {
4304    int tw, th;
4305    Eina_Rectangle rect;
4306    API_ENTRY;
4307
4308    if (cw->ec->input_only || (!cw->updates)) return;
4309    if (cw->nocomp) return;
4310    rect.x = x, rect.y = y;
4311    rect.w = w, rect.h = h;
4312    evas_object_smart_callback_call(obj, "damage", &rect);
4313
4314    if (e_comp_is_on_overlay(cw->ec))
4315      {
4316         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4317         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4318         * E module attempts to block screen update due to the particular policy.
4319         */
4320         if (e_pixmap_resource_get(cw->ec->pixmap))
4321           cw->hwc_need_update = EINA_TRUE;
4322      }
4323
4324    /* ignore overdraw */
4325    if (cw->updates_full)
4326      {
4327         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4328         e_comp_object_render_update_add(obj);
4329
4330         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4331           evas_object_show(cw->smart_obj);
4332
4333         return;
4334      }
4335    /* clip rect to client surface */
4336    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4337    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4338    /* if rect is the total size of the client after clip, clear the updates
4339     * since this is guaranteed to be the whole region anyway
4340     */
4341    eina_tiler_area_size_get(cw->updates, &tw, &th);
4342    if ((w > tw) || (h > th))
4343      {
4344         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4345         eina_tiler_clear(cw->updates);
4346         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4347         x = 0, y = 0;
4348         tw = cw->ec->client.w, th = cw->ec->client.h;
4349      }
4350    if ((!x) && (!y) && (w == tw) && (h == th))
4351      {
4352         eina_tiler_clear(cw->updates);
4353         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4354         cw->updates_full = 1;
4355         cw->update_count = 0;
4356      }
4357    cw->update_count++;
4358    if (cw->update_count > UPDATE_MAX)
4359      {
4360         /* this is going to get really dumb, so just update the whole thing */
4361         eina_tiler_clear(cw->updates);
4362         cw->update_count = cw->updates_full = 1;
4363         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4364         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4365      }
4366    else
4367      {
4368         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4369         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4370      }
4371    cw->updates_exist = 1;
4372    e_comp_object_render_update_add(obj);
4373
4374    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4375      evas_object_show(cw->smart_obj);
4376 }
4377
4378 EINTERN Eina_Bool
4379 e_comp_object_damage_exists(Evas_Object *obj)
4380 {
4381    API_ENTRY EINA_FALSE;
4382    return cw->updates_exist;
4383 }
4384
4385 EINTERN void
4386 e_comp_object_render_update_add(Evas_Object *obj)
4387 {
4388    API_ENTRY;
4389
4390    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4391    if (cw->render_update_lock.lock) return;
4392    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4393    if (!cw->update)
4394      {
4395         cw->update = 1;
4396         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4397      }
4398    e_comp_render_queue();
4399 }
4400
4401 EINTERN void
4402 e_comp_object_render_update_del(Evas_Object *obj)
4403 {
4404    API_ENTRY;
4405
4406    if (cw->ec->input_only || (!cw->updates)) return;
4407    if (!cw->update) return;
4408    cw->update = 0;
4409    /* this gets called during comp animating to clear the update flag */
4410    if (e_comp->grabbed) return;
4411    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4412    if (!e_comp->updates)
4413      {
4414         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4415         if (e_comp->render_animator)
4416           ecore_animator_freeze(e_comp->render_animator);
4417      }
4418 }
4419
4420 EINTERN void
4421 e_comp_object_shape_apply(Evas_Object *obj)
4422 {
4423    Eina_List *l;
4424    Evas_Object *o;
4425    unsigned int i, *pix, *p;
4426    int w, h, px, py;
4427
4428    API_ENTRY;
4429    if (!cw->ec) return; //NYI
4430    if (cw->external_content) return;
4431    if (cw->ec->shaped)
4432      {
4433         if ((cw->ec->shape_rects_num >= 1) &&
4434             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4435            return;
4436      }
4437    if (cw->native)
4438      {
4439         ERR("BUGGER: shape with native surface? cw=%p", cw);
4440         return;
4441      }
4442    evas_object_image_size_get(cw->obj, &w, &h);
4443    if ((w < 1) || (h < 1)) return;
4444
4445    if (cw->ec->shaped)
4446      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4447    _e_comp_object_alpha_set(cw);
4448    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4449       evas_object_image_alpha_set(o, 1);
4450
4451    p = pix = evas_object_image_data_get(cw->obj, 1);
4452    if (!pix)
4453      {
4454         evas_object_image_data_set(cw->obj, pix);
4455         return;
4456      }
4457    if (cw->ec->shaped)
4458      {
4459         unsigned char *spix, *sp;
4460
4461         spix = calloc(w * h, sizeof(unsigned char));
4462         if (!spix) return;
4463         for (i = 0; i < cw->ec->shape_rects_num; i++)
4464           {
4465              int rx, ry, rw, rh;
4466
4467              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4468              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4469              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4470              sp = spix + (w * ry) + rx;
4471              for (py = 0; py < rh; py++)
4472                {
4473                   for (px = 0; px < rw; px++)
4474                     {
4475                        *sp = 0xff; sp++;
4476                     }
4477                   sp += w - rw;
4478                }
4479           }
4480         sp = spix;
4481         for (py = 0; py < h; py++)
4482           {
4483              for (px = 0; px < w; px++)
4484                {
4485                   unsigned int mask, imask;
4486
4487                   mask = ((unsigned int)(*sp)) << 24;
4488                   imask = mask >> 8;
4489                   imask |= imask >> 8;
4490                   imask |= imask >> 8;
4491                   *p = mask | (*p & imask);
4492                   //if (*sp) *p = 0xff000000 | *p;
4493                   //else *p = 0x00000000;
4494                   sp++;
4495                   p++;
4496                }
4497           }
4498         free(spix);
4499      }
4500    else
4501       {
4502          for (py = 0; py < h; py++)
4503            {
4504               for (px = 0; px < w; px++)
4505                 *p |= 0xff000000;
4506            }
4507       }
4508    evas_object_image_data_set(cw->obj, pix);
4509    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4510    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4511      {
4512         evas_object_image_data_set(o, pix);
4513         evas_object_image_data_update_add(o, 0, 0, w, h);
4514      }
4515 // don't need to fix alpha chanel as blending
4516 // should be totally off here regardless of
4517 // alpha channel content
4518 }
4519
4520 static void
4521 _e_comp_object_clear(E_Comp_Object *cw)
4522 {
4523    Eina_List *l;
4524    Evas_Object *o;
4525
4526    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4527
4528    if (cw->render_update_lock.lock) return;
4529
4530    if (cw->ec->pixmap)
4531      e_pixmap_clear(cw->ec->pixmap);
4532    if (cw->native)
4533      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4534    evas_object_image_size_set(cw->obj, 1, 1);
4535    evas_object_image_data_set(cw->obj, NULL);
4536    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4537      {
4538         evas_object_image_size_set(o, 1, 1);
4539         evas_object_image_data_set(o, NULL);
4540      }
4541    cw->native = 0;
4542    e_comp_object_render_update_del(cw->smart_obj);
4543 }
4544
4545 static Eina_Bool
4546 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4547 {
4548     int r, g, b, a;
4549
4550     API_ENTRY EINA_FALSE;
4551
4552     if (cw->transparent.set == set)
4553        return EINA_TRUE;
4554
4555     if (set)
4556       {
4557          evas_object_color_get(obj, &r, &g, &b, &a);
4558          evas_object_color_set(obj, 0, 0, 0, 0);
4559
4560          cw->transparent.user_r = r;
4561          cw->transparent.user_g = g;
4562          cw->transparent.user_b = b;
4563          cw->transparent.user_a = a;
4564
4565          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4566                cw->ec,
4567                cw->transparent.user_r,
4568                cw->transparent.user_g,
4569                cw->transparent.user_b,
4570                cw->transparent.user_a);
4571
4572          cw->transparent.set = EINA_TRUE;
4573       }
4574     else
4575       {
4576          cw->transparent.set = EINA_FALSE;
4577
4578          evas_object_color_set(obj,
4579                                cw->transparent.user_r,
4580                                cw->transparent.user_g,
4581                                cw->transparent.user_b,
4582                                cw->transparent.user_a);
4583
4584          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4585                cw->ec,
4586                cw->transparent.user_r,
4587                cw->transparent.user_g,
4588                cw->transparent.user_b,
4589                cw->transparent.user_a);
4590       }
4591
4592    return EINA_TRUE;
4593 }
4594
4595 /* helper function to simplify toggling of redirection for display servers which support it */
4596 EINTERN void
4597 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4598 {
4599    API_ENTRY;
4600
4601    set = !!set;
4602    if (cw->redirected == set) return;
4603    cw->redirected = set;
4604    if (cw->external_content) return;
4605
4606    e_comp_object_map_update(obj);
4607
4608    if (set)
4609      {
4610         if (cw->updates_exist)
4611           e_comp_object_render_update_add(obj);
4612         else
4613           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4614
4615         _e_comp_object_transparent_set(obj, EINA_FALSE);
4616         evas_object_smart_callback_call(obj, "redirected", NULL);
4617      }
4618    else
4619      {
4620         _e_comp_object_clear(cw);
4621         _e_comp_object_transparent_set(obj, EINA_TRUE);
4622         evas_object_smart_callback_call(obj, "unredirected", NULL);
4623      }
4624 }
4625
4626 static void
4627 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4628 {
4629    E_Comp_Object *cw;
4630    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4631
4632    if (cw->buffer_destroy_listener.notify)
4633      {
4634         cw->buffer_destroy_listener.notify = NULL;
4635         wl_list_remove(&cw->buffer_destroy_listener.link);
4636      }
4637
4638    if (e_object_is_del(E_OBJECT(cw->ec)))
4639      {
4640         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4641           return;
4642      }
4643    else
4644      {
4645         /* if it's current displaying buffer, do not remove its content */
4646         if (!evas_object_visible_get(cw->ec->frame))
4647           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4648      }
4649 }
4650
4651 static void
4652 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4653 {
4654    Eina_List *l;
4655    Evas_Object *o;
4656
4657    if (cw->buffer_destroy_listener.notify)
4658      {
4659         wl_list_remove(&cw->buffer_destroy_listener.link);
4660         cw->buffer_destroy_listener.notify = NULL;
4661      }
4662
4663    if (cw->tbm_surface)
4664      {
4665         tbm_surface_internal_unref(cw->tbm_surface);
4666         cw->tbm_surface = NULL;
4667      }
4668
4669    if (ns)
4670      {
4671         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4672           {
4673              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4674              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4675           }
4676         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4677           {
4678              tbm_surface_internal_ref(ns->data.tbm.buffer);
4679              cw->tbm_surface = ns->data.tbm.buffer;
4680           }
4681      }
4682
4683    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4684    evas_object_image_native_surface_set(cw->obj, ns);
4685    TRACE_DS_END();
4686    if (with_mirror)
4687      {
4688         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4689           {
4690              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4691              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4692              evas_object_image_native_surface_set(o, ns);
4693              TRACE_DS_END();
4694           }
4695      }
4696 }
4697
4698 EINTERN void
4699 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4700 {
4701    Evas_Native_Surface ns;
4702
4703    API_ENTRY;
4704    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4705    if (cw->ec->input_only) return;
4706    if (cw->external_content) return;
4707    if (cw->render_update_lock.lock) return;
4708    set = !!set;
4709
4710    memset(&ns, 0, sizeof(Evas_Native_Surface));
4711
4712    if (set)
4713      {
4714         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4715         set = (!cw->ec->shaped);
4716         if (set)
4717           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4718      }
4719    cw->native = set;
4720
4721    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4722 }
4723
4724 EINTERN void
4725 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4726 {
4727    API_ENTRY;
4728    if (cw->ec->input_only) return;
4729    E_FREE(cw->ns);
4730    if (ns)
4731      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4732    _e_comp_object_alpha_set(cw);
4733    if (cw->native)
4734      e_comp_object_native_surface_set(obj, cw->native);
4735    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4736 }
4737
4738 EINTERN void
4739 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4740 {
4741    API_ENTRY;
4742
4743    set = !!set;
4744
4745    if (cw->blanked == set) return;
4746    cw->blanked = set;
4747    _e_comp_object_alpha_set(cw);
4748    if (set)
4749      {
4750         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4751         evas_object_image_data_set(cw->obj, NULL);
4752         return;
4753      }
4754    if (cw->native)
4755      e_comp_object_native_surface_set(obj, 1);
4756    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4757 }
4758
4759 static void
4760 _e_comp_object_damage_trace_rect_set(Evas_Object *obj, Eina_Rectangle *origin, int dmg_x, int dmg_y, int dmg_w, int dmg_h)
4761 {
4762    Evas_Object *o;
4763    int obj_x, obj_y;
4764
4765    if (!_damage_trace) return;
4766
4767    API_ENTRY;
4768
4769    if (!evas_object_visible_get(cw->obj)) return;
4770
4771    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
4772
4773    o = evas_object_rectangle_add(e_comp->evas);
4774    evas_object_layer_set(o, E_LAYER_MAX);
4775    evas_object_name_set(o, "damage_trace");
4776    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
4777    evas_object_resize(o, dmg_w, dmg_h);
4778    evas_object_color_set(o, 0, 128, 0, 128);
4779    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
4780    evas_object_pass_events_set(o, EINA_TRUE);
4781    evas_object_show(o);
4782
4783    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
4784          cw->ec,
4785          dmg_w, dmg_h, dmg_x, dmg_y,
4786          origin->w, origin->h, origin->x, origin->y);
4787
4788    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
4789 }
4790
4791 /* mark an object as dirty and setup damages */
4792 E_API void
4793 e_comp_object_dirty(Evas_Object *obj)
4794 {
4795    Eina_Iterator *it;
4796    Eina_Rectangle *rect;
4797    Eina_List *ll;
4798    Evas_Object *o;
4799    int w, h, tw, th;
4800    Eina_Bool dirty, visible;
4801    E_Map *m = NULL;
4802
4803    API_ENTRY;
4804    if (cw->external_content) return;
4805    if (!cw->redirected) return;
4806    if (cw->render_update_lock.lock)
4807      {
4808         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4809         return;
4810      }
4811    /* only actually dirty if pixmap is available */
4812    if (!e_pixmap_resource_get(cw->ec->pixmap))
4813      {
4814         // e_pixmap_size_get returns last attached buffer size
4815         // eventhough it is destroyed
4816         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
4817         return;
4818      }
4819    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4820    visible = cw->visible;
4821    if (!dirty) w = h = 1;
4822    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4823    if (!dirty)
4824      evas_object_image_data_set(cw->obj, NULL);
4825    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4826    evas_object_image_size_set(cw->obj, tw, th);
4827    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
4828    if (cw->pending_updates)
4829      eina_tiler_area_size_set(cw->pending_updates, w, h);
4830    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4831      {
4832         evas_object_image_pixels_dirty_set(o, dirty);
4833         if (!dirty)
4834           evas_object_image_data_set(o, NULL);
4835         evas_object_image_size_set(o, tw, th);
4836         visible |= evas_object_visible_get(o);
4837      }
4838    if (!dirty)
4839      {
4840         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4841         return;
4842      }
4843
4844    e_comp_object_native_surface_set(obj, 1);
4845
4846    m = _e_comp_object_map_damage_transform_get(cw->ec);
4847    it = eina_tiler_iterator_new(cw->updates);
4848    EINA_ITERATOR_FOREACH(it, rect)
4849      {
4850         /* evas converts damage according to rotation of ecore_evas in damage_region_set
4851          * of evas engine and doesn't convert damage according to evas_map.
4852          * so damage of evas_object_image use surface coordinate.
4853          */
4854         if (m)
4855           {
4856              int damage_x, damage_y, damage_w, damage_h;
4857
4858              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
4859                                                       &damage_x, &damage_y, &damage_w, &damage_h);
4860              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
4861              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
4862           }
4863         else
4864           {
4865              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4866              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
4867           }
4868
4869         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4870           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4871         if (cw->pending_updates)
4872           eina_tiler_rect_add(cw->pending_updates, rect);
4873      }
4874    eina_iterator_free(it);
4875    if (m) e_map_free(m);
4876    if (cw->pending_updates)
4877      eina_tiler_clear(cw->updates);
4878    else
4879      {
4880         cw->pending_updates = cw->updates;
4881         cw->updates = eina_tiler_new(w, h);
4882         eina_tiler_tile_size_set(cw->updates, 1, 1);
4883      }
4884    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4885    evas_object_smart_callback_call(obj, "dirty", NULL);
4886    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4887    /* force render if main object is hidden but mirrors are visible */
4888    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4889    e_comp_object_render(obj);
4890 }
4891
4892 E_API Eina_Bool
4893 e_comp_object_render(Evas_Object *obj)
4894 {
4895    Eina_List *l;
4896    Evas_Object *o;
4897    int pw, ph;
4898    unsigned int *pix;
4899
4900    API_ENTRY EINA_FALSE;
4901
4902    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
4903    if (cw->ec->input_only) return EINA_TRUE;
4904    if (cw->external_content) return EINA_TRUE;
4905    if (cw->native) return EINA_FALSE;
4906    /* if comp object is not redirected state, comp object should not be set by newly committed data
4907       because image size of comp object is 1x1 and it should not be shown on canvas */
4908    if (!cw->redirected) return EINA_TRUE;
4909    if (cw->render_update_lock.lock)
4910      {
4911         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4912         return EINA_TRUE;
4913      }
4914    e_comp_object_render_update_del(obj);
4915    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
4916
4917    if (!cw->pending_updates)
4918      {
4919         WRN("RENDER [%p]: NO RECTS!", cw->ec);
4920         evas_object_image_data_set(cw->obj, NULL);
4921         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4922           evas_object_image_data_set(o, NULL);
4923         return EINA_FALSE;
4924      }
4925
4926    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
4927
4928    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
4929
4930    pix = e_pixmap_image_data_get(cw->ec->pixmap);
4931    if (!pix)
4932      {
4933         e_pixmap_image_refresh(cw->ec->pixmap);
4934         pix = e_pixmap_image_data_get(cw->ec->pixmap);
4935      }
4936
4937    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
4938      e_pixmap_image_data_ref(cw->ec->pixmap);
4939
4940    /* set pixel data */
4941    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
4942    _e_comp_object_alpha_set(cw);
4943    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4944      {
4945         evas_object_image_data_set(o, pix);
4946         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
4947         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
4948      }
4949
4950    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
4951
4952    e_comp_client_post_update_add(cw->ec);
4953
4954    return EINA_TRUE;
4955 }
4956
4957 /* create a duplicate of an evas object */
4958 E_API Evas_Object *
4959 e_comp_object_util_mirror_add(Evas_Object *obj)
4960 {
4961    Evas_Object *o;
4962    int w, h, tw, th;
4963    unsigned int *pix = NULL;
4964    Eina_Bool argb = EINA_FALSE;
4965
4966    SOFT_ENTRY(NULL);
4967
4968    if (!cw)
4969      cw = evas_object_data_get(obj, "comp_mirror");
4970    if (!cw)
4971      {
4972         o = evas_object_image_filled_add(evas_object_evas_get(obj));
4973         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
4974         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
4975         evas_object_image_alpha_set(o, 1);
4976         evas_object_image_source_set(o, obj);
4977         return o;
4978      }
4979    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
4980    if (cw->external_content)
4981      {
4982         ERR("%p of client %p is external content.", obj, cw->ec);
4983         return NULL;
4984      }
4985    o = evas_object_image_filled_add(evas_object_evas_get(obj));
4986    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
4987    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
4988    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
4989    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
4990    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
4991    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
4992    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
4993    evas_object_data_set(o, "comp_mirror", cw);
4994
4995    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
4996    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4997
4998    evas_object_image_size_set(o, tw, th);
4999
5000    if (cw->ec->shaped)
5001      pix = evas_object_image_data_get(cw->obj, 0);
5002    else
5003      {
5004         if (cw->native)
5005           {
5006              if (cw->ns)
5007                evas_object_image_native_surface_set(o, cw->ns);
5008              else
5009                {
5010                   Evas_Native_Surface ns;
5011                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5012                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5013                     evas_object_image_native_surface_set(o, &ns);
5014                }
5015           }
5016         else
5017           {
5018              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5019              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5020              if ((argb) &&
5021                  (e_pixmap_image_exists(cw->ec->pixmap)))
5022                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5023              else
5024                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5025           }
5026      }
5027    if (pix)
5028      {
5029       Eina_Bool dirty;
5030
5031       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5032       evas_object_image_pixels_dirty_set(o, dirty);
5033       evas_object_image_data_set(o, pix);
5034       evas_object_image_data_set(cw->obj, pix);
5035       if (dirty)
5036         evas_object_image_data_update_add(o, 0, 0, tw, th);
5037    }
5038    return o;
5039 }
5040
5041 //////////////////////////////////////////////////////
5042
5043 EINTERN Eina_Bool
5044 e_comp_object_effect_allowed_get(Evas_Object *obj)
5045 {
5046    API_ENTRY EINA_FALSE;
5047
5048    if (!cw->shobj) return EINA_FALSE;
5049    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5050    return !e_comp_config_get()->match.disable_borders;
5051 }
5052
5053 /* setup an api effect for a client */
5054 E_API Eina_Bool
5055 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5056 {
5057    char buf[4096];
5058    Eina_Stringshare *grp;
5059    E_Comp_Config *config;
5060    Eina_Bool loaded = EINA_FALSE;
5061
5062    API_ENTRY EINA_FALSE;
5063    if (!cw->shobj) return EINA_FALSE; //input window
5064
5065    if (!effect) effect = "none";
5066    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5067
5068    config = e_comp_config_get();
5069    if ((config) && (config->effect_file))
5070      {
5071         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5072           {
5073              cw->effect_set = EINA_TRUE;
5074              loaded = EINA_TRUE;
5075           }
5076      }
5077
5078    if (!loaded)
5079      {
5080         edje_object_file_get(cw->effect_obj, NULL, &grp);
5081         cw->effect_set = !eina_streq(effect, "none");
5082         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5083         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5084           {
5085              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5086              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5087                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5088                  {
5089                     if (cw->effect_running)
5090                       {
5091                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5092                            return EINA_FALSE;
5093                       }
5094                     cw->effect_set = EINA_FALSE;
5095                     return cw->effect_set;
5096                  }
5097           }
5098      }
5099    if (cw->effect_running)
5100      {
5101         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5102           return EINA_FALSE;
5103      }
5104    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5105    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5106    if (cw->effect_clip)
5107      {
5108         evas_object_clip_unset(cw->clip);
5109         cw->effect_clip = 0;
5110      }
5111    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5112
5113    _e_comp_object_dim_update(cw);
5114
5115    return cw->effect_set;
5116 }
5117
5118 /* set params for embryo scripts in effect */
5119 E_API void
5120 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5121 {
5122    Edje_Message_Int_Set *msg;
5123    unsigned int x;
5124
5125    API_ENTRY;
5126    EINA_SAFETY_ON_NULL_RETURN(params);
5127    EINA_SAFETY_ON_FALSE_RETURN(count);
5128    if (!cw->effect_set) return;
5129
5130    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5131    msg->count = (int)count;
5132    for (x = 0; x < count; x++)
5133       msg->val[x] = params[x];
5134    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5135    edje_object_message_signal_process(cw->effect_obj);
5136 }
5137
5138 static void
5139 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5140 {
5141    Edje_Signal_Cb end_cb;
5142    void *end_data;
5143    E_Comp_Object *cw = data;
5144
5145    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5146    cw->effect_running = 0;
5147    if (!_e_comp_object_animating_end(cw)) return;
5148
5149    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5150      {
5151         evas_object_data_del(cw->smart_obj, "effect_running");
5152         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5153         e_comp_visibility_calculation_set(EINA_TRUE);
5154      }
5155
5156    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5157    if (!end_cb) return;
5158    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5159    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5160    end_cb(end_data, cw->smart_obj, emission, source);
5161 }
5162
5163 /* clip effect to client's zone */
5164 EINTERN void
5165 e_comp_object_effect_clip(Evas_Object *obj)
5166 {
5167    API_ENTRY;
5168    E_Zone *zone;
5169    zone = e_comp_zone_find_by_ec(cw->ec);
5170    if (!zone) return;
5171    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5172    if (!cw->effect_clip_able) return;
5173    evas_object_clip_set(cw->smart_obj, zone->bg_clip_object);
5174    cw->effect_clip = 1;
5175 }
5176
5177 /* unclip effect from client's zone */
5178 EINTERN void
5179 e_comp_object_effect_unclip(Evas_Object *obj)
5180 {
5181    API_ENTRY;
5182    if (!cw->effect_clip) return;
5183    evas_object_clip_unset(cw->smart_obj);
5184    cw->effect_clip = 0;
5185 }
5186
5187 /* start effect, running end_cb after */
5188 E_API Eina_Bool
5189 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5190 {
5191    API_ENTRY EINA_FALSE;
5192    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5193    if (!cw->effect_set) return EINA_FALSE;
5194
5195    if (cw->effect_running)
5196      {
5197         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5198      }
5199
5200    e_comp_object_effect_clip(obj);
5201    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5202
5203    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5204    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5205    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5206    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5207
5208    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5209    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5210
5211    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5212    _e_comp_object_animating_begin(cw);
5213    cw->effect_running = 1;
5214    return EINA_TRUE;
5215 }
5216
5217 /* stop a currently-running effect immediately */
5218 E_API Eina_Bool
5219 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5220 {
5221    int ret = 0;
5222    Edje_Signal_Cb end_cb_before = NULL;
5223    void *end_data_before = NULL;
5224    API_ENTRY EINA_FALSE;
5225
5226    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5227    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5228
5229    if (end_cb_before != end_cb) return EINA_TRUE;
5230    e_comp_object_effect_unclip(obj);
5231    if (cw->effect_clip)
5232      {
5233         evas_object_clip_unset(cw->effect_obj);
5234         cw->effect_clip = 0;
5235      }
5236    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5237    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5238
5239    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5240      {
5241         evas_object_data_del(cw->smart_obj, "effect_running");
5242         e_comp_visibility_calculation_set(EINA_TRUE);
5243      }
5244
5245    cw->effect_running = 0;
5246    ret = _e_comp_object_animating_end(cw);
5247
5248    if ((ret) && (end_cb_before))
5249      {
5250         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5251         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5252      }
5253
5254    return ret;
5255 }
5256
5257 static int
5258 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5259 {
5260    return a->pri - b->pri;
5261 }
5262
5263 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5264 E_API E_Comp_Object_Mover *
5265 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5266 {
5267    E_Comp_Object_Mover *prov;
5268
5269    prov = E_NEW(E_Comp_Object_Mover, 1);
5270    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5271    prov->func = provider;
5272    prov->data = (void*)data;
5273    prov->pri = pri;
5274    prov->sig = sig;
5275    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5276      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5277    return prov;
5278 }
5279
5280 E_API void
5281 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5282 {
5283    EINA_SAFETY_ON_NULL_RETURN(prov);
5284    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5285    free(prov);
5286 }
5287
5288 E_API Evas_Object *
5289 e_comp_object_effect_object_get(Evas_Object *obj)
5290 {
5291    API_ENTRY NULL;
5292
5293    return cw->effect_obj;
5294 }
5295
5296 E_API Eina_Bool
5297 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5298 {
5299    API_ENTRY EINA_FALSE;
5300    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5301    if (!cw->effect_set) return EINA_FALSE;
5302
5303    cw->hiding = set;
5304
5305    return EINA_TRUE;
5306 }
5307
5308 ////////////////////////////////////
5309
5310 static void
5311 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5312 {
5313    if (e_comp->autoclose.obj)
5314      {
5315         e_comp_ungrab_input(0, 1);
5316         if (e_comp->autoclose.del_cb)
5317           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5318         else if (!already_del)
5319           {
5320              evas_object_hide(e_comp->autoclose.obj);
5321              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5322           }
5323         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5324      }
5325    e_comp->autoclose.obj = NULL;
5326    e_comp->autoclose.data = NULL;
5327    e_comp->autoclose.del_cb = NULL;
5328    e_comp->autoclose.key_cb = NULL;
5329    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5330 }
5331
5332 static void
5333 _e_comp_object_autoclose_mouse_up_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
5334 {
5335    _e_comp_object_autoclose_cleanup(0);
5336 }
5337
5338 static void
5339 _e_comp_object_autoclose_setup(Evas_Object *obj)
5340 {
5341    if (!e_comp->autoclose.rect)
5342      {
5343         /* create rect just below autoclose object to catch mouse events */
5344         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5345         evas_object_move(e_comp->autoclose.rect, 0, 0);
5346         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5347         evas_object_show(e_comp->autoclose.rect);
5348         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5349         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5350         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5351         e_comp_grab_input(0, 1);
5352      }
5353    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5354    evas_object_focus_set(obj, 1);
5355 }
5356
5357 static void
5358 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5359 {
5360    _e_comp_object_autoclose_setup(obj);
5361    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5362 }
5363
5364 static void
5365 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5366 {
5367    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5368    _e_comp_object_autoclose_cleanup(1);
5369    if (e_client_focused_get()) return;
5370
5371    E_Zone *zone = e_zone_current_get();
5372    if (!zone) return;
5373
5374    e_zone_focus_reset(zone);
5375 }
5376
5377 EINTERN void
5378 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5379 {
5380    SOFT_ENTRY();
5381
5382    if (e_comp->autoclose.obj)
5383      {
5384         if (e_comp->autoclose.obj == obj) return;
5385         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5386         e_comp->autoclose.obj = obj;
5387         e_comp->autoclose.del_cb = del_cb;
5388         e_comp->autoclose.key_cb = cb;
5389         e_comp->autoclose.data = (void*)data;
5390         if (evas_object_visible_get(obj))
5391           _e_comp_object_autoclose_setup(obj);
5392         else
5393           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5394         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5395         return;
5396      }
5397    e_comp->autoclose.obj = obj;
5398    e_comp->autoclose.del_cb = del_cb;
5399    e_comp->autoclose.key_cb = cb;
5400    e_comp->autoclose.data = (void*)data;
5401    if (evas_object_visible_get(obj))
5402      _e_comp_object_autoclose_setup(obj);
5403    else
5404      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5405    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5406 }
5407
5408 E_API unsigned int
5409 e_comp_object_is_animating(Evas_Object *obj)
5410 {
5411    API_ENTRY 0;
5412
5413    return cw->animating;
5414 }
5415
5416 E_API void
5417 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5418 {
5419    API_ENTRY;
5420
5421    if ((cw->external_content) &&
5422        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5423      {
5424         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5425             "But current external content is %d object for %p.",
5426             cw->content_type, cw->ec);
5427         return;
5428      }
5429
5430    cw->user_alpha_set = EINA_TRUE;
5431    cw->user_alpha = alpha;
5432
5433    if (!cw->obj) return;
5434
5435    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5436
5437    evas_object_image_alpha_set(cw->obj, alpha);
5438
5439    if ((!cw->native) && (!cw->external_content))
5440      evas_object_image_data_set(cw->obj, NULL);
5441 }
5442
5443 EINTERN Eina_Bool
5444 e_comp_object_alpha_get(Evas_Object *obj)
5445 {
5446    API_ENTRY EINA_FALSE;
5447
5448    return evas_object_image_alpha_get(cw->obj);
5449 }
5450
5451 E_API void
5452 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5453 {
5454    Eina_Bool mask_set = EINA_FALSE;
5455    Evas_Object *o;
5456
5457    API_ENTRY;
5458    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5459    if (cw->ec->input_only) return;
5460    mask_set = !!set;
5461
5462    if (mask_set)
5463      {
5464         if (!cw->mask.obj)
5465           {
5466              o = evas_object_rectangle_add(e_comp->evas);
5467              evas_object_color_set(o, 0, 0, 0, 0);
5468              evas_object_clip_set(o, cw->clip);
5469              evas_object_smart_member_add(o, obj);
5470              evas_object_move(o, 0, 0);
5471              evas_object_resize(o, cw->w, cw->h);
5472              /* save render op value to restore when clear a mask.
5473               *
5474               * NOTE: DO NOT change the render op on ec->frame while mask object
5475               * is set. it will overwrite the changed op value. */
5476              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5477              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5478              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5479              if (cw->visible) evas_object_show(o);
5480
5481              cw->mask.obj = o;
5482              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5483              ELOGF("COMP", "         |mask_obj", cw->ec);
5484              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5485           }
5486      }
5487    else
5488      {
5489         if (cw->mask.obj)
5490           {
5491              evas_object_smart_member_del(cw->mask.obj);
5492              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5493
5494              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5495              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5496           }
5497      }
5498 }
5499
5500 E_API Eina_Bool
5501 e_comp_object_mask_has(Evas_Object *obj)
5502 {
5503    API_ENTRY EINA_FALSE;
5504
5505    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5506 }
5507
5508 EINTERN void
5509 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5510 {
5511    int tw, th;
5512    API_ENTRY;
5513
5514    if ((cw->external_content) &&
5515        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5516      {
5517         WRN("Can set up size to ONLY evas \"image\" object. "
5518             "But current external content is %d object for %p.",
5519             cw->content_type, cw->ec);
5520         return;
5521      }
5522
5523    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5524
5525    evas_object_image_size_set(cw->obj, tw, th);
5526 }
5527
5528 E_API void
5529 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5530 {
5531    Eina_Bool transform_set = EINA_FALSE;
5532    API_ENTRY;
5533    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5534    if (cw->ec->input_only) return;
5535
5536    transform_set = !!set;
5537
5538    if (transform_set)
5539      {
5540         if (!cw->transform_bg_obj)
5541           {
5542              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5543              evas_object_move(o, 0, 0);
5544              evas_object_resize(o, 1, 1);
5545              if (cw->transform_bg_color.a >= 255)
5546                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5547              else
5548                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5549              evas_object_color_set(o,
5550                                    cw->transform_bg_color.r,
5551                                    cw->transform_bg_color.g,
5552                                    cw->transform_bg_color.b,
5553                                    cw->transform_bg_color.a);
5554              if (cw->visible) evas_object_show(o);
5555
5556              cw->transform_bg_obj = o;
5557              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5558           }
5559 #ifdef REFACTOR_DESK_AREA
5560         e_comp_object_transform_obj_stack_update(obj);
5561 #else
5562         _e_comp_object_transform_obj_stack_update(obj);
5563 #endif
5564      }
5565    else
5566      {
5567         if (cw->transform_bg_obj)
5568           {
5569              evas_object_smart_member_del(cw->transform_bg_obj);
5570              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5571           }
5572      }
5573 }
5574
5575 E_API void
5576 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5577 {
5578    API_ENTRY;
5579
5580    cw->transform_bg_color.r = r;
5581    cw->transform_bg_color.g = g;
5582    cw->transform_bg_color.b = b;
5583    cw->transform_bg_color.a = a;
5584
5585    if (cw->transform_bg_obj)
5586      {
5587         evas_object_color_set(cw->transform_bg_obj,
5588                               cw->transform_bg_color.r,
5589                               cw->transform_bg_color.g,
5590                               cw->transform_bg_color.b,
5591                               cw->transform_bg_color.a);
5592      }
5593 }
5594
5595 EINTERN void
5596 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5597 {
5598    API_ENTRY;
5599    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5600    if (cw->ec->input_only) return;
5601    if (!cw->transform_bg_obj) return;
5602
5603    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5604 }
5605
5606 EINTERN void
5607 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5608 {
5609    API_ENTRY;
5610    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5611    if (cw->ec->input_only) return;
5612    if (!cw->transform_bg_obj) return;
5613
5614    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5615 }
5616
5617 E_API void
5618 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5619 {
5620    Eina_Bool transform_set = EINA_FALSE;
5621    API_ENTRY;
5622    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5623    if (cw->ec->input_only) return;
5624
5625    transform_set = !!set;
5626
5627    if (transform_set)
5628      {
5629         if (!cw->transform_tranp_obj)
5630           {
5631              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5632              evas_object_move(o, 0, 0);
5633              evas_object_resize(o, 1, 1);
5634              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5635              evas_object_color_set(o, 0, 0, 0, 0);
5636              if (cw->visible) evas_object_show(o);
5637
5638              cw->transform_tranp_obj = o;
5639              evas_object_pass_events_set(cw->transform_tranp_obj, EINA_TRUE);
5640              ELOGF("TRANSFORM","transform set: TRUE", cw->ec);
5641              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5642           }
5643 #ifdef REFACTOR_DESK_AREA
5644         e_comp_object_transform_obj_stack_update(obj);
5645 #else
5646         _e_comp_object_transform_obj_stack_update(obj);
5647 #endif
5648      }
5649    else
5650      {
5651         if (cw->transform_tranp_obj)
5652           {
5653              ELOGF("TRANSFORM","transform set: FALSE", cw->ec);
5654              evas_object_smart_member_del(cw->transform_tranp_obj);
5655              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5656           }
5657      }
5658 }
5659
5660 EINTERN void
5661 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5662 {
5663    API_ENTRY;
5664    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5665    if (cw->ec->input_only) return;
5666    if (!cw->transform_tranp_obj) return;
5667
5668    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5669 }
5670
5671 EINTERN void
5672 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5673 {
5674    API_ENTRY;
5675    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5676    if (cw->ec->input_only) return;
5677    if (!cw->transform_tranp_obj) return;
5678
5679    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5680 }
5681
5682 #ifdef REFACTOR_DESK_AREA
5683 #else
5684 EINTERN void
5685 e_comp_object_layer_update(Evas_Object *obj,
5686                            Evas_Object *above, Evas_Object *below)
5687 {
5688    E_Comp_Object *cw2 = NULL;
5689    Evas_Object *o = NULL;
5690    short layer;
5691
5692    API_ENTRY;
5693
5694    if (cw->ec->layer_block) return;
5695    if ((above) && (below))
5696      {
5697         ERR("Invalid layer update request! cw=%p", cw);
5698         return;
5699      }
5700
5701    o = above?:below;
5702
5703    if (o)
5704      {
5705         layer = evas_object_layer_get(o);
5706         cw2 = evas_object_data_get(o, "comp_obj");
5707         while (!cw2)
5708           {
5709              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5710
5711              o = evas_object_above_get(o);
5712              if ((!o) || (o == cw->smart_obj)) break;
5713              if (evas_object_layer_get(o) != layer)
5714                {
5715                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5716                }
5717              if (!o)
5718                {
5719                   E_Client *ec;
5720                   ec = e_client_top_get();
5721                   if (ec) o = ec->frame;
5722                }
5723
5724              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5725           }
5726      }
5727
5728    _e_comp_object_layers_remove(cw);
5729    if (cw2)
5730      {
5731         if (cw2->layer > cw->layer)
5732           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5733         else if (cw2->layer == cw->layer)
5734           {
5735              if (above)
5736                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5737              else if (o == obj)
5738                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5739              else if (below)
5740                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5741           }
5742         else
5743           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5744      }
5745    else
5746      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5747 }
5748 #endif
5749
5750 EINTERN int
5751 e_comp_object_layer_get(Evas_Object *obj)
5752 {
5753    API_ENTRY -1;
5754    return cw->layer;
5755 }
5756
5757 E_API Eina_Bool
5758 e_comp_object_content_set(Evas_Object *obj,
5759                           Evas_Object *content,
5760                           E_Comp_Object_Content_Type type)
5761 {
5762    API_ENTRY EINA_FALSE;
5763
5764    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5765    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5766    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5767
5768    if (cw->obj)
5769      {
5770         ERR("Can't set e.swallow.content to requested content. "
5771             "Previous comp object should not be changed at all.");
5772         return EINA_FALSE;
5773      }
5774
5775    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5776
5777    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5778        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5779      {
5780         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5781             type, content, cw->ec, cw->ec->pixmap);
5782         return EINA_FALSE;
5783      }
5784
5785    cw->external_content = EINA_TRUE;
5786
5787    cw->obj = content;
5788    cw->content_type = type;
5789    e_util_size_debug_set(cw->obj, 1);
5790    evas_object_name_set(cw->obj, "cw->obj");
5791    _e_comp_object_alpha_set(cw);
5792
5793    if (cw->shobj)
5794      _e_comp_object_shadow_setup(cw);
5795
5796    wl_signal_emit_mutable(&cw->events.content_type_set, NULL);
5797
5798    return EINA_TRUE;
5799 }
5800
5801 EINTERN Eina_Bool
5802 e_comp_object_content_unset(Evas_Object *obj)
5803 {
5804    API_ENTRY EINA_FALSE;
5805
5806    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5807    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5808
5809    if (!cw->obj && !cw->ec->visible)
5810      {
5811         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
5812         return EINA_TRUE;
5813      }
5814
5815    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5816      {
5817         ELOGF("COMP", "has been set to internal image object already", cw->ec);
5818         return EINA_TRUE;
5819      }
5820
5821    if (cw->obj)
5822      {
5823         if (cw->frame_object)
5824           edje_object_part_unswallow(cw->frame_object, cw->obj);
5825         else if (cw->shobj)
5826           edje_object_part_unswallow(cw->shobj, cw->obj);
5827
5828         evas_object_del(cw->obj);
5829         evas_object_hide(cw->obj);
5830         cw->obj = NULL;
5831      }
5832
5833    cw->external_content = EINA_FALSE;
5834    if (cw->ec->is_cursor)
5835      {
5836         int pw, ph;
5837         DBG("%p is cursor surface..", cw->ec);
5838         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
5839           pw = ph = 1;
5840         evas_object_resize(cw->ec->frame, pw, ph);
5841         evas_object_hide(cw->ec->frame);
5842         return EINA_TRUE;
5843      }
5844
5845
5846    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
5847    cw->obj = evas_object_image_filled_add(e_comp->evas);
5848    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
5849    e_util_size_debug_set(cw->obj, 1);
5850    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
5851    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
5852    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
5853    evas_object_name_set(cw->obj, "cw->obj");
5854    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
5855    _e_comp_object_alpha_set(cw);
5856
5857    if (cw->shobj)
5858      _e_comp_object_shadow_setup(cw);
5859
5860    if (cw->visible)
5861      {
5862         cw->visible = 0;
5863         _e_comp_intercept_show_helper(cw);
5864         cw->visible = 1;
5865      }
5866
5867    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
5868    e_comp_object_dirty(cw->smart_obj);
5869    e_comp_object_render(cw->smart_obj);
5870    e_comp_object_render_update_add(obj);
5871
5872    wl_signal_emit_mutable(&cw->events.content_type_set, NULL);
5873
5874    return EINA_TRUE;
5875 }
5876
5877 EINTERN Evas_Object *
5878 e_comp_object_content_get(Evas_Object *obj)
5879 {
5880    API_ENTRY NULL;
5881
5882    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
5883
5884    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5885      {
5886         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
5887         return NULL;
5888      }
5889
5890    return cw->obj;
5891 }
5892
5893 E_API E_Comp_Object_Content_Type
5894 e_comp_object_content_type_get(Evas_Object *obj)
5895 {
5896    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
5897
5898    return cw->content_type;
5899 }
5900
5901 E_API void
5902 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
5903 {
5904    API_ENTRY;
5905    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5906    E_Comp_Config *conf = e_comp_config_get();
5907    if (cw->ec->input_only) return;
5908    if (!conf->dim_rect_enable) return;
5909
5910    cw->dim.mask_set = mask_set;
5911    cw->dim.mask_x = x;
5912    cw->dim.mask_y = y;
5913    cw->dim.mask_w = w;
5914    cw->dim.mask_h = h;
5915
5916    if (!cw->dim.enable) return;
5917    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
5918 }
5919
5920 EINTERN void
5921 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
5922 {
5923    Eina_Bool mask_set = EINA_FALSE;
5924    Evas_Object *o;
5925
5926    API_ENTRY;
5927    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5928    E_Comp_Config *conf = e_comp_config_get();
5929    if (cw->ec->input_only) return;
5930    if (!conf->dim_rect_enable) return;
5931
5932    mask_set = !!set;
5933
5934    if (mask_set)
5935      {
5936         if (cw->dim.mask_obj)
5937           {
5938              evas_object_smart_member_del(cw->dim.mask_obj);
5939              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
5940           }
5941
5942         ELOGF("COMP", "DIM  |Mask applied on Dim rect mask_rect[%d %d %d %d]", cw->ec, cw->dim.mask_x, cw->dim.mask_y, cw->dim.mask_w, cw->dim.mask_h);
5943         o = evas_object_rectangle_add(e_comp->evas);
5944         evas_object_color_set(o, 0, 0, 0, 0);
5945         evas_object_smart_member_add(o, obj);
5946         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
5947         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
5948
5949         evas_object_render_op_set(o, EVAS_RENDER_COPY);
5950         if (cw->visible) evas_object_show(o);
5951
5952         cw->dim.mask_obj = o;
5953         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
5954
5955         evas_object_layer_set(cw->dim.mask_obj, 9998);
5956      }
5957    else
5958      {
5959         if (cw->dim.mask_obj)
5960           {
5961              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
5962              evas_object_smart_member_del(cw->dim.mask_obj);
5963              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
5964           }
5965      }
5966 }
5967
5968 E_API void
5969 e_comp_object_dim_client_set(E_Client *ec)
5970 {
5971    E_Comp_Config *conf = e_comp_config_get();
5972
5973    if (!conf->dim_rect_enable) return ;
5974    if (dim_client == ec) return;
5975
5976    Eina_Bool prev_dim = EINA_FALSE;
5977    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
5978
5979    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
5980       prev_dim = EINA_TRUE;
5981
5982    if (prev_dim && dim_client->visible && ec)
5983      {
5984         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
5985         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
5986      }
5987    else
5988      {
5989         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
5990         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
5991      }
5992    dim_client = ec;
5993 }
5994
5995 EINTERN E_Client *
5996 e_comp_object_dim_client_get(void)
5997 {
5998    E_Comp_Config *conf = e_comp_config_get();
5999
6000    if (!conf->dim_rect_enable ) return NULL;
6001
6002    return dim_client;
6003 }
6004
6005 static void
6006 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6007 {
6008    API_ENTRY;
6009    char emit[32] = "\0";
6010    E_Comp_Config *conf = e_comp_config_get();
6011
6012    if (!ec) return;
6013    if (!conf->dim_rect_enable) return;
6014    if (!cw->effect_obj) return;
6015    if (enable == cw->dim.enable) return;
6016
6017    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6018    if (noeffect || !conf->dim_rect_effect)
6019      {
6020         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6021      }
6022    else
6023      {
6024         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6025      }
6026
6027    cw->dim.enable = enable;
6028
6029    if (cw->dim.mask_set && !enable)
6030      {
6031         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6032         edje_object_signal_emit(cw->effect_obj, emit, "e");
6033      }
6034    else if (cw->dim.mask_set && enable)
6035      {
6036         edje_object_signal_emit(cw->effect_obj, emit, "e");
6037         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6038      }
6039    else
6040      {
6041         edje_object_signal_emit(cw->effect_obj, emit, "e");
6042      }
6043 }
6044
6045 static Eina_Bool
6046 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6047 {
6048    API_ENTRY EINA_FALSE;
6049    E_Comp_Config *conf = e_comp_config_get();
6050
6051    if (!ec) return EINA_FALSE;
6052    if (!conf->dim_rect_enable) return EINA_FALSE;
6053
6054    if (cw->dim.enable) return EINA_TRUE;
6055
6056    return EINA_FALSE;
6057 }
6058
6059 static void
6060 _e_comp_object_dim_update(E_Comp_Object *cw)
6061 {
6062    E_Comp_Config *conf = e_comp_config_get();
6063
6064    if (!cw) return;
6065    if (!conf->dim_rect_enable) return;
6066    if (!cw->effect_obj) return;
6067    if (cw->dim.enable)
6068      {
6069         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6070         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6071
6072         if (cw->dim.mask_set)
6073           {
6074              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6075           }
6076      }
6077 }
6078
6079 EINTERN void
6080 e_comp_object_clear(Evas_Object *obj)
6081 {
6082    API_ENTRY;
6083
6084    _e_comp_object_clear(cw);
6085 }
6086
6087 EINTERN Eina_Bool
6088 e_comp_object_hwc_update_exists(Evas_Object *obj)
6089 {
6090    API_ENTRY EINA_FALSE;
6091    return cw->hwc_need_update;
6092 }
6093
6094 // will remove out
6095 E_API void
6096 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6097 {
6098    API_ENTRY;
6099    cw->hwc_need_update = set;
6100 }
6101
6102 E_API Eina_Bool
6103 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6104 {
6105    API_ENTRY EINA_FALSE;
6106    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6107 }
6108
6109 EINTERN void
6110 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6111 {
6112    API_ENTRY;
6113    if (cw->indicator.obj != indicator)
6114      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6115    cw->indicator.obj = indicator;
6116    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6117 }
6118
6119 EINTERN void
6120 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6121 {
6122    API_ENTRY;
6123    if (cw->indicator.obj != indicator) return;
6124    cw->indicator.obj = NULL;
6125    edje_object_part_unswallow(cw->shobj, indicator);
6126 }
6127
6128 EINTERN void
6129 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6130 {
6131    API_ENTRY;
6132    Edje_Message_Int_Set *msg;
6133
6134    if (!cw->indicator.obj) return;
6135
6136    cw->indicator.w = w;
6137    cw->indicator.h = h;
6138
6139    if (!cw->shobj) return;
6140
6141    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6142    msg->count = 2;
6143    msg->val[0] = w;
6144    msg->val[1] = h;
6145    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6146    edje_object_message_signal_process(cw->shobj);
6147 }
6148
6149 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6150 EINTERN void
6151 e_comp_object_map_update(Evas_Object *obj)
6152 {
6153    API_ENTRY;
6154    E_Client *ec = cw->ec;
6155    E_Comp_Wl_Client_Data *cdata;
6156    E_Map *map;
6157    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6158    char buffer[128];
6159    char *p = buffer;
6160    int l, remain = sizeof buffer;
6161
6162    if (!ec) return;
6163    if (e_object_is_del(E_OBJECT(ec))) return;
6164    cdata = e_client_cdata_get(ec);
6165    if (!cdata) return;
6166
6167    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6168     * when new buffer is attached.
6169     */
6170    if (!cdata->buffer_ref.buffer) return;
6171
6172    if ((!cw->redirected) ||
6173        (e_client_video_hw_composition_check(ec)) ||
6174        (!e_comp_wl_output_buffer_transform_get(ec) &&
6175         cdata->scaler.buffer_viewport.buffer.scale == 1))
6176      {
6177         if (evas_object_map_enable_get(cw->effect_obj))
6178           {
6179              ELOGF("TRANSFORM", "map: disable", cw->ec);
6180              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6181              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6182              evas_object_resize(cw->effect_obj, tw, th);
6183           }
6184
6185         return;
6186      }
6187
6188    map = e_map_new();
6189    EINA_SAFETY_ON_NULL_RETURN(map);
6190
6191    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6192
6193    x1 = y1 = 0;
6194    x2 = bw;
6195    y2 = bh;
6196
6197    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6198
6199    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6200    e_map_point_image_uv_set(map, 0, x, y);
6201    l = snprintf(p, remain, "%d,%d", x, y);
6202    p += l, remain -= l;
6203
6204    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6205    e_map_point_image_uv_set(map, 1, x, y);
6206    l = snprintf(p, remain, " %d,%d", x, y);
6207    p += l, remain -= l;
6208
6209    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6210    e_map_point_image_uv_set(map, 2, x, y);
6211    l = snprintf(p, remain, " %d,%d", x, y);
6212    p += l, remain -= l;
6213
6214    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6215    e_map_point_image_uv_set(map, 3, x, y);
6216    l = snprintf(p, remain, " %d,%d", x, y);
6217    p += l, remain -= l;
6218
6219    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6220          cw->ec,
6221          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6222
6223    e_comp_object_map_set(cw->effect_obj, map);
6224    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6225
6226    e_map_free(map);
6227
6228    /* if there's screen rotation with comp mode, then ec->effect_obj and
6229     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6230     */
6231    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6232    evas_object_resize(cw->effect_obj, tw, th);
6233 }
6234
6235 EINTERN Eina_Bool
6236 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6237 {
6238    API_ENTRY EINA_FALSE;
6239
6240    cw->render_trace = set;
6241
6242    return EINA_TRUE;
6243 }
6244
6245 E_API Eina_Bool
6246 e_comp_object_native_usable_get(Evas_Object *obj)
6247 {
6248    API_ENTRY EINA_FALSE;
6249    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6250
6251    if (cw->ec->input_only) return EINA_FALSE;
6252    if (cw->external_content) return EINA_FALSE;
6253    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6254
6255    /* just return true value, if it is normal case */
6256    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6257
6258    /* abnormal case */
6259    Evas_Native_Surface *ns;
6260    ns = evas_object_image_native_surface_get(cw->obj);
6261
6262    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6263    if (ns)
6264      {
6265         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6266         return EINA_TRUE;
6267      }
6268
6269    return EINA_FALSE;
6270 }
6271
6272 EINTERN Eina_Bool
6273 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6274 {
6275    API_ENTRY EINA_FALSE;
6276    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6277    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6278    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6279
6280    if (cw->image_filter == filter) return EINA_TRUE;
6281
6282    switch (filter)
6283      {
6284       case E_COMP_IMAGE_FILTER_BLUR:
6285          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6286          break;
6287       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6288          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6289          break;
6290       case E_COMP_IMAGE_FILTER_INVERSE:
6291          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6292          break;
6293       case E_COMP_IMAGE_FILTER_NONE:
6294       default:
6295          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6296          break;
6297      }
6298
6299    cw->image_filter = filter;
6300
6301    wl_signal_emit_mutable(&cw->events.image_filter_set, NULL);
6302
6303    return EINA_TRUE;
6304 }
6305
6306 EINTERN E_Comp_Image_Filter
6307 e_comp_object_image_filter_get(Evas_Object *obj)
6308 {
6309    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6310    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6311    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6312    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6313
6314    return cw->image_filter;
6315 }
6316
6317 static void
6318 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6319 {
6320    Evas_Object *obj;
6321
6322    if (!_damage_trace) return;
6323
6324    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6325      evas_object_del(obj);
6326
6327    _damage_trace_post_objs = NULL;
6328 }
6329
6330 static void
6331 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6332 {
6333    if (!_damage_trace) return;
6334
6335    _damage_trace_post_objs = _damage_trace_objs;
6336    _damage_trace_objs = NULL;
6337 }
6338
6339 EINTERN void
6340 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6341 {
6342    if (_damage_trace == onoff) return;
6343
6344    if (onoff)
6345      {
6346         evas_event_callback_add(e_comp->evas,
6347                                 EVAS_CALLBACK_RENDER_PRE,
6348                                 _e_comp_object_damage_trace_render_pre_cb,
6349                                 NULL);
6350
6351         evas_event_callback_add(e_comp->evas,
6352                                 EVAS_CALLBACK_RENDER_POST,
6353                                 _e_comp_object_damage_trace_render_post_cb,
6354                                 NULL);
6355      }
6356    else
6357      {
6358         Evas_Object *obj;
6359
6360         EINA_LIST_FREE(_damage_trace_objs, obj)
6361           evas_object_del(obj);
6362
6363         _damage_trace_objs = NULL;
6364
6365         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6366           evas_object_del(obj);
6367
6368         _damage_trace_post_objs = NULL;
6369
6370         evas_event_callback_del(e_comp->evas,
6371                                 EVAS_CALLBACK_RENDER_PRE,
6372                                 _e_comp_object_damage_trace_render_pre_cb);
6373
6374         evas_event_callback_del(e_comp->evas,
6375                                 EVAS_CALLBACK_RENDER_POST,
6376                                 _e_comp_object_damage_trace_render_post_cb);
6377      }
6378
6379    _damage_trace = onoff;
6380 }
6381
6382 EINTERN Eina_Bool
6383 e_comp_object_redirected_get(Evas_Object *obj)
6384 {
6385    API_ENTRY EINA_FALSE;
6386    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6387
6388    return cw->redirected;
6389 }
6390
6391 EINTERN Eina_Bool
6392 e_comp_object_color_visible_get(Evas_Object *obj)
6393 {
6394    API_ENTRY EINA_FALSE;
6395    int a;
6396
6397    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6398
6399    e_comp_object_color_get(obj, NULL, NULL, NULL, &a);
6400    if (a <= 0)
6401      return EINA_FALSE;
6402
6403    evas_object_color_get(cw->effect_obj, NULL, NULL, NULL, &a);
6404    if (a <= 0)
6405      return EINA_FALSE;
6406
6407    evas_object_color_get(cw->shobj, NULL, NULL, NULL, &a);
6408    if (a <= 0)
6409      return EINA_FALSE;
6410
6411    evas_object_color_get(cw->obj, NULL, NULL, NULL, &a);
6412    if (a <= 0)
6413      return EINA_FALSE;
6414
6415    return EINA_TRUE;
6416 }
6417
6418 E_API Eina_Bool
6419 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6420 {
6421    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6422
6423    return e_map_set_to_comp_object(em, obj);
6424 }
6425
6426 EINTERN E_Map *
6427 e_comp_object_map_get(const Evas_Object *obj)
6428 {
6429    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6430
6431    return e_map_get_from_comp_object(obj);
6432 }
6433
6434 E_API Eina_Bool
6435 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6436 {
6437    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6438
6439    evas_object_map_enable_set(obj, enable);
6440
6441    return EINA_TRUE;
6442 }
6443
6444 E_API Eina_Bool
6445 e_comp_object_render_update_lock(Evas_Object *obj)
6446 {
6447    E_Comp_Wl_Buffer *buffer;
6448    struct wayland_tbm_client_queue *cqueue;
6449
6450    API_ENTRY EINA_FALSE;
6451
6452    if (cw->render_update_lock.lock == 0)
6453      {
6454         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6455
6456         buffer = e_pixmap_resource_get(cw->ec->pixmap);
6457         if ((buffer) && (buffer->resource))
6458           {
6459              cqueue = e_comp_wl_tbm_client_queue_get(cw->ec);
6460              if (cqueue)
6461                wayland_tbm_server_client_queue_flush(cqueue);
6462           }
6463
6464         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, buffer);
6465         e_comp_object_render_update_del(obj);
6466
6467         ELOGF("COMP", "Render update lock enabled", cw->ec);
6468      }
6469
6470    cw->render_update_lock.lock++;
6471
6472    return EINA_TRUE;
6473 }
6474
6475 E_API void
6476 e_comp_object_render_update_unlock(Evas_Object *obj)
6477 {
6478    API_ENTRY;
6479
6480    if (cw->render_update_lock.lock == 0)
6481      return;
6482
6483    cw->render_update_lock.lock--;
6484
6485    if (cw->render_update_lock.lock == 0)
6486      {
6487
6488         if (cw->render_update_lock.pending_move_set)
6489           {
6490              evas_object_move(obj,
6491                               cw->render_update_lock.pending_move_x,
6492                               cw->render_update_lock.pending_move_y);
6493              cw->render_update_lock.pending_move_x = 0;
6494              cw->render_update_lock.pending_move_y = 0;
6495              cw->render_update_lock.pending_move_set = EINA_FALSE;
6496           }
6497
6498         if (cw->render_update_lock.pending_resize_set)
6499           {
6500              evas_object_resize(obj,
6501                                 cw->render_update_lock.pending_resize_w,
6502                                 cw->render_update_lock.pending_resize_h);
6503              cw->render_update_lock.pending_resize_w = 0;
6504              cw->render_update_lock.pending_resize_h = 0;
6505              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6506           }
6507
6508         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6509
6510         if ((cw->ec->exp_iconify.buffer_flush) &&
6511             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6512             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6513           e_comp_object_clear(obj);
6514         else
6515           e_comp_object_render_update_add(obj);
6516
6517         ELOGF("COMP", "Render update lock disabled", cw->ec);
6518      }
6519 }
6520
6521 E_API Eina_Bool
6522 e_comp_object_render_update_lock_get(Evas_Object *obj)
6523 {
6524    API_ENTRY EINA_FALSE;
6525
6526    if (cw->render_update_lock.lock > 0)
6527      return EINA_TRUE;
6528
6529    return EINA_FALSE;
6530 }
6531
6532 E_API void
6533 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6534 {
6535    API_ENTRY;
6536
6537    if (cw->transparent.set)
6538      {
6539         if (r) *r = cw->transparent.user_r;
6540         if (g) *g = cw->transparent.user_g;
6541         if (b) *b = cw->transparent.user_b;
6542         if (a) *a = cw->transparent.user_a;
6543      }
6544    else
6545      {
6546         evas_object_color_get(obj, r, g, b, a);
6547      }
6548 }
6549
6550 EINTERN void
6551 e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op)
6552 {
6553    API_ENTRY;
6554
6555    evas_object_render_op_set(cw->obj, op);
6556
6557    wl_signal_emit_mutable(&cw->events.render_op_set, NULL);
6558 }
6559
6560 EINTERN Evas_Render_Op
6561 e_comp_object_render_op_get(Evas_Object *obj)
6562 {
6563    API_ENTRY EVAS_RENDER_BLEND;
6564
6565    return evas_object_render_op_get(cw->obj);
6566 }
6567
6568 EINTERN void
6569 e_comp_object_lower_listener_add(Evas_Object *obj, struct wl_listener *listener)
6570 {
6571    API_ENTRY;
6572    wl_signal_add(&cw->events.lower, listener);
6573 }
6574
6575 #ifdef REFACTOR_DESK_AREA
6576 EINTERN void
6577 e_comp_object_lower_done_listener_add(Evas_Object *obj, struct wl_listener *listener)
6578 {
6579    API_ENTRY;
6580    wl_signal_add(&cw->events.lower_done, listener);
6581 }
6582
6583 EINTERN void
6584 e_comp_object_raise_listener_add(Evas_Object *obj, struct wl_listener *listener)
6585 {
6586    API_ENTRY;
6587    wl_signal_add(&cw->events.raise, listener);
6588 }
6589 #endif
6590
6591 EINTERN void
6592 e_comp_object_show_listener_add(Evas_Object *obj, struct wl_listener *listener)
6593 {
6594    API_ENTRY;
6595    wl_signal_add(&cw->events.show, listener);
6596 }
6597
6598 EINTERN void
6599 e_comp_object_hide_listener_add(Evas_Object *obj, struct wl_listener *listener)
6600 {
6601    API_ENTRY;
6602    wl_signal_add(&cw->events.hide, listener);
6603 }
6604
6605 #ifdef REFACTOR_DESK_AREA
6606 EINTERN void
6607 e_comp_object_set_layer_listener_add(Evas_Object *obj, struct wl_listener *listener)
6608 {
6609    API_ENTRY;
6610    wl_signal_add(&cw->events.set_layer, listener);
6611 }
6612
6613 EINTERN void
6614 e_comp_object_stack_above_listener_add(Evas_Object *obj, struct wl_listener *listener)
6615 {
6616    API_ENTRY;
6617    wl_signal_add(&cw->events.stack_above, listener);
6618 }
6619
6620 EINTERN void
6621 e_comp_object_stack_below_listener_add(Evas_Object *obj, struct wl_listener *listener)
6622 {
6623    API_ENTRY;
6624    wl_signal_add(&cw->events.stack_below, listener);
6625 }
6626 #endif
6627
6628 EINTERN void
6629 e_comp_object_image_filter_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6630 {
6631    API_ENTRY;
6632    wl_signal_add(&cw->events.image_filter_set, listener);
6633 }
6634
6635 EINTERN void
6636 e_comp_object_render_op_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6637 {
6638    API_ENTRY;
6639    wl_signal_add(&cw->events.render_op_set, listener);
6640 }
6641
6642 EINTERN void
6643 e_comp_object_content_type_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6644 {
6645    API_ENTRY;
6646    wl_signal_add(&cw->events.content_type_set, listener);
6647 }