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