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