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