e_desk_area: enable REFACTOR_DESK_AREA flag
[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_mutable(&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_mutable(&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_mutable(&cw->events.lower_done, NULL);
1950 #else
1951              wl_signal_emit_mutable(&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_mutable(&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_mutable(&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_mutable(&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_mutable(&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_mutable(&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_mutable(&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_mutable(&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_mutable(&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_mutable(&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_title_set(Evas_Object *obj, const char *name)
4195 {
4196    API_ENTRY EINA_FALSE;
4197    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4198    eina_stringshare_replace(&cw->frame_name, name);
4199    if (cw->frame_object)
4200      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4201    return EINA_TRUE;
4202 }
4203
4204 EINTERN Eina_Bool
4205 e_comp_object_frame_exists(Evas_Object *obj)
4206 {
4207    API_ENTRY EINA_FALSE;
4208    return !!cw->frame_object;
4209 }
4210
4211 EINTERN Eina_Bool
4212 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4213 {
4214    Evas_Object *o, *pbg;
4215    char buf[4096];
4216    int ok;
4217    Eina_Stringshare *theme;
4218
4219    API_ENTRY EINA_FALSE;
4220
4221    if (!e_util_strcmp(cw->frame_theme, name))
4222     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4223    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4224      return _e_comp_object_shadow_setup(cw);
4225    pbg = cw->frame_object;
4226    theme = eina_stringshare_add(name);
4227
4228    if (cw->frame_object)
4229      {
4230         int w, h;
4231
4232         w = cw->ec->w, h = cw->ec->h;
4233         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4234         if ((cw->ec->w != w) || (cw->ec->h != h))
4235           {
4236              cw->ec->changes.size = 1;
4237              EC_CHANGED(cw->ec);
4238           }
4239         E_FREE_FUNC(cw->frame_object, evas_object_del);
4240         if (!name) goto reshadow;
4241      }
4242    o = edje_object_add(e_comp->evas);
4243    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4244    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4245    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4246      {
4247         cw->frame_object = NULL;
4248         evas_object_del(o);
4249         eina_stringshare_del(cw->frame_theme);
4250         cw->frame_theme = theme;
4251         goto reshadow;
4252      }
4253    if (!ok)
4254      {
4255         if (theme != e_config->theme_default_border_style)
4256           {
4257              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4258              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4259           }
4260         if (!ok)
4261           {
4262              ok = e_theme_edje_object_set(o, "base/theme/border",
4263                                           "e/widgets/border/default/border");
4264              if (ok && (theme == e_config->theme_default_border_style))
4265                {
4266                   /* Reset default border style to default */
4267                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4268                   e_config_save_queue();
4269                }
4270           }
4271      }
4272
4273    if (ok)
4274      {
4275         cw->frame_object = o;
4276         eina_stringshare_del(cw->frame_theme);
4277         cw->frame_theme = theme;
4278         evas_object_name_set(o, "cw->frame_object");
4279
4280         if (cw->frame_name)
4281           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4282
4283         if (!pbg)
4284           {
4285              cw->ec->changes.icon = 1;
4286              EC_CHANGED(cw->ec);
4287           }
4288      }
4289    else
4290      {
4291         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4292         evas_object_del(o);
4293      }
4294 reshadow:
4295    if (cw->shobj)
4296      _e_comp_object_shadow_setup(cw);
4297    do
4298      {
4299         int old_x, old_y, new_x = 0, new_y = 0;
4300
4301         old_x = cw->x, old_y = cw->y;
4302
4303         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4304         if (pbg)
4305           new_x = cw->ec->x, new_y = cw->ec->y;
4306         else if (cw->ec->placed || (!cw->ec->new_client))
4307           {
4308              /* if no previous frame:
4309               * - reapply client_inset
4310               * - clamp to zone
4311               */
4312              int x, y;
4313
4314              if (cw->ec->changes.size)
4315                {
4316                   x = cw->ec->x;
4317                   y = cw->ec->y;
4318                }
4319              else
4320                {
4321                   E_Zone *zone;
4322                   zone = e_comp_zone_find_by_ec(cw->ec);
4323                   if (!zone) break;
4324
4325                   x = cw->ec->client.x, y = cw->ec->client.y;
4326                   x = MAX(zone->x, cw->ec->client.x - cw->client_inset.l);
4327                   y = MAX(zone->y, cw->ec->client.y - cw->client_inset.t);
4328                }
4329              new_x = x, new_y = y;
4330           }
4331
4332         if (old_x != new_x || old_y != new_y)
4333           {
4334              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4335              cw->y = cw->x = -99999;
4336              evas_object_move(obj, new_x, new_y);
4337           }
4338      } while (0);
4339
4340    if (cw->ec->maximized)
4341      {
4342         cw->ec->changes.need_maximize = 1;
4343         EC_CHANGED(cw->ec);
4344      }
4345    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4346    if (cw->frame_object)
4347      {
4348         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4349      }
4350    else
4351      cw->frame_extends = 0;
4352    evas_object_del(pbg);
4353    return EINA_TRUE;
4354 }
4355
4356 E_API void
4357 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4358 {
4359    E_Comp_Object_Mover *prov;
4360
4361    API_ENTRY;
4362    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4363    edje_object_signal_emit(cw->shobj, sig, src);
4364    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4365    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4366        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4367      return;
4368    /* start with highest priority callback first */
4369    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4370      {
4371         if (!e_util_glob_match(sig, prov->sig)) continue;
4372         if (prov->func(prov->data, obj, sig)) break;
4373      }
4374 }
4375
4376 E_API void
4377 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4378 {
4379    /* FIXME: at some point I guess this should use eo to inherit
4380     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4381     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4382     */
4383    API_ENTRY;
4384    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4385 }
4386
4387 E_API void
4388 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4389 {
4390    API_ENTRY;
4391    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4392 }
4393
4394 E_API void
4395 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4396 {
4397    API_ENTRY;
4398    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4399 }
4400
4401 E_API void
4402 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4403 {
4404    int tw, th;
4405    Eina_Rectangle rect;
4406    API_ENTRY;
4407
4408    if (cw->ec->input_only || (!cw->updates)) return;
4409    if (cw->nocomp) return;
4410    rect.x = x, rect.y = y;
4411    rect.w = w, rect.h = h;
4412    evas_object_smart_callback_call(obj, "damage", &rect);
4413
4414    if (e_comp_is_on_overlay(cw->ec))
4415      {
4416         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4417         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4418         * E module attempts to block screen update due to the particular policy.
4419         */
4420         if (e_pixmap_resource_get(cw->ec->pixmap))
4421           cw->hwc_need_update = EINA_TRUE;
4422      }
4423
4424    /* ignore overdraw */
4425    if (cw->updates_full)
4426      {
4427         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4428         e_comp_object_render_update_add(obj);
4429
4430         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4431           evas_object_show(cw->smart_obj);
4432
4433         return;
4434      }
4435    /* clip rect to client surface */
4436    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4437    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4438    /* if rect is the total size of the client after clip, clear the updates
4439     * since this is guaranteed to be the whole region anyway
4440     */
4441    eina_tiler_area_size_get(cw->updates, &tw, &th);
4442    if ((w > tw) || (h > th))
4443      {
4444         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4445         eina_tiler_clear(cw->updates);
4446         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4447         x = 0, y = 0;
4448         tw = cw->ec->client.w, th = cw->ec->client.h;
4449      }
4450    if ((!x) && (!y) && (w == tw) && (h == th))
4451      {
4452         eina_tiler_clear(cw->updates);
4453         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4454         cw->updates_full = 1;
4455         cw->update_count = 0;
4456      }
4457    cw->update_count++;
4458    if (cw->update_count > UPDATE_MAX)
4459      {
4460         /* this is going to get really dumb, so just update the whole thing */
4461         eina_tiler_clear(cw->updates);
4462         cw->update_count = cw->updates_full = 1;
4463         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4464         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4465      }
4466    else
4467      {
4468         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4469         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4470      }
4471    cw->updates_exist = 1;
4472    e_comp_object_render_update_add(obj);
4473
4474    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4475      evas_object_show(cw->smart_obj);
4476 }
4477
4478 EINTERN Eina_Bool
4479 e_comp_object_damage_exists(Evas_Object *obj)
4480 {
4481    API_ENTRY EINA_FALSE;
4482    return cw->updates_exist;
4483 }
4484
4485 EINTERN void
4486 e_comp_object_render_update_add(Evas_Object *obj)
4487 {
4488    API_ENTRY;
4489
4490    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4491    if (cw->render_update_lock.lock) return;
4492    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4493    if (!cw->update)
4494      {
4495         cw->update = 1;
4496         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4497      }
4498    e_comp_render_queue();
4499 }
4500
4501 EINTERN void
4502 e_comp_object_render_update_del(Evas_Object *obj)
4503 {
4504    API_ENTRY;
4505
4506    if (cw->ec->input_only || (!cw->updates)) return;
4507    if (!cw->update) return;
4508    cw->update = 0;
4509    /* this gets called during comp animating to clear the update flag */
4510    if (e_comp->grabbed) return;
4511    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4512    if (!e_comp->updates)
4513      {
4514         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4515         if (e_comp->render_animator)
4516           ecore_animator_freeze(e_comp->render_animator);
4517      }
4518 }
4519
4520 EINTERN void
4521 e_comp_object_shape_apply(Evas_Object *obj)
4522 {
4523    Eina_List *l;
4524    Evas_Object *o;
4525    unsigned int i, *pix, *p;
4526    int w, h, px, py;
4527
4528    API_ENTRY;
4529    if (!cw->ec) return; //NYI
4530    if (cw->external_content) return;
4531    if (cw->ec->shaped)
4532      {
4533         if ((cw->ec->shape_rects_num >= 1) &&
4534             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4535            return;
4536      }
4537    if (cw->native)
4538      {
4539         ERR("BUGGER: shape with native surface? cw=%p", cw);
4540         return;
4541      }
4542    evas_object_image_size_get(cw->obj, &w, &h);
4543    if ((w < 1) || (h < 1)) return;
4544
4545    if (cw->ec->shaped)
4546      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4547    _e_comp_object_alpha_set(cw);
4548    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4549       evas_object_image_alpha_set(o, 1);
4550
4551    p = pix = evas_object_image_data_get(cw->obj, 1);
4552    if (!pix)
4553      {
4554         evas_object_image_data_set(cw->obj, pix);
4555         return;
4556      }
4557    if (cw->ec->shaped)
4558      {
4559         unsigned char *spix, *sp;
4560
4561         spix = calloc(w * h, sizeof(unsigned char));
4562         if (!spix) return;
4563         for (i = 0; i < cw->ec->shape_rects_num; i++)
4564           {
4565              int rx, ry, rw, rh;
4566
4567              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4568              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4569              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4570              sp = spix + (w * ry) + rx;
4571              for (py = 0; py < rh; py++)
4572                {
4573                   for (px = 0; px < rw; px++)
4574                     {
4575                        *sp = 0xff; sp++;
4576                     }
4577                   sp += w - rw;
4578                }
4579           }
4580         sp = spix;
4581         for (py = 0; py < h; py++)
4582           {
4583              for (px = 0; px < w; px++)
4584                {
4585                   unsigned int mask, imask;
4586
4587                   mask = ((unsigned int)(*sp)) << 24;
4588                   imask = mask >> 8;
4589                   imask |= imask >> 8;
4590                   imask |= imask >> 8;
4591                   *p = mask | (*p & imask);
4592                   //if (*sp) *p = 0xff000000 | *p;
4593                   //else *p = 0x00000000;
4594                   sp++;
4595                   p++;
4596                }
4597           }
4598         free(spix);
4599      }
4600    else
4601       {
4602          for (py = 0; py < h; py++)
4603            {
4604               for (px = 0; px < w; px++)
4605                 *p |= 0xff000000;
4606            }
4607       }
4608    evas_object_image_data_set(cw->obj, pix);
4609    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4610    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4611      {
4612         evas_object_image_data_set(o, pix);
4613         evas_object_image_data_update_add(o, 0, 0, w, h);
4614      }
4615 // don't need to fix alpha chanel as blending
4616 // should be totally off here regardless of
4617 // alpha channel content
4618 }
4619
4620 static void
4621 _e_comp_object_clear(E_Comp_Object *cw)
4622 {
4623    Eina_List *l;
4624    Evas_Object *o;
4625
4626    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4627
4628    if (cw->render_update_lock.lock) return;
4629
4630    if (cw->ec->pixmap)
4631      e_pixmap_clear(cw->ec->pixmap);
4632    if (cw->native)
4633      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4634    evas_object_image_size_set(cw->obj, 1, 1);
4635    evas_object_image_data_set(cw->obj, NULL);
4636    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4637      {
4638         evas_object_image_size_set(o, 1, 1);
4639         evas_object_image_data_set(o, NULL);
4640      }
4641    cw->native = 0;
4642    e_comp_object_render_update_del(cw->smart_obj);
4643 }
4644
4645 static Eina_Bool
4646 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4647 {
4648     int r, g, b, a;
4649
4650     API_ENTRY EINA_FALSE;
4651
4652     if (cw->transparent.set == set)
4653        return EINA_TRUE;
4654
4655     if (set)
4656       {
4657          evas_object_color_get(obj, &r, &g, &b, &a);
4658
4659          cw->transparent.user_r = r;
4660          cw->transparent.user_g = g;
4661          cw->transparent.user_b = b;
4662          cw->transparent.user_a = a;
4663
4664          cw->transparent.setting = EINA_TRUE;
4665          evas_object_color_set(obj, 0, 0, 0, 0);
4666          cw->transparent.setting = EINA_FALSE;
4667
4668          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4669                cw->ec,
4670                cw->transparent.user_r,
4671                cw->transparent.user_g,
4672                cw->transparent.user_b,
4673                cw->transparent.user_a);
4674
4675          cw->transparent.set = EINA_TRUE;
4676       }
4677     else
4678       {
4679          cw->transparent.set = EINA_FALSE;
4680
4681          evas_object_color_set(obj,
4682                                cw->transparent.user_r,
4683                                cw->transparent.user_g,
4684                                cw->transparent.user_b,
4685                                cw->transparent.user_a);
4686
4687          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4688                cw->ec,
4689                cw->transparent.user_r,
4690                cw->transparent.user_g,
4691                cw->transparent.user_b,
4692                cw->transparent.user_a);
4693       }
4694
4695    return EINA_TRUE;
4696 }
4697
4698 /* helper function to simplify toggling of redirection for display servers which support it */
4699 EINTERN void
4700 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4701 {
4702    API_ENTRY;
4703
4704    set = !!set;
4705    if (cw->redirected == set) return;
4706    cw->redirected = set;
4707    if (cw->external_content) return;
4708
4709    e_comp_object_map_update(obj);
4710
4711    if (set)
4712      {
4713         if (cw->updates_exist)
4714           e_comp_object_render_update_add(obj);
4715         else
4716           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4717
4718         _e_comp_object_transparent_set(obj, EINA_FALSE);
4719         evas_object_smart_callback_call(obj, "redirected", NULL);
4720      }
4721    else
4722      {
4723         _e_comp_object_clear(cw);
4724         _e_comp_object_transparent_set(obj, EINA_TRUE);
4725         evas_object_smart_callback_call(obj, "unredirected", NULL);
4726      }
4727 }
4728
4729 static void
4730 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4731 {
4732    E_Comp_Object *cw;
4733    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4734
4735    if (cw->buffer_destroy_listener.notify)
4736      {
4737         cw->buffer_destroy_listener.notify = NULL;
4738         wl_list_remove(&cw->buffer_destroy_listener.link);
4739      }
4740
4741    if (e_object_is_del(E_OBJECT(cw->ec)))
4742      {
4743         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4744           return;
4745      }
4746    else
4747      {
4748         /* if it's current displaying buffer, do not remove its content */
4749         if (!evas_object_visible_get(cw->ec->frame))
4750           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4751      }
4752 }
4753
4754 static void
4755 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4756 {
4757    Eina_List *l;
4758    Evas_Object *o;
4759
4760    if (cw->buffer_destroy_listener.notify)
4761      {
4762         wl_list_remove(&cw->buffer_destroy_listener.link);
4763         cw->buffer_destroy_listener.notify = NULL;
4764      }
4765
4766    if (cw->tbm_surface)
4767      {
4768         tbm_surface_internal_unref(cw->tbm_surface);
4769         cw->tbm_surface = NULL;
4770      }
4771
4772    if (ns)
4773      {
4774         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4775           {
4776              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4777              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4778           }
4779         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4780           {
4781              tbm_surface_internal_ref(ns->data.tbm.buffer);
4782              cw->tbm_surface = ns->data.tbm.buffer;
4783           }
4784      }
4785
4786    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4787    evas_object_image_native_surface_set(cw->obj, ns);
4788    TRACE_DS_END();
4789    if (with_mirror)
4790      {
4791         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4792           {
4793              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4794              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4795              evas_object_image_native_surface_set(o, ns);
4796              TRACE_DS_END();
4797           }
4798      }
4799 }
4800
4801 EINTERN void
4802 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4803 {
4804    Evas_Native_Surface ns;
4805
4806    API_ENTRY;
4807    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4808    if (cw->ec->input_only) return;
4809    if (cw->external_content) return;
4810    if (cw->render_update_lock.lock) return;
4811    set = !!set;
4812
4813    memset(&ns, 0, sizeof(Evas_Native_Surface));
4814
4815    if (set)
4816      {
4817         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4818         set = (!cw->ec->shaped);
4819         if (set)
4820           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4821      }
4822    cw->native = set;
4823
4824    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4825 }
4826
4827 EINTERN void
4828 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4829 {
4830    API_ENTRY;
4831    if (cw->ec->input_only) return;
4832    E_FREE(cw->ns);
4833    if (ns)
4834      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4835    _e_comp_object_alpha_set(cw);
4836    if (cw->native)
4837      e_comp_object_native_surface_set(obj, cw->native);
4838    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4839 }
4840
4841 EINTERN void
4842 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4843 {
4844    API_ENTRY;
4845
4846    set = !!set;
4847
4848    if (cw->blanked == set) return;
4849    cw->blanked = set;
4850    _e_comp_object_alpha_set(cw);
4851    if (set)
4852      {
4853         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4854         evas_object_image_data_set(cw->obj, NULL);
4855         return;
4856      }
4857    if (cw->native)
4858      e_comp_object_native_surface_set(obj, 1);
4859    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4860 }
4861
4862 static void
4863 _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)
4864 {
4865    Evas_Object *o;
4866    int obj_x, obj_y;
4867
4868    if (!_damage_trace) return;
4869
4870    API_ENTRY;
4871
4872    if (!evas_object_visible_get(cw->obj)) return;
4873
4874    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
4875
4876    o = evas_object_rectangle_add(e_comp->evas);
4877    evas_object_layer_set(o, E_LAYER_MAX);
4878    evas_object_name_set(o, "damage_trace");
4879    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
4880    evas_object_resize(o, dmg_w, dmg_h);
4881    evas_object_color_set(o, 0, 128, 0, 128);
4882    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
4883    evas_object_pass_events_set(o, EINA_TRUE);
4884    evas_object_show(o);
4885
4886    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
4887          cw->ec,
4888          dmg_w, dmg_h, dmg_x, dmg_y,
4889          origin->w, origin->h, origin->x, origin->y);
4890
4891    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
4892 }
4893
4894 /* mark an object as dirty and setup damages */
4895 E_API void
4896 e_comp_object_dirty(Evas_Object *obj)
4897 {
4898    Eina_Iterator *it;
4899    Eina_Rectangle *rect;
4900    Eina_List *ll;
4901    Evas_Object *o;
4902    int w, h, tw, th;
4903    Eina_Bool dirty, visible;
4904    E_Map *m = NULL;
4905
4906    API_ENTRY;
4907    if (cw->external_content) return;
4908    if (!cw->redirected) return;
4909    if (cw->render_update_lock.lock)
4910      {
4911         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4912         return;
4913      }
4914    /* only actually dirty if pixmap is available */
4915    if (!e_pixmap_resource_get(cw->ec->pixmap))
4916      {
4917         // e_pixmap_size_get returns last attached buffer size
4918         // eventhough it is destroyed
4919         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
4920         return;
4921      }
4922    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4923    visible = cw->visible;
4924    if (!dirty) w = h = 1;
4925    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4926    if (!dirty)
4927      evas_object_image_data_set(cw->obj, NULL);
4928    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4929    evas_object_image_size_set(cw->obj, tw, th);
4930    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
4931    if (cw->pending_updates)
4932      eina_tiler_area_size_set(cw->pending_updates, w, h);
4933    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4934      {
4935         evas_object_image_pixels_dirty_set(o, dirty);
4936         if (!dirty)
4937           evas_object_image_data_set(o, NULL);
4938         evas_object_image_size_set(o, tw, th);
4939         visible |= evas_object_visible_get(o);
4940      }
4941    if (!dirty)
4942      {
4943         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4944         return;
4945      }
4946
4947    e_comp_object_native_surface_set(obj, 1);
4948
4949    m = _e_comp_object_map_damage_transform_get(cw->ec);
4950    it = eina_tiler_iterator_new(cw->updates);
4951    EINA_ITERATOR_FOREACH(it, rect)
4952      {
4953         /* evas converts damage according to rotation of ecore_evas in damage_region_set
4954          * of evas engine and doesn't convert damage according to evas_map.
4955          * so damage of evas_object_image use surface coordinate.
4956          */
4957         if (m)
4958           {
4959              int damage_x, damage_y, damage_w, damage_h;
4960
4961              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
4962                                                       &damage_x, &damage_y, &damage_w, &damage_h);
4963              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
4964              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
4965           }
4966         else
4967           {
4968              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4969              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
4970           }
4971
4972         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4973           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4974         if (cw->pending_updates)
4975           eina_tiler_rect_add(cw->pending_updates, rect);
4976      }
4977    eina_iterator_free(it);
4978    if (m) e_map_free(m);
4979    if (cw->pending_updates)
4980      eina_tiler_clear(cw->updates);
4981    else
4982      {
4983         cw->pending_updates = cw->updates;
4984         cw->updates = eina_tiler_new(w, h);
4985         eina_tiler_tile_size_set(cw->updates, 1, 1);
4986      }
4987    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4988    evas_object_smart_callback_call(obj, "dirty", NULL);
4989    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4990    /* force render if main object is hidden but mirrors are visible */
4991    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4992    e_comp_object_render(obj);
4993 }
4994
4995 E_API Eina_Bool
4996 e_comp_object_render(Evas_Object *obj)
4997 {
4998    Eina_List *l;
4999    Evas_Object *o;
5000    int pw, ph;
5001    unsigned int *pix;
5002
5003    API_ENTRY EINA_FALSE;
5004
5005    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5006    if (cw->ec->input_only) return EINA_TRUE;
5007    if (cw->external_content) return EINA_TRUE;
5008    if (cw->native) return EINA_FALSE;
5009    /* if comp object is not redirected state, comp object should not be set by newly committed data
5010       because image size of comp object is 1x1 and it should not be shown on canvas */
5011    if (!cw->redirected) return EINA_TRUE;
5012    if (cw->render_update_lock.lock)
5013      {
5014         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5015         return EINA_TRUE;
5016      }
5017    e_comp_object_render_update_del(obj);
5018    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
5019
5020    if (!cw->pending_updates)
5021      {
5022         WRN("RENDER [%p]: NO RECTS!", cw->ec);
5023         evas_object_image_data_set(cw->obj, NULL);
5024         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5025           evas_object_image_data_set(o, NULL);
5026         return EINA_FALSE;
5027      }
5028
5029    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
5030
5031    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
5032
5033    pix = e_pixmap_image_data_get(cw->ec->pixmap);
5034    if (!pix)
5035      {
5036         e_pixmap_image_refresh(cw->ec->pixmap);
5037         pix = e_pixmap_image_data_get(cw->ec->pixmap);
5038      }
5039
5040    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
5041      e_pixmap_image_data_ref(cw->ec->pixmap);
5042
5043    /* set pixel data */
5044    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
5045    _e_comp_object_alpha_set(cw);
5046    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5047      {
5048         evas_object_image_data_set(o, pix);
5049         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5050         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
5051      }
5052
5053    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
5054
5055    e_comp_client_post_update_add(cw->ec);
5056
5057    return EINA_TRUE;
5058 }
5059
5060 /* create a duplicate of an evas object */
5061 E_API Evas_Object *
5062 e_comp_object_util_mirror_add(Evas_Object *obj)
5063 {
5064    Evas_Object *o;
5065    int w, h, tw, th;
5066    unsigned int *pix = NULL;
5067    Eina_Bool argb = EINA_FALSE;
5068
5069    SOFT_ENTRY(NULL);
5070
5071    if (!cw)
5072      cw = evas_object_data_get(obj, "comp_mirror");
5073    if (!cw)
5074      {
5075         o = evas_object_image_filled_add(evas_object_evas_get(obj));
5076         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5077         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5078         evas_object_image_alpha_set(o, 1);
5079         evas_object_image_source_set(o, obj);
5080         return o;
5081      }
5082    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
5083    if (cw->external_content)
5084      {
5085         ERR("%p of client %p is external content.", obj, cw->ec);
5086         return NULL;
5087      }
5088    o = evas_object_image_filled_add(evas_object_evas_get(obj));
5089    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5090    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5091    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
5092    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
5093    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
5094    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
5095    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
5096    evas_object_data_set(o, "comp_mirror", cw);
5097
5098    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5099    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5100
5101    evas_object_image_size_set(o, tw, th);
5102
5103    if (cw->ec->shaped)
5104      pix = evas_object_image_data_get(cw->obj, 0);
5105    else
5106      {
5107         if (cw->native)
5108           {
5109              if (cw->ns)
5110                evas_object_image_native_surface_set(o, cw->ns);
5111              else
5112                {
5113                   Evas_Native_Surface ns;
5114                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5115                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5116                     evas_object_image_native_surface_set(o, &ns);
5117                }
5118           }
5119         else
5120           {
5121              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5122              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5123              if ((argb) &&
5124                  (e_pixmap_image_exists(cw->ec->pixmap)))
5125                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5126              else
5127                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5128           }
5129      }
5130    if (pix)
5131      {
5132       Eina_Bool dirty;
5133
5134       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5135       evas_object_image_pixels_dirty_set(o, dirty);
5136       evas_object_image_data_set(o, pix);
5137       evas_object_image_data_set(cw->obj, pix);
5138       if (dirty)
5139         evas_object_image_data_update_add(o, 0, 0, tw, th);
5140    }
5141    return o;
5142 }
5143
5144 //////////////////////////////////////////////////////
5145
5146 EINTERN Eina_Bool
5147 e_comp_object_effect_allowed_get(Evas_Object *obj)
5148 {
5149    API_ENTRY EINA_FALSE;
5150
5151    if (!cw->shobj) return EINA_FALSE;
5152    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5153    return !e_comp_config_get()->match.disable_borders;
5154 }
5155
5156 /* setup an api effect for a client */
5157 E_API Eina_Bool
5158 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5159 {
5160    char buf[4096];
5161    Eina_Stringshare *grp;
5162    E_Comp_Config *config;
5163    Eina_Bool loaded = EINA_FALSE;
5164
5165    API_ENTRY EINA_FALSE;
5166    if (!cw->shobj) return EINA_FALSE; //input window
5167
5168    if (!effect) effect = "none";
5169    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5170
5171    config = e_comp_config_get();
5172    if ((config) && (config->effect_file))
5173      {
5174         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5175           {
5176              cw->effect_set = EINA_TRUE;
5177              loaded = EINA_TRUE;
5178           }
5179      }
5180
5181    if (!loaded)
5182      {
5183         edje_object_file_get(cw->effect_obj, NULL, &grp);
5184         cw->effect_set = !eina_streq(effect, "none");
5185         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5186         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5187           {
5188              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5189              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5190                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5191                  {
5192                     if (cw->effect_running)
5193                       {
5194                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5195                            return EINA_FALSE;
5196                       }
5197                     cw->effect_set = EINA_FALSE;
5198                     return cw->effect_set;
5199                  }
5200           }
5201      }
5202    if (cw->effect_running)
5203      {
5204         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5205           return EINA_FALSE;
5206      }
5207    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5208    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5209    if (cw->effect_clip)
5210      {
5211         evas_object_clip_unset(cw->clip);
5212         cw->effect_clip = 0;
5213      }
5214    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5215
5216    _e_comp_object_dim_update(cw);
5217
5218    return cw->effect_set;
5219 }
5220
5221 /* set params for embryo scripts in effect */
5222 E_API void
5223 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5224 {
5225    Edje_Message_Int_Set *msg;
5226    unsigned int x;
5227
5228    API_ENTRY;
5229    EINA_SAFETY_ON_NULL_RETURN(params);
5230    EINA_SAFETY_ON_FALSE_RETURN(count);
5231    if (!cw->effect_set) return;
5232
5233    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5234    msg->count = (int)count;
5235    for (x = 0; x < count; x++)
5236       msg->val[x] = params[x];
5237    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5238    edje_object_message_signal_process(cw->effect_obj);
5239 }
5240
5241 static void
5242 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5243 {
5244    Edje_Signal_Cb end_cb;
5245    void *end_data;
5246    E_Comp_Object *cw = data;
5247
5248    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5249    cw->effect_running = 0;
5250    if (!_e_comp_object_animating_end(cw)) return;
5251
5252    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5253      {
5254         evas_object_data_del(cw->smart_obj, "effect_running");
5255         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5256         e_comp_visibility_calculation_set(EINA_TRUE);
5257      }
5258
5259    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5260    if (!end_cb) return;
5261    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5262    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5263    end_cb(end_data, cw->smart_obj, emission, source);
5264 }
5265
5266 /* clip effect to client's zone */
5267 EINTERN void
5268 e_comp_object_effect_clip(Evas_Object *obj)
5269 {
5270    API_ENTRY;
5271    E_Zone *zone;
5272    zone = e_comp_zone_find_by_ec(cw->ec);
5273    if (!zone) return;
5274    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5275    if (!cw->effect_clip_able) return;
5276    evas_object_clip_set(cw->smart_obj, zone->bg_clip_object);
5277    cw->effect_clip = 1;
5278 }
5279
5280 /* unclip effect from client's zone */
5281 EINTERN void
5282 e_comp_object_effect_unclip(Evas_Object *obj)
5283 {
5284    API_ENTRY;
5285    if (!cw->effect_clip) return;
5286    evas_object_clip_unset(cw->smart_obj);
5287    cw->effect_clip = 0;
5288 }
5289
5290 /* start effect, running end_cb after */
5291 E_API Eina_Bool
5292 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5293 {
5294    API_ENTRY EINA_FALSE;
5295    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5296    if (!cw->effect_set) return EINA_FALSE;
5297
5298    if (cw->effect_running)
5299      {
5300         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5301      }
5302
5303    e_comp_object_effect_clip(obj);
5304    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5305
5306    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5307    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5308    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5309    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5310
5311    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5312    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5313
5314    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5315    _e_comp_object_animating_begin(cw);
5316    cw->effect_running = 1;
5317    return EINA_TRUE;
5318 }
5319
5320 /* stop a currently-running effect immediately */
5321 E_API Eina_Bool
5322 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5323 {
5324    int ret = 0;
5325    Edje_Signal_Cb end_cb_before = NULL;
5326    void *end_data_before = NULL;
5327    API_ENTRY EINA_FALSE;
5328
5329    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5330    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5331
5332    if (end_cb_before != end_cb) return EINA_TRUE;
5333    e_comp_object_effect_unclip(obj);
5334    if (cw->effect_clip)
5335      {
5336         evas_object_clip_unset(cw->effect_obj);
5337         cw->effect_clip = 0;
5338      }
5339    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5340    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5341
5342    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5343      {
5344         evas_object_data_del(cw->smart_obj, "effect_running");
5345         e_comp_visibility_calculation_set(EINA_TRUE);
5346      }
5347
5348    cw->effect_running = 0;
5349    ret = _e_comp_object_animating_end(cw);
5350
5351    if ((ret) && (end_cb_before))
5352      {
5353         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5354         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5355      }
5356
5357    return ret;
5358 }
5359
5360 static int
5361 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5362 {
5363    return a->pri - b->pri;
5364 }
5365
5366 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5367 E_API E_Comp_Object_Mover *
5368 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5369 {
5370    E_Comp_Object_Mover *prov;
5371
5372    prov = E_NEW(E_Comp_Object_Mover, 1);
5373    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5374    prov->func = provider;
5375    prov->data = (void*)data;
5376    prov->pri = pri;
5377    prov->sig = sig;
5378    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5379      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5380    return prov;
5381 }
5382
5383 E_API void
5384 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5385 {
5386    EINA_SAFETY_ON_NULL_RETURN(prov);
5387    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5388    free(prov);
5389 }
5390
5391 E_API Evas_Object *
5392 e_comp_object_effect_object_get(Evas_Object *obj)
5393 {
5394    API_ENTRY NULL;
5395
5396    return cw->effect_obj;
5397 }
5398
5399 E_API Eina_Bool
5400 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5401 {
5402    API_ENTRY EINA_FALSE;
5403    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5404    if (!cw->effect_set) return EINA_FALSE;
5405
5406    cw->hiding = set;
5407
5408    return EINA_TRUE;
5409 }
5410
5411 ////////////////////////////////////
5412
5413 static void
5414 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5415 {
5416    if (e_comp->autoclose.obj)
5417      {
5418         e_comp_ungrab_input(0, 1);
5419         if (e_comp->autoclose.del_cb)
5420           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5421         else if (!already_del)
5422           {
5423              evas_object_hide(e_comp->autoclose.obj);
5424              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5425           }
5426         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5427      }
5428    e_comp->autoclose.obj = NULL;
5429    e_comp->autoclose.data = NULL;
5430    e_comp->autoclose.del_cb = NULL;
5431    e_comp->autoclose.key_cb = NULL;
5432    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5433 }
5434
5435 static void
5436 _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)
5437 {
5438    _e_comp_object_autoclose_cleanup(0);
5439 }
5440
5441 static void
5442 _e_comp_object_autoclose_setup(Evas_Object *obj)
5443 {
5444    if (!e_comp->autoclose.rect)
5445      {
5446         /* create rect just below autoclose object to catch mouse events */
5447         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5448         evas_object_move(e_comp->autoclose.rect, 0, 0);
5449         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5450         evas_object_show(e_comp->autoclose.rect);
5451         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5452         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5453         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5454         e_comp_grab_input(0, 1);
5455      }
5456    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5457    evas_object_focus_set(obj, 1);
5458 }
5459
5460 static void
5461 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5462 {
5463    _e_comp_object_autoclose_setup(obj);
5464    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5465 }
5466
5467 static void
5468 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5469 {
5470    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5471    _e_comp_object_autoclose_cleanup(1);
5472    if (e_client_focused_get()) return;
5473
5474    E_Zone *zone = e_zone_current_get();
5475    if (!zone) return;
5476
5477    e_zone_focus_reset(zone);
5478 }
5479
5480 EINTERN void
5481 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5482 {
5483    SOFT_ENTRY();
5484
5485    if (e_comp->autoclose.obj)
5486      {
5487         if (e_comp->autoclose.obj == obj) return;
5488         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
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         return;
5499      }
5500    e_comp->autoclose.obj = obj;
5501    e_comp->autoclose.del_cb = del_cb;
5502    e_comp->autoclose.key_cb = cb;
5503    e_comp->autoclose.data = (void*)data;
5504    if (evas_object_visible_get(obj))
5505      _e_comp_object_autoclose_setup(obj);
5506    else
5507      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5508    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5509 }
5510
5511 E_API unsigned int
5512 e_comp_object_is_animating(Evas_Object *obj)
5513 {
5514    API_ENTRY 0;
5515
5516    return cw->animating;
5517 }
5518
5519 E_API void
5520 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5521 {
5522    API_ENTRY;
5523
5524    if ((cw->external_content) &&
5525        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5526      {
5527         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5528             "But current external content is %d object for %p.",
5529             cw->content_type, cw->ec);
5530         return;
5531      }
5532
5533    cw->user_alpha_set = EINA_TRUE;
5534    cw->user_alpha = alpha;
5535
5536    if (!cw->obj) return;
5537
5538    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5539
5540    evas_object_image_alpha_set(cw->obj, alpha);
5541
5542    if ((!cw->native) && (!cw->external_content))
5543      evas_object_image_data_set(cw->obj, NULL);
5544 }
5545
5546 EINTERN Eina_Bool
5547 e_comp_object_alpha_get(Evas_Object *obj)
5548 {
5549    API_ENTRY EINA_FALSE;
5550
5551    return evas_object_image_alpha_get(cw->obj);
5552 }
5553
5554 E_API void
5555 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5556 {
5557    Eina_Bool mask_set = EINA_FALSE;
5558    Evas_Object *o;
5559
5560    API_ENTRY;
5561    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5562    if (cw->ec->input_only) return;
5563    mask_set = !!set;
5564
5565    if (mask_set)
5566      {
5567         if (!cw->mask.obj)
5568           {
5569              o = evas_object_rectangle_add(e_comp->evas);
5570              evas_object_color_set(o, 0, 0, 0, 0);
5571              evas_object_clip_set(o, cw->clip);
5572              evas_object_smart_member_add(o, obj);
5573              evas_object_move(o, 0, 0);
5574              evas_object_resize(o, cw->w, cw->h);
5575              /* save render op value to restore when clear a mask.
5576               *
5577               * NOTE: DO NOT change the render op on ec->frame while mask object
5578               * is set. it will overwrite the changed op value. */
5579              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5580              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5581              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5582              if (cw->visible) evas_object_show(o);
5583
5584              cw->mask.obj = o;
5585              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5586              ELOGF("COMP", "         |mask_obj", cw->ec);
5587              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5588           }
5589      }
5590    else
5591      {
5592         if (cw->mask.obj)
5593           {
5594              evas_object_smart_member_del(cw->mask.obj);
5595              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5596
5597              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5598              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5599           }
5600      }
5601 }
5602
5603 E_API Eina_Bool
5604 e_comp_object_mask_has(Evas_Object *obj)
5605 {
5606    API_ENTRY EINA_FALSE;
5607
5608    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5609 }
5610
5611 EINTERN void
5612 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5613 {
5614    int tw, th;
5615    API_ENTRY;
5616
5617    if ((cw->external_content) &&
5618        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5619      {
5620         WRN("Can set up size to ONLY evas \"image\" object. "
5621             "But current external content is %d object for %p.",
5622             cw->content_type, cw->ec);
5623         return;
5624      }
5625
5626    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5627
5628    evas_object_image_size_set(cw->obj, tw, th);
5629 }
5630
5631 E_API void
5632 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5633 {
5634    Eina_Bool transform_set = EINA_FALSE;
5635    API_ENTRY;
5636    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5637    if (cw->ec->input_only) return;
5638
5639    transform_set = !!set;
5640
5641    if (transform_set)
5642      {
5643         if (!cw->transform_bg_obj)
5644           {
5645              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5646              evas_object_move(o, 0, 0);
5647              evas_object_resize(o, 1, 1);
5648              if (cw->transform_bg_color.a >= 255)
5649                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5650              else
5651                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5652              evas_object_color_set(o,
5653                                    cw->transform_bg_color.r,
5654                                    cw->transform_bg_color.g,
5655                                    cw->transform_bg_color.b,
5656                                    cw->transform_bg_color.a);
5657              if (cw->visible) evas_object_show(o);
5658
5659              cw->transform_bg_obj = o;
5660              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5661           }
5662 #ifdef REFACTOR_DESK_AREA
5663         e_comp_object_transform_obj_stack_update(obj);
5664 #else
5665         _e_comp_object_transform_obj_stack_update(obj);
5666 #endif
5667      }
5668    else
5669      {
5670         if (cw->transform_bg_obj)
5671           {
5672              evas_object_smart_member_del(cw->transform_bg_obj);
5673              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5674           }
5675      }
5676 }
5677
5678 E_API void
5679 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5680 {
5681    API_ENTRY;
5682
5683    cw->transform_bg_color.r = r;
5684    cw->transform_bg_color.g = g;
5685    cw->transform_bg_color.b = b;
5686    cw->transform_bg_color.a = a;
5687
5688    if (cw->transform_bg_obj)
5689      {
5690         evas_object_color_set(cw->transform_bg_obj,
5691                               cw->transform_bg_color.r,
5692                               cw->transform_bg_color.g,
5693                               cw->transform_bg_color.b,
5694                               cw->transform_bg_color.a);
5695      }
5696 }
5697
5698 EINTERN void
5699 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
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(cw->transform_bg_obj, vertices);
5707 }
5708
5709 EINTERN void
5710 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5711 {
5712    API_ENTRY;
5713    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5714    if (cw->ec->input_only) return;
5715    if (!cw->transform_bg_obj) return;
5716
5717    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5718 }
5719
5720 E_API void
5721 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5722 {
5723    Eina_Bool transform_set = EINA_FALSE;
5724    API_ENTRY;
5725    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5726    if (cw->ec->input_only) return;
5727
5728    transform_set = !!set;
5729
5730    if (transform_set)
5731      {
5732         if (!cw->transform_tranp_obj)
5733           {
5734              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5735              evas_object_move(o, 0, 0);
5736              evas_object_resize(o, 1, 1);
5737              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5738              evas_object_color_set(o, 0, 0, 0, 0);
5739              if (cw->visible) evas_object_show(o);
5740
5741              cw->transform_tranp_obj = o;
5742              evas_object_pass_events_set(cw->transform_tranp_obj, EINA_TRUE);
5743              ELOGF("TRANSFORM","transform set: TRUE", cw->ec);
5744              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5745           }
5746 #ifdef REFACTOR_DESK_AREA
5747         e_comp_object_transform_obj_stack_update(obj);
5748 #else
5749         _e_comp_object_transform_obj_stack_update(obj);
5750 #endif
5751      }
5752    else
5753      {
5754         if (cw->transform_tranp_obj)
5755           {
5756              ELOGF("TRANSFORM","transform set: FALSE", cw->ec);
5757              evas_object_smart_member_del(cw->transform_tranp_obj);
5758              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5759           }
5760      }
5761 }
5762
5763 EINTERN void
5764 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
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(cw->transform_tranp_obj, vertices);
5772 }
5773
5774 EINTERN void
5775 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5776 {
5777    API_ENTRY;
5778    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5779    if (cw->ec->input_only) return;
5780    if (!cw->transform_tranp_obj) return;
5781
5782    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5783 }
5784
5785 #ifdef REFACTOR_DESK_AREA
5786 #else
5787 EINTERN void
5788 e_comp_object_layer_update(Evas_Object *obj,
5789                            Evas_Object *above, Evas_Object *below)
5790 {
5791    E_Comp_Object *cw2 = NULL;
5792    Evas_Object *o = NULL;
5793    short layer;
5794
5795    API_ENTRY;
5796
5797    if (cw->ec->layer_block) return;
5798    if ((above) && (below))
5799      {
5800         ERR("Invalid layer update request! cw=%p", cw);
5801         return;
5802      }
5803
5804    o = above?:below;
5805
5806    if (o)
5807      {
5808         layer = evas_object_layer_get(o);
5809         cw2 = evas_object_data_get(o, "comp_obj");
5810         while (!cw2)
5811           {
5812              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5813
5814              o = evas_object_above_get(o);
5815              if ((!o) || (o == cw->smart_obj)) break;
5816              if (evas_object_layer_get(o) != layer)
5817                {
5818                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5819                }
5820              if (!o)
5821                {
5822                   E_Client *ec;
5823                   ec = e_client_top_get();
5824                   if (ec) o = ec->frame;
5825                }
5826
5827              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5828           }
5829      }
5830
5831    _e_comp_object_layers_remove(cw);
5832    if (cw2)
5833      {
5834         if (cw2->layer > cw->layer)
5835           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5836         else if (cw2->layer == cw->layer)
5837           {
5838              if (above)
5839                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5840              else if (o == obj)
5841                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5842              else if (below)
5843                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5844           }
5845         else
5846           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5847      }
5848    else
5849      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5850 }
5851 #endif
5852
5853 EINTERN int
5854 e_comp_object_layer_get(Evas_Object *obj)
5855 {
5856    API_ENTRY -1;
5857    return cw->layer;
5858 }
5859
5860 E_API Eina_Bool
5861 e_comp_object_content_set(Evas_Object *obj,
5862                           Evas_Object *content,
5863                           E_Comp_Object_Content_Type type)
5864 {
5865    API_ENTRY EINA_FALSE;
5866
5867    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5868    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5869    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5870
5871    if (cw->obj)
5872      {
5873         ERR("Can't set e.swallow.content to requested content. "
5874             "Previous comp object should not be changed at all.");
5875         return EINA_FALSE;
5876      }
5877
5878    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5879
5880    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5881        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5882      {
5883         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5884             type, content, cw->ec, cw->ec->pixmap);
5885         return EINA_FALSE;
5886      }
5887
5888    cw->external_content = EINA_TRUE;
5889
5890    cw->obj = content;
5891    cw->content_type = type;
5892    e_util_size_debug_set(cw->obj, 1);
5893    evas_object_name_set(cw->obj, "cw->obj");
5894    _e_comp_object_alpha_set(cw);
5895
5896    if (cw->shobj)
5897      _e_comp_object_shadow_setup(cw);
5898
5899    wl_signal_emit_mutable(&cw->events.content_type_set, NULL);
5900
5901    return EINA_TRUE;
5902 }
5903
5904 EINTERN Eina_Bool
5905 e_comp_object_content_unset(Evas_Object *obj)
5906 {
5907    API_ENTRY EINA_FALSE;
5908
5909    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5910    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5911
5912    if (!cw->obj && !cw->ec->visible)
5913      {
5914         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
5915         return EINA_TRUE;
5916      }
5917
5918    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5919      {
5920         ELOGF("COMP", "has been set to internal image object already", cw->ec);
5921         return EINA_TRUE;
5922      }
5923
5924    if (cw->obj)
5925      {
5926         if (cw->frame_object)
5927           edje_object_part_unswallow(cw->frame_object, cw->obj);
5928         else if (cw->shobj)
5929           edje_object_part_unswallow(cw->shobj, cw->obj);
5930
5931         evas_object_del(cw->obj);
5932         evas_object_hide(cw->obj);
5933         cw->obj = NULL;
5934      }
5935
5936    cw->external_content = EINA_FALSE;
5937    if (cw->ec->is_cursor)
5938      {
5939         int pw, ph;
5940         DBG("%p is cursor surface..", cw->ec);
5941         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
5942           pw = ph = 1;
5943         evas_object_resize(cw->ec->frame, pw, ph);
5944         evas_object_hide(cw->ec->frame);
5945         return EINA_TRUE;
5946      }
5947
5948
5949    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
5950    cw->obj = evas_object_image_filled_add(e_comp->evas);
5951    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
5952    e_util_size_debug_set(cw->obj, 1);
5953    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
5954    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
5955    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
5956    evas_object_name_set(cw->obj, "cw->obj");
5957    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
5958    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_obj_color_set, cw);
5959    _e_comp_object_alpha_set(cw);
5960
5961    if (cw->shobj)
5962      _e_comp_object_shadow_setup(cw);
5963
5964    if (cw->visible)
5965      {
5966         cw->visible = 0;
5967         _e_comp_intercept_show_helper(cw);
5968         cw->visible = 1;
5969      }
5970
5971    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
5972    e_comp_object_dirty(cw->smart_obj);
5973    e_comp_object_render(cw->smart_obj);
5974    e_comp_object_render_update_add(obj);
5975
5976    wl_signal_emit_mutable(&cw->events.content_type_set, NULL);
5977
5978    return EINA_TRUE;
5979 }
5980
5981 EINTERN Evas_Object *
5982 e_comp_object_content_get(Evas_Object *obj)
5983 {
5984    API_ENTRY NULL;
5985
5986    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
5987
5988    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5989      {
5990         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
5991         return NULL;
5992      }
5993
5994    return cw->obj;
5995 }
5996
5997 E_API E_Comp_Object_Content_Type
5998 e_comp_object_content_type_get(Evas_Object *obj)
5999 {
6000    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
6001
6002    return cw->content_type;
6003 }
6004
6005 E_API void
6006 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
6007 {
6008    API_ENTRY;
6009    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6010    E_Comp_Config *conf = e_comp_config_get();
6011    if (cw->ec->input_only) return;
6012    if (!conf->dim_rect_enable) return;
6013
6014    cw->dim.mask_set = mask_set;
6015    cw->dim.mask_x = x;
6016    cw->dim.mask_y = y;
6017    cw->dim.mask_w = w;
6018    cw->dim.mask_h = h;
6019
6020    if (!cw->dim.enable) return;
6021    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
6022 }
6023
6024 EINTERN void
6025 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
6026 {
6027    Eina_Bool mask_set = EINA_FALSE;
6028    Evas_Object *o;
6029
6030    API_ENTRY;
6031    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6032    E_Comp_Config *conf = e_comp_config_get();
6033    if (cw->ec->input_only) return;
6034    if (!conf->dim_rect_enable) return;
6035
6036    mask_set = !!set;
6037
6038    if (mask_set)
6039      {
6040         if (cw->dim.mask_obj)
6041           {
6042              evas_object_smart_member_del(cw->dim.mask_obj);
6043              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6044           }
6045
6046         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);
6047         o = evas_object_rectangle_add(e_comp->evas);
6048         evas_object_color_set(o, 0, 0, 0, 0);
6049         evas_object_smart_member_add(o, obj);
6050         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
6051         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
6052
6053         evas_object_render_op_set(o, EVAS_RENDER_COPY);
6054         if (cw->visible) evas_object_show(o);
6055
6056         cw->dim.mask_obj = o;
6057         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
6058
6059         evas_object_layer_set(cw->dim.mask_obj, 9998);
6060      }
6061    else
6062      {
6063         if (cw->dim.mask_obj)
6064           {
6065              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
6066              evas_object_smart_member_del(cw->dim.mask_obj);
6067              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6068           }
6069      }
6070 }
6071
6072 E_API void
6073 e_comp_object_dim_client_set(E_Client *ec)
6074 {
6075    E_Comp_Config *conf = e_comp_config_get();
6076
6077    if (!conf->dim_rect_enable) return ;
6078    if (dim_client == ec) return;
6079
6080    Eina_Bool prev_dim = EINA_FALSE;
6081    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
6082
6083    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
6084       prev_dim = EINA_TRUE;
6085
6086    if (prev_dim && dim_client->visible && ec)
6087      {
6088         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
6089         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
6090      }
6091    else
6092      {
6093         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
6094         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
6095      }
6096    dim_client = ec;
6097 }
6098
6099 EINTERN E_Client *
6100 e_comp_object_dim_client_get(void)
6101 {
6102    E_Comp_Config *conf = e_comp_config_get();
6103
6104    if (!conf->dim_rect_enable ) return NULL;
6105
6106    return dim_client;
6107 }
6108
6109 static void
6110 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6111 {
6112    API_ENTRY;
6113    char emit[32] = "\0";
6114    E_Comp_Config *conf = e_comp_config_get();
6115
6116    if (!ec) return;
6117    if (!conf->dim_rect_enable) return;
6118    if (!cw->effect_obj) return;
6119    if (enable == cw->dim.enable) return;
6120
6121    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6122    if (noeffect || !conf->dim_rect_effect)
6123      {
6124         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6125      }
6126    else
6127      {
6128         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6129      }
6130
6131    cw->dim.enable = enable;
6132
6133    if (cw->dim.mask_set && !enable)
6134      {
6135         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6136         edje_object_signal_emit(cw->effect_obj, emit, "e");
6137      }
6138    else if (cw->dim.mask_set && enable)
6139      {
6140         edje_object_signal_emit(cw->effect_obj, emit, "e");
6141         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6142      }
6143    else
6144      {
6145         edje_object_signal_emit(cw->effect_obj, emit, "e");
6146      }
6147 }
6148
6149 static Eina_Bool
6150 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6151 {
6152    API_ENTRY EINA_FALSE;
6153    E_Comp_Config *conf = e_comp_config_get();
6154
6155    if (!ec) return EINA_FALSE;
6156    if (!conf->dim_rect_enable) return EINA_FALSE;
6157
6158    if (cw->dim.enable) return EINA_TRUE;
6159
6160    return EINA_FALSE;
6161 }
6162
6163 static void
6164 _e_comp_object_dim_update(E_Comp_Object *cw)
6165 {
6166    E_Comp_Config *conf = e_comp_config_get();
6167
6168    if (!cw) return;
6169    if (!conf->dim_rect_enable) return;
6170    if (!cw->effect_obj) return;
6171    if (cw->dim.enable)
6172      {
6173         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6174         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6175
6176         if (cw->dim.mask_set)
6177           {
6178              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6179           }
6180      }
6181 }
6182
6183 EINTERN void
6184 e_comp_object_clear(Evas_Object *obj)
6185 {
6186    API_ENTRY;
6187
6188    _e_comp_object_clear(cw);
6189 }
6190
6191 EINTERN Eina_Bool
6192 e_comp_object_hwc_update_exists(Evas_Object *obj)
6193 {
6194    API_ENTRY EINA_FALSE;
6195    return cw->hwc_need_update;
6196 }
6197
6198 // will remove out
6199 E_API void
6200 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6201 {
6202    API_ENTRY;
6203    cw->hwc_need_update = set;
6204 }
6205
6206 E_API Eina_Bool
6207 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6208 {
6209    API_ENTRY EINA_FALSE;
6210    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6211 }
6212
6213 EINTERN void
6214 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6215 {
6216    API_ENTRY;
6217    if (cw->indicator.obj != indicator)
6218      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6219    cw->indicator.obj = indicator;
6220    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6221 }
6222
6223 EINTERN void
6224 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6225 {
6226    API_ENTRY;
6227    if (cw->indicator.obj != indicator) return;
6228    cw->indicator.obj = NULL;
6229    edje_object_part_unswallow(cw->shobj, indicator);
6230 }
6231
6232 EINTERN void
6233 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6234 {
6235    API_ENTRY;
6236    Edje_Message_Int_Set *msg;
6237
6238    if (!cw->indicator.obj) return;
6239
6240    cw->indicator.w = w;
6241    cw->indicator.h = h;
6242
6243    if (!cw->shobj) return;
6244
6245    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6246    msg->count = 2;
6247    msg->val[0] = w;
6248    msg->val[1] = h;
6249    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6250    edje_object_message_signal_process(cw->shobj);
6251 }
6252
6253 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6254 EINTERN void
6255 e_comp_object_map_update(Evas_Object *obj)
6256 {
6257    API_ENTRY;
6258    E_Client *ec = cw->ec;
6259    E_Comp_Wl_Client_Data *cdata;
6260    E_Map *map;
6261    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6262    char buffer[128];
6263    char *p = buffer;
6264    int l, remain = sizeof buffer;
6265
6266    if (!ec) return;
6267    if (e_object_is_del(E_OBJECT(ec))) return;
6268    cdata = e_client_cdata_get(ec);
6269    if (!cdata) return;
6270
6271    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6272     * when new buffer is attached.
6273     */
6274    if (!cdata->buffer_ref.buffer) return;
6275
6276    if ((!cw->redirected) ||
6277        (e_client_video_hw_composition_check(ec)) ||
6278        (!e_comp_wl_output_buffer_transform_get(ec) &&
6279         cdata->scaler.buffer_viewport.buffer.scale == 1))
6280      {
6281         if (evas_object_map_enable_get(cw->effect_obj))
6282           {
6283              ELOGF("TRANSFORM", "map: disable", cw->ec);
6284              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6285              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6286              evas_object_resize(cw->effect_obj, tw, th);
6287           }
6288
6289         return;
6290      }
6291
6292    map = e_map_new();
6293    EINA_SAFETY_ON_NULL_RETURN(map);
6294
6295    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6296
6297    x1 = y1 = 0;
6298    x2 = bw;
6299    y2 = bh;
6300
6301    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6302
6303    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6304    e_map_point_image_uv_set(map, 0, x, y);
6305    l = snprintf(p, remain, "%d,%d", x, y);
6306    p += l, remain -= l;
6307
6308    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6309    e_map_point_image_uv_set(map, 1, x, y);
6310    l = snprintf(p, remain, " %d,%d", x, y);
6311    p += l, remain -= l;
6312
6313    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6314    e_map_point_image_uv_set(map, 2, x, y);
6315    l = snprintf(p, remain, " %d,%d", x, y);
6316    p += l, remain -= l;
6317
6318    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6319    e_map_point_image_uv_set(map, 3, x, y);
6320    l = snprintf(p, remain, " %d,%d", x, y);
6321    p += l, remain -= l;
6322
6323    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6324          cw->ec,
6325          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6326
6327    e_comp_object_map_set(cw->effect_obj, map);
6328    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6329
6330    e_map_free(map);
6331
6332    /* if there's screen rotation with comp mode, then ec->effect_obj and
6333     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6334     */
6335    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6336    evas_object_resize(cw->effect_obj, tw, th);
6337 }
6338
6339 EINTERN Eina_Bool
6340 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6341 {
6342    API_ENTRY EINA_FALSE;
6343
6344    cw->render_trace = set;
6345
6346    return EINA_TRUE;
6347 }
6348
6349 E_API Eina_Bool
6350 e_comp_object_native_usable_get(Evas_Object *obj)
6351 {
6352    API_ENTRY EINA_FALSE;
6353    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6354
6355    if (cw->ec->input_only) return EINA_FALSE;
6356    if (cw->external_content) return EINA_FALSE;
6357    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6358
6359    /* just return true value, if it is normal case */
6360    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6361
6362    /* abnormal case */
6363    Evas_Native_Surface *ns;
6364    ns = evas_object_image_native_surface_get(cw->obj);
6365
6366    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6367    if (ns)
6368      {
6369         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6370         return EINA_TRUE;
6371      }
6372
6373    return EINA_FALSE;
6374 }
6375
6376 EINTERN Eina_Bool
6377 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6378 {
6379    API_ENTRY EINA_FALSE;
6380    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6381    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6382    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6383
6384    if (cw->image_filter == filter) return EINA_TRUE;
6385
6386    switch (filter)
6387      {
6388       case E_COMP_IMAGE_FILTER_BLUR:
6389          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6390          break;
6391       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6392          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6393          break;
6394       case E_COMP_IMAGE_FILTER_INVERSE:
6395          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6396          break;
6397       case E_COMP_IMAGE_FILTER_NONE:
6398       default:
6399          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6400          break;
6401      }
6402
6403    cw->image_filter = filter;
6404
6405    wl_signal_emit_mutable(&cw->events.image_filter_set, NULL);
6406
6407    return EINA_TRUE;
6408 }
6409
6410 EINTERN E_Comp_Image_Filter
6411 e_comp_object_image_filter_get(Evas_Object *obj)
6412 {
6413    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6414    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6415    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6416    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6417
6418    return cw->image_filter;
6419 }
6420
6421 static void
6422 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6423 {
6424    Evas_Object *obj;
6425
6426    if (!_damage_trace) return;
6427
6428    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6429      evas_object_del(obj);
6430
6431    _damage_trace_post_objs = NULL;
6432 }
6433
6434 static void
6435 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6436 {
6437    if (!_damage_trace) return;
6438
6439    _damage_trace_post_objs = _damage_trace_objs;
6440    _damage_trace_objs = NULL;
6441 }
6442
6443 EINTERN void
6444 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6445 {
6446    if (_damage_trace == onoff) return;
6447
6448    if (onoff)
6449      {
6450         evas_event_callback_add(e_comp->evas,
6451                                 EVAS_CALLBACK_RENDER_PRE,
6452                                 _e_comp_object_damage_trace_render_pre_cb,
6453                                 NULL);
6454
6455         evas_event_callback_add(e_comp->evas,
6456                                 EVAS_CALLBACK_RENDER_POST,
6457                                 _e_comp_object_damage_trace_render_post_cb,
6458                                 NULL);
6459      }
6460    else
6461      {
6462         Evas_Object *obj;
6463
6464         EINA_LIST_FREE(_damage_trace_objs, obj)
6465           evas_object_del(obj);
6466
6467         _damage_trace_objs = NULL;
6468
6469         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6470           evas_object_del(obj);
6471
6472         _damage_trace_post_objs = NULL;
6473
6474         evas_event_callback_del(e_comp->evas,
6475                                 EVAS_CALLBACK_RENDER_PRE,
6476                                 _e_comp_object_damage_trace_render_pre_cb);
6477
6478         evas_event_callback_del(e_comp->evas,
6479                                 EVAS_CALLBACK_RENDER_POST,
6480                                 _e_comp_object_damage_trace_render_post_cb);
6481      }
6482
6483    _damage_trace = onoff;
6484 }
6485
6486 EINTERN Eina_Bool
6487 e_comp_object_redirected_get(Evas_Object *obj)
6488 {
6489    API_ENTRY EINA_FALSE;
6490    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6491
6492    return cw->redirected;
6493 }
6494
6495 EINTERN Eina_Bool
6496 e_comp_object_color_visible_get(Evas_Object *obj)
6497 {
6498    API_ENTRY EINA_FALSE;
6499
6500    return cw->color_visible;
6501 }
6502
6503 E_API Eina_Bool
6504 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6505 {
6506    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6507
6508    return e_map_set_to_comp_object(em, obj);
6509 }
6510
6511 EINTERN E_Map *
6512 e_comp_object_map_get(const Evas_Object *obj)
6513 {
6514    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6515
6516    return e_map_get_from_comp_object(obj);
6517 }
6518
6519 E_API Eina_Bool
6520 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6521 {
6522    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6523
6524    evas_object_map_enable_set(obj, enable);
6525
6526    return EINA_TRUE;
6527 }
6528
6529 E_API Eina_Bool
6530 e_comp_object_render_update_lock(Evas_Object *obj)
6531 {
6532    E_Comp_Wl_Buffer *buffer;
6533    struct wayland_tbm_client_queue *cqueue;
6534
6535    API_ENTRY EINA_FALSE;
6536
6537    if (cw->render_update_lock.lock == 0)
6538      {
6539         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6540
6541         buffer = e_pixmap_resource_get(cw->ec->pixmap);
6542         if ((buffer) && (buffer->resource))
6543           {
6544              cqueue = e_comp_wl_tbm_client_queue_get(cw->ec);
6545              if (cqueue)
6546                wayland_tbm_server_client_queue_flush(cqueue);
6547           }
6548
6549         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, buffer);
6550         e_comp_object_render_update_del(obj);
6551
6552         ELOGF("COMP", "Render update lock enabled", cw->ec);
6553      }
6554
6555    cw->render_update_lock.lock++;
6556
6557    return EINA_TRUE;
6558 }
6559
6560 E_API void
6561 e_comp_object_render_update_unlock(Evas_Object *obj)
6562 {
6563    API_ENTRY;
6564
6565    if (cw->render_update_lock.lock == 0)
6566      return;
6567
6568    cw->render_update_lock.lock--;
6569
6570    if (cw->render_update_lock.lock == 0)
6571      {
6572
6573         if (cw->render_update_lock.pending_move_set)
6574           {
6575              evas_object_move(obj,
6576                               cw->render_update_lock.pending_move_x,
6577                               cw->render_update_lock.pending_move_y);
6578              cw->render_update_lock.pending_move_x = 0;
6579              cw->render_update_lock.pending_move_y = 0;
6580              cw->render_update_lock.pending_move_set = EINA_FALSE;
6581           }
6582
6583         if (cw->render_update_lock.pending_resize_set)
6584           {
6585              evas_object_resize(obj,
6586                                 cw->render_update_lock.pending_resize_w,
6587                                 cw->render_update_lock.pending_resize_h);
6588              cw->render_update_lock.pending_resize_w = 0;
6589              cw->render_update_lock.pending_resize_h = 0;
6590              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6591           }
6592
6593         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6594
6595         if ((cw->ec->exp_iconify.buffer_flush) &&
6596             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6597             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6598           e_comp_object_clear(obj);
6599         else
6600           e_comp_object_render_update_add(obj);
6601
6602         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_UNSET, cw->ec);
6603
6604         ELOGF("COMP", "Render update lock disabled", cw->ec);
6605      }
6606 }
6607
6608 E_API Eina_Bool
6609 e_comp_object_render_update_lock_get(Evas_Object *obj)
6610 {
6611    API_ENTRY EINA_FALSE;
6612
6613    if (cw->render_update_lock.lock > 0)
6614      return EINA_TRUE;
6615
6616    return EINA_FALSE;
6617 }
6618
6619 E_API void
6620 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6621 {
6622    API_ENTRY;
6623
6624    if ((cw->transparent.set) || (cw->transparent.setting))
6625      {
6626         if (r) *r = cw->transparent.user_r;
6627         if (g) *g = cw->transparent.user_g;
6628         if (b) *b = cw->transparent.user_b;
6629         if (a) *a = cw->transparent.user_a;
6630      }
6631    else
6632      {
6633         evas_object_color_get(obj, r, g, b, a);
6634      }
6635 }
6636
6637 EINTERN void
6638 e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op)
6639 {
6640    API_ENTRY;
6641
6642    evas_object_render_op_set(cw->obj, op);
6643
6644    wl_signal_emit_mutable(&cw->events.render_op_set, NULL);
6645 }
6646
6647 EINTERN Evas_Render_Op
6648 e_comp_object_render_op_get(Evas_Object *obj)
6649 {
6650    API_ENTRY EVAS_RENDER_BLEND;
6651
6652    return evas_object_render_op_get(cw->obj);
6653 }
6654
6655 EINTERN void
6656 e_comp_object_lower_listener_add(Evas_Object *obj, struct wl_listener *listener)
6657 {
6658    API_ENTRY;
6659    wl_signal_add(&cw->events.lower, listener);
6660 }
6661
6662 #ifdef REFACTOR_DESK_AREA
6663 EINTERN void
6664 e_comp_object_lower_done_listener_add(Evas_Object *obj, struct wl_listener *listener)
6665 {
6666    API_ENTRY;
6667    wl_signal_add(&cw->events.lower_done, listener);
6668 }
6669
6670 EINTERN void
6671 e_comp_object_raise_listener_add(Evas_Object *obj, struct wl_listener *listener)
6672 {
6673    API_ENTRY;
6674    wl_signal_add(&cw->events.raise, listener);
6675 }
6676 #endif
6677
6678 EINTERN void
6679 e_comp_object_show_listener_add(Evas_Object *obj, struct wl_listener *listener)
6680 {
6681    API_ENTRY;
6682    wl_signal_add(&cw->events.show, listener);
6683 }
6684
6685 EINTERN void
6686 e_comp_object_hide_listener_add(Evas_Object *obj, struct wl_listener *listener)
6687 {
6688    API_ENTRY;
6689    wl_signal_add(&cw->events.hide, listener);
6690 }
6691
6692 #ifdef REFACTOR_DESK_AREA
6693 EINTERN void
6694 e_comp_object_set_layer_listener_add(Evas_Object *obj, struct wl_listener *listener)
6695 {
6696    API_ENTRY;
6697    wl_signal_add(&cw->events.set_layer, listener);
6698 }
6699
6700 EINTERN void
6701 e_comp_object_stack_above_listener_add(Evas_Object *obj, struct wl_listener *listener)
6702 {
6703    API_ENTRY;
6704    wl_signal_add(&cw->events.stack_above, listener);
6705 }
6706
6707 EINTERN void
6708 e_comp_object_stack_below_listener_add(Evas_Object *obj, struct wl_listener *listener)
6709 {
6710    API_ENTRY;
6711    wl_signal_add(&cw->events.stack_below, listener);
6712 }
6713 #endif
6714
6715 EINTERN void
6716 e_comp_object_image_filter_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6717 {
6718    API_ENTRY;
6719    wl_signal_add(&cw->events.image_filter_set, listener);
6720 }
6721
6722 EINTERN void
6723 e_comp_object_render_op_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6724 {
6725    API_ENTRY;
6726    wl_signal_add(&cw->events.render_op_set, listener);
6727 }
6728
6729 EINTERN void
6730 e_comp_object_content_type_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6731 {
6732    API_ENTRY;
6733    wl_signal_add(&cw->events.content_type_set, listener);
6734 }
6735
6736 EINTERN void
6737 e_comp_object_color_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6738 {
6739    API_ENTRY;
6740    wl_signal_add(&cw->events.color_set, listener);
6741 }
6742
6743 EINTERN void
6744 e_comp_object_color_visible_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6745 {
6746    API_ENTRY;
6747    wl_signal_add(&cw->events.color_visible_set, listener);
6748 }