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