e_comp_object: add e_comp_object_color_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    wl_signal_emit_mutable(&cw->events.color_set, NULL);
2715 }
2716 ////////////////////////////////////////////////////
2717
2718 static void
2719 _e_comp_object_frame_recalc(E_Comp_Object *cw)
2720 {
2721    int w, h, ox, oy, ow, oh;
2722    Eina_List *l;
2723    Eina_Bool pass_event_flag = EINA_FALSE;
2724    E_Input_Rect_Data *input_rect_data;
2725    E_Input_Rect_Smart_Data *input_rect_sd;
2726
2727    if (cw->frame_object)
2728      {
2729         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
2730         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
2731         /* set a fixed size, force edje calc, check size difference */
2732         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
2733         edje_object_message_signal_process(cw->frame_object);
2734         edje_object_calc_force(cw->frame_object);
2735         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
2736         cw->client_inset.l = ox;
2737         cw->client_inset.r = MAX(w, 50) - (ox + ow);
2738         cw->client_inset.t = oy;
2739         cw->client_inset.b = MAX(h, 50) - (oy + oh);
2740         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
2741         evas_object_resize(cw->frame_object, w, h);
2742
2743         if (cw->input_obj)
2744           {
2745              input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2746              if (input_rect_sd)
2747                {
2748                   EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2749                     {
2750                        if (input_rect_data->obj)
2751                          {
2752                             pass_event_flag = EINA_TRUE;
2753                             break;
2754                          }
2755                     }
2756                }
2757           }
2758         evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
2759         evas_object_pass_events_set(cw->obj, pass_event_flag);
2760      }
2761    else
2762      {
2763         cw->client_inset.l = 0;
2764         cw->client_inset.r = 0;
2765         cw->client_inset.t = 0;
2766         cw->client_inset.b = 0;
2767      }
2768    cw->client_inset.calc = !!cw->frame_object;
2769 }
2770
2771 static void
2772 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2773 {
2774    E_Comp_Object *cw = data;
2775    E_Zone *zone;
2776    int w, h, pw, ph;
2777
2778    /* - get current size
2779     * - calc new size
2780     * - readjust for new frame size
2781     */
2782
2783    w = cw->ec->w, h = cw->ec->h;
2784    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
2785
2786    _e_comp_object_frame_recalc(cw);
2787
2788    if (!cw->ec->fullscreen)
2789      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
2790
2791    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2792    if (cw->ec->fullscreen)
2793      {
2794         zone = e_comp_zone_find_by_ec(cw->ec);
2795         if (!zone) return;
2796         evas_object_resize(cw->ec->frame, zone->w, zone->h);
2797      }
2798    else if (cw->ec->new_client)
2799      {
2800         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
2801         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
2802         evas_object_resize(cw->ec->frame, w, h);
2803      }
2804    else if ((w != cw->ec->w) || (h != cw->ec->h))
2805      evas_object_resize(cw->ec->frame, w, h);
2806 }
2807
2808 static void
2809 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2810 {
2811    E_Comp_Object *cw = data;
2812
2813    _e_comp_object_shadow_setup(cw);
2814    if (cw->frame_object)
2815      {
2816         _e_comp_object_shadow(cw);
2817         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2818         _e_comp_object_frame_recalc(cw);
2819         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2820      }
2821 }
2822
2823 static void
2824 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2825 {
2826    E_Comp_Object *cw = data;
2827
2828    if (_e_comp_object_shadow_setup(cw))
2829      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2830    if (cw->frame_object)
2831      {
2832         _e_comp_object_shadow(cw);
2833         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2834         _e_comp_object_frame_recalc(cw);
2835         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2836      }
2837 }
2838
2839 static void
2840 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2841 {
2842    E_Comp_Object *cw = data;
2843
2844    if (cw->frame_object)
2845      {
2846         _e_comp_object_shadow(cw);
2847         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2848         _e_comp_object_frame_recalc(cw);
2849         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2850      }
2851 }
2852
2853 static void
2854 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2855 {
2856    E_Comp_Object *cw = data;
2857
2858    if (_e_comp_object_shadow_setup(cw))
2859      {
2860         EC_CHANGED(cw->ec);
2861         cw->ec->changes.size = 1;
2862      }
2863    if (cw->frame_object)
2864      {
2865         _e_comp_object_shadow(cw);
2866         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
2867         _e_comp_object_frame_recalc(cw);
2868         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2869      }
2870 }
2871
2872 static void
2873 _e_comp_smart_cb_sticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2874 {
2875    e_comp_object_signal_emit(obj, "e,state,sticky", "e");
2876 }
2877
2878 static void
2879 _e_comp_smart_cb_unsticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2880 {
2881    e_comp_object_signal_emit(obj, "e,state,unsticky", "e");
2882 }
2883
2884 static void
2885 _e_comp_smart_cb_unhung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2886 {
2887    E_Comp_Object *cw = data;
2888
2889    if (!cw->ec) return; //NYI
2890    e_comp_object_signal_emit(cw->smart_obj, "e,state,unhung", "e");
2891 }
2892
2893 static void
2894 _e_comp_smart_cb_hung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2895 {
2896    E_Comp_Object *cw = data;
2897
2898    if (!cw->ec) return; //NYI
2899    e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
2900 }
2901
2902 static void
2903 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2904 {
2905    e_comp_object_signal_emit(obj, "e,state,focused", "e");
2906 }
2907
2908 static void
2909 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2910 {
2911    E_Comp_Object *cw = data;
2912
2913    if (!e_object_is_del(E_OBJECT(cw->ec)))
2914      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
2915 }
2916
2917 static void
2918 _e_comp_input_obj_smart_add(Evas_Object *obj)
2919 {
2920    E_Input_Rect_Smart_Data *input_rect_sd;
2921    input_rect_sd = E_NEW(E_Input_Rect_Smart_Data, 1);
2922
2923    if (!input_rect_sd) return;
2924    evas_object_smart_data_set(obj, input_rect_sd);
2925 }
2926
2927 static void
2928 _e_comp_input_obj_smart_del(Evas_Object *obj)
2929 {
2930    E_Input_Rect_Smart_Data *input_rect_sd;
2931    E_Input_Rect_Data *input_rect_data;
2932
2933    input_rect_sd = evas_object_smart_data_get(obj);
2934    if (!input_rect_sd) return;
2935
2936    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
2937      {
2938         if (input_rect_data->obj)
2939           {
2940              evas_object_smart_member_del(input_rect_data->obj);
2941              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
2942           }
2943         E_FREE(input_rect_data);
2944      }
2945    E_FREE(input_rect_sd);
2946 }
2947
2948 static void
2949 _e_comp_input_obj_smart_move(Evas_Object *obj, int x, int y)
2950 {
2951    E_Input_Rect_Smart_Data *input_rect_sd;
2952    E_Input_Rect_Data *input_rect_data;
2953    Eina_List *l;
2954    E_Comp_Object *cw;
2955
2956    input_rect_sd = evas_object_smart_data_get(obj);
2957    if (!input_rect_sd) return;
2958
2959    cw = input_rect_sd->cw;
2960    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2961      {
2962         if (input_rect_data->obj)
2963           {
2964              evas_object_geometry_set(input_rect_data->obj,
2965                x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2966                y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2967                input_rect_data->rect.w, input_rect_data->rect.h);
2968           }
2969      }
2970 }
2971
2972 static void
2973 _e_comp_input_obj_smart_resize(Evas_Object *obj, int w, int h)
2974 {
2975    E_Input_Rect_Smart_Data *input_rect_sd;
2976    E_Input_Rect_Data *input_rect_data;
2977    Eina_List *l;
2978    E_Comp_Object *cw;
2979
2980    input_rect_sd = evas_object_smart_data_get(obj);
2981    if (!input_rect_sd) return;
2982
2983    cw = input_rect_sd->cw;
2984    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2985      {
2986         if (input_rect_data->obj)
2987           {
2988              evas_object_geometry_set(input_rect_data->obj,
2989                cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2990                cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2991                input_rect_data->rect.w, input_rect_data->rect.h);
2992           }
2993      }
2994 }
2995
2996 static void
2997 _e_comp_input_obj_smart_show(Evas_Object *obj)
2998 {
2999    E_Input_Rect_Smart_Data *input_rect_sd;
3000    E_Input_Rect_Data *input_rect_data;
3001    Eina_List *l;
3002
3003    input_rect_sd = evas_object_smart_data_get(obj);
3004    if (!input_rect_sd) return;
3005
3006    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3007      {
3008         if (input_rect_data->obj)
3009           {
3010              evas_object_show(input_rect_data->obj);
3011           }
3012      }
3013 }
3014
3015 static void
3016 _e_comp_input_obj_smart_hide(Evas_Object *obj)
3017 {
3018    E_Input_Rect_Smart_Data *input_rect_sd;
3019    E_Input_Rect_Data *input_rect_data;
3020    Eina_List *l;
3021
3022    input_rect_sd = evas_object_smart_data_get(obj);
3023    if (!input_rect_sd) return;
3024
3025    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3026      {
3027         if (input_rect_data->obj)
3028           {
3029              evas_object_hide(input_rect_data->obj);
3030           }
3031      }
3032 }
3033
3034 static void
3035 _e_comp_input_obj_smart_init(void)
3036 {
3037    if (_e_comp_input_obj_smart) return;
3038    {
3039       static const Evas_Smart_Class sc =
3040       {
3041          INPUT_OBJ_SMART_NAME,
3042          EVAS_SMART_CLASS_VERSION,
3043          _e_comp_input_obj_smart_add,
3044          _e_comp_input_obj_smart_del,
3045          _e_comp_input_obj_smart_move,
3046          _e_comp_input_obj_smart_resize,
3047          _e_comp_input_obj_smart_show,
3048          _e_comp_input_obj_smart_hide,
3049          NULL,
3050          NULL,
3051          NULL,
3052          NULL,
3053          NULL,
3054          NULL,
3055
3056          NULL,
3057          NULL,
3058          NULL,
3059          NULL
3060       };
3061       _e_comp_input_obj_smart = evas_smart_class_new(&sc);
3062    }
3063 }
3064
3065
3066 static void
3067 _e_comp_smart_add(Evas_Object *obj)
3068 {
3069    E_Comp_Object *cw;
3070
3071    cw = E_NEW(E_Comp_Object, 1);
3072    EINA_SAFETY_ON_NULL_RETURN(cw);
3073
3074    wl_signal_init(&cw->events.lower);
3075 #ifdef REFACTOR_DESK_AREA
3076    wl_signal_init(&cw->events.lower_done);
3077    wl_signal_init(&cw->events.raise);
3078 #endif
3079    wl_signal_init(&cw->events.show);
3080    wl_signal_init(&cw->events.hide);
3081 #ifdef REFACTOR_DESK_AREA
3082    wl_signal_init(&cw->events.set_layer);
3083    wl_signal_init(&cw->events.stack_above);
3084    wl_signal_init(&cw->events.stack_below);
3085 #endif
3086    wl_signal_init(&cw->events.image_filter_set);
3087    wl_signal_init(&cw->events.render_op_set);
3088    wl_signal_init(&cw->events.content_type_set);
3089    wl_signal_init(&cw->events.color_set);
3090
3091    cw->smart_obj = obj;
3092    cw->x = cw->y = cw->w = cw->h = -1;
3093    evas_object_smart_data_set(obj, cw);
3094    cw->opacity = 255.0;
3095    cw->external_content = 0;
3096    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
3097    cw->transform_bg_color.r = 0;
3098    cw->transform_bg_color.g = 0;
3099    cw->transform_bg_color.b = 0;
3100    cw->transform_bg_color.a = 255;
3101    evas_object_data_set(obj, "comp_obj", cw);
3102    evas_object_move(obj, -1, -1);
3103    /* intercept ALL the callbacks! */
3104    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
3105    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
3106    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
3107    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
3108    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
3109    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
3110    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
3111    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
3112    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
3113    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
3114    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_color_set, cw);
3115
3116    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
3117    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
3118    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
3119    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
3120
3121    evas_object_smart_callback_add(obj, "stick", _e_comp_smart_cb_sticky, cw);
3122    evas_object_smart_callback_add(obj, "unstick", _e_comp_smart_cb_unsticky, cw);
3123
3124    evas_object_smart_callback_add(obj, "hung", _e_comp_smart_cb_hung, cw);
3125    evas_object_smart_callback_add(obj, "unhung", _e_comp_smart_cb_unhung, cw);
3126
3127    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
3128
3129    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
3130    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
3131 }
3132
3133 static void
3134 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3135 {
3136    INTERNAL_ENTRY;
3137    evas_object_color_set(cw->clip, r, g, b, a);
3138    evas_object_smart_callback_call(obj, "color_set", NULL);
3139 }
3140
3141
3142 static void
3143 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3144 {
3145    INTERNAL_ENTRY;
3146    evas_object_clip_set(cw->clip, clip);
3147 }
3148
3149 static void
3150 _e_comp_smart_clip_unset(Evas_Object *obj)
3151 {
3152    INTERNAL_ENTRY;
3153    evas_object_clip_unset(cw->clip);
3154 }
3155
3156 static void
3157 _e_comp_smart_hide(Evas_Object *obj)
3158 {
3159    TRACE_DS_BEGIN(COMP:SMART HIDE);
3160
3161    INTERNAL_ENTRY;
3162    cw->visible = 0;
3163    cw->hiding = 0;
3164    evas_object_hide(cw->clip);
3165    if (cw->input_obj) evas_object_hide(cw->input_obj);
3166    evas_object_hide(cw->effect_obj);
3167    if (cw->default_input_obj) evas_object_hide(cw->default_input_obj);
3168    if (cw->transform_bg_obj) evas_object_hide(cw->transform_bg_obj);
3169    if (cw->transform_tranp_obj) evas_object_hide(cw->transform_tranp_obj);
3170    if (stopping)
3171      {
3172         TRACE_DS_END();
3173         return;
3174      }
3175
3176    /* unset native surface if current displaying buffer was destroied */
3177    if (!cw->buffer_destroy_listener.notify)
3178      {
3179         Evas_Native_Surface *ns;
3180         ns = evas_object_image_native_surface_get(cw->obj);
3181         if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
3182           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
3183      }
3184
3185    if (!cw->ec->input_only)
3186      {
3187         edje_object_freeze(cw->effect_obj);
3188         edje_object_freeze(cw->shobj);
3189         edje_object_play_set(cw->shobj, 0);
3190         if (cw->frame_object)
3191           edje_object_play_set(cw->frame_object, 0);
3192      }
3193
3194    e_comp_render_queue(); //force nocomp recheck
3195
3196    TRACE_DS_END();
3197 }
3198
3199 static void
3200 _e_comp_smart_show(Evas_Object *obj)
3201 {
3202    E_Client *tmp;
3203    Eina_List *l;
3204
3205    INTERNAL_ENTRY;
3206    cw->defer_hide = 0;
3207    cw->visible = 1;
3208    if ((cw->w < 0) || (cw->h < 0))
3209      CRI("ACK! ec:%p", cw->ec);
3210
3211    TRACE_DS_BEGIN(COMP:SMART SHOW);
3212
3213    e_comp_object_map_update(obj);
3214
3215    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
3216      evas_object_show(tmp->frame);
3217
3218    evas_object_show(cw->clip);
3219    if (cw->input_obj) evas_object_show(cw->input_obj);
3220    if (!cw->ec->input_only)
3221      {
3222         edje_object_thaw(cw->effect_obj);
3223         edje_object_thaw(cw->shobj);
3224         edje_object_play_set(cw->shobj, 1);
3225         if (cw->frame_object)
3226           edje_object_play_set(cw->frame_object, 1);
3227      }
3228    evas_object_show(cw->effect_obj);
3229    if (cw->mask.obj) evas_object_show(cw->mask.obj);
3230    if (cw->transform_bg_obj) evas_object_show(cw->transform_bg_obj);
3231    if (cw->transform_tranp_obj) evas_object_show(cw->transform_tranp_obj);
3232    if (cw->default_input_obj) evas_object_show(cw->default_input_obj);
3233    e_comp_render_queue();
3234    if (cw->ec->input_only)
3235      {
3236         TRACE_DS_END();
3237         return;
3238      }
3239    if (cw->ec->iconic && (!cw->ec->new_client))
3240      {
3241         if (e_client_is_iconified_by_client(cw->ec))
3242           {
3243              ELOGF("COMP", "Set launching flag..", cw->ec);
3244              cw->ec->launching = EINA_TRUE;
3245           }
3246
3247         e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
3248      }
3249    else if (!cw->showing) /* if set, client was ec->hidden during show animation */
3250      {
3251         cw->showing = 1;
3252         ELOGF("COMP", "Set launching flag..", cw->ec);
3253         cw->ec->launching = EINA_TRUE;
3254
3255         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
3256         _e_comp_object_animating_begin(cw);
3257         if (!_e_comp_object_effect_visibility_start(cw, 1))
3258           {
3259              TRACE_DS_END();
3260              return;
3261           }
3262      }
3263    /* ensure some random effect doesn't lock the client offscreen */
3264    if (!cw->animating)
3265      {
3266         cw->showing = 0;
3267         e_comp_object_effect_set(obj, NULL);
3268      }
3269
3270    _e_comp_object_dim_update(cw);
3271
3272    TRACE_DS_END();
3273 }
3274
3275 static void
3276 _e_comp_smart_del(Evas_Object *obj)
3277 {
3278    Eina_List *l;
3279
3280    INTERNAL_ENTRY;
3281
3282    if (cw->buffer_destroy_listener.notify)
3283      {
3284         wl_list_remove(&cw->buffer_destroy_listener.link);
3285         cw->buffer_destroy_listener.notify = NULL;
3286      }
3287
3288    if (cw->tbm_surface)
3289      {
3290         tbm_surface_internal_unref(cw->tbm_surface);
3291         cw->tbm_surface = NULL;
3292      }
3293
3294    if (cw->render_update_lock.buffer_ref.buffer)
3295      {
3296         ELOGF("COMP", "Clear buffer_ref of render_update_lock:%d",
3297               cw->ec, cw->render_update_lock.lock);
3298         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
3299      }
3300
3301    e_comp_object_render_update_del(cw->smart_obj);
3302    E_FREE_FUNC(cw->updates, eina_tiler_free);
3303    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
3304    free(cw->ns);
3305
3306    if (cw->obj_mirror)
3307      {
3308         Evas_Object *o;
3309
3310         EINA_LIST_FREE(cw->obj_mirror, o)
3311           {
3312              evas_object_image_data_set(o, NULL);
3313              evas_object_freeze_events_set(o, 1);
3314              evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
3315              evas_object_del(o);
3316           }
3317      }
3318 #ifdef REFACTOR_DESK_AREA
3319 #else
3320    _e_comp_object_layers_remove(cw);
3321 #endif
3322    l = evas_object_data_get(obj, "comp_object-to_del");
3323    E_FREE_LIST(l, evas_object_del);
3324    _e_comp_object_mouse_event_callback_unset(cw);
3325    evas_object_del(cw->clip);
3326    evas_object_del(cw->obj);
3327    evas_object_del(cw->shobj);
3328    evas_object_del(cw->effect_obj);
3329    evas_object_del(cw->frame_object);
3330    evas_object_del(cw->input_obj);
3331    evas_object_del(cw->mask.obj);
3332    if (cw->dim.mask_obj) evas_object_del(cw->dim.mask_obj);
3333    evas_object_del(cw->transform_bg_obj);
3334    evas_object_del(cw->transform_tranp_obj);
3335    evas_object_del(cw->default_input_obj);
3336    eina_stringshare_del(cw->frame_theme);
3337    eina_stringshare_del(cw->frame_name);
3338    if (cw->animating)
3339      {
3340         cw->animating = 0;
3341         e_comp->animating--;
3342         UNREFD(cw->ec, 2);
3343         e_object_unref(E_OBJECT(cw->ec));
3344      }
3345    cw->ec->frame = NULL;
3346    free(cw);
3347 }
3348
3349 static void
3350 _e_comp_smart_move(Evas_Object *obj, int x, int y)
3351 {
3352    INTERNAL_ENTRY;
3353
3354    cw->x = x, cw->y = y;
3355    evas_object_move(cw->effect_obj, x, y);
3356    evas_object_move(cw->default_input_obj, x, y);
3357    if (cw->input_obj) evas_object_move(cw->input_obj, x, y);
3358
3359    e_comp_object_map_update(obj);
3360 }
3361
3362 static void
3363 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
3364 {
3365    Eina_Bool first = EINA_FALSE;
3366    int tw, th;
3367
3368    INTERNAL_ENTRY;
3369
3370    if (!cw->effect_obj) CRI("ACK! ec:%p", cw->ec);
3371
3372    TRACE_DS_BEGIN(COMP:SMART RESIZE);
3373
3374    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
3375
3376    if (cw->w != w || cw->h != h)
3377      e_comp_object_map_update(obj);
3378
3379    first = ((cw->w < 1) || (cw->h < 1));
3380    cw->w = w, cw->h = h;
3381
3382    int ww, hh, pw, ph;
3383
3384    if (cw->frame_object)
3385      e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
3386    else
3387      ww = w, hh = h;
3388    /* verify pixmap:object size */
3389    if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
3390      {
3391         if ((ww != pw) || (hh != ph))
3392           ELOGF("COMP", "CW RSZ: %dx%d || PX: %dx%d.", cw->ec, ww, hh, pw, ph);
3393      }
3394    evas_object_resize(cw->effect_obj, tw, th);
3395    evas_object_resize(cw->default_input_obj, w, h);
3396    if (cw->input_obj)
3397      evas_object_resize(cw->input_obj, w, h);
3398    if (cw->mask.obj)
3399      evas_object_resize(cw->mask.obj, w, h);
3400    /* resize render update tiler */
3401    if (!first)
3402      {
3403         RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
3404         cw->updates_full = 0;
3405         if (cw->updates) eina_tiler_clear(cw->updates);
3406      }
3407    else
3408      {
3409         RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3410         if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3411      }
3412
3413    if (!cw->visible)
3414      {
3415         TRACE_DS_END();
3416         return;
3417      }
3418    e_comp_render_queue();
3419
3420    TRACE_DS_END();
3421 }
3422
3423 static void
3424 _e_comp_smart_init(void)
3425 {
3426    if (_e_comp_smart) return;
3427    {
3428       static const Evas_Smart_Class sc =
3429       {
3430          SMART_NAME,
3431          EVAS_SMART_CLASS_VERSION,
3432          _e_comp_smart_add,
3433          _e_comp_smart_del,
3434          _e_comp_smart_move,
3435          _e_comp_smart_resize,
3436          _e_comp_smart_show,
3437          _e_comp_smart_hide,
3438          _e_comp_smart_color_set,
3439          _e_comp_smart_clip_set,
3440          _e_comp_smart_clip_unset,
3441          NULL,
3442          NULL,
3443          NULL,
3444
3445          NULL,
3446          NULL,
3447          NULL,
3448          NULL
3449       };
3450       _e_comp_smart = evas_smart_class_new(&sc);
3451    }
3452 }
3453
3454 EINTERN void
3455 e_comp_object_init(void)
3456 {
3457    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
3458    E_EVENT_COMP_OBJECT_IMG_RENDER = ecore_event_type_new();
3459    E_EVENT_COMP_OBJECT_EFFECT_START = ecore_event_type_new();
3460    E_EVENT_COMP_OBJECT_EFFECT_END = ecore_event_type_new();
3461 }
3462
3463 EINTERN void
3464 e_comp_object_shutdown(void)
3465 {
3466
3467 }
3468
3469 EINTERN Eina_Bool
3470 e_comp_object_mirror_visibility_check(Evas_Object *obj)
3471 {
3472    API_ENTRY EINA_FALSE;
3473    return !!cw->force_visible;
3474 }
3475 /////////////////////////////////////////////////////////
3476
3477 static void
3478 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3479 {
3480    Eina_List *l;
3481    Eina_Bool comp_object;
3482
3483    comp_object = !!evas_object_data_get(obj, "comp_object");
3484    if (comp_object)
3485      {
3486         Evas_Object *o;
3487
3488         o = edje_object_part_swallow_get(obj, "e.swallow.content");
3489         evas_object_del(o);
3490         e_comp_render_queue();
3491      }
3492    l = evas_object_data_get(obj, "comp_object-to_del");
3493    E_FREE_LIST(l, evas_object_del);
3494 }
3495
3496 static void
3497 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3498 {
3499    if (e_comp_util_object_is_above_nocomp(obj) &&
3500        (!evas_object_data_get(obj, "comp_override")))
3501      {
3502         evas_object_data_set(obj, "comp_override", (void*)1);
3503         e_comp_override_add();
3504      }
3505 }
3506
3507 static void
3508 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
3509 {
3510    Eina_Bool ref = EINA_TRUE;
3511    if (evas_object_visible_get(obj))
3512      {
3513         void *d;
3514
3515         d = evas_object_data_del(obj, "comp_hiding");
3516         if (d)
3517           /* currently trying to hide */
3518           ref = EINA_FALSE;
3519         else
3520           /* already visible */
3521           return;
3522      }
3523
3524    evas_object_show(obj);
3525    if (ref)
3526      {
3527         evas_object_ref(obj);
3528         evas_object_data_set(obj, "comp_ref", (void*)1);
3529      }
3530    edje_object_signal_emit(obj, "e,state,visible", "e");
3531    evas_object_data_set(obj, "comp_showing", (void*)1);
3532    if (e_comp_util_object_is_above_nocomp(obj))
3533      {
3534         evas_object_data_set(obj, "comp_override", (void*)1);
3535         e_comp_override_add();
3536      }
3537 }
3538
3539 static void
3540 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
3541 {
3542    if (!evas_object_visible_get(obj)) return;
3543    /* already hiding */
3544    if (evas_object_data_get(obj, "comp_hiding")) return;
3545    if (!evas_object_data_del(obj, "comp_showing"))
3546      {
3547         evas_object_ref(obj);
3548         evas_object_data_set(obj, "comp_ref", (void*)1);
3549      }
3550    edje_object_signal_emit(obj, "e,state,hidden", "e");
3551    evas_object_data_set(obj, "comp_hiding", (void*)1);
3552
3553    if (evas_object_data_del(obj, "comp_override"))
3554      e_comp_override_timed_pop();
3555 }
3556
3557 static void
3558 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
3559 {
3560    if (!e_util_strcmp(emission, "e,action,hide,done"))
3561      {
3562         if (!evas_object_data_del(obj, "comp_hiding")) return;
3563         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
3564         evas_object_hide(obj);
3565         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
3566      }
3567    else
3568      evas_object_data_del(obj, "comp_showing");
3569    if (evas_object_data_del(obj, "comp_ref"))
3570      evas_object_unref(obj);
3571 }
3572
3573 static void
3574 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3575 {
3576    if (data)
3577      {
3578         int w, h;
3579
3580         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3581      }
3582 }
3583
3584 E_API E_Comp_Object_Hook *
3585 e_comp_object_hook_add(E_Comp_Object_Hook_Point hookpoint, E_Comp_Object_Hook_Cb func, const void *data)
3586 {
3587    E_Comp_Object_Hook *ch;
3588
3589    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_HOOK_LAST, NULL);
3590    ch = E_NEW(E_Comp_Object_Hook, 1);
3591    if (!ch) return NULL;
3592    ch->hookpoint = hookpoint;
3593    ch->func = func;
3594    ch->data = (void*)data;
3595    _e_comp_object_hooks[hookpoint] = eina_inlist_append(_e_comp_object_hooks[hookpoint], EINA_INLIST_GET(ch));
3596    return ch;
3597 }
3598
3599 E_API void
3600 e_comp_object_hook_del(E_Comp_Object_Hook *ch)
3601 {
3602    ch->delete_me = 1;
3603    if (_e_comp_object_hooks_walking == 0)
3604      {
3605         _e_comp_object_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3606         free(ch);
3607      }
3608    else
3609      _e_comp_object_hooks_delete++;
3610 }
3611
3612 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
3613 E_API E_Comp_Object_Intercept_Hook *
3614 e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data)
3615 {
3616    E_Comp_Object_Intercept_Hook *ch;
3617
3618    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_INTERCEPT_HOOK_LAST, NULL);
3619    ch = E_NEW(E_Comp_Object_Intercept_Hook, 1);
3620    if (!ch) return NULL;
3621    ch->hookpoint = hookpoint;
3622    ch->func = func;
3623    ch->data = (void*)data;
3624    _e_comp_object_intercept_hooks[hookpoint] = eina_inlist_append(_e_comp_object_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3625    return ch;
3626 }
3627
3628 E_API void
3629 e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch)
3630 {
3631    ch->delete_me = 1;
3632    if (_e_comp_object_intercept_hooks_walking == 0)
3633      {
3634         _e_comp_object_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3635         free(ch);
3636      }
3637    else
3638      _e_comp_object_intercept_hooks_delete++;
3639 }
3640 #endif
3641
3642 E_API Evas_Object *
3643 e_comp_object_util_add(Evas_Object *obj)
3644 {
3645    Evas_Object *o;
3646    const char *name;
3647    E_Comp_Config *conf = e_comp_config_get();
3648    Eina_Bool skip = EINA_FALSE;
3649    char buf[1024];
3650    int ok = 0;
3651    int x, y, w, h;
3652    Eina_Bool vis;
3653
3654    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
3655
3656    name = evas_object_name_get(obj);
3657    vis = evas_object_visible_get(obj);
3658    o = edje_object_add(e_comp->evas);
3659    evas_object_data_set(o, "comp_object", (void*)1);
3660    if (name)
3661      skip = (!strncmp(name, "noshadow", 8));
3662    if (skip)
3663      evas_object_data_set(o, "comp_object_skip", (void*)1);
3664
3665    if (conf->shadow_style)
3666      {
3667         snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
3668         ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3669      }
3670    if (!ok)
3671      e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default");
3672    if (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow")))
3673      edje_object_signal_emit(o, "e,state,shadow,on", "e");
3674    else
3675      edje_object_signal_emit(o, "e,state,shadow,off", "e");
3676
3677    evas_object_geometry_get(obj, &x, &y, &w, &h);
3678    evas_object_geometry_set(o, x, y, w, h);
3679    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
3680
3681    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, NULL);
3682
3683    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, NULL);
3684    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, NULL);
3685    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, NULL);
3686    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3687    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, NULL);
3688    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, NULL);
3689
3690    e_comp_object_signal_emit(o, "e,state,hidden", "e");
3691
3692    edje_object_part_swallow(o, "e.swallow.content", obj);
3693
3694    _e_comp_object_event_add(o);
3695
3696    if (vis)
3697      evas_object_show(o);
3698
3699    return o;
3700 }
3701
3702 /* utility functions for deleting objects when their "owner" is deleted */
3703 EINTERN void
3704 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
3705 {
3706    Eina_List *l;
3707
3708    SOFT_ENTRY();
3709    EINA_SAFETY_ON_NULL_RETURN(to_del);
3710    l = evas_object_data_get(obj, "comp_object-to_del");
3711    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
3712    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
3713    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3714 }
3715
3716 EINTERN void
3717 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3718 {
3719    Eina_List *l;
3720
3721    SOFT_ENTRY();
3722    EINA_SAFETY_ON_NULL_RETURN(to_del);
3723    l = evas_object_data_get(obj, "comp_object-to_del");
3724    if (l)
3725      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3726 }
3727
3728 /////////////////////////////////////////////////////////
3729
3730 EINTERN Evas_Object *
3731 e_comp_object_client_add(E_Client *ec)
3732 {
3733    Evas_Object *o;
3734    E_Comp_Object *cw;
3735
3736    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3737    if (ec->frame) return NULL;
3738    _e_comp_smart_init();
3739    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3740    cw = evas_object_smart_data_get(o);
3741    if (!cw) return NULL;
3742    evas_object_data_set(o, "E_Client", ec);
3743    cw->ec = ec;
3744    ec->frame = o;
3745    evas_object_data_set(o, "comp_object", (void*)1);
3746
3747    _e_comp_object_event_add(o);
3748
3749    return o;
3750 }
3751
3752 /* utility functions for getting client inset */
3753 E_API void
3754 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3755 {
3756    API_ENTRY;
3757    if (!cw->client_inset.calc)
3758      {
3759         if (ax) *ax = x;
3760         if (ay) *ay = y;
3761         return;
3762      }
3763    if (ax) *ax = x - cw->client_inset.l;
3764    if (ay) *ay = y - cw->client_inset.t;
3765 }
3766
3767 E_API void
3768 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3769 {
3770    API_ENTRY;
3771    if (!cw->client_inset.calc)
3772      {
3773         if (ax) *ax = x;
3774         if (ay) *ay = y;
3775         return;
3776      }
3777    if (ax) *ax = x + cw->client_inset.l;
3778    if (ay) *ay = y + cw->client_inset.t;
3779 }
3780
3781 E_API void
3782 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3783 {
3784    API_ENTRY;
3785    if (!cw->client_inset.calc)
3786      {
3787         if (aw) *aw = w;
3788         if (ah) *ah = h;
3789         return;
3790      }
3791    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
3792    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
3793 }
3794
3795 E_API void
3796 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3797 {
3798    API_ENTRY;
3799    if (!cw->client_inset.calc)
3800      {
3801         if (aw) *aw = w;
3802         if (ah) *ah = h;
3803         return;
3804      }
3805    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
3806    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
3807 }
3808
3809 E_API E_Client *
3810 e_comp_object_client_get(Evas_Object *obj)
3811 {
3812    Evas_Object *o;
3813
3814    SOFT_ENTRY(NULL);
3815    /* FIXME: remove this when eo is used */
3816    o = evas_object_data_get(obj, "comp_smart_obj");
3817    if (o)
3818      return e_comp_object_client_get(o);
3819    return cw ? cw->ec : NULL;
3820 }
3821
3822 EINTERN void
3823 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3824 {
3825    API_ENTRY;
3826    if (cw->frame_extends)
3827      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
3828    else
3829      {
3830         if (x) *x = 0;
3831         if (y) *y = 0;
3832         if (w) *w  = cw->ec->w;
3833         if (h) *h  = cw->ec->h;
3834      }
3835 }
3836
3837 EINTERN E_Zone *
3838 e_comp_object_util_zone_get(Evas_Object *obj)
3839 {
3840    E_Zone *zone = NULL;
3841
3842    SOFT_ENTRY(NULL);
3843    if (cw)
3844      zone = e_comp_zone_find_by_ec(cw->ec);
3845    if (!zone)
3846      {
3847         int x, y;
3848
3849         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3850         zone = e_comp_zone_xy_get(x, y);
3851      }
3852    return zone;
3853 }
3854
3855 EINTERN void
3856 e_comp_object_util_center(Evas_Object *obj)
3857 {
3858    int x, y, w, h, ow, oh;
3859    E_Zone *zone;
3860
3861    SOFT_ENTRY();
3862
3863    zone = e_comp_object_util_zone_get(obj);
3864    EINA_SAFETY_ON_NULL_RETURN(zone);
3865    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
3866    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3867      ow = cw->ec->w, oh = cw->ec->h;
3868    else
3869      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3870    x = x + (w - ow) / 2;
3871    y = y + (h - oh) / 2;
3872    evas_object_move(obj, x, y);
3873 }
3874
3875 EINTERN void
3876 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
3877 {
3878    int x, y, w, h, ow, oh;
3879
3880    SOFT_ENTRY();
3881    EINA_SAFETY_ON_NULL_RETURN(on);
3882    evas_object_geometry_get(on, &x, &y, &w, &h);
3883    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3884      ow = cw->ec->w, oh = cw->ec->h;
3885    else
3886      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3887    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
3888 }
3889
3890 EINTERN void
3891 e_comp_object_util_fullscreen(Evas_Object *obj)
3892 {
3893    SOFT_ENTRY();
3894
3895    if (cw)
3896      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
3897    else
3898      {
3899         evas_object_move(obj, 0, 0);
3900         evas_object_resize(obj, e_comp->w, e_comp->h);
3901      }
3902 }
3903
3904 EINTERN void
3905 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
3906 {
3907    E_Zone *zone;
3908    int zx, zy, zw, zh;
3909    int ow, oh;
3910    SOFT_ENTRY();
3911
3912    if (cw)
3913      ow = cw->w, oh = cw->h;
3914    else
3915      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3916    zone = e_comp_object_util_zone_get(obj);
3917    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
3918    if (x) *x = zx + (zw - ow) / 2;
3919    if (y) *y = zy + (zh - oh) / 2;
3920 }
3921
3922 EINTERN void
3923 e_comp_object_input_objs_del(Evas_Object *obj)
3924 {
3925    API_ENTRY;
3926    E_Input_Rect_Data *input_rect_data;
3927    E_Input_Rect_Smart_Data *input_rect_sd;
3928
3929    if (!cw->input_obj)
3930      return;
3931
3932    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
3933    if (!input_rect_sd) return;
3934
3935    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
3936      {
3937         if (input_rect_data->obj)
3938           {
3939              evas_object_smart_member_del(input_rect_data->obj);
3940              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
3941           }
3942         E_FREE(input_rect_data);
3943      }
3944 }
3945
3946 E_API void
3947 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
3948 {
3949    API_ENTRY;
3950    E_Input_Rect_Data *input_rect_data = NULL;
3951    E_Input_Rect_Smart_Data *input_rect_sd;
3952    int client_w, client_h;
3953
3954    if (cw->ec->client.w)
3955      client_w = cw->ec->client.w;
3956    else
3957      client_w = cw->ec->w;
3958
3959    if (cw->ec->client.h)
3960      client_h = cw->ec->client.h;
3961    else
3962      client_h = cw->ec->h;
3963
3964    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
3965
3966    if (!cw->input_obj)
3967      {
3968         _e_comp_input_obj_smart_init();
3969         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
3970         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
3971         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
3972
3973         if (input_rect_sd)
3974           input_rect_sd->cw = cw;
3975      }
3976
3977    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
3978    if (input_rect_sd)
3979      {
3980         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
3981         if (input_rect_data)
3982           {
3983              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
3984              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
3985           }
3986      }
3987
3988    if ((input_rect_data) &&
3989        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
3990      {
3991         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
3992         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
3993         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
3994         evas_object_clip_set(input_rect_data->obj, cw->clip);
3995         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
3996         evas_object_geometry_set(input_rect_data->obj,
3997           cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l) + x,
3998           cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t) + y, w, h);
3999         evas_object_pass_events_set(cw->default_input_obj, 1);
4000         evas_object_pass_events_set(cw->obj, 1);
4001         if (cw->visible)
4002           {
4003              evas_object_show(input_rect_data->obj);
4004              evas_object_show(cw->input_obj);
4005           }
4006      }
4007    else
4008      {
4009         evas_object_smart_member_del(cw->input_obj);
4010         E_FREE_FUNC(cw->input_obj, evas_object_del);
4011         evas_object_pass_events_set(cw->default_input_obj, 0);
4012         evas_object_pass_events_set(cw->obj, 0);
4013      }
4014 }
4015
4016 E_API void
4017 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4018 {
4019    API_ENTRY;
4020    E_Input_Rect_Smart_Data *input_rect_sd;
4021    E_Input_Rect_Data *input_rect_data;
4022    Eina_List *l;
4023
4024    if (!cw->input_obj) return;
4025
4026    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4027    if (input_rect_sd)
4028      {
4029         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4030           {
4031              *list = eina_list_append(*list, &input_rect_data->rect);
4032           }
4033      }
4034 }
4035
4036 EINTERN void
4037 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4038 {
4039    API_ENTRY;
4040    if (l) *l = cw->client_inset.l;
4041    if (r) *r = cw->client_inset.r;
4042    if (t) *t = cw->client_inset.t;
4043    if (b) *b = cw->client_inset.b;
4044 }
4045
4046 /* set geometry for CSD */
4047 EINTERN void
4048 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4049 {
4050    Eina_Bool calc;
4051    int tx, ty, tw, th;
4052
4053    API_ENTRY;
4054    if (cw->frame_object)
4055      CRI("ACK! ec:%p", cw->ec);
4056    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4057        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4058    calc = cw->client_inset.calc;
4059    cw->client_inset.calc = l || r || t || b;
4060    eina_stringshare_replace(&cw->frame_theme, "borderless");
4061    if (cw->client_inset.calc)
4062      {
4063         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4064         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4065         e_client_size_set(cw->ec, tw, th);
4066      }
4067    else if (cw->ec->maximized || cw->ec->fullscreen)
4068      {
4069         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4070         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4071      }
4072    if (!cw->ec->new_client)
4073      {
4074         if (calc && cw->client_inset.calc)
4075           {
4076              tx = cw->ec->x - (l - cw->client_inset.l);
4077              ty = cw->ec->y - (t - cw->client_inset.t);
4078              e_client_pos_set(cw->ec, tx, ty);
4079           }
4080         cw->ec->changes.pos = cw->ec->changes.size = 1;
4081         EC_CHANGED(cw->ec);
4082      }
4083    cw->client_inset.l = l;
4084    cw->client_inset.r = r;
4085    cw->client_inset.t = t;
4086    cw->client_inset.b = b;
4087 }
4088
4089 EINTERN Eina_Bool
4090 e_comp_object_frame_allowed(Evas_Object *obj)
4091 {
4092    API_ENTRY EINA_FALSE;
4093    return (cw->frame_object || (!cw->client_inset.calc));
4094 }
4095
4096 EINTERN Eina_Bool
4097 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
4098 {
4099    API_ENTRY EINA_FALSE;
4100    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4101    eina_stringshare_replace(&cw->frame_name, name);
4102    if (cw->frame_object)
4103      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4104    return EINA_TRUE;
4105 }
4106
4107 EINTERN Eina_Bool
4108 e_comp_object_frame_exists(Evas_Object *obj)
4109 {
4110    API_ENTRY EINA_FALSE;
4111    return !!cw->frame_object;
4112 }
4113
4114 EINTERN Eina_Bool
4115 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4116 {
4117    Evas_Object *o, *pbg;
4118    char buf[4096];
4119    int ok;
4120    Eina_Stringshare *theme;
4121
4122    API_ENTRY EINA_FALSE;
4123
4124    if (!e_util_strcmp(cw->frame_theme, name))
4125     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4126    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4127      return _e_comp_object_shadow_setup(cw);
4128    pbg = cw->frame_object;
4129    theme = eina_stringshare_add(name);
4130
4131    if (cw->frame_object)
4132      {
4133         int w, h;
4134
4135         w = cw->ec->w, h = cw->ec->h;
4136         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4137         if ((cw->ec->w != w) || (cw->ec->h != h))
4138           {
4139              cw->ec->changes.size = 1;
4140              EC_CHANGED(cw->ec);
4141           }
4142         E_FREE_FUNC(cw->frame_object, evas_object_del);
4143         if (!name) goto reshadow;
4144      }
4145    o = edje_object_add(e_comp->evas);
4146    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4147    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4148    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4149      {
4150         cw->frame_object = NULL;
4151         evas_object_del(o);
4152         eina_stringshare_del(cw->frame_theme);
4153         cw->frame_theme = theme;
4154         goto reshadow;
4155      }
4156    if (!ok)
4157      {
4158         if (theme != e_config->theme_default_border_style)
4159           {
4160              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4161              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4162           }
4163         if (!ok)
4164           {
4165              ok = e_theme_edje_object_set(o, "base/theme/border",
4166                                           "e/widgets/border/default/border");
4167              if (ok && (theme == e_config->theme_default_border_style))
4168                {
4169                   /* Reset default border style to default */
4170                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4171                   e_config_save_queue();
4172                }
4173           }
4174      }
4175
4176    if (ok)
4177      {
4178         cw->frame_object = o;
4179         eina_stringshare_del(cw->frame_theme);
4180         cw->frame_theme = theme;
4181         evas_object_name_set(o, "cw->frame_object");
4182
4183         if (cw->frame_name)
4184           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4185
4186         if (!pbg)
4187           {
4188              cw->ec->changes.icon = 1;
4189              EC_CHANGED(cw->ec);
4190           }
4191      }
4192    else
4193      {
4194         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4195         evas_object_del(o);
4196      }
4197 reshadow:
4198    if (cw->shobj)
4199      _e_comp_object_shadow_setup(cw);
4200    do
4201      {
4202         int old_x, old_y, new_x = 0, new_y = 0;
4203
4204         old_x = cw->x, old_y = cw->y;
4205
4206         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4207         if (pbg)
4208           new_x = cw->ec->x, new_y = cw->ec->y;
4209         else if (cw->ec->placed || (!cw->ec->new_client))
4210           {
4211              /* if no previous frame:
4212               * - reapply client_inset
4213               * - clamp to zone
4214               */
4215              int x, y;
4216
4217              if (cw->ec->changes.size)
4218                {
4219                   x = cw->ec->x;
4220                   y = cw->ec->y;
4221                }
4222              else
4223                {
4224                   E_Zone *zone;
4225                   zone = e_comp_zone_find_by_ec(cw->ec);
4226                   if (!zone) break;
4227
4228                   x = cw->ec->client.x, y = cw->ec->client.y;
4229                   x = MAX(zone->x, cw->ec->client.x - cw->client_inset.l);
4230                   y = MAX(zone->y, cw->ec->client.y - cw->client_inset.t);
4231                }
4232              new_x = x, new_y = y;
4233           }
4234
4235         if (old_x != new_x || old_y != new_y)
4236           {
4237              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4238              cw->y = cw->x = -99999;
4239              evas_object_move(obj, new_x, new_y);
4240           }
4241      } while (0);
4242
4243    if (cw->ec->maximized)
4244      {
4245         cw->ec->changes.need_maximize = 1;
4246         EC_CHANGED(cw->ec);
4247      }
4248    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4249    if (cw->frame_object)
4250      {
4251         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4252      }
4253    else
4254      cw->frame_extends = 0;
4255    evas_object_del(pbg);
4256    return EINA_TRUE;
4257 }
4258
4259 E_API void
4260 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4261 {
4262    E_Comp_Object_Mover *prov;
4263
4264    API_ENTRY;
4265    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4266    edje_object_signal_emit(cw->shobj, sig, src);
4267    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4268    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4269        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4270      return;
4271    /* start with highest priority callback first */
4272    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4273      {
4274         if (!e_util_glob_match(sig, prov->sig)) continue;
4275         if (prov->func(prov->data, obj, sig)) break;
4276      }
4277 }
4278
4279 E_API void
4280 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4281 {
4282    /* FIXME: at some point I guess this should use eo to inherit
4283     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4284     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4285     */
4286    API_ENTRY;
4287    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4288 }
4289
4290 E_API void
4291 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4292 {
4293    API_ENTRY;
4294    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4295 }
4296
4297 E_API void
4298 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4299 {
4300    API_ENTRY;
4301    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4302 }
4303
4304 E_API void
4305 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4306 {
4307    int tw, th;
4308    Eina_Rectangle rect;
4309    API_ENTRY;
4310
4311    if (cw->ec->input_only || (!cw->updates)) return;
4312    if (cw->nocomp) return;
4313    rect.x = x, rect.y = y;
4314    rect.w = w, rect.h = h;
4315    evas_object_smart_callback_call(obj, "damage", &rect);
4316
4317    if (e_comp_is_on_overlay(cw->ec))
4318      {
4319         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4320         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4321         * E module attempts to block screen update due to the particular policy.
4322         */
4323         if (e_pixmap_resource_get(cw->ec->pixmap))
4324           cw->hwc_need_update = EINA_TRUE;
4325      }
4326
4327    /* ignore overdraw */
4328    if (cw->updates_full)
4329      {
4330         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4331         e_comp_object_render_update_add(obj);
4332
4333         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4334           evas_object_show(cw->smart_obj);
4335
4336         return;
4337      }
4338    /* clip rect to client surface */
4339    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4340    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4341    /* if rect is the total size of the client after clip, clear the updates
4342     * since this is guaranteed to be the whole region anyway
4343     */
4344    eina_tiler_area_size_get(cw->updates, &tw, &th);
4345    if ((w > tw) || (h > th))
4346      {
4347         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4348         eina_tiler_clear(cw->updates);
4349         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4350         x = 0, y = 0;
4351         tw = cw->ec->client.w, th = cw->ec->client.h;
4352      }
4353    if ((!x) && (!y) && (w == tw) && (h == th))
4354      {
4355         eina_tiler_clear(cw->updates);
4356         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4357         cw->updates_full = 1;
4358         cw->update_count = 0;
4359      }
4360    cw->update_count++;
4361    if (cw->update_count > UPDATE_MAX)
4362      {
4363         /* this is going to get really dumb, so just update the whole thing */
4364         eina_tiler_clear(cw->updates);
4365         cw->update_count = cw->updates_full = 1;
4366         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4367         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4368      }
4369    else
4370      {
4371         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4372         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4373      }
4374    cw->updates_exist = 1;
4375    e_comp_object_render_update_add(obj);
4376
4377    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4378      evas_object_show(cw->smart_obj);
4379 }
4380
4381 EINTERN Eina_Bool
4382 e_comp_object_damage_exists(Evas_Object *obj)
4383 {
4384    API_ENTRY EINA_FALSE;
4385    return cw->updates_exist;
4386 }
4387
4388 EINTERN void
4389 e_comp_object_render_update_add(Evas_Object *obj)
4390 {
4391    API_ENTRY;
4392
4393    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4394    if (cw->render_update_lock.lock) return;
4395    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4396    if (!cw->update)
4397      {
4398         cw->update = 1;
4399         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4400      }
4401    e_comp_render_queue();
4402 }
4403
4404 EINTERN void
4405 e_comp_object_render_update_del(Evas_Object *obj)
4406 {
4407    API_ENTRY;
4408
4409    if (cw->ec->input_only || (!cw->updates)) return;
4410    if (!cw->update) return;
4411    cw->update = 0;
4412    /* this gets called during comp animating to clear the update flag */
4413    if (e_comp->grabbed) return;
4414    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4415    if (!e_comp->updates)
4416      {
4417         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4418         if (e_comp->render_animator)
4419           ecore_animator_freeze(e_comp->render_animator);
4420      }
4421 }
4422
4423 EINTERN void
4424 e_comp_object_shape_apply(Evas_Object *obj)
4425 {
4426    Eina_List *l;
4427    Evas_Object *o;
4428    unsigned int i, *pix, *p;
4429    int w, h, px, py;
4430
4431    API_ENTRY;
4432    if (!cw->ec) return; //NYI
4433    if (cw->external_content) return;
4434    if (cw->ec->shaped)
4435      {
4436         if ((cw->ec->shape_rects_num >= 1) &&
4437             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4438            return;
4439      }
4440    if (cw->native)
4441      {
4442         ERR("BUGGER: shape with native surface? cw=%p", cw);
4443         return;
4444      }
4445    evas_object_image_size_get(cw->obj, &w, &h);
4446    if ((w < 1) || (h < 1)) return;
4447
4448    if (cw->ec->shaped)
4449      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4450    _e_comp_object_alpha_set(cw);
4451    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4452       evas_object_image_alpha_set(o, 1);
4453
4454    p = pix = evas_object_image_data_get(cw->obj, 1);
4455    if (!pix)
4456      {
4457         evas_object_image_data_set(cw->obj, pix);
4458         return;
4459      }
4460    if (cw->ec->shaped)
4461      {
4462         unsigned char *spix, *sp;
4463
4464         spix = calloc(w * h, sizeof(unsigned char));
4465         if (!spix) return;
4466         for (i = 0; i < cw->ec->shape_rects_num; i++)
4467           {
4468              int rx, ry, rw, rh;
4469
4470              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4471              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4472              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4473              sp = spix + (w * ry) + rx;
4474              for (py = 0; py < rh; py++)
4475                {
4476                   for (px = 0; px < rw; px++)
4477                     {
4478                        *sp = 0xff; sp++;
4479                     }
4480                   sp += w - rw;
4481                }
4482           }
4483         sp = spix;
4484         for (py = 0; py < h; py++)
4485           {
4486              for (px = 0; px < w; px++)
4487                {
4488                   unsigned int mask, imask;
4489
4490                   mask = ((unsigned int)(*sp)) << 24;
4491                   imask = mask >> 8;
4492                   imask |= imask >> 8;
4493                   imask |= imask >> 8;
4494                   *p = mask | (*p & imask);
4495                   //if (*sp) *p = 0xff000000 | *p;
4496                   //else *p = 0x00000000;
4497                   sp++;
4498                   p++;
4499                }
4500           }
4501         free(spix);
4502      }
4503    else
4504       {
4505          for (py = 0; py < h; py++)
4506            {
4507               for (px = 0; px < w; px++)
4508                 *p |= 0xff000000;
4509            }
4510       }
4511    evas_object_image_data_set(cw->obj, pix);
4512    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4513    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4514      {
4515         evas_object_image_data_set(o, pix);
4516         evas_object_image_data_update_add(o, 0, 0, w, h);
4517      }
4518 // don't need to fix alpha chanel as blending
4519 // should be totally off here regardless of
4520 // alpha channel content
4521 }
4522
4523 static void
4524 _e_comp_object_clear(E_Comp_Object *cw)
4525 {
4526    Eina_List *l;
4527    Evas_Object *o;
4528
4529    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4530
4531    if (cw->render_update_lock.lock) return;
4532
4533    if (cw->ec->pixmap)
4534      e_pixmap_clear(cw->ec->pixmap);
4535    if (cw->native)
4536      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4537    evas_object_image_size_set(cw->obj, 1, 1);
4538    evas_object_image_data_set(cw->obj, NULL);
4539    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4540      {
4541         evas_object_image_size_set(o, 1, 1);
4542         evas_object_image_data_set(o, NULL);
4543      }
4544    cw->native = 0;
4545    e_comp_object_render_update_del(cw->smart_obj);
4546 }
4547
4548 static Eina_Bool
4549 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4550 {
4551     int r, g, b, a;
4552
4553     API_ENTRY EINA_FALSE;
4554
4555     if (cw->transparent.set == set)
4556        return EINA_TRUE;
4557
4558     if (set)
4559       {
4560          evas_object_color_get(obj, &r, &g, &b, &a);
4561          evas_object_color_set(obj, 0, 0, 0, 0);
4562
4563          cw->transparent.user_r = r;
4564          cw->transparent.user_g = g;
4565          cw->transparent.user_b = b;
4566          cw->transparent.user_a = a;
4567
4568          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4569                cw->ec,
4570                cw->transparent.user_r,
4571                cw->transparent.user_g,
4572                cw->transparent.user_b,
4573                cw->transparent.user_a);
4574
4575          cw->transparent.set = EINA_TRUE;
4576       }
4577     else
4578       {
4579          cw->transparent.set = EINA_FALSE;
4580
4581          evas_object_color_set(obj,
4582                                cw->transparent.user_r,
4583                                cw->transparent.user_g,
4584                                cw->transparent.user_b,
4585                                cw->transparent.user_a);
4586
4587          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4588                cw->ec,
4589                cw->transparent.user_r,
4590                cw->transparent.user_g,
4591                cw->transparent.user_b,
4592                cw->transparent.user_a);
4593       }
4594
4595    return EINA_TRUE;
4596 }
4597
4598 /* helper function to simplify toggling of redirection for display servers which support it */
4599 EINTERN void
4600 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4601 {
4602    API_ENTRY;
4603
4604    set = !!set;
4605    if (cw->redirected == set) return;
4606    cw->redirected = set;
4607    if (cw->external_content) return;
4608
4609    e_comp_object_map_update(obj);
4610
4611    if (set)
4612      {
4613         if (cw->updates_exist)
4614           e_comp_object_render_update_add(obj);
4615         else
4616           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4617
4618         _e_comp_object_transparent_set(obj, EINA_FALSE);
4619         evas_object_smart_callback_call(obj, "redirected", NULL);
4620      }
4621    else
4622      {
4623         _e_comp_object_clear(cw);
4624         _e_comp_object_transparent_set(obj, EINA_TRUE);
4625         evas_object_smart_callback_call(obj, "unredirected", NULL);
4626      }
4627 }
4628
4629 static void
4630 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4631 {
4632    E_Comp_Object *cw;
4633    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4634
4635    if (cw->buffer_destroy_listener.notify)
4636      {
4637         cw->buffer_destroy_listener.notify = NULL;
4638         wl_list_remove(&cw->buffer_destroy_listener.link);
4639      }
4640
4641    if (e_object_is_del(E_OBJECT(cw->ec)))
4642      {
4643         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4644           return;
4645      }
4646    else
4647      {
4648         /* if it's current displaying buffer, do not remove its content */
4649         if (!evas_object_visible_get(cw->ec->frame))
4650           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4651      }
4652 }
4653
4654 static void
4655 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4656 {
4657    Eina_List *l;
4658    Evas_Object *o;
4659
4660    if (cw->buffer_destroy_listener.notify)
4661      {
4662         wl_list_remove(&cw->buffer_destroy_listener.link);
4663         cw->buffer_destroy_listener.notify = NULL;
4664      }
4665
4666    if (cw->tbm_surface)
4667      {
4668         tbm_surface_internal_unref(cw->tbm_surface);
4669         cw->tbm_surface = NULL;
4670      }
4671
4672    if (ns)
4673      {
4674         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4675           {
4676              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4677              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4678           }
4679         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4680           {
4681              tbm_surface_internal_ref(ns->data.tbm.buffer);
4682              cw->tbm_surface = ns->data.tbm.buffer;
4683           }
4684      }
4685
4686    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4687    evas_object_image_native_surface_set(cw->obj, ns);
4688    TRACE_DS_END();
4689    if (with_mirror)
4690      {
4691         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4692           {
4693              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4694              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4695              evas_object_image_native_surface_set(o, ns);
4696              TRACE_DS_END();
4697           }
4698      }
4699 }
4700
4701 EINTERN void
4702 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4703 {
4704    Evas_Native_Surface ns;
4705
4706    API_ENTRY;
4707    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4708    if (cw->ec->input_only) return;
4709    if (cw->external_content) return;
4710    if (cw->render_update_lock.lock) return;
4711    set = !!set;
4712
4713    memset(&ns, 0, sizeof(Evas_Native_Surface));
4714
4715    if (set)
4716      {
4717         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4718         set = (!cw->ec->shaped);
4719         if (set)
4720           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4721      }
4722    cw->native = set;
4723
4724    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4725 }
4726
4727 EINTERN void
4728 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4729 {
4730    API_ENTRY;
4731    if (cw->ec->input_only) return;
4732    E_FREE(cw->ns);
4733    if (ns)
4734      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4735    _e_comp_object_alpha_set(cw);
4736    if (cw->native)
4737      e_comp_object_native_surface_set(obj, cw->native);
4738    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4739 }
4740
4741 EINTERN void
4742 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4743 {
4744    API_ENTRY;
4745
4746    set = !!set;
4747
4748    if (cw->blanked == set) return;
4749    cw->blanked = set;
4750    _e_comp_object_alpha_set(cw);
4751    if (set)
4752      {
4753         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4754         evas_object_image_data_set(cw->obj, NULL);
4755         return;
4756      }
4757    if (cw->native)
4758      e_comp_object_native_surface_set(obj, 1);
4759    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4760 }
4761
4762 static void
4763 _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)
4764 {
4765    Evas_Object *o;
4766    int obj_x, obj_y;
4767
4768    if (!_damage_trace) return;
4769
4770    API_ENTRY;
4771
4772    if (!evas_object_visible_get(cw->obj)) return;
4773
4774    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
4775
4776    o = evas_object_rectangle_add(e_comp->evas);
4777    evas_object_layer_set(o, E_LAYER_MAX);
4778    evas_object_name_set(o, "damage_trace");
4779    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
4780    evas_object_resize(o, dmg_w, dmg_h);
4781    evas_object_color_set(o, 0, 128, 0, 128);
4782    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
4783    evas_object_pass_events_set(o, EINA_TRUE);
4784    evas_object_show(o);
4785
4786    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
4787          cw->ec,
4788          dmg_w, dmg_h, dmg_x, dmg_y,
4789          origin->w, origin->h, origin->x, origin->y);
4790
4791    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
4792 }
4793
4794 /* mark an object as dirty and setup damages */
4795 E_API void
4796 e_comp_object_dirty(Evas_Object *obj)
4797 {
4798    Eina_Iterator *it;
4799    Eina_Rectangle *rect;
4800    Eina_List *ll;
4801    Evas_Object *o;
4802    int w, h, tw, th;
4803    Eina_Bool dirty, visible;
4804    E_Map *m = NULL;
4805
4806    API_ENTRY;
4807    if (cw->external_content) return;
4808    if (!cw->redirected) return;
4809    if (cw->render_update_lock.lock)
4810      {
4811         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4812         return;
4813      }
4814    /* only actually dirty if pixmap is available */
4815    if (!e_pixmap_resource_get(cw->ec->pixmap))
4816      {
4817         // e_pixmap_size_get returns last attached buffer size
4818         // eventhough it is destroyed
4819         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
4820         return;
4821      }
4822    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4823    visible = cw->visible;
4824    if (!dirty) w = h = 1;
4825    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4826    if (!dirty)
4827      evas_object_image_data_set(cw->obj, NULL);
4828    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4829    evas_object_image_size_set(cw->obj, tw, th);
4830    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
4831    if (cw->pending_updates)
4832      eina_tiler_area_size_set(cw->pending_updates, w, h);
4833    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4834      {
4835         evas_object_image_pixels_dirty_set(o, dirty);
4836         if (!dirty)
4837           evas_object_image_data_set(o, NULL);
4838         evas_object_image_size_set(o, tw, th);
4839         visible |= evas_object_visible_get(o);
4840      }
4841    if (!dirty)
4842      {
4843         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4844         return;
4845      }
4846
4847    e_comp_object_native_surface_set(obj, 1);
4848
4849    m = _e_comp_object_map_damage_transform_get(cw->ec);
4850    it = eina_tiler_iterator_new(cw->updates);
4851    EINA_ITERATOR_FOREACH(it, rect)
4852      {
4853         /* evas converts damage according to rotation of ecore_evas in damage_region_set
4854          * of evas engine and doesn't convert damage according to evas_map.
4855          * so damage of evas_object_image use surface coordinate.
4856          */
4857         if (m)
4858           {
4859              int damage_x, damage_y, damage_w, damage_h;
4860
4861              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
4862                                                       &damage_x, &damage_y, &damage_w, &damage_h);
4863              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
4864              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
4865           }
4866         else
4867           {
4868              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4869              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
4870           }
4871
4872         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4873           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4874         if (cw->pending_updates)
4875           eina_tiler_rect_add(cw->pending_updates, rect);
4876      }
4877    eina_iterator_free(it);
4878    if (m) e_map_free(m);
4879    if (cw->pending_updates)
4880      eina_tiler_clear(cw->updates);
4881    else
4882      {
4883         cw->pending_updates = cw->updates;
4884         cw->updates = eina_tiler_new(w, h);
4885         eina_tiler_tile_size_set(cw->updates, 1, 1);
4886      }
4887    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4888    evas_object_smart_callback_call(obj, "dirty", NULL);
4889    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4890    /* force render if main object is hidden but mirrors are visible */
4891    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4892    e_comp_object_render(obj);
4893 }
4894
4895 E_API Eina_Bool
4896 e_comp_object_render(Evas_Object *obj)
4897 {
4898    Eina_List *l;
4899    Evas_Object *o;
4900    int pw, ph;
4901    unsigned int *pix;
4902
4903    API_ENTRY EINA_FALSE;
4904
4905    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
4906    if (cw->ec->input_only) return EINA_TRUE;
4907    if (cw->external_content) return EINA_TRUE;
4908    if (cw->native) return EINA_FALSE;
4909    /* if comp object is not redirected state, comp object should not be set by newly committed data
4910       because image size of comp object is 1x1 and it should not be shown on canvas */
4911    if (!cw->redirected) return EINA_TRUE;
4912    if (cw->render_update_lock.lock)
4913      {
4914         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4915         return EINA_TRUE;
4916      }
4917    e_comp_object_render_update_del(obj);
4918    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
4919
4920    if (!cw->pending_updates)
4921      {
4922         WRN("RENDER [%p]: NO RECTS!", cw->ec);
4923         evas_object_image_data_set(cw->obj, NULL);
4924         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4925           evas_object_image_data_set(o, NULL);
4926         return EINA_FALSE;
4927      }
4928
4929    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
4930
4931    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
4932
4933    pix = e_pixmap_image_data_get(cw->ec->pixmap);
4934    if (!pix)
4935      {
4936         e_pixmap_image_refresh(cw->ec->pixmap);
4937         pix = e_pixmap_image_data_get(cw->ec->pixmap);
4938      }
4939
4940    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
4941      e_pixmap_image_data_ref(cw->ec->pixmap);
4942
4943    /* set pixel data */
4944    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
4945    _e_comp_object_alpha_set(cw);
4946    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4947      {
4948         evas_object_image_data_set(o, pix);
4949         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
4950         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
4951      }
4952
4953    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
4954
4955    e_comp_client_post_update_add(cw->ec);
4956
4957    return EINA_TRUE;
4958 }
4959
4960 /* create a duplicate of an evas object */
4961 E_API Evas_Object *
4962 e_comp_object_util_mirror_add(Evas_Object *obj)
4963 {
4964    Evas_Object *o;
4965    int w, h, tw, th;
4966    unsigned int *pix = NULL;
4967    Eina_Bool argb = EINA_FALSE;
4968
4969    SOFT_ENTRY(NULL);
4970
4971    if (!cw)
4972      cw = evas_object_data_get(obj, "comp_mirror");
4973    if (!cw)
4974      {
4975         o = evas_object_image_filled_add(evas_object_evas_get(obj));
4976         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
4977         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
4978         evas_object_image_alpha_set(o, 1);
4979         evas_object_image_source_set(o, obj);
4980         return o;
4981      }
4982    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
4983    if (cw->external_content)
4984      {
4985         ERR("%p of client %p is external content.", obj, cw->ec);
4986         return NULL;
4987      }
4988    o = evas_object_image_filled_add(evas_object_evas_get(obj));
4989    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
4990    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
4991    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
4992    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
4993    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
4994    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
4995    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
4996    evas_object_data_set(o, "comp_mirror", cw);
4997
4998    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
4999    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5000
5001    evas_object_image_size_set(o, tw, th);
5002
5003    if (cw->ec->shaped)
5004      pix = evas_object_image_data_get(cw->obj, 0);
5005    else
5006      {
5007         if (cw->native)
5008           {
5009              if (cw->ns)
5010                evas_object_image_native_surface_set(o, cw->ns);
5011              else
5012                {
5013                   Evas_Native_Surface ns;
5014                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5015                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5016                     evas_object_image_native_surface_set(o, &ns);
5017                }
5018           }
5019         else
5020           {
5021              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5022              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5023              if ((argb) &&
5024                  (e_pixmap_image_exists(cw->ec->pixmap)))
5025                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5026              else
5027                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5028           }
5029      }
5030    if (pix)
5031      {
5032       Eina_Bool dirty;
5033
5034       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5035       evas_object_image_pixels_dirty_set(o, dirty);
5036       evas_object_image_data_set(o, pix);
5037       evas_object_image_data_set(cw->obj, pix);
5038       if (dirty)
5039         evas_object_image_data_update_add(o, 0, 0, tw, th);
5040    }
5041    return o;
5042 }
5043
5044 //////////////////////////////////////////////////////
5045
5046 EINTERN Eina_Bool
5047 e_comp_object_effect_allowed_get(Evas_Object *obj)
5048 {
5049    API_ENTRY EINA_FALSE;
5050
5051    if (!cw->shobj) return EINA_FALSE;
5052    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5053    return !e_comp_config_get()->match.disable_borders;
5054 }
5055
5056 /* setup an api effect for a client */
5057 E_API Eina_Bool
5058 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5059 {
5060    char buf[4096];
5061    Eina_Stringshare *grp;
5062    E_Comp_Config *config;
5063    Eina_Bool loaded = EINA_FALSE;
5064
5065    API_ENTRY EINA_FALSE;
5066    if (!cw->shobj) return EINA_FALSE; //input window
5067
5068    if (!effect) effect = "none";
5069    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5070
5071    config = e_comp_config_get();
5072    if ((config) && (config->effect_file))
5073      {
5074         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5075           {
5076              cw->effect_set = EINA_TRUE;
5077              loaded = EINA_TRUE;
5078           }
5079      }
5080
5081    if (!loaded)
5082      {
5083         edje_object_file_get(cw->effect_obj, NULL, &grp);
5084         cw->effect_set = !eina_streq(effect, "none");
5085         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5086         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5087           {
5088              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5089              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5090                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5091                  {
5092                     if (cw->effect_running)
5093                       {
5094                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5095                            return EINA_FALSE;
5096                       }
5097                     cw->effect_set = EINA_FALSE;
5098                     return cw->effect_set;
5099                  }
5100           }
5101      }
5102    if (cw->effect_running)
5103      {
5104         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5105           return EINA_FALSE;
5106      }
5107    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5108    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5109    if (cw->effect_clip)
5110      {
5111         evas_object_clip_unset(cw->clip);
5112         cw->effect_clip = 0;
5113      }
5114    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5115
5116    _e_comp_object_dim_update(cw);
5117
5118    return cw->effect_set;
5119 }
5120
5121 /* set params for embryo scripts in effect */
5122 E_API void
5123 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5124 {
5125    Edje_Message_Int_Set *msg;
5126    unsigned int x;
5127
5128    API_ENTRY;
5129    EINA_SAFETY_ON_NULL_RETURN(params);
5130    EINA_SAFETY_ON_FALSE_RETURN(count);
5131    if (!cw->effect_set) return;
5132
5133    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5134    msg->count = (int)count;
5135    for (x = 0; x < count; x++)
5136       msg->val[x] = params[x];
5137    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5138    edje_object_message_signal_process(cw->effect_obj);
5139 }
5140
5141 static void
5142 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5143 {
5144    Edje_Signal_Cb end_cb;
5145    void *end_data;
5146    E_Comp_Object *cw = data;
5147
5148    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5149    cw->effect_running = 0;
5150    if (!_e_comp_object_animating_end(cw)) return;
5151
5152    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5153      {
5154         evas_object_data_del(cw->smart_obj, "effect_running");
5155         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5156         e_comp_visibility_calculation_set(EINA_TRUE);
5157      }
5158
5159    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5160    if (!end_cb) return;
5161    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5162    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5163    end_cb(end_data, cw->smart_obj, emission, source);
5164 }
5165
5166 /* clip effect to client's zone */
5167 EINTERN void
5168 e_comp_object_effect_clip(Evas_Object *obj)
5169 {
5170    API_ENTRY;
5171    E_Zone *zone;
5172    zone = e_comp_zone_find_by_ec(cw->ec);
5173    if (!zone) return;
5174    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5175    if (!cw->effect_clip_able) return;
5176    evas_object_clip_set(cw->smart_obj, zone->bg_clip_object);
5177    cw->effect_clip = 1;
5178 }
5179
5180 /* unclip effect from client's zone */
5181 EINTERN void
5182 e_comp_object_effect_unclip(Evas_Object *obj)
5183 {
5184    API_ENTRY;
5185    if (!cw->effect_clip) return;
5186    evas_object_clip_unset(cw->smart_obj);
5187    cw->effect_clip = 0;
5188 }
5189
5190 /* start effect, running end_cb after */
5191 E_API Eina_Bool
5192 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5193 {
5194    API_ENTRY EINA_FALSE;
5195    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5196    if (!cw->effect_set) return EINA_FALSE;
5197
5198    if (cw->effect_running)
5199      {
5200         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5201      }
5202
5203    e_comp_object_effect_clip(obj);
5204    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5205
5206    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5207    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5208    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5209    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5210
5211    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5212    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5213
5214    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5215    _e_comp_object_animating_begin(cw);
5216    cw->effect_running = 1;
5217    return EINA_TRUE;
5218 }
5219
5220 /* stop a currently-running effect immediately */
5221 E_API Eina_Bool
5222 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5223 {
5224    int ret = 0;
5225    Edje_Signal_Cb end_cb_before = NULL;
5226    void *end_data_before = NULL;
5227    API_ENTRY EINA_FALSE;
5228
5229    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5230    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5231
5232    if (end_cb_before != end_cb) return EINA_TRUE;
5233    e_comp_object_effect_unclip(obj);
5234    if (cw->effect_clip)
5235      {
5236         evas_object_clip_unset(cw->effect_obj);
5237         cw->effect_clip = 0;
5238      }
5239    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5240    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5241
5242    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5243      {
5244         evas_object_data_del(cw->smart_obj, "effect_running");
5245         e_comp_visibility_calculation_set(EINA_TRUE);
5246      }
5247
5248    cw->effect_running = 0;
5249    ret = _e_comp_object_animating_end(cw);
5250
5251    if ((ret) && (end_cb_before))
5252      {
5253         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5254         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5255      }
5256
5257    return ret;
5258 }
5259
5260 static int
5261 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5262 {
5263    return a->pri - b->pri;
5264 }
5265
5266 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5267 E_API E_Comp_Object_Mover *
5268 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5269 {
5270    E_Comp_Object_Mover *prov;
5271
5272    prov = E_NEW(E_Comp_Object_Mover, 1);
5273    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5274    prov->func = provider;
5275    prov->data = (void*)data;
5276    prov->pri = pri;
5277    prov->sig = sig;
5278    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5279      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5280    return prov;
5281 }
5282
5283 E_API void
5284 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5285 {
5286    EINA_SAFETY_ON_NULL_RETURN(prov);
5287    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5288    free(prov);
5289 }
5290
5291 E_API Evas_Object *
5292 e_comp_object_effect_object_get(Evas_Object *obj)
5293 {
5294    API_ENTRY NULL;
5295
5296    return cw->effect_obj;
5297 }
5298
5299 E_API Eina_Bool
5300 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5301 {
5302    API_ENTRY EINA_FALSE;
5303    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5304    if (!cw->effect_set) return EINA_FALSE;
5305
5306    cw->hiding = set;
5307
5308    return EINA_TRUE;
5309 }
5310
5311 ////////////////////////////////////
5312
5313 static void
5314 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5315 {
5316    if (e_comp->autoclose.obj)
5317      {
5318         e_comp_ungrab_input(0, 1);
5319         if (e_comp->autoclose.del_cb)
5320           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5321         else if (!already_del)
5322           {
5323              evas_object_hide(e_comp->autoclose.obj);
5324              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5325           }
5326         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5327      }
5328    e_comp->autoclose.obj = NULL;
5329    e_comp->autoclose.data = NULL;
5330    e_comp->autoclose.del_cb = NULL;
5331    e_comp->autoclose.key_cb = NULL;
5332    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5333 }
5334
5335 static void
5336 _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)
5337 {
5338    _e_comp_object_autoclose_cleanup(0);
5339 }
5340
5341 static void
5342 _e_comp_object_autoclose_setup(Evas_Object *obj)
5343 {
5344    if (!e_comp->autoclose.rect)
5345      {
5346         /* create rect just below autoclose object to catch mouse events */
5347         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5348         evas_object_move(e_comp->autoclose.rect, 0, 0);
5349         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5350         evas_object_show(e_comp->autoclose.rect);
5351         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5352         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5353         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5354         e_comp_grab_input(0, 1);
5355      }
5356    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5357    evas_object_focus_set(obj, 1);
5358 }
5359
5360 static void
5361 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5362 {
5363    _e_comp_object_autoclose_setup(obj);
5364    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5365 }
5366
5367 static void
5368 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5369 {
5370    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5371    _e_comp_object_autoclose_cleanup(1);
5372    if (e_client_focused_get()) return;
5373
5374    E_Zone *zone = e_zone_current_get();
5375    if (!zone) return;
5376
5377    e_zone_focus_reset(zone);
5378 }
5379
5380 EINTERN void
5381 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5382 {
5383    SOFT_ENTRY();
5384
5385    if (e_comp->autoclose.obj)
5386      {
5387         if (e_comp->autoclose.obj == obj) return;
5388         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5389         e_comp->autoclose.obj = obj;
5390         e_comp->autoclose.del_cb = del_cb;
5391         e_comp->autoclose.key_cb = cb;
5392         e_comp->autoclose.data = (void*)data;
5393         if (evas_object_visible_get(obj))
5394           _e_comp_object_autoclose_setup(obj);
5395         else
5396           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5397         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5398         return;
5399      }
5400    e_comp->autoclose.obj = obj;
5401    e_comp->autoclose.del_cb = del_cb;
5402    e_comp->autoclose.key_cb = cb;
5403    e_comp->autoclose.data = (void*)data;
5404    if (evas_object_visible_get(obj))
5405      _e_comp_object_autoclose_setup(obj);
5406    else
5407      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5408    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5409 }
5410
5411 E_API unsigned int
5412 e_comp_object_is_animating(Evas_Object *obj)
5413 {
5414    API_ENTRY 0;
5415
5416    return cw->animating;
5417 }
5418
5419 E_API void
5420 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5421 {
5422    API_ENTRY;
5423
5424    if ((cw->external_content) &&
5425        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5426      {
5427         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5428             "But current external content is %d object for %p.",
5429             cw->content_type, cw->ec);
5430         return;
5431      }
5432
5433    cw->user_alpha_set = EINA_TRUE;
5434    cw->user_alpha = alpha;
5435
5436    if (!cw->obj) return;
5437
5438    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5439
5440    evas_object_image_alpha_set(cw->obj, alpha);
5441
5442    if ((!cw->native) && (!cw->external_content))
5443      evas_object_image_data_set(cw->obj, NULL);
5444 }
5445
5446 EINTERN Eina_Bool
5447 e_comp_object_alpha_get(Evas_Object *obj)
5448 {
5449    API_ENTRY EINA_FALSE;
5450
5451    return evas_object_image_alpha_get(cw->obj);
5452 }
5453
5454 E_API void
5455 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5456 {
5457    Eina_Bool mask_set = EINA_FALSE;
5458    Evas_Object *o;
5459
5460    API_ENTRY;
5461    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5462    if (cw->ec->input_only) return;
5463    mask_set = !!set;
5464
5465    if (mask_set)
5466      {
5467         if (!cw->mask.obj)
5468           {
5469              o = evas_object_rectangle_add(e_comp->evas);
5470              evas_object_color_set(o, 0, 0, 0, 0);
5471              evas_object_clip_set(o, cw->clip);
5472              evas_object_smart_member_add(o, obj);
5473              evas_object_move(o, 0, 0);
5474              evas_object_resize(o, cw->w, cw->h);
5475              /* save render op value to restore when clear a mask.
5476               *
5477               * NOTE: DO NOT change the render op on ec->frame while mask object
5478               * is set. it will overwrite the changed op value. */
5479              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5480              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5481              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5482              if (cw->visible) evas_object_show(o);
5483
5484              cw->mask.obj = o;
5485              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5486              ELOGF("COMP", "         |mask_obj", cw->ec);
5487              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5488           }
5489      }
5490    else
5491      {
5492         if (cw->mask.obj)
5493           {
5494              evas_object_smart_member_del(cw->mask.obj);
5495              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5496
5497              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5498              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5499           }
5500      }
5501 }
5502
5503 E_API Eina_Bool
5504 e_comp_object_mask_has(Evas_Object *obj)
5505 {
5506    API_ENTRY EINA_FALSE;
5507
5508    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5509 }
5510
5511 EINTERN void
5512 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5513 {
5514    int tw, th;
5515    API_ENTRY;
5516
5517    if ((cw->external_content) &&
5518        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5519      {
5520         WRN("Can set up size to ONLY evas \"image\" object. "
5521             "But current external content is %d object for %p.",
5522             cw->content_type, cw->ec);
5523         return;
5524      }
5525
5526    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5527
5528    evas_object_image_size_set(cw->obj, tw, th);
5529 }
5530
5531 E_API void
5532 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5533 {
5534    Eina_Bool transform_set = EINA_FALSE;
5535    API_ENTRY;
5536    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5537    if (cw->ec->input_only) return;
5538
5539    transform_set = !!set;
5540
5541    if (transform_set)
5542      {
5543         if (!cw->transform_bg_obj)
5544           {
5545              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5546              evas_object_move(o, 0, 0);
5547              evas_object_resize(o, 1, 1);
5548              if (cw->transform_bg_color.a >= 255)
5549                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5550              else
5551                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5552              evas_object_color_set(o,
5553                                    cw->transform_bg_color.r,
5554                                    cw->transform_bg_color.g,
5555                                    cw->transform_bg_color.b,
5556                                    cw->transform_bg_color.a);
5557              if (cw->visible) evas_object_show(o);
5558
5559              cw->transform_bg_obj = o;
5560              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5561           }
5562 #ifdef REFACTOR_DESK_AREA
5563         e_comp_object_transform_obj_stack_update(obj);
5564 #else
5565         _e_comp_object_transform_obj_stack_update(obj);
5566 #endif
5567      }
5568    else
5569      {
5570         if (cw->transform_bg_obj)
5571           {
5572              evas_object_smart_member_del(cw->transform_bg_obj);
5573              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5574           }
5575      }
5576 }
5577
5578 E_API void
5579 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5580 {
5581    API_ENTRY;
5582
5583    cw->transform_bg_color.r = r;
5584    cw->transform_bg_color.g = g;
5585    cw->transform_bg_color.b = b;
5586    cw->transform_bg_color.a = a;
5587
5588    if (cw->transform_bg_obj)
5589      {
5590         evas_object_color_set(cw->transform_bg_obj,
5591                               cw->transform_bg_color.r,
5592                               cw->transform_bg_color.g,
5593                               cw->transform_bg_color.b,
5594                               cw->transform_bg_color.a);
5595      }
5596 }
5597
5598 EINTERN void
5599 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5600 {
5601    API_ENTRY;
5602    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5603    if (cw->ec->input_only) return;
5604    if (!cw->transform_bg_obj) return;
5605
5606    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5607 }
5608
5609 EINTERN void
5610 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5611 {
5612    API_ENTRY;
5613    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5614    if (cw->ec->input_only) return;
5615    if (!cw->transform_bg_obj) return;
5616
5617    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5618 }
5619
5620 E_API void
5621 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5622 {
5623    Eina_Bool transform_set = EINA_FALSE;
5624    API_ENTRY;
5625    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5626    if (cw->ec->input_only) return;
5627
5628    transform_set = !!set;
5629
5630    if (transform_set)
5631      {
5632         if (!cw->transform_tranp_obj)
5633           {
5634              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5635              evas_object_move(o, 0, 0);
5636              evas_object_resize(o, 1, 1);
5637              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5638              evas_object_color_set(o, 0, 0, 0, 0);
5639              if (cw->visible) evas_object_show(o);
5640
5641              cw->transform_tranp_obj = o;
5642              evas_object_pass_events_set(cw->transform_tranp_obj, EINA_TRUE);
5643              ELOGF("TRANSFORM","transform set: TRUE", cw->ec);
5644              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5645           }
5646 #ifdef REFACTOR_DESK_AREA
5647         e_comp_object_transform_obj_stack_update(obj);
5648 #else
5649         _e_comp_object_transform_obj_stack_update(obj);
5650 #endif
5651      }
5652    else
5653      {
5654         if (cw->transform_tranp_obj)
5655           {
5656              ELOGF("TRANSFORM","transform set: FALSE", cw->ec);
5657              evas_object_smart_member_del(cw->transform_tranp_obj);
5658              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5659           }
5660      }
5661 }
5662
5663 EINTERN void
5664 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5665 {
5666    API_ENTRY;
5667    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5668    if (cw->ec->input_only) return;
5669    if (!cw->transform_tranp_obj) return;
5670
5671    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5672 }
5673
5674 EINTERN void
5675 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5676 {
5677    API_ENTRY;
5678    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5679    if (cw->ec->input_only) return;
5680    if (!cw->transform_tranp_obj) return;
5681
5682    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5683 }
5684
5685 #ifdef REFACTOR_DESK_AREA
5686 #else
5687 EINTERN void
5688 e_comp_object_layer_update(Evas_Object *obj,
5689                            Evas_Object *above, Evas_Object *below)
5690 {
5691    E_Comp_Object *cw2 = NULL;
5692    Evas_Object *o = NULL;
5693    short layer;
5694
5695    API_ENTRY;
5696
5697    if (cw->ec->layer_block) return;
5698    if ((above) && (below))
5699      {
5700         ERR("Invalid layer update request! cw=%p", cw);
5701         return;
5702      }
5703
5704    o = above?:below;
5705
5706    if (o)
5707      {
5708         layer = evas_object_layer_get(o);
5709         cw2 = evas_object_data_get(o, "comp_obj");
5710         while (!cw2)
5711           {
5712              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5713
5714              o = evas_object_above_get(o);
5715              if ((!o) || (o == cw->smart_obj)) break;
5716              if (evas_object_layer_get(o) != layer)
5717                {
5718                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5719                }
5720              if (!o)
5721                {
5722                   E_Client *ec;
5723                   ec = e_client_top_get();
5724                   if (ec) o = ec->frame;
5725                }
5726
5727              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5728           }
5729      }
5730
5731    _e_comp_object_layers_remove(cw);
5732    if (cw2)
5733      {
5734         if (cw2->layer > cw->layer)
5735           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5736         else if (cw2->layer == cw->layer)
5737           {
5738              if (above)
5739                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5740              else if (o == obj)
5741                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5742              else if (below)
5743                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5744           }
5745         else
5746           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5747      }
5748    else
5749      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5750 }
5751 #endif
5752
5753 EINTERN int
5754 e_comp_object_layer_get(Evas_Object *obj)
5755 {
5756    API_ENTRY -1;
5757    return cw->layer;
5758 }
5759
5760 E_API Eina_Bool
5761 e_comp_object_content_set(Evas_Object *obj,
5762                           Evas_Object *content,
5763                           E_Comp_Object_Content_Type type)
5764 {
5765    API_ENTRY EINA_FALSE;
5766
5767    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5768    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5769    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5770
5771    if (cw->obj)
5772      {
5773         ERR("Can't set e.swallow.content to requested content. "
5774             "Previous comp object should not be changed at all.");
5775         return EINA_FALSE;
5776      }
5777
5778    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5779
5780    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5781        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5782      {
5783         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5784             type, content, cw->ec, cw->ec->pixmap);
5785         return EINA_FALSE;
5786      }
5787
5788    cw->external_content = EINA_TRUE;
5789
5790    cw->obj = content;
5791    cw->content_type = type;
5792    e_util_size_debug_set(cw->obj, 1);
5793    evas_object_name_set(cw->obj, "cw->obj");
5794    _e_comp_object_alpha_set(cw);
5795
5796    if (cw->shobj)
5797      _e_comp_object_shadow_setup(cw);
5798
5799    wl_signal_emit_mutable(&cw->events.content_type_set, NULL);
5800
5801    return EINA_TRUE;
5802 }
5803
5804 EINTERN Eina_Bool
5805 e_comp_object_content_unset(Evas_Object *obj)
5806 {
5807    API_ENTRY EINA_FALSE;
5808
5809    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5810    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5811
5812    if (!cw->obj && !cw->ec->visible)
5813      {
5814         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
5815         return EINA_TRUE;
5816      }
5817
5818    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5819      {
5820         ELOGF("COMP", "has been set to internal image object already", cw->ec);
5821         return EINA_TRUE;
5822      }
5823
5824    if (cw->obj)
5825      {
5826         if (cw->frame_object)
5827           edje_object_part_unswallow(cw->frame_object, cw->obj);
5828         else if (cw->shobj)
5829           edje_object_part_unswallow(cw->shobj, cw->obj);
5830
5831         evas_object_del(cw->obj);
5832         evas_object_hide(cw->obj);
5833         cw->obj = NULL;
5834      }
5835
5836    cw->external_content = EINA_FALSE;
5837    if (cw->ec->is_cursor)
5838      {
5839         int pw, ph;
5840         DBG("%p is cursor surface..", cw->ec);
5841         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
5842           pw = ph = 1;
5843         evas_object_resize(cw->ec->frame, pw, ph);
5844         evas_object_hide(cw->ec->frame);
5845         return EINA_TRUE;
5846      }
5847
5848
5849    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
5850    cw->obj = evas_object_image_filled_add(e_comp->evas);
5851    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
5852    e_util_size_debug_set(cw->obj, 1);
5853    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
5854    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
5855    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
5856    evas_object_name_set(cw->obj, "cw->obj");
5857    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
5858    _e_comp_object_alpha_set(cw);
5859
5860    if (cw->shobj)
5861      _e_comp_object_shadow_setup(cw);
5862
5863    if (cw->visible)
5864      {
5865         cw->visible = 0;
5866         _e_comp_intercept_show_helper(cw);
5867         cw->visible = 1;
5868      }
5869
5870    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
5871    e_comp_object_dirty(cw->smart_obj);
5872    e_comp_object_render(cw->smart_obj);
5873    e_comp_object_render_update_add(obj);
5874
5875    wl_signal_emit_mutable(&cw->events.content_type_set, NULL);
5876
5877    return EINA_TRUE;
5878 }
5879
5880 EINTERN Evas_Object *
5881 e_comp_object_content_get(Evas_Object *obj)
5882 {
5883    API_ENTRY NULL;
5884
5885    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
5886
5887    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5888      {
5889         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
5890         return NULL;
5891      }
5892
5893    return cw->obj;
5894 }
5895
5896 E_API E_Comp_Object_Content_Type
5897 e_comp_object_content_type_get(Evas_Object *obj)
5898 {
5899    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
5900
5901    return cw->content_type;
5902 }
5903
5904 E_API void
5905 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
5906 {
5907    API_ENTRY;
5908    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5909    E_Comp_Config *conf = e_comp_config_get();
5910    if (cw->ec->input_only) return;
5911    if (!conf->dim_rect_enable) return;
5912
5913    cw->dim.mask_set = mask_set;
5914    cw->dim.mask_x = x;
5915    cw->dim.mask_y = y;
5916    cw->dim.mask_w = w;
5917    cw->dim.mask_h = h;
5918
5919    if (!cw->dim.enable) return;
5920    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
5921 }
5922
5923 EINTERN void
5924 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
5925 {
5926    Eina_Bool mask_set = EINA_FALSE;
5927    Evas_Object *o;
5928
5929    API_ENTRY;
5930    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5931    E_Comp_Config *conf = e_comp_config_get();
5932    if (cw->ec->input_only) return;
5933    if (!conf->dim_rect_enable) return;
5934
5935    mask_set = !!set;
5936
5937    if (mask_set)
5938      {
5939         if (cw->dim.mask_obj)
5940           {
5941              evas_object_smart_member_del(cw->dim.mask_obj);
5942              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
5943           }
5944
5945         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);
5946         o = evas_object_rectangle_add(e_comp->evas);
5947         evas_object_color_set(o, 0, 0, 0, 0);
5948         evas_object_smart_member_add(o, obj);
5949         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
5950         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
5951
5952         evas_object_render_op_set(o, EVAS_RENDER_COPY);
5953         if (cw->visible) evas_object_show(o);
5954
5955         cw->dim.mask_obj = o;
5956         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
5957
5958         evas_object_layer_set(cw->dim.mask_obj, 9998);
5959      }
5960    else
5961      {
5962         if (cw->dim.mask_obj)
5963           {
5964              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
5965              evas_object_smart_member_del(cw->dim.mask_obj);
5966              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
5967           }
5968      }
5969 }
5970
5971 E_API void
5972 e_comp_object_dim_client_set(E_Client *ec)
5973 {
5974    E_Comp_Config *conf = e_comp_config_get();
5975
5976    if (!conf->dim_rect_enable) return ;
5977    if (dim_client == ec) return;
5978
5979    Eina_Bool prev_dim = EINA_FALSE;
5980    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
5981
5982    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
5983       prev_dim = EINA_TRUE;
5984
5985    if (prev_dim && dim_client->visible && ec)
5986      {
5987         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
5988         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
5989      }
5990    else
5991      {
5992         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
5993         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
5994      }
5995    dim_client = ec;
5996 }
5997
5998 EINTERN E_Client *
5999 e_comp_object_dim_client_get(void)
6000 {
6001    E_Comp_Config *conf = e_comp_config_get();
6002
6003    if (!conf->dim_rect_enable ) return NULL;
6004
6005    return dim_client;
6006 }
6007
6008 static void
6009 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6010 {
6011    API_ENTRY;
6012    char emit[32] = "\0";
6013    E_Comp_Config *conf = e_comp_config_get();
6014
6015    if (!ec) return;
6016    if (!conf->dim_rect_enable) return;
6017    if (!cw->effect_obj) return;
6018    if (enable == cw->dim.enable) return;
6019
6020    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6021    if (noeffect || !conf->dim_rect_effect)
6022      {
6023         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6024      }
6025    else
6026      {
6027         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6028      }
6029
6030    cw->dim.enable = enable;
6031
6032    if (cw->dim.mask_set && !enable)
6033      {
6034         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6035         edje_object_signal_emit(cw->effect_obj, emit, "e");
6036      }
6037    else if (cw->dim.mask_set && enable)
6038      {
6039         edje_object_signal_emit(cw->effect_obj, emit, "e");
6040         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6041      }
6042    else
6043      {
6044         edje_object_signal_emit(cw->effect_obj, emit, "e");
6045      }
6046 }
6047
6048 static Eina_Bool
6049 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6050 {
6051    API_ENTRY EINA_FALSE;
6052    E_Comp_Config *conf = e_comp_config_get();
6053
6054    if (!ec) return EINA_FALSE;
6055    if (!conf->dim_rect_enable) return EINA_FALSE;
6056
6057    if (cw->dim.enable) return EINA_TRUE;
6058
6059    return EINA_FALSE;
6060 }
6061
6062 static void
6063 _e_comp_object_dim_update(E_Comp_Object *cw)
6064 {
6065    E_Comp_Config *conf = e_comp_config_get();
6066
6067    if (!cw) return;
6068    if (!conf->dim_rect_enable) return;
6069    if (!cw->effect_obj) return;
6070    if (cw->dim.enable)
6071      {
6072         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6073         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6074
6075         if (cw->dim.mask_set)
6076           {
6077              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6078           }
6079      }
6080 }
6081
6082 EINTERN void
6083 e_comp_object_clear(Evas_Object *obj)
6084 {
6085    API_ENTRY;
6086
6087    _e_comp_object_clear(cw);
6088 }
6089
6090 EINTERN Eina_Bool
6091 e_comp_object_hwc_update_exists(Evas_Object *obj)
6092 {
6093    API_ENTRY EINA_FALSE;
6094    return cw->hwc_need_update;
6095 }
6096
6097 // will remove out
6098 E_API void
6099 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6100 {
6101    API_ENTRY;
6102    cw->hwc_need_update = set;
6103 }
6104
6105 E_API Eina_Bool
6106 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6107 {
6108    API_ENTRY EINA_FALSE;
6109    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6110 }
6111
6112 EINTERN void
6113 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6114 {
6115    API_ENTRY;
6116    if (cw->indicator.obj != indicator)
6117      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6118    cw->indicator.obj = indicator;
6119    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6120 }
6121
6122 EINTERN void
6123 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6124 {
6125    API_ENTRY;
6126    if (cw->indicator.obj != indicator) return;
6127    cw->indicator.obj = NULL;
6128    edje_object_part_unswallow(cw->shobj, indicator);
6129 }
6130
6131 EINTERN void
6132 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6133 {
6134    API_ENTRY;
6135    Edje_Message_Int_Set *msg;
6136
6137    if (!cw->indicator.obj) return;
6138
6139    cw->indicator.w = w;
6140    cw->indicator.h = h;
6141
6142    if (!cw->shobj) return;
6143
6144    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6145    msg->count = 2;
6146    msg->val[0] = w;
6147    msg->val[1] = h;
6148    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6149    edje_object_message_signal_process(cw->shobj);
6150 }
6151
6152 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6153 EINTERN void
6154 e_comp_object_map_update(Evas_Object *obj)
6155 {
6156    API_ENTRY;
6157    E_Client *ec = cw->ec;
6158    E_Comp_Wl_Client_Data *cdata;
6159    E_Map *map;
6160    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6161    char buffer[128];
6162    char *p = buffer;
6163    int l, remain = sizeof buffer;
6164
6165    if (!ec) return;
6166    if (e_object_is_del(E_OBJECT(ec))) return;
6167    cdata = e_client_cdata_get(ec);
6168    if (!cdata) return;
6169
6170    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6171     * when new buffer is attached.
6172     */
6173    if (!cdata->buffer_ref.buffer) return;
6174
6175    if ((!cw->redirected) ||
6176        (e_client_video_hw_composition_check(ec)) ||
6177        (!e_comp_wl_output_buffer_transform_get(ec) &&
6178         cdata->scaler.buffer_viewport.buffer.scale == 1))
6179      {
6180         if (evas_object_map_enable_get(cw->effect_obj))
6181           {
6182              ELOGF("TRANSFORM", "map: disable", cw->ec);
6183              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6184              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6185              evas_object_resize(cw->effect_obj, tw, th);
6186           }
6187
6188         return;
6189      }
6190
6191    map = e_map_new();
6192    EINA_SAFETY_ON_NULL_RETURN(map);
6193
6194    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6195
6196    x1 = y1 = 0;
6197    x2 = bw;
6198    y2 = bh;
6199
6200    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6201
6202    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6203    e_map_point_image_uv_set(map, 0, x, y);
6204    l = snprintf(p, remain, "%d,%d", x, y);
6205    p += l, remain -= l;
6206
6207    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6208    e_map_point_image_uv_set(map, 1, x, y);
6209    l = snprintf(p, remain, " %d,%d", x, y);
6210    p += l, remain -= l;
6211
6212    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6213    e_map_point_image_uv_set(map, 2, x, y);
6214    l = snprintf(p, remain, " %d,%d", x, y);
6215    p += l, remain -= l;
6216
6217    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6218    e_map_point_image_uv_set(map, 3, x, y);
6219    l = snprintf(p, remain, " %d,%d", x, y);
6220    p += l, remain -= l;
6221
6222    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6223          cw->ec,
6224          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6225
6226    e_comp_object_map_set(cw->effect_obj, map);
6227    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6228
6229    e_map_free(map);
6230
6231    /* if there's screen rotation with comp mode, then ec->effect_obj and
6232     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6233     */
6234    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6235    evas_object_resize(cw->effect_obj, tw, th);
6236 }
6237
6238 EINTERN Eina_Bool
6239 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6240 {
6241    API_ENTRY EINA_FALSE;
6242
6243    cw->render_trace = set;
6244
6245    return EINA_TRUE;
6246 }
6247
6248 E_API Eina_Bool
6249 e_comp_object_native_usable_get(Evas_Object *obj)
6250 {
6251    API_ENTRY EINA_FALSE;
6252    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6253
6254    if (cw->ec->input_only) return EINA_FALSE;
6255    if (cw->external_content) return EINA_FALSE;
6256    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6257
6258    /* just return true value, if it is normal case */
6259    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6260
6261    /* abnormal case */
6262    Evas_Native_Surface *ns;
6263    ns = evas_object_image_native_surface_get(cw->obj);
6264
6265    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6266    if (ns)
6267      {
6268         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6269         return EINA_TRUE;
6270      }
6271
6272    return EINA_FALSE;
6273 }
6274
6275 EINTERN Eina_Bool
6276 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6277 {
6278    API_ENTRY EINA_FALSE;
6279    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6280    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6281    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6282
6283    if (cw->image_filter == filter) return EINA_TRUE;
6284
6285    switch (filter)
6286      {
6287       case E_COMP_IMAGE_FILTER_BLUR:
6288          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6289          break;
6290       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6291          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6292          break;
6293       case E_COMP_IMAGE_FILTER_INVERSE:
6294          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6295          break;
6296       case E_COMP_IMAGE_FILTER_NONE:
6297       default:
6298          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6299          break;
6300      }
6301
6302    cw->image_filter = filter;
6303
6304    wl_signal_emit_mutable(&cw->events.image_filter_set, NULL);
6305
6306    return EINA_TRUE;
6307 }
6308
6309 EINTERN E_Comp_Image_Filter
6310 e_comp_object_image_filter_get(Evas_Object *obj)
6311 {
6312    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6313    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6314    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6315    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6316
6317    return cw->image_filter;
6318 }
6319
6320 static void
6321 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6322 {
6323    Evas_Object *obj;
6324
6325    if (!_damage_trace) return;
6326
6327    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6328      evas_object_del(obj);
6329
6330    _damage_trace_post_objs = NULL;
6331 }
6332
6333 static void
6334 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6335 {
6336    if (!_damage_trace) return;
6337
6338    _damage_trace_post_objs = _damage_trace_objs;
6339    _damage_trace_objs = NULL;
6340 }
6341
6342 EINTERN void
6343 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6344 {
6345    if (_damage_trace == onoff) return;
6346
6347    if (onoff)
6348      {
6349         evas_event_callback_add(e_comp->evas,
6350                                 EVAS_CALLBACK_RENDER_PRE,
6351                                 _e_comp_object_damage_trace_render_pre_cb,
6352                                 NULL);
6353
6354         evas_event_callback_add(e_comp->evas,
6355                                 EVAS_CALLBACK_RENDER_POST,
6356                                 _e_comp_object_damage_trace_render_post_cb,
6357                                 NULL);
6358      }
6359    else
6360      {
6361         Evas_Object *obj;
6362
6363         EINA_LIST_FREE(_damage_trace_objs, obj)
6364           evas_object_del(obj);
6365
6366         _damage_trace_objs = NULL;
6367
6368         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6369           evas_object_del(obj);
6370
6371         _damage_trace_post_objs = NULL;
6372
6373         evas_event_callback_del(e_comp->evas,
6374                                 EVAS_CALLBACK_RENDER_PRE,
6375                                 _e_comp_object_damage_trace_render_pre_cb);
6376
6377         evas_event_callback_del(e_comp->evas,
6378                                 EVAS_CALLBACK_RENDER_POST,
6379                                 _e_comp_object_damage_trace_render_post_cb);
6380      }
6381
6382    _damage_trace = onoff;
6383 }
6384
6385 EINTERN Eina_Bool
6386 e_comp_object_redirected_get(Evas_Object *obj)
6387 {
6388    API_ENTRY EINA_FALSE;
6389    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6390
6391    return cw->redirected;
6392 }
6393
6394 EINTERN Eina_Bool
6395 e_comp_object_color_visible_get(Evas_Object *obj)
6396 {
6397    API_ENTRY EINA_FALSE;
6398    int a;
6399
6400    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6401
6402    e_comp_object_color_get(obj, NULL, NULL, NULL, &a);
6403    if (a <= 0)
6404      return EINA_FALSE;
6405
6406    evas_object_color_get(cw->effect_obj, NULL, NULL, NULL, &a);
6407    if (a <= 0)
6408      return EINA_FALSE;
6409
6410    evas_object_color_get(cw->shobj, NULL, NULL, NULL, &a);
6411    if (a <= 0)
6412      return EINA_FALSE;
6413
6414    evas_object_color_get(cw->obj, NULL, NULL, NULL, &a);
6415    if (a <= 0)
6416      return EINA_FALSE;
6417
6418    return EINA_TRUE;
6419 }
6420
6421 E_API Eina_Bool
6422 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6423 {
6424    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6425
6426    return e_map_set_to_comp_object(em, obj);
6427 }
6428
6429 EINTERN E_Map *
6430 e_comp_object_map_get(const Evas_Object *obj)
6431 {
6432    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6433
6434    return e_map_get_from_comp_object(obj);
6435 }
6436
6437 E_API Eina_Bool
6438 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6439 {
6440    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6441
6442    evas_object_map_enable_set(obj, enable);
6443
6444    return EINA_TRUE;
6445 }
6446
6447 E_API Eina_Bool
6448 e_comp_object_render_update_lock(Evas_Object *obj)
6449 {
6450    E_Comp_Wl_Buffer *buffer;
6451    struct wayland_tbm_client_queue *cqueue;
6452
6453    API_ENTRY EINA_FALSE;
6454
6455    if (cw->render_update_lock.lock == 0)
6456      {
6457         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6458
6459         buffer = e_pixmap_resource_get(cw->ec->pixmap);
6460         if ((buffer) && (buffer->resource))
6461           {
6462              cqueue = e_comp_wl_tbm_client_queue_get(cw->ec);
6463              if (cqueue)
6464                wayland_tbm_server_client_queue_flush(cqueue);
6465           }
6466
6467         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, buffer);
6468         e_comp_object_render_update_del(obj);
6469
6470         ELOGF("COMP", "Render update lock enabled", cw->ec);
6471      }
6472
6473    cw->render_update_lock.lock++;
6474
6475    return EINA_TRUE;
6476 }
6477
6478 E_API void
6479 e_comp_object_render_update_unlock(Evas_Object *obj)
6480 {
6481    API_ENTRY;
6482
6483    if (cw->render_update_lock.lock == 0)
6484      return;
6485
6486    cw->render_update_lock.lock--;
6487
6488    if (cw->render_update_lock.lock == 0)
6489      {
6490
6491         if (cw->render_update_lock.pending_move_set)
6492           {
6493              evas_object_move(obj,
6494                               cw->render_update_lock.pending_move_x,
6495                               cw->render_update_lock.pending_move_y);
6496              cw->render_update_lock.pending_move_x = 0;
6497              cw->render_update_lock.pending_move_y = 0;
6498              cw->render_update_lock.pending_move_set = EINA_FALSE;
6499           }
6500
6501         if (cw->render_update_lock.pending_resize_set)
6502           {
6503              evas_object_resize(obj,
6504                                 cw->render_update_lock.pending_resize_w,
6505                                 cw->render_update_lock.pending_resize_h);
6506              cw->render_update_lock.pending_resize_w = 0;
6507              cw->render_update_lock.pending_resize_h = 0;
6508              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6509           }
6510
6511         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6512
6513         if ((cw->ec->exp_iconify.buffer_flush) &&
6514             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6515             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6516           e_comp_object_clear(obj);
6517         else
6518           e_comp_object_render_update_add(obj);
6519
6520         ELOGF("COMP", "Render update lock disabled", cw->ec);
6521      }
6522 }
6523
6524 E_API Eina_Bool
6525 e_comp_object_render_update_lock_get(Evas_Object *obj)
6526 {
6527    API_ENTRY EINA_FALSE;
6528
6529    if (cw->render_update_lock.lock > 0)
6530      return EINA_TRUE;
6531
6532    return EINA_FALSE;
6533 }
6534
6535 E_API void
6536 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6537 {
6538    API_ENTRY;
6539
6540    if (cw->transparent.set)
6541      {
6542         if (r) *r = cw->transparent.user_r;
6543         if (g) *g = cw->transparent.user_g;
6544         if (b) *b = cw->transparent.user_b;
6545         if (a) *a = cw->transparent.user_a;
6546      }
6547    else
6548      {
6549         evas_object_color_get(obj, r, g, b, a);
6550      }
6551 }
6552
6553 EINTERN void
6554 e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op)
6555 {
6556    API_ENTRY;
6557
6558    evas_object_render_op_set(cw->obj, op);
6559
6560    wl_signal_emit_mutable(&cw->events.render_op_set, NULL);
6561 }
6562
6563 EINTERN Evas_Render_Op
6564 e_comp_object_render_op_get(Evas_Object *obj)
6565 {
6566    API_ENTRY EVAS_RENDER_BLEND;
6567
6568    return evas_object_render_op_get(cw->obj);
6569 }
6570
6571 EINTERN void
6572 e_comp_object_lower_listener_add(Evas_Object *obj, struct wl_listener *listener)
6573 {
6574    API_ENTRY;
6575    wl_signal_add(&cw->events.lower, listener);
6576 }
6577
6578 #ifdef REFACTOR_DESK_AREA
6579 EINTERN void
6580 e_comp_object_lower_done_listener_add(Evas_Object *obj, struct wl_listener *listener)
6581 {
6582    API_ENTRY;
6583    wl_signal_add(&cw->events.lower_done, listener);
6584 }
6585
6586 EINTERN void
6587 e_comp_object_raise_listener_add(Evas_Object *obj, struct wl_listener *listener)
6588 {
6589    API_ENTRY;
6590    wl_signal_add(&cw->events.raise, listener);
6591 }
6592 #endif
6593
6594 EINTERN void
6595 e_comp_object_show_listener_add(Evas_Object *obj, struct wl_listener *listener)
6596 {
6597    API_ENTRY;
6598    wl_signal_add(&cw->events.show, listener);
6599 }
6600
6601 EINTERN void
6602 e_comp_object_hide_listener_add(Evas_Object *obj, struct wl_listener *listener)
6603 {
6604    API_ENTRY;
6605    wl_signal_add(&cw->events.hide, listener);
6606 }
6607
6608 #ifdef REFACTOR_DESK_AREA
6609 EINTERN void
6610 e_comp_object_set_layer_listener_add(Evas_Object *obj, struct wl_listener *listener)
6611 {
6612    API_ENTRY;
6613    wl_signal_add(&cw->events.set_layer, listener);
6614 }
6615
6616 EINTERN void
6617 e_comp_object_stack_above_listener_add(Evas_Object *obj, struct wl_listener *listener)
6618 {
6619    API_ENTRY;
6620    wl_signal_add(&cw->events.stack_above, listener);
6621 }
6622
6623 EINTERN void
6624 e_comp_object_stack_below_listener_add(Evas_Object *obj, struct wl_listener *listener)
6625 {
6626    API_ENTRY;
6627    wl_signal_add(&cw->events.stack_below, listener);
6628 }
6629 #endif
6630
6631 EINTERN void
6632 e_comp_object_image_filter_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6633 {
6634    API_ENTRY;
6635    wl_signal_add(&cw->events.image_filter_set, listener);
6636 }
6637
6638 EINTERN void
6639 e_comp_object_render_op_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6640 {
6641    API_ENTRY;
6642    wl_signal_add(&cw->events.render_op_set, listener);
6643 }
6644
6645 EINTERN void
6646 e_comp_object_content_type_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6647 {
6648    API_ENTRY;
6649    wl_signal_add(&cw->events.content_type_set, listener);
6650 }
6651
6652 EINTERN void
6653 e_comp_object_color_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6654 {
6655    API_ENTRY;
6656    wl_signal_add(&cw->events.color_set, listener);
6657 }