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