e_win: remove e_win
[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 EINTERN int E_EVENT_COMP_OBJECT_ADD = -1;
251
252 /* ecore event define */
253 EINTERN int E_EVENT_COMP_OBJECT_IMG_RENDER = -1;
254 EINTERN int E_EVENT_COMP_OBJECT_EFFECT_START = -1;
255 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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 EINTERN 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         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
4094         zone = e_comp_zone_xy_get(x, y);
4095      }
4096    return zone;
4097 }
4098
4099 EINTERN void
4100 e_comp_object_util_center(Evas_Object *obj)
4101 {
4102    int x, y, w, h, ow, oh;
4103    E_Zone *zone;
4104
4105    SOFT_ENTRY();
4106
4107    zone = e_comp_object_util_zone_get(obj);
4108    EINA_SAFETY_ON_NULL_RETURN(zone);
4109    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
4110    if (cw && (cw->ec->changes.size || cw->ec->new_client))
4111      ow = cw->ec->w, oh = cw->ec->h;
4112    else
4113      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4114    x = x + (w - ow) / 2;
4115    y = y + (h - oh) / 2;
4116    evas_object_move(obj, x, y);
4117 }
4118
4119 EINTERN void
4120 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
4121 {
4122    int x, y, w, h, ow, oh;
4123
4124    SOFT_ENTRY();
4125    EINA_SAFETY_ON_NULL_RETURN(on);
4126    evas_object_geometry_get(on, &x, &y, &w, &h);
4127    if (cw && (cw->ec->changes.size || cw->ec->new_client))
4128      ow = cw->ec->w, oh = cw->ec->h;
4129    else
4130      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4131    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
4132 }
4133
4134 EINTERN void
4135 e_comp_object_util_fullscreen(Evas_Object *obj)
4136 {
4137    SOFT_ENTRY();
4138
4139    if (cw)
4140      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
4141    else
4142      {
4143         evas_object_move(obj, 0, 0);
4144         evas_object_resize(obj, e_comp->w, e_comp->h);
4145      }
4146 }
4147
4148 EINTERN void
4149 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
4150 {
4151    E_Zone *zone;
4152    int zx, zy, zw, zh;
4153    int ow, oh;
4154    SOFT_ENTRY();
4155
4156    if (cw)
4157      ow = cw->w, oh = cw->h;
4158    else
4159      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4160    zone = e_comp_object_util_zone_get(obj);
4161    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
4162    if (x) *x = zx + (zw - ow) / 2;
4163    if (y) *y = zy + (zh - oh) / 2;
4164 }
4165
4166 EINTERN void
4167 e_comp_object_input_objs_del(Evas_Object *obj)
4168 {
4169    API_ENTRY;
4170    E_Input_Rect_Data *input_rect_data;
4171    E_Input_Rect_Smart_Data *input_rect_sd;
4172
4173    if (!cw->input_obj)
4174      return;
4175
4176    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4177    if (!input_rect_sd) return;
4178
4179    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
4180      {
4181         if (input_rect_data->obj)
4182           {
4183              evas_object_smart_member_del(input_rect_data->obj);
4184              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
4185           }
4186         E_FREE(input_rect_data);
4187      }
4188 }
4189
4190 E_API void
4191 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
4192 {
4193    API_ENTRY;
4194    E_Input_Rect_Data *input_rect_data = NULL;
4195    E_Input_Rect_Smart_Data *input_rect_sd;
4196    int client_w, client_h;
4197
4198    if (cw->ec->client.w)
4199      client_w = cw->ec->client.w;
4200    else
4201      client_w = cw->ec->w;
4202
4203    if (cw->ec->client.h)
4204      client_h = cw->ec->client.h;
4205    else
4206      client_h = cw->ec->h;
4207
4208    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
4209
4210    if (!cw->input_obj)
4211      {
4212         _e_comp_input_obj_smart_init();
4213         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
4214         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
4215         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4216
4217         if (input_rect_sd)
4218           input_rect_sd->cw = cw;
4219      }
4220
4221    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4222    if (input_rect_sd)
4223      {
4224         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
4225         if (input_rect_data)
4226           {
4227              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
4228              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
4229           }
4230      }
4231
4232    if ((input_rect_data) &&
4233        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
4234      {
4235         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
4236         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
4237         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
4238         evas_object_clip_set(input_rect_data->obj, cw->clip);
4239         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
4240         evas_object_geometry_set(input_rect_data->obj,
4241           MAX(cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l), 0) + x,
4242           MAX(cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t), 0) + y, w, h);
4243         evas_object_pass_events_set(cw->default_input_obj, 1);
4244         evas_object_pass_events_set(cw->obj, 1);
4245         if (cw->visible)
4246           {
4247              evas_object_show(input_rect_data->obj);
4248              evas_object_show(cw->input_obj);
4249           }
4250      }
4251    else
4252      {
4253         evas_object_smart_member_del(cw->input_obj);
4254         E_FREE_FUNC(cw->input_obj, evas_object_del);
4255         evas_object_pass_events_set(cw->default_input_obj, 0);
4256         evas_object_pass_events_set(cw->obj, 0);
4257      }
4258 }
4259
4260 EINTERN void
4261 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4262 {
4263    API_ENTRY;
4264    E_Input_Rect_Smart_Data *input_rect_sd;
4265    E_Input_Rect_Data *input_rect_data;
4266    Eina_List *l;
4267
4268    if (!cw->input_obj) return;
4269
4270    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4271    if (input_rect_sd)
4272      {
4273         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4274           {
4275              *list = eina_list_append(*list, &input_rect_data->rect);
4276           }
4277      }
4278 }
4279
4280 EINTERN void
4281 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4282 {
4283    API_ENTRY;
4284    if (l) *l = cw->client_inset.l;
4285    if (r) *r = cw->client_inset.r;
4286    if (t) *t = cw->client_inset.t;
4287    if (b) *b = cw->client_inset.b;
4288 }
4289
4290 /* set geometry for CSD */
4291 EINTERN void
4292 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4293 {
4294    Eina_Bool calc;
4295    int tx, ty, tw, th;
4296
4297    API_ENTRY;
4298    if (cw->frame_object)
4299      CRI("ACK! ec:%p", cw->ec);
4300    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4301        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4302    calc = cw->client_inset.calc;
4303    cw->client_inset.calc = l || r || t || b;
4304    eina_stringshare_replace(&cw->frame_theme, "borderless");
4305    if (cw->client_inset.calc)
4306      {
4307         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4308         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4309         e_client_size_set(cw->ec, tw, th);
4310      }
4311    else if (cw->ec->maximized || cw->ec->fullscreen)
4312      {
4313         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4314         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4315      }
4316    if (!cw->ec->new_client)
4317      {
4318         if (calc && cw->client_inset.calc)
4319           {
4320              tx = cw->ec->x - (l - cw->client_inset.l);
4321              ty = cw->ec->y - (t - cw->client_inset.t);
4322              e_client_pos_set(cw->ec, tx, ty);
4323           }
4324         cw->ec->changes.pos = cw->ec->changes.size = 1;
4325         EC_CHANGED(cw->ec);
4326      }
4327    cw->client_inset.l = l;
4328    cw->client_inset.r = r;
4329    cw->client_inset.t = t;
4330    cw->client_inset.b = b;
4331 }
4332
4333 EINTERN Eina_Bool
4334 e_comp_object_frame_allowed(Evas_Object *obj)
4335 {
4336    API_ENTRY EINA_FALSE;
4337    return (!cw->ec->mwm.borderless) && (cw->frame_object || (!cw->client_inset.calc));
4338 }
4339
4340 EINTERN Eina_Bool
4341 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
4342 {
4343    API_ENTRY EINA_FALSE;
4344    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4345    eina_stringshare_replace(&cw->frame_name, name);
4346    if (cw->frame_object)
4347      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4348    return EINA_TRUE;
4349 }
4350
4351 EINTERN Eina_Bool
4352 e_comp_object_frame_exists(Evas_Object *obj)
4353 {
4354    API_ENTRY EINA_FALSE;
4355    return !!cw->frame_object;
4356 }
4357
4358 EINTERN Eina_Bool
4359 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4360 {
4361    Evas_Object *o, *pbg;
4362    char buf[4096];
4363    int ok;
4364    Eina_Stringshare *theme;
4365
4366    API_ENTRY EINA_FALSE;
4367
4368    if (!e_util_strcmp(cw->frame_theme, name))
4369     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4370    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4371      return _e_comp_object_shadow_setup(cw);
4372    pbg = cw->frame_object;
4373    theme = eina_stringshare_add(name);
4374
4375    if (cw->frame_object)
4376      {
4377         int w, h;
4378
4379         w = cw->ec->w, h = cw->ec->h;
4380         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4381         if ((cw->ec->w != w) || (cw->ec->h != h))
4382           {
4383              cw->ec->changes.size = 1;
4384              EC_CHANGED(cw->ec);
4385           }
4386         E_FREE_FUNC(cw->frame_object, evas_object_del);
4387         if (!name) goto reshadow;
4388      }
4389    o = edje_object_add(e_comp->evas);
4390    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4391    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4392    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4393      {
4394         cw->frame_object = NULL;
4395         evas_object_del(o);
4396         eina_stringshare_del(cw->frame_theme);
4397         cw->frame_theme = theme;
4398         goto reshadow;
4399      }
4400    if (!ok)
4401      {
4402         if (theme != e_config->theme_default_border_style)
4403           {
4404              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4405              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4406           }
4407         if (!ok)
4408           {
4409              ok = e_theme_edje_object_set(o, "base/theme/border",
4410                                           "e/widgets/border/default/border");
4411              if (ok && (theme == e_config->theme_default_border_style))
4412                {
4413                   /* Reset default border style to default */
4414                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4415                   e_config_save_queue();
4416                }
4417           }
4418      }
4419
4420    if (ok)
4421      {
4422         cw->frame_object = o;
4423         eina_stringshare_del(cw->frame_theme);
4424         cw->frame_theme = theme;
4425         evas_object_name_set(o, "cw->frame_object");
4426
4427         if (cw->frame_name)
4428           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4429
4430         if (!pbg)
4431           {
4432              cw->ec->changes.icon = 1;
4433              EC_CHANGED(cw->ec);
4434           }
4435      }
4436    else
4437      {
4438         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4439         evas_object_del(o);
4440      }
4441 reshadow:
4442    if (cw->shobj)
4443      _e_comp_object_shadow_setup(cw);
4444    do
4445      {
4446         int old_x, old_y, new_x = 0, new_y = 0;
4447
4448         old_x = cw->x, old_y = cw->y;
4449
4450         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4451         if (pbg)
4452           new_x = cw->ec->x, new_y = cw->ec->y;
4453         else if (cw->ec->placed || (!cw->ec->new_client))
4454           {
4455              /* if no previous frame:
4456               * - reapply client_inset
4457               * - clamp to zone
4458               */
4459              int x, y;
4460
4461              if (cw->ec->changes.size)
4462                {
4463                   x = cw->ec->x;
4464                   y = cw->ec->y;
4465                }
4466              else
4467                {
4468                   x = cw->ec->client.x, y = cw->ec->client.y;
4469                   x = MAX(cw->ec->zone->x, cw->ec->client.x - cw->client_inset.l);
4470                   y = MAX(cw->ec->zone->y, cw->ec->client.y - cw->client_inset.t);
4471                }
4472              new_x = x, new_y = y;
4473           }
4474
4475         if (old_x != new_x || old_y != new_y)
4476           {
4477              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4478              cw->y = cw->x = -99999;
4479              evas_object_move(obj, new_x, new_y);
4480           }
4481      } while (0);
4482
4483    if (cw->ec->maximized)
4484      {
4485         cw->ec->changes.need_maximize = 1;
4486         EC_CHANGED(cw->ec);
4487      }
4488    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4489    if (cw->frame_object)
4490      {
4491         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4492      }
4493    else
4494      cw->frame_extends = 0;
4495    evas_object_del(pbg);
4496    return EINA_TRUE;
4497 }
4498
4499 E_API void
4500 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4501 {
4502    E_Comp_Object_Mover *prov;
4503
4504    API_ENTRY;
4505    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4506    edje_object_signal_emit(cw->shobj, sig, src);
4507    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4508    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4509        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4510      return;
4511    /* start with highest priority callback first */
4512    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4513      {
4514         if (!e_util_glob_match(sig, prov->sig)) continue;
4515         if (prov->func(prov->data, obj, sig)) break;
4516      }
4517 }
4518
4519 E_API void
4520 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4521 {
4522    /* FIXME: at some point I guess this should use eo to inherit
4523     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4524     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4525     */
4526    API_ENTRY;
4527    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4528 }
4529
4530 E_API void
4531 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4532 {
4533    API_ENTRY;
4534    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4535 }
4536
4537 E_API void
4538 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4539 {
4540    API_ENTRY;
4541    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4542 }
4543
4544 E_API void
4545 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4546 {
4547    int tw, th;
4548    Eina_Rectangle rect;
4549    API_ENTRY;
4550
4551    if (cw->ec->input_only || (!cw->updates)) return;
4552    if (cw->nocomp) return;
4553    rect.x = x, rect.y = y;
4554    rect.w = w, rect.h = h;
4555    evas_object_smart_callback_call(obj, "damage", &rect);
4556
4557    if (e_comp_is_on_overlay(cw->ec))
4558      {
4559         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4560         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4561         * E module attempts to block screen update due to the particular policy.
4562         */
4563         if (e_pixmap_resource_get(cw->ec->pixmap))
4564           cw->hwc_need_update = EINA_TRUE;
4565      }
4566
4567    /* ignore overdraw */
4568    if (cw->updates_full)
4569      {
4570         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4571         e_comp_object_render_update_add(obj);
4572
4573         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4574           evas_object_show(cw->smart_obj);
4575
4576         return;
4577      }
4578    /* clip rect to client surface */
4579    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4580    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4581    /* if rect is the total size of the client after clip, clear the updates
4582     * since this is guaranteed to be the whole region anyway
4583     */
4584    eina_tiler_area_size_get(cw->updates, &tw, &th);
4585    if ((w > tw) || (h > th))
4586      {
4587         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4588         eina_tiler_clear(cw->updates);
4589         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4590         x = 0, y = 0;
4591         tw = cw->ec->client.w, th = cw->ec->client.h;
4592      }
4593    if ((!x) && (!y) && (w == tw) && (h == th))
4594      {
4595         eina_tiler_clear(cw->updates);
4596         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4597         cw->updates_full = 1;
4598         cw->update_count = 0;
4599      }
4600    cw->update_count++;
4601    if (cw->update_count > UPDATE_MAX)
4602      {
4603         /* this is going to get really dumb, so just update the whole thing */
4604         eina_tiler_clear(cw->updates);
4605         cw->update_count = cw->updates_full = 1;
4606         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4607         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4608      }
4609    else
4610      {
4611         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4612         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4613      }
4614    cw->updates_exist = 1;
4615    e_comp_object_render_update_add(obj);
4616
4617    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4618      evas_object_show(cw->smart_obj);
4619 }
4620
4621 EINTERN Eina_Bool
4622 e_comp_object_damage_exists(Evas_Object *obj)
4623 {
4624    API_ENTRY EINA_FALSE;
4625    return cw->updates_exist;
4626 }
4627
4628 EINTERN void
4629 e_comp_object_render_update_add(Evas_Object *obj)
4630 {
4631    API_ENTRY;
4632
4633    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4634    if (cw->render_update_lock.lock) return;
4635    if (e_object_is_del(E_OBJECT(cw->ec)))
4636      CRI("CAN'T RENDER A DELETED CLIENT!!! ec:%p", cw->ec);
4637    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4638    if (!cw->update)
4639      {
4640         cw->update = 1;
4641         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4642      }
4643    e_comp_render_queue();
4644 }
4645
4646 EINTERN void
4647 e_comp_object_render_update_del(Evas_Object *obj)
4648 {
4649    API_ENTRY;
4650
4651    if (cw->ec->input_only || (!cw->updates)) return;
4652    if (!cw->update) return;
4653    cw->update = 0;
4654    /* this gets called during comp animating to clear the update flag */
4655    if (e_comp->grabbed) return;
4656    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4657    if (!e_comp->updates)
4658      {
4659         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4660         if (e_comp->render_animator)
4661           ecore_animator_freeze(e_comp->render_animator);
4662      }
4663 }
4664
4665 EINTERN void
4666 e_comp_object_shape_apply(Evas_Object *obj)
4667 {
4668    Eina_List *l;
4669    Evas_Object *o;
4670    unsigned int i, *pix, *p;
4671    int w, h, px, py;
4672
4673    API_ENTRY;
4674    if (!cw->ec) return; //NYI
4675    if (cw->external_content) return;
4676    if (cw->ec->shaped)
4677      {
4678         if ((cw->ec->shape_rects_num >= 1) &&
4679             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4680            return;
4681      }
4682    if (cw->native)
4683      {
4684         ERR("BUGGER: shape with native surface? cw=%p", cw);
4685         return;
4686      }
4687    evas_object_image_size_get(cw->obj, &w, &h);
4688    if ((w < 1) || (h < 1)) return;
4689
4690    if (cw->ec->shaped)
4691      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4692    _e_comp_object_alpha_set(cw);
4693    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4694       evas_object_image_alpha_set(o, 1);
4695
4696    p = pix = evas_object_image_data_get(cw->obj, 1);
4697    if (!pix)
4698      {
4699         evas_object_image_data_set(cw->obj, pix);
4700         return;
4701      }
4702    if (cw->ec->shaped)
4703      {
4704         unsigned char *spix, *sp;
4705
4706         spix = calloc(w * h, sizeof(unsigned char));
4707         if (!spix) return;
4708         for (i = 0; i < cw->ec->shape_rects_num; i++)
4709           {
4710              int rx, ry, rw, rh;
4711
4712              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4713              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4714              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4715              sp = spix + (w * ry) + rx;
4716              for (py = 0; py < rh; py++)
4717                {
4718                   for (px = 0; px < rw; px++)
4719                     {
4720                        *sp = 0xff; sp++;
4721                     }
4722                   sp += w - rw;
4723                }
4724           }
4725         sp = spix;
4726         for (py = 0; py < h; py++)
4727           {
4728              for (px = 0; px < w; px++)
4729                {
4730                   unsigned int mask, imask;
4731
4732                   mask = ((unsigned int)(*sp)) << 24;
4733                   imask = mask >> 8;
4734                   imask |= imask >> 8;
4735                   imask |= imask >> 8;
4736                   *p = mask | (*p & imask);
4737                   //if (*sp) *p = 0xff000000 | *p;
4738                   //else *p = 0x00000000;
4739                   sp++;
4740                   p++;
4741                }
4742           }
4743         free(spix);
4744      }
4745    else
4746       {
4747          for (py = 0; py < h; py++)
4748            {
4749               for (px = 0; px < w; px++)
4750                 *p |= 0xff000000;
4751            }
4752       }
4753    evas_object_image_data_set(cw->obj, pix);
4754    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4755    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4756      {
4757         evas_object_image_data_set(o, pix);
4758         evas_object_image_data_update_add(o, 0, 0, w, h);
4759      }
4760 // don't need to fix alpha chanel as blending
4761 // should be totally off here regardless of
4762 // alpha channel content
4763 }
4764
4765 static void
4766 _e_comp_object_clear(E_Comp_Object *cw)
4767 {
4768    Eina_List *l;
4769    Evas_Object *o;
4770
4771    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4772
4773    if (cw->render_update_lock.lock) return;
4774
4775    if (cw->ec->pixmap)
4776      e_pixmap_clear(cw->ec->pixmap);
4777    if (cw->native)
4778      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4779    evas_object_image_size_set(cw->obj, 1, 1);
4780    evas_object_image_data_set(cw->obj, NULL);
4781    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4782      {
4783         evas_object_image_size_set(o, 1, 1);
4784         evas_object_image_data_set(o, NULL);
4785      }
4786    cw->native = 0;
4787    e_comp_object_render_update_del(cw->smart_obj);
4788 }
4789
4790 static Eina_Bool
4791 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4792 {
4793     int r, g, b, a;
4794
4795     API_ENTRY EINA_FALSE;
4796
4797     if (cw->transparent.set == set)
4798        return EINA_TRUE;
4799
4800     if (set)
4801       {
4802          evas_object_color_get(obj, &r, &g, &b, &a);
4803          evas_object_color_set(obj, 0, 0, 0, 0);
4804
4805          cw->transparent.user_r = r;
4806          cw->transparent.user_g = g;
4807          cw->transparent.user_b = b;
4808          cw->transparent.user_a = a;
4809
4810          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4811                cw->ec,
4812                cw->transparent.user_r,
4813                cw->transparent.user_g,
4814                cw->transparent.user_b,
4815                cw->transparent.user_a);
4816
4817          cw->transparent.set = EINA_TRUE;
4818       }
4819     else
4820       {
4821          cw->transparent.set = EINA_FALSE;
4822
4823          evas_object_color_set(obj,
4824                                cw->transparent.user_r,
4825                                cw->transparent.user_g,
4826                                cw->transparent.user_b,
4827                                cw->transparent.user_a);
4828
4829          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4830                cw->ec,
4831                cw->transparent.user_r,
4832                cw->transparent.user_g,
4833                cw->transparent.user_b,
4834                cw->transparent.user_a);
4835       }
4836
4837    return EINA_TRUE;
4838 }
4839
4840 /* helper function to simplify toggling of redirection for display servers which support it */
4841 EINTERN void
4842 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4843 {
4844    API_ENTRY;
4845
4846    set = !!set;
4847    if (cw->redirected == set) return;
4848    cw->redirected = set;
4849    if (cw->external_content) return;
4850
4851    e_comp_object_map_update(obj);
4852
4853    if (set)
4854      {
4855         if (cw->updates_exist)
4856           e_comp_object_render_update_add(obj);
4857         else
4858           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4859
4860         _e_comp_object_transparent_set(obj, EINA_FALSE);
4861         evas_object_smart_callback_call(obj, "redirected", NULL);
4862      }
4863    else
4864      {
4865         _e_comp_object_clear(cw);
4866         _e_comp_object_transparent_set(obj, EINA_TRUE);
4867         evas_object_smart_callback_call(obj, "unredirected", NULL);
4868      }
4869 }
4870
4871 static void
4872 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4873 {
4874    E_Comp_Object *cw;
4875    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4876
4877    if (cw->buffer_destroy_listener.notify)
4878      {
4879         cw->buffer_destroy_listener.notify = NULL;
4880         wl_list_remove(&cw->buffer_destroy_listener.link);
4881      }
4882
4883    if (e_object_is_del(E_OBJECT(cw->ec)))
4884      {
4885         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4886           return;
4887      }
4888    else
4889      {
4890         /* if it's current displaying buffer, do not remove its content */
4891         if (!evas_object_visible_get(cw->ec->frame))
4892           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4893      }
4894 }
4895
4896 static void
4897 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4898 {
4899    Eina_List *l;
4900    Evas_Object *o;
4901
4902    if (cw->buffer_destroy_listener.notify)
4903      {
4904         wl_list_remove(&cw->buffer_destroy_listener.link);
4905         cw->buffer_destroy_listener.notify = NULL;
4906      }
4907
4908    if (cw->tbm_surface)
4909      {
4910         tbm_surface_internal_unref(cw->tbm_surface);
4911         cw->tbm_surface = NULL;
4912      }
4913
4914    if (ns)
4915      {
4916         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4917           {
4918              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4919              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4920           }
4921         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4922           {
4923              tbm_surface_internal_ref(ns->data.tbm.buffer);
4924              cw->tbm_surface = ns->data.tbm.buffer;
4925           }
4926      }
4927
4928    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4929    evas_object_image_native_surface_set(cw->obj, ns);
4930    TRACE_DS_END();
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              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4937              evas_object_image_native_surface_set(o, ns);
4938              TRACE_DS_END();
4939           }
4940      }
4941 }
4942
4943 EINTERN void
4944 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4945 {
4946    Evas_Native_Surface ns;
4947
4948    API_ENTRY;
4949    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4950    if (cw->ec->input_only) return;
4951    if (cw->external_content) return;
4952    if (cw->render_update_lock.lock) return;
4953    set = !!set;
4954
4955    memset(&ns, 0, sizeof(Evas_Native_Surface));
4956
4957    if (set)
4958      {
4959         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4960         set = (!cw->ec->shaped);
4961         if (set)
4962           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4963      }
4964    cw->native = set;
4965
4966    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4967 }
4968
4969 EINTERN void
4970 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4971 {
4972    API_ENTRY;
4973    if (cw->ec->input_only) return;
4974    E_FREE(cw->ns);
4975    if (ns)
4976      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4977    _e_comp_object_alpha_set(cw);
4978    if (cw->native)
4979      e_comp_object_native_surface_set(obj, cw->native);
4980    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4981 }
4982
4983 EINTERN void
4984 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4985 {
4986    API_ENTRY;
4987
4988    set = !!set;
4989
4990    if (cw->blanked == set) return;
4991    cw->blanked = set;
4992    _e_comp_object_alpha_set(cw);
4993    if (set)
4994      {
4995         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4996         evas_object_image_data_set(cw->obj, NULL);
4997         return;
4998      }
4999    if (cw->native)
5000      e_comp_object_native_surface_set(obj, 1);
5001    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
5002 }
5003
5004 static void
5005 _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)
5006 {
5007    Evas_Object *o;
5008    int obj_x, obj_y;
5009
5010    if (!_damage_trace) return;
5011
5012    API_ENTRY;
5013
5014    if (!evas_object_visible_get(cw->obj)) return;
5015
5016    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
5017
5018    o = evas_object_rectangle_add(e_comp->evas);
5019    evas_object_layer_set(o, E_LAYER_MAX);
5020    evas_object_name_set(o, "damage_trace");
5021    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
5022    evas_object_resize(o, dmg_w, dmg_h);
5023    evas_object_color_set(o, 0, 128, 0, 128);
5024    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5025    evas_object_pass_events_set(o, EINA_TRUE);
5026    evas_object_show(o);
5027
5028    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
5029          cw->ec,
5030          dmg_w, dmg_h, dmg_x, dmg_y,
5031          origin->w, origin->h, origin->x, origin->y);
5032
5033    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
5034 }
5035
5036 /* mark an object as dirty and setup damages */
5037 EINTERN void
5038 e_comp_object_dirty(Evas_Object *obj)
5039 {
5040    Eina_Iterator *it;
5041    Eina_Rectangle *rect;
5042    Eina_List *ll;
5043    Evas_Object *o;
5044    int w, h, tw, th;
5045    Eina_Bool dirty, visible;
5046    E_Map *m = NULL;
5047
5048    API_ENTRY;
5049    if (cw->external_content) return;
5050    if (!cw->redirected) return;
5051    if (cw->render_update_lock.lock)
5052      {
5053         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5054         return;
5055      }
5056    /* only actually dirty if pixmap is available */
5057    if (!e_pixmap_resource_get(cw->ec->pixmap))
5058      {
5059         // e_pixmap_size_get returns last attached buffer size
5060         // eventhough it is destroyed
5061         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
5062         return;
5063      }
5064    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
5065    visible = cw->visible;
5066    if (!dirty) w = h = 1;
5067    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
5068    if (!dirty)
5069      evas_object_image_data_set(cw->obj, NULL);
5070    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5071    evas_object_image_size_set(cw->obj, tw, th);
5072    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
5073    if (cw->pending_updates)
5074      eina_tiler_area_size_set(cw->pending_updates, w, h);
5075    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
5076      {
5077         evas_object_image_pixels_dirty_set(o, dirty);
5078         if (!dirty)
5079           evas_object_image_data_set(o, NULL);
5080         evas_object_image_size_set(o, tw, th);
5081         visible |= evas_object_visible_get(o);
5082      }
5083    if (!dirty)
5084      {
5085         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
5086         return;
5087      }
5088
5089    e_comp_object_native_surface_set(obj, 1);
5090
5091    m = _e_comp_object_map_damage_transform_get(cw->ec);
5092    it = eina_tiler_iterator_new(cw->updates);
5093    EINA_ITERATOR_FOREACH(it, rect)
5094      {
5095         /* evas converts damage according to rotation of ecore_evas in damage_region_set
5096          * of evas engine and doesn't convert damage according to evas_map.
5097          * so damage of evas_object_image use surface coordinate.
5098          */
5099         if (m)
5100           {
5101              int damage_x, damage_y, damage_w, damage_h;
5102
5103              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
5104                                                       &damage_x, &damage_y, &damage_w, &damage_h);
5105              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
5106              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
5107           }
5108         else
5109           {
5110              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
5111              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
5112           }
5113
5114         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
5115           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
5116         if (cw->pending_updates)
5117           eina_tiler_rect_add(cw->pending_updates, rect);
5118      }
5119    eina_iterator_free(it);
5120    if (m) e_map_free(m);
5121    if (cw->pending_updates)
5122      eina_tiler_clear(cw->updates);
5123    else
5124      {
5125         cw->pending_updates = cw->updates;
5126         cw->updates = eina_tiler_new(w, h);
5127         eina_tiler_tile_size_set(cw->updates, 1, 1);
5128      }
5129    cw->update_count = cw->updates_full = cw->updates_exist = 0;
5130    evas_object_smart_callback_call(obj, "dirty", NULL);
5131    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
5132    /* force render if main object is hidden but mirrors are visible */
5133    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
5134    e_comp_object_render(obj);
5135 }
5136
5137 EINTERN Eina_Bool
5138 e_comp_object_render(Evas_Object *obj)
5139 {
5140    Eina_List *l;
5141    Evas_Object *o;
5142    int pw, ph;
5143    unsigned int *pix;
5144
5145    API_ENTRY EINA_FALSE;
5146
5147    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5148    if (cw->ec->input_only) return EINA_TRUE;
5149    if (cw->external_content) return EINA_TRUE;
5150    if (cw->native) return EINA_FALSE;
5151    /* if comp object is not redirected state, comp object should not be set by newly committed data
5152       because image size of comp object is 1x1 and it should not be shown on canvas */
5153    if (!cw->redirected) return EINA_TRUE;
5154    if (cw->render_update_lock.lock)
5155      {
5156         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5157         return EINA_TRUE;
5158      }
5159    e_comp_object_render_update_del(obj);
5160    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
5161
5162    if (!cw->pending_updates)
5163      {
5164         WRN("RENDER [%p]: NO RECTS!", cw->ec);
5165         evas_object_image_data_set(cw->obj, NULL);
5166         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5167           evas_object_image_data_set(o, NULL);
5168         return EINA_FALSE;
5169      }
5170
5171    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
5172
5173    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
5174
5175    pix = e_pixmap_image_data_get(cw->ec->pixmap);
5176    if (!pix)
5177      {
5178         e_pixmap_image_refresh(cw->ec->pixmap);
5179         pix = e_pixmap_image_data_get(cw->ec->pixmap);
5180      }
5181
5182    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
5183      e_pixmap_image_data_ref(cw->ec->pixmap);
5184
5185    /* set pixel data */
5186    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
5187    _e_comp_object_alpha_set(cw);
5188    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5189      {
5190         evas_object_image_data_set(o, pix);
5191         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5192         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
5193      }
5194
5195    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
5196
5197    e_comp_client_post_update_add(cw->ec);
5198
5199    return EINA_TRUE;
5200 }
5201
5202 /* create a duplicate of an evas object */
5203 EINTERN Evas_Object *
5204 e_comp_object_util_mirror_add(Evas_Object *obj)
5205 {
5206    Evas_Object *o;
5207    int w, h, tw, th;
5208    unsigned int *pix = NULL;
5209    Eina_Bool argb = EINA_FALSE;
5210
5211    SOFT_ENTRY(NULL);
5212
5213    if (!cw)
5214      cw = evas_object_data_get(obj, "comp_mirror");
5215    if (!cw)
5216      {
5217         o = evas_object_image_filled_add(evas_object_evas_get(obj));
5218         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5219         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5220         evas_object_image_alpha_set(o, 1);
5221         evas_object_image_source_set(o, obj);
5222         return o;
5223      }
5224    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
5225    if (cw->external_content)
5226      {
5227         ERR("%p of client %p is external content.", obj, cw->ec);
5228         return NULL;
5229      }
5230    o = evas_object_image_filled_add(evas_object_evas_get(obj));
5231    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5232    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5233    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
5234    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
5235    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
5236    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
5237    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
5238    evas_object_data_set(o, "comp_mirror", cw);
5239
5240    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5241    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5242
5243    evas_object_image_size_set(o, tw, th);
5244
5245    if (cw->ec->shaped)
5246      pix = evas_object_image_data_get(cw->obj, 0);
5247    else
5248      {
5249         if (cw->native)
5250           {
5251              if (cw->ns)
5252                evas_object_image_native_surface_set(o, cw->ns);
5253              else
5254                {
5255                   Evas_Native_Surface ns;
5256                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5257                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5258                     evas_object_image_native_surface_set(o, &ns);
5259                }
5260           }
5261         else
5262           {
5263              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5264              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5265              if ((argb) &&
5266                  (e_pixmap_image_exists(cw->ec->pixmap)))
5267                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5268              else
5269                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5270           }
5271      }
5272    if (pix)
5273      {
5274       Eina_Bool dirty;
5275
5276       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5277       evas_object_image_pixels_dirty_set(o, dirty);
5278       evas_object_image_data_set(o, pix);
5279       evas_object_image_data_set(cw->obj, pix);
5280       if (dirty)
5281         evas_object_image_data_update_add(o, 0, 0, tw, th);
5282    }
5283    return o;
5284 }
5285
5286 //////////////////////////////////////////////////////
5287
5288 EINTERN Eina_Bool
5289 e_comp_object_effect_allowed_get(Evas_Object *obj)
5290 {
5291    API_ENTRY EINA_FALSE;
5292
5293    if (!cw->shobj) return EINA_FALSE;
5294    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5295    return !e_comp_config_get()->match.disable_borders;
5296 }
5297
5298 /* setup an api effect for a client */
5299 E_API Eina_Bool
5300 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5301 {
5302    char buf[4096];
5303    Eina_Stringshare *grp;
5304    E_Comp_Config *config;
5305    Eina_Bool loaded = EINA_FALSE;
5306
5307    API_ENTRY EINA_FALSE;
5308    if (!cw->shobj) return EINA_FALSE; //input window
5309
5310    if (!effect) effect = "none";
5311    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5312
5313    config = e_comp_config_get();
5314    if ((config) && (config->effect_file))
5315      {
5316         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5317           {
5318              cw->effect_set = EINA_TRUE;
5319              loaded = EINA_TRUE;
5320           }
5321      }
5322
5323    if (!loaded)
5324      {
5325         edje_object_file_get(cw->effect_obj, NULL, &grp);
5326         cw->effect_set = !eina_streq(effect, "none");
5327         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5328         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5329           {
5330              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5331              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5332                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5333                  {
5334                     if (cw->effect_running)
5335                       {
5336                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5337                            return EINA_FALSE;
5338                       }
5339                     cw->effect_set = EINA_FALSE;
5340                     return cw->effect_set;
5341                  }
5342           }
5343      }
5344    if (cw->effect_running)
5345      {
5346         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5347           return EINA_FALSE;
5348      }
5349    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5350    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5351    if (cw->effect_clip)
5352      {
5353         evas_object_clip_unset(cw->clip);
5354         cw->effect_clip = 0;
5355      }
5356    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5357
5358    _e_comp_object_dim_update(cw);
5359
5360    return cw->effect_set;
5361 }
5362
5363 /* set params for embryo scripts in effect */
5364 E_API void
5365 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5366 {
5367    Edje_Message_Int_Set *msg;
5368    unsigned int x;
5369
5370    API_ENTRY;
5371    EINA_SAFETY_ON_NULL_RETURN(params);
5372    EINA_SAFETY_ON_FALSE_RETURN(count);
5373    if (!cw->effect_set) return;
5374
5375    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5376    msg->count = (int)count;
5377    for (x = 0; x < count; x++)
5378       msg->val[x] = params[x];
5379    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5380    edje_object_message_signal_process(cw->effect_obj);
5381 }
5382
5383 static void
5384 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5385 {
5386    Edje_Signal_Cb end_cb;
5387    void *end_data;
5388    E_Comp_Object *cw = data;
5389
5390    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5391    cw->effect_running = 0;
5392    if (!_e_comp_object_animating_end(cw)) return;
5393
5394    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5395      {
5396         evas_object_data_del(cw->smart_obj, "effect_running");
5397         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5398         e_client_visibility_calculate();
5399      }
5400
5401    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5402    if (!end_cb) return;
5403    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5404    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5405    end_cb(end_data, cw->smart_obj, emission, source);
5406 }
5407
5408 /* clip effect to client's zone */
5409 EINTERN void
5410 e_comp_object_effect_clip(Evas_Object *obj)
5411 {
5412    API_ENTRY;
5413    if (!cw->ec->zone) return;
5414    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5415    if (!cw->effect_clip_able) return;
5416    evas_object_clip_set(cw->smart_obj, cw->ec->zone->bg_clip_object);
5417    cw->effect_clip = 1;
5418 }
5419
5420 /* unclip effect from client's zone */
5421 EINTERN void
5422 e_comp_object_effect_unclip(Evas_Object *obj)
5423 {
5424    API_ENTRY;
5425    if (!cw->effect_clip) return;
5426    evas_object_clip_unset(cw->smart_obj);
5427    cw->effect_clip = 0;
5428 }
5429
5430 /* start effect, running end_cb after */
5431 E_API Eina_Bool
5432 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5433 {
5434    API_ENTRY EINA_FALSE;
5435    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5436    if (!cw->effect_set) return EINA_FALSE;
5437
5438    if (cw->effect_running)
5439      {
5440         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5441      }
5442
5443    e_comp_object_effect_clip(obj);
5444    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5445
5446    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5447    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5448    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5449    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5450
5451    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5452    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5453
5454    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5455    _e_comp_object_animating_begin(cw);
5456    cw->effect_running = 1;
5457    return EINA_TRUE;
5458 }
5459
5460 /* stop a currently-running effect immediately */
5461 E_API Eina_Bool
5462 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5463 {
5464    int ret = 0;
5465    Edje_Signal_Cb end_cb_before = NULL;
5466    void *end_data_before = NULL;
5467    API_ENTRY EINA_FALSE;
5468
5469    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5470    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5471
5472    if (end_cb_before != end_cb) return EINA_TRUE;
5473    e_comp_object_effect_unclip(obj);
5474    if (cw->effect_clip)
5475      {
5476         evas_object_clip_unset(cw->effect_obj);
5477         cw->effect_clip = 0;
5478      }
5479    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5480    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5481
5482    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5483      {
5484         evas_object_data_del(cw->smart_obj, "effect_running");
5485         e_client_visibility_calculate();
5486      }
5487
5488    cw->effect_running = 0;
5489    ret = _e_comp_object_animating_end(cw);
5490
5491    if ((ret) && (end_cb_before))
5492      {
5493         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5494         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5495      }
5496
5497    return ret;
5498 }
5499
5500 static int
5501 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5502 {
5503    return a->pri - b->pri;
5504 }
5505
5506 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5507 E_API E_Comp_Object_Mover *
5508 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5509 {
5510    E_Comp_Object_Mover *prov;
5511
5512    prov = E_NEW(E_Comp_Object_Mover, 1);
5513    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5514    prov->func = provider;
5515    prov->data = (void*)data;
5516    prov->pri = pri;
5517    prov->sig = sig;
5518    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5519      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5520    return prov;
5521 }
5522
5523 E_API void
5524 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5525 {
5526    EINA_SAFETY_ON_NULL_RETURN(prov);
5527    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5528    free(prov);
5529 }
5530
5531 E_API Evas_Object *
5532 e_comp_object_effect_object_get(Evas_Object *obj)
5533 {
5534    API_ENTRY NULL;
5535
5536    return cw->effect_obj;
5537 }
5538
5539 EINTERN Eina_Bool
5540 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5541 {
5542    API_ENTRY EINA_FALSE;
5543    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5544    if (!cw->effect_set) return EINA_FALSE;
5545
5546    cw->hiding = set;
5547
5548    return EINA_TRUE;
5549 }
5550
5551 ////////////////////////////////////
5552
5553 static void
5554 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5555 {
5556    if (e_comp->autoclose.obj)
5557      {
5558         e_comp_ungrab_input(0, 1);
5559         if (e_comp->autoclose.del_cb)
5560           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5561         else if (!already_del)
5562           {
5563              evas_object_hide(e_comp->autoclose.obj);
5564              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5565           }
5566         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5567      }
5568    e_comp->autoclose.obj = NULL;
5569    e_comp->autoclose.data = NULL;
5570    e_comp->autoclose.del_cb = NULL;
5571    e_comp->autoclose.key_cb = NULL;
5572    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5573 }
5574
5575 static void
5576 _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)
5577 {
5578    _e_comp_object_autoclose_cleanup(0);
5579 }
5580
5581 static void
5582 _e_comp_object_autoclose_setup(Evas_Object *obj)
5583 {
5584    if (!e_comp->autoclose.rect)
5585      {
5586         /* create rect just below autoclose object to catch mouse events */
5587         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5588         evas_object_move(e_comp->autoclose.rect, 0, 0);
5589         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5590         evas_object_show(e_comp->autoclose.rect);
5591         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5592         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5593         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5594         e_comp_grab_input(0, 1);
5595      }
5596    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5597    evas_object_focus_set(obj, 1);
5598 }
5599
5600 static void
5601 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5602 {
5603    _e_comp_object_autoclose_setup(obj);
5604    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5605 }
5606
5607 static void
5608 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5609 {
5610    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5611    _e_comp_object_autoclose_cleanup(1);
5612    if (e_client_focused_get()) return;
5613    if (e_config->focus_policy != E_FOCUS_MOUSE)
5614      e_client_refocus();
5615 }
5616
5617 EINTERN void
5618 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5619 {
5620    SOFT_ENTRY();
5621
5622    if (e_comp->autoclose.obj)
5623      {
5624         if (e_comp->autoclose.obj == obj) return;
5625         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5626         e_comp->autoclose.obj = obj;
5627         e_comp->autoclose.del_cb = del_cb;
5628         e_comp->autoclose.key_cb = cb;
5629         e_comp->autoclose.data = (void*)data;
5630         if (evas_object_visible_get(obj))
5631           _e_comp_object_autoclose_setup(obj);
5632         else
5633           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5634         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5635         return;
5636      }
5637    e_comp->autoclose.obj = obj;
5638    e_comp->autoclose.del_cb = del_cb;
5639    e_comp->autoclose.key_cb = cb;
5640    e_comp->autoclose.data = (void*)data;
5641    if (evas_object_visible_get(obj))
5642      _e_comp_object_autoclose_setup(obj);
5643    else
5644      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5645    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5646 }
5647
5648 E_API unsigned int
5649 e_comp_object_is_animating(Evas_Object *obj)
5650 {
5651    API_ENTRY 0;
5652
5653    return cw->animating;
5654 }
5655
5656 E_API void
5657 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5658 {
5659    API_ENTRY;
5660
5661    if ((cw->external_content) &&
5662        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5663      {
5664         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5665             "But current external content is %d object for %p.",
5666             cw->content_type, cw->ec);
5667         return;
5668      }
5669
5670    cw->user_alpha_set = EINA_TRUE;
5671    cw->user_alpha = alpha;
5672
5673    if (!cw->obj) return;
5674
5675    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5676
5677    evas_object_image_alpha_set(cw->obj, alpha);
5678
5679    if ((!cw->native) && (!cw->external_content))
5680      evas_object_image_data_set(cw->obj, NULL);
5681 }
5682
5683 EINTERN Eina_Bool
5684 e_comp_object_alpha_get(Evas_Object *obj)
5685 {
5686    API_ENTRY EINA_FALSE;
5687
5688    return evas_object_image_alpha_get(cw->obj);
5689 }
5690
5691 E_API void
5692 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5693 {
5694    Eina_Bool mask_set = EINA_FALSE;
5695    Evas_Object *o;
5696
5697    API_ENTRY;
5698    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5699    if (cw->ec->input_only) return;
5700    mask_set = !!set;
5701
5702    if (mask_set)
5703      {
5704         if (!cw->mask.obj)
5705           {
5706              o = evas_object_rectangle_add(e_comp->evas);
5707              evas_object_color_set(o, 0, 0, 0, 0);
5708              evas_object_clip_set(o, cw->clip);
5709              evas_object_smart_member_add(o, obj);
5710              evas_object_move(o, 0, 0);
5711              evas_object_resize(o, cw->w, cw->h);
5712              /* save render op value to restore when clear a mask.
5713               *
5714               * NOTE: DO NOT change the render op on ec->frame while mask object
5715               * is set. it will overwrite the changed op value. */
5716              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5717              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5718              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5719              if (cw->visible) evas_object_show(o);
5720
5721              cw->mask.obj = o;
5722              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5723              ELOGF("COMP", "         |mask_obj", cw->ec);
5724              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5725           }
5726      }
5727    else
5728      {
5729         if (cw->mask.obj)
5730           {
5731              evas_object_smart_member_del(cw->mask.obj);
5732              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5733
5734              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5735              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5736           }
5737      }
5738 }
5739
5740 E_API Eina_Bool
5741 e_comp_object_mask_has(Evas_Object *obj)
5742 {
5743    API_ENTRY EINA_FALSE;
5744
5745    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5746 }
5747
5748 EINTERN void
5749 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5750 {
5751    int tw, th;
5752    API_ENTRY;
5753
5754    if ((cw->external_content) &&
5755        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5756      {
5757         WRN("Can set up size to ONLY evas \"image\" object. "
5758             "But current external content is %d object for %p.",
5759             cw->content_type, cw->ec);
5760         return;
5761      }
5762
5763    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5764
5765    evas_object_image_size_set(cw->obj, tw, th);
5766 }
5767
5768 E_API void
5769 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5770 {
5771    Eina_Bool transform_set = EINA_FALSE;
5772    API_ENTRY;
5773    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5774    if (cw->ec->input_only) return;
5775
5776    transform_set = !!set;
5777
5778    if (transform_set)
5779      {
5780         if (!cw->transform_bg_obj)
5781           {
5782              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5783              evas_object_move(o, 0, 0);
5784              evas_object_resize(o, 1, 1);
5785              if (cw->transform_bg_color.a >= 255)
5786                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5787              else
5788                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5789              evas_object_color_set(o,
5790                                    cw->transform_bg_color.r,
5791                                    cw->transform_bg_color.g,
5792                                    cw->transform_bg_color.b,
5793                                    cw->transform_bg_color.a);
5794              if (cw->visible) evas_object_show(o);
5795
5796              cw->transform_bg_obj = o;
5797              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5798           }
5799         _e_comp_object_transform_obj_stack_update(obj);
5800      }
5801    else
5802      {
5803         if (cw->transform_bg_obj)
5804           {
5805              evas_object_smart_member_del(cw->transform_bg_obj);
5806              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5807           }
5808      }
5809 }
5810
5811 E_API void
5812 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5813 {
5814    API_ENTRY;
5815
5816    cw->transform_bg_color.r = r;
5817    cw->transform_bg_color.g = g;
5818    cw->transform_bg_color.b = b;
5819    cw->transform_bg_color.a = a;
5820
5821    if (cw->transform_bg_obj)
5822      {
5823         evas_object_color_set(cw->transform_bg_obj,
5824                               cw->transform_bg_color.r,
5825                               cw->transform_bg_color.g,
5826                               cw->transform_bg_color.b,
5827                               cw->transform_bg_color.a);
5828      }
5829 }
5830
5831 EINTERN void
5832 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5833 {
5834    API_ENTRY;
5835    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5836    if (cw->ec->input_only) return;
5837    if (!cw->transform_bg_obj) return;
5838
5839    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5840 }
5841
5842 EINTERN void
5843 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5844 {
5845    API_ENTRY;
5846    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5847    if (cw->ec->input_only) return;
5848    if (!cw->transform_bg_obj) return;
5849
5850    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5851 }
5852
5853 EINTERN void
5854 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5855 {
5856    Eina_Bool transform_set = EINA_FALSE;
5857    API_ENTRY;
5858    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5859    if (cw->ec->input_only) return;
5860
5861    transform_set = !!set;
5862
5863    if (transform_set)
5864      {
5865         if (!cw->transform_tranp_obj)
5866           {
5867              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5868              evas_object_move(o, 0, 0);
5869              evas_object_resize(o, 1, 1);
5870              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5871              evas_object_color_set(o, 0, 0, 0, 0);
5872              if (cw->visible) evas_object_show(o);
5873
5874              cw->transform_tranp_obj = o;
5875              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5876           }
5877         _e_comp_object_transform_obj_stack_update(obj);
5878      }
5879    else
5880      {
5881         if (cw->transform_tranp_obj)
5882           {
5883              evas_object_smart_member_del(cw->transform_tranp_obj);
5884              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5885           }
5886      }
5887 }
5888
5889 EINTERN void
5890 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5891 {
5892    API_ENTRY;
5893    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5894    if (cw->ec->input_only) return;
5895    if (!cw->transform_tranp_obj) return;
5896
5897    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5898 }
5899
5900 EINTERN void
5901 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5902 {
5903    API_ENTRY;
5904    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5905    if (cw->ec->input_only) return;
5906    if (!cw->transform_tranp_obj) return;
5907
5908    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5909 }
5910
5911 EINTERN void
5912 e_comp_object_layer_update(Evas_Object *obj,
5913                            Evas_Object *above, Evas_Object *below)
5914 {
5915    E_Comp_Object *cw2 = NULL;
5916    Evas_Object *o = NULL;
5917    short layer;
5918
5919    API_ENTRY;
5920
5921    if (cw->ec->layer_block) return;
5922    if ((above) && (below))
5923      {
5924         ERR("Invalid layer update request! cw=%p", cw);
5925         return;
5926      }
5927
5928    o = above?:below;
5929
5930    if (o)
5931      {
5932         layer = evas_object_layer_get(o);
5933         cw2 = evas_object_data_get(o, "comp_obj");
5934         while (!cw2)
5935           {
5936              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5937
5938              o = evas_object_above_get(o);
5939              if ((!o) || (o == cw->smart_obj)) break;
5940              if (evas_object_layer_get(o) != layer)
5941                {
5942                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5943                }
5944              if (!o)
5945                {
5946                   E_Client *ec;
5947                   ec = e_client_top_get();
5948                   if (ec) o = ec->frame;
5949                }
5950
5951              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5952           }
5953      }
5954
5955    _e_comp_object_layers_remove(cw);
5956    if (cw2)
5957      {
5958         if (cw2->layer > cw->layer)
5959           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5960         else if (cw2->layer == cw->layer)
5961           {
5962              if (above)
5963                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5964              else if (o == obj)
5965                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5966              else if (below)
5967                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5968           }
5969         else
5970           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5971      }
5972    else
5973      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5974 }
5975
5976 EINTERN int
5977 e_comp_object_layer_get(Evas_Object *obj)
5978 {
5979    API_ENTRY -1;
5980    return cw->layer;
5981 }
5982
5983 E_API Eina_Bool
5984 e_comp_object_content_set(Evas_Object *obj,
5985                           Evas_Object *content,
5986                           E_Comp_Object_Content_Type type)
5987 {
5988    API_ENTRY EINA_FALSE;
5989
5990    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5991    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5992    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5993
5994    if (cw->obj)
5995      {
5996         ERR("Can't set e.swallow.content to requested content. "
5997             "Previous comp object should not be changed at all.");
5998         return EINA_FALSE;
5999      }
6000
6001    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
6002
6003    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
6004        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
6005      {
6006         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
6007             type, content, cw->ec, cw->ec->pixmap);
6008         return EINA_FALSE;
6009      }
6010
6011    cw->external_content = EINA_TRUE;
6012
6013    cw->obj = content;
6014    cw->content_type = type;
6015    e_util_size_debug_set(cw->obj, 1);
6016    evas_object_name_set(cw->obj, "cw->obj");
6017    _e_comp_object_alpha_set(cw);
6018
6019    if (cw->shobj)
6020      _e_comp_object_shadow_setup(cw);
6021
6022    return EINA_TRUE;
6023 }
6024
6025 EINTERN Eina_Bool
6026 e_comp_object_content_unset(Evas_Object *obj)
6027 {
6028    API_ENTRY EINA_FALSE;
6029
6030    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6031    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
6032
6033    if (!cw->obj && !cw->ec->visible)
6034      {
6035         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
6036         return EINA_TRUE;
6037      }
6038
6039    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
6040      {
6041         ELOGF("COMP", "has been set to internal image object already", cw->ec);
6042         return EINA_TRUE;
6043      }
6044
6045    if (cw->obj)
6046      {
6047         if (cw->frame_object)
6048           edje_object_part_unswallow(cw->frame_object, cw->obj);
6049         else if (cw->shobj)
6050           edje_object_part_unswallow(cw->shobj, cw->obj);
6051
6052         evas_object_del(cw->obj);
6053         evas_object_hide(cw->obj);
6054         cw->obj = NULL;
6055      }
6056
6057    cw->external_content = EINA_FALSE;
6058    if (cw->ec->is_cursor)
6059      {
6060         int pw, ph;
6061         DBG("%p is cursor surface..", cw->ec);
6062         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
6063           pw = ph = 1;
6064         evas_object_resize(cw->ec->frame, pw, ph);
6065         evas_object_hide(cw->ec->frame);
6066         return EINA_TRUE;
6067      }
6068
6069
6070    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
6071    cw->obj = evas_object_image_filled_add(e_comp->evas);
6072    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
6073    e_util_size_debug_set(cw->obj, 1);
6074    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
6075    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
6076    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
6077    evas_object_name_set(cw->obj, "cw->obj");
6078    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
6079    _e_comp_object_alpha_set(cw);
6080
6081    if (cw->shobj)
6082      _e_comp_object_shadow_setup(cw);
6083
6084    if (cw->visible)
6085      {
6086         cw->visible = 0;
6087         _e_comp_intercept_show_helper(cw);
6088         cw->visible = 1;
6089      }
6090
6091    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
6092    e_comp_object_dirty(cw->smart_obj);
6093    e_comp_object_render(cw->smart_obj);
6094    e_comp_object_render_update_add(obj);
6095
6096    return EINA_TRUE;
6097 }
6098
6099 EINTERN Evas_Object *
6100 e_comp_object_content_get(Evas_Object *obj)
6101 {
6102    API_ENTRY NULL;
6103
6104    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
6105
6106    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
6107      {
6108         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
6109         return NULL;
6110      }
6111
6112    return cw->obj;
6113 }
6114
6115 E_API E_Comp_Object_Content_Type
6116 e_comp_object_content_type_get(Evas_Object *obj)
6117 {
6118    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
6119
6120    return cw->content_type;
6121 }
6122
6123 E_API void
6124 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
6125 {
6126    API_ENTRY;
6127    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6128    E_Comp_Config *conf = e_comp_config_get();
6129    if (cw->ec->input_only) return;
6130    if (!conf->dim_rect_enable) return;
6131
6132    cw->dim.mask_set = mask_set;
6133    cw->dim.mask_x = x;
6134    cw->dim.mask_y = y;
6135    cw->dim.mask_w = w;
6136    cw->dim.mask_h = h;
6137
6138    if (!cw->dim.enable) return;
6139    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
6140 }
6141
6142 EINTERN void
6143 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
6144 {
6145    Eina_Bool mask_set = EINA_FALSE;
6146    Evas_Object *o;
6147
6148    API_ENTRY;
6149    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6150    E_Comp_Config *conf = e_comp_config_get();
6151    if (cw->ec->input_only) return;
6152    if (!conf->dim_rect_enable) return;
6153
6154    mask_set = !!set;
6155
6156    if (mask_set)
6157      {
6158         if (cw->dim.mask_obj)
6159           {
6160              evas_object_smart_member_del(cw->dim.mask_obj);
6161              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6162           }
6163
6164         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);
6165         o = evas_object_rectangle_add(e_comp->evas);
6166         evas_object_color_set(o, 0, 0, 0, 0);
6167         evas_object_smart_member_add(o, obj);
6168         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
6169         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
6170
6171         evas_object_render_op_set(o, EVAS_RENDER_COPY);
6172         if (cw->visible) evas_object_show(o);
6173
6174         cw->dim.mask_obj = o;
6175         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
6176
6177         evas_object_layer_set(cw->dim.mask_obj, 9998);
6178      }
6179    else
6180      {
6181         if (cw->dim.mask_obj)
6182           {
6183              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
6184              evas_object_smart_member_del(cw->dim.mask_obj);
6185              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6186           }
6187      }
6188 }
6189
6190 E_API void
6191 e_comp_object_dim_client_set(E_Client *ec)
6192 {
6193    E_Comp_Config *conf = e_comp_config_get();
6194
6195    if (!conf->dim_rect_enable) return ;
6196    if (dim_client == ec) return;
6197
6198    Eina_Bool prev_dim = EINA_FALSE;
6199    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
6200
6201    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
6202       prev_dim = EINA_TRUE;
6203
6204    if (prev_dim && dim_client->visible && ec)
6205      {
6206         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
6207         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
6208      }
6209    else
6210      {
6211         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
6212         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
6213      }
6214    dim_client = ec;
6215 }
6216
6217 EINTERN E_Client *
6218 e_comp_object_dim_client_get(void)
6219 {
6220    E_Comp_Config *conf = e_comp_config_get();
6221
6222    if (!conf->dim_rect_enable ) return NULL;
6223
6224    return dim_client;
6225 }
6226
6227 static void
6228 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6229 {
6230    API_ENTRY;
6231    char emit[32] = "\0";
6232    E_Comp_Config *conf = e_comp_config_get();
6233
6234    if (!ec) return;
6235    if (!conf->dim_rect_enable) return;
6236    if (!cw->effect_obj) return;
6237    if (enable == cw->dim.enable) return;
6238
6239    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6240    if (noeffect || !conf->dim_rect_effect)
6241      {
6242         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6243      }
6244    else
6245      {
6246         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6247      }
6248
6249    cw->dim.enable = enable;
6250
6251    if (cw->dim.mask_set && !enable)
6252      {
6253         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6254         edje_object_signal_emit(cw->effect_obj, emit, "e");
6255      }
6256    else if (cw->dim.mask_set && enable)
6257      {
6258         edje_object_signal_emit(cw->effect_obj, emit, "e");
6259         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6260      }
6261    else
6262      {
6263         edje_object_signal_emit(cw->effect_obj, emit, "e");
6264      }
6265 }
6266
6267 static Eina_Bool
6268 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6269 {
6270    API_ENTRY EINA_FALSE;
6271    E_Comp_Config *conf = e_comp_config_get();
6272
6273    if (!ec) return EINA_FALSE;
6274    if (!conf->dim_rect_enable) return EINA_FALSE;
6275
6276    if (cw->dim.enable) return EINA_TRUE;
6277
6278    return EINA_FALSE;
6279 }
6280
6281 static void
6282 _e_comp_object_dim_update(E_Comp_Object *cw)
6283 {
6284    E_Comp_Config *conf = e_comp_config_get();
6285
6286    if (!cw) return;
6287    if (!conf->dim_rect_enable) return;
6288    if (!cw->effect_obj) return;
6289    if (cw->dim.enable)
6290      {
6291         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6292         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6293
6294         if (cw->dim.mask_set)
6295           {
6296              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6297           }
6298      }
6299 }
6300
6301 EINTERN void
6302 e_comp_object_clear(Evas_Object *obj)
6303 {
6304    API_ENTRY;
6305
6306    _e_comp_object_clear(cw);
6307 }
6308
6309 EINTERN Eina_Bool
6310 e_comp_object_hwc_update_exists(Evas_Object *obj)
6311 {
6312    API_ENTRY EINA_FALSE;
6313    return cw->hwc_need_update;
6314 }
6315
6316 // will remove out
6317 E_API void
6318 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6319 {
6320    API_ENTRY;
6321    cw->hwc_need_update = set;
6322 }
6323
6324 EINTERN Eina_Bool
6325 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6326 {
6327    API_ENTRY EINA_FALSE;
6328    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6329 }
6330
6331 EINTERN void
6332 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6333 {
6334    API_ENTRY;
6335    if (cw->indicator.obj != indicator)
6336      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6337    cw->indicator.obj = indicator;
6338    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6339 }
6340
6341 EINTERN void
6342 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6343 {
6344    API_ENTRY;
6345    if (cw->indicator.obj != indicator) return;
6346    cw->indicator.obj = NULL;
6347    edje_object_part_unswallow(cw->shobj, indicator);
6348 }
6349
6350 EINTERN void
6351 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6352 {
6353    API_ENTRY;
6354    Edje_Message_Int_Set *msg;
6355
6356    if (!cw->indicator.obj) return;
6357
6358    cw->indicator.w = w;
6359    cw->indicator.h = h;
6360
6361    if (!cw->shobj) return;
6362
6363    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6364    msg->count = 2;
6365    msg->val[0] = w;
6366    msg->val[1] = h;
6367    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6368    edje_object_message_signal_process(cw->shobj);
6369 }
6370
6371 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6372 EINTERN void
6373 e_comp_object_map_update(Evas_Object *obj)
6374 {
6375    API_ENTRY;
6376    E_Client *ec = cw->ec;
6377    E_Comp_Wl_Client_Data *cdata;
6378    E_Map *map;
6379    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6380    char buffer[128];
6381    char *p = buffer;
6382    int l, remain = sizeof buffer;
6383
6384    if (!ec) return;
6385    if (e_object_is_del(E_OBJECT(ec))) return;
6386    cdata = e_client_cdata_get(ec);
6387    if (!cdata) return;
6388
6389    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6390     * when new buffer is attached.
6391     */
6392    if (!cdata->buffer_ref.buffer) return;
6393
6394    if ((!cw->redirected) ||
6395        (e_client_video_hw_composition_check(ec)) ||
6396        (!e_comp_wl_output_buffer_transform_get(ec) &&
6397         cdata->scaler.buffer_viewport.buffer.scale == 1))
6398      {
6399         if (evas_object_map_enable_get(cw->effect_obj))
6400           {
6401              ELOGF("TRANSFORM", "map: disable", cw->ec);
6402              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6403              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6404              evas_object_resize(cw->effect_obj, tw, th);
6405           }
6406
6407         return;
6408      }
6409
6410    map = e_map_new();
6411    EINA_SAFETY_ON_NULL_RETURN(map);
6412
6413    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6414
6415    x1 = y1 = 0;
6416    x2 = bw;
6417    y2 = bh;
6418
6419    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6420
6421    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6422    e_map_point_image_uv_set(map, 0, x, y);
6423    l = snprintf(p, remain, "%d,%d", x, y);
6424    p += l, remain -= l;
6425
6426    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6427    e_map_point_image_uv_set(map, 1, x, y);
6428    l = snprintf(p, remain, " %d,%d", x, y);
6429    p += l, remain -= l;
6430
6431    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6432    e_map_point_image_uv_set(map, 2, x, y);
6433    l = snprintf(p, remain, " %d,%d", x, y);
6434    p += l, remain -= l;
6435
6436    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6437    e_map_point_image_uv_set(map, 3, x, y);
6438    l = snprintf(p, remain, " %d,%d", x, y);
6439    p += l, remain -= l;
6440
6441    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6442          cw->ec,
6443          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6444
6445    e_comp_object_map_set(cw->effect_obj, map);
6446    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6447
6448    e_map_free(map);
6449
6450    /* if there's screen rotation with comp mode, then ec->effect_obj and
6451     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6452     */
6453    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6454    evas_object_resize(cw->effect_obj, tw, th);
6455 }
6456
6457 EINTERN Eina_Bool
6458 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6459 {
6460    API_ENTRY EINA_FALSE;
6461
6462    cw->render_trace = set;
6463
6464    return EINA_TRUE;
6465 }
6466
6467 EINTERN Eina_Bool
6468 e_comp_object_native_usable_get(Evas_Object *obj)
6469 {
6470    API_ENTRY EINA_FALSE;
6471    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6472
6473    if (cw->ec->input_only) return EINA_FALSE;
6474    if (cw->external_content) return EINA_FALSE;
6475    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6476
6477    /* just return true value, if it is normal case */
6478    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6479
6480    /* abnormal case */
6481    Evas_Native_Surface *ns;
6482    ns = evas_object_image_native_surface_get(cw->obj);
6483
6484    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6485    if (ns)
6486      {
6487         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6488         return EINA_TRUE;
6489      }
6490
6491    return EINA_FALSE;
6492 }
6493
6494 EINTERN Eina_Bool
6495 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6496 {
6497    API_ENTRY EINA_FALSE;
6498    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6499    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6500    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6501
6502    switch (filter)
6503      {
6504       case E_COMP_IMAGE_FILTER_BLUR:
6505          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6506          break;
6507       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6508          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6509          break;
6510       case E_COMP_IMAGE_FILTER_INVERSE:
6511          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6512          break;
6513       case E_COMP_IMAGE_FILTER_NONE:
6514       default:
6515          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6516          break;
6517      }
6518
6519    cw->image_filter = filter;
6520
6521    return EINA_TRUE;
6522 }
6523
6524 EINTERN E_Comp_Image_Filter
6525 e_comp_object_image_filter_get(Evas_Object *obj)
6526 {
6527    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6528    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6529    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6530    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6531
6532    return cw->image_filter;
6533 }
6534
6535 static void
6536 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6537 {
6538    Evas_Object *obj;
6539
6540    if (!_damage_trace) return;
6541
6542    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6543      evas_object_del(obj);
6544
6545    _damage_trace_post_objs = NULL;
6546 }
6547
6548 static void
6549 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6550 {
6551    if (!_damage_trace) return;
6552
6553    _damage_trace_post_objs = _damage_trace_objs;
6554    _damage_trace_objs = NULL;
6555 }
6556
6557 EINTERN void
6558 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6559 {
6560    if (_damage_trace == onoff) return;
6561
6562    if (onoff)
6563      {
6564         evas_event_callback_add(e_comp->evas,
6565                                 EVAS_CALLBACK_RENDER_PRE,
6566                                 _e_comp_object_damage_trace_render_pre_cb,
6567                                 NULL);
6568
6569         evas_event_callback_add(e_comp->evas,
6570                                 EVAS_CALLBACK_RENDER_POST,
6571                                 _e_comp_object_damage_trace_render_post_cb,
6572                                 NULL);
6573      }
6574    else
6575      {
6576         Evas_Object *obj;
6577
6578         EINA_LIST_FREE(_damage_trace_objs, obj)
6579           evas_object_del(obj);
6580
6581         _damage_trace_objs = NULL;
6582
6583         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6584           evas_object_del(obj);
6585
6586         _damage_trace_post_objs = NULL;
6587
6588         evas_event_callback_del(e_comp->evas,
6589                                 EVAS_CALLBACK_RENDER_PRE,
6590                                 _e_comp_object_damage_trace_render_pre_cb);
6591
6592         evas_event_callback_del(e_comp->evas,
6593                                 EVAS_CALLBACK_RENDER_POST,
6594                                 _e_comp_object_damage_trace_render_post_cb);
6595      }
6596
6597    _damage_trace = onoff;
6598 }
6599
6600 EINTERN Eina_Bool
6601 e_comp_object_redirected_get(Evas_Object *obj)
6602 {
6603    API_ENTRY EINA_FALSE;
6604    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6605
6606    return cw->redirected;
6607 }
6608
6609 EINTERN Eina_Bool
6610 e_comp_object_color_visible_get(Evas_Object *obj)
6611 {
6612    API_ENTRY EINA_FALSE;
6613    int a;
6614
6615    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6616
6617    e_comp_object_color_get(obj, NULL, NULL, NULL, &a);
6618    if (a <= 0)
6619      return EINA_FALSE;
6620
6621    evas_object_color_get(cw->effect_obj, NULL, NULL, NULL, &a);
6622    if (a <= 0)
6623      return EINA_FALSE;
6624
6625    evas_object_color_get(cw->shobj, NULL, NULL, NULL, &a);
6626    if (a <= 0)
6627      return EINA_FALSE;
6628
6629    evas_object_color_get(cw->obj, NULL, NULL, NULL, &a);
6630    if (a <= 0)
6631      return EINA_FALSE;
6632
6633    return EINA_TRUE;
6634 }
6635
6636 E_API Eina_Bool
6637 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6638 {
6639    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6640
6641    return e_map_set_to_comp_object(em, obj);
6642 }
6643
6644 EINTERN E_Map *
6645 e_comp_object_map_get(const Evas_Object *obj)
6646 {
6647    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6648
6649    return e_map_get_from_comp_object(obj);
6650 }
6651
6652 E_API Eina_Bool
6653 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6654 {
6655    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6656
6657    evas_object_map_enable_set(obj, enable);
6658
6659    return EINA_TRUE;
6660 }
6661
6662 E_API Eina_Bool
6663 e_comp_object_render_update_lock(Evas_Object *obj)
6664 {
6665    API_ENTRY EINA_FALSE;
6666
6667    if (cw->render_update_lock.lock == 0)
6668      {
6669         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6670         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref,
6671                                    e_pixmap_resource_get(cw->ec->pixmap));
6672         e_comp_object_render_update_del(obj);
6673         ELOGF("COMP", "Render update lock enabled", cw->ec);
6674      }
6675
6676    cw->render_update_lock.lock++;
6677
6678    return EINA_TRUE;
6679 }
6680
6681 E_API void
6682 e_comp_object_render_update_unlock(Evas_Object *obj)
6683 {
6684    API_ENTRY;
6685
6686    if (cw->render_update_lock.lock == 0)
6687      return;
6688
6689    cw->render_update_lock.lock--;
6690
6691    if (cw->render_update_lock.lock == 0)
6692      {
6693
6694         if (cw->render_update_lock.pending_move_set)
6695           {
6696              evas_object_move(obj,
6697                               cw->render_update_lock.pending_move_x,
6698                               cw->render_update_lock.pending_move_y);
6699              cw->render_update_lock.pending_move_x = 0;
6700              cw->render_update_lock.pending_move_y = 0;
6701              cw->render_update_lock.pending_move_set = EINA_FALSE;
6702           }
6703
6704         if (cw->render_update_lock.pending_resize_set)
6705           {
6706              evas_object_resize(obj,
6707                                 cw->render_update_lock.pending_resize_w,
6708                                 cw->render_update_lock.pending_resize_h);
6709              cw->render_update_lock.pending_resize_w = 0;
6710              cw->render_update_lock.pending_resize_h = 0;
6711              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6712           }
6713
6714         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6715
6716         if ((cw->ec->exp_iconify.buffer_flush) &&
6717             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6718             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6719           e_comp_object_clear(obj);
6720         else
6721           e_comp_object_render_update_add(obj);
6722
6723         ELOGF("COMP", "Render update lock disabled", cw->ec);
6724      }
6725 }
6726
6727 E_API Eina_Bool
6728 e_comp_object_render_update_lock_get(Evas_Object *obj)
6729 {
6730    API_ENTRY EINA_FALSE;
6731
6732    if (cw->render_update_lock.lock > 0)
6733      return EINA_TRUE;
6734
6735    return EINA_FALSE;
6736 }
6737
6738 E_API void
6739 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6740 {
6741    API_ENTRY;
6742
6743    if (cw->transparent.set)
6744      {
6745         if (r) *r = cw->transparent.user_r;
6746         if (g) *g = cw->transparent.user_g;
6747         if (b) *b = cw->transparent.user_b;
6748         if (a) *a = cw->transparent.user_a;
6749      }
6750    else
6751      {
6752         evas_object_color_get(obj, r, g, b, a);
6753      }
6754 }