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