e_hints: remove the unused funtions
[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
1951    e_config->transient.raise = oldraise;
1952
1953    _e_comp_object_layers_remove(cw);
1954    cw->layer = e_comp_canvas_layer_map(layer);
1955    _e_comp_object_layers_add(cw, NULL, NULL, 0);
1956    //if (cw->ec->new_client)
1957      //INF("CLIENT STACKED %p: %u", cw->ec, layer);
1958    _e_comp_object_layer_set(obj, layer);
1959    if (!e_comp->layers[cw->layer].obj) return; //this is a layer marker
1960    evas_object_stack_below(obj, e_comp->layers[cw->layer].obj);
1961    if (evas_object_below_get(obj) == e_comp->layers[cw->layer].obj)
1962      {
1963         /* can't stack a client above its own layer marker */
1964         CRI("STACKING ERROR!!! ec:%p (cw->layer:%d, ec->layer:%d)", cw->ec, cw->layer, cw->ec->layer);
1965      }
1966    if (!cw->visible) return;
1967    e_comp_render_queue();
1968    _e_comp_object_transform_obj_stack_update(obj);
1969 }
1970
1971 typedef void (*E_Comp_Object_Stack_Func)(Evas_Object *obj, Evas_Object *stack);
1972
1973 static void
1974 _e_comp_object_raise(Evas_Object *obj)
1975 {
1976    evas_object_raise(obj);
1977
1978    if (evas_object_smart_smart_get(obj))
1979      {
1980         E_Client *ec = e_comp_object_client_get(obj);
1981         if (ec)
1982           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1983      }
1984 }
1985
1986 static void
1987 _e_comp_object_lower(Evas_Object *obj)
1988 {
1989    evas_object_lower(obj);
1990
1991    if (evas_object_smart_smart_get(obj))
1992      {
1993         E_Client *ec = e_comp_object_client_get(obj);
1994         if (ec)
1995           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
1996      }
1997 }
1998
1999 static void
2000 _e_comp_object_stack_above(Evas_Object *obj, Evas_Object *target)
2001 {
2002    evas_object_stack_above(obj, target);
2003
2004    if (evas_object_smart_smart_get(obj))
2005      {
2006         E_Client *ec = e_comp_object_client_get(obj);
2007         if (ec)
2008           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
2009      }
2010 }
2011
2012 static void
2013 _e_comp_object_stack_below(Evas_Object *obj, Evas_Object *target)
2014 {
2015    evas_object_stack_below(obj, target);
2016
2017    if (evas_object_smart_smart_get(obj))
2018      {
2019         E_Client *ec = e_comp_object_client_get(obj);
2020         if (ec)
2021           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RESTACK, ec);
2022      }
2023 }
2024
2025 static void
2026 _e_comp_object_layer_set(Evas_Object *obj, short layer)
2027 {
2028    evas_object_layer_set(obj, layer);
2029
2030    if (evas_object_smart_smart_get(obj))
2031      {
2032         E_Client *ec = e_comp_object_client_get(obj);
2033         if (ec)
2034           _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_LAYER_SET, ec);
2035      }
2036 }
2037
2038 static Eina_Bool
2039 _e_comp_object_is_pending(E_Client *ec)
2040 {
2041    E_Client *topmost;
2042
2043    if (!ec) return EINA_FALSE;
2044
2045    topmost = e_comp_wl_topmost_parent_get(ec);
2046
2047    return (topmost) ? topmost->layer_pending : EINA_FALSE;
2048 }
2049
2050 static void
2051 _e_comp_intercept_stack_helper(E_Comp_Object *cw, Evas_Object *stack, E_Comp_Object_Stack_Func stack_cb)
2052 {
2053    E_Comp_Object *cw2 = NULL;
2054    E_Client *ecstack;
2055    short layer;
2056    Evas_Object *o = stack;
2057    Eina_Bool raising = stack_cb == _e_comp_object_stack_above;
2058
2059    /* We should consider topmost's layer_pending for subsurface */
2060    if ((cw->ec->layer_block) || _e_comp_object_is_pending(cw->ec))
2061      {
2062         if (_e_comp_object_is_pending(cw->ec))
2063           e_comp_object_layer_update(cw->smart_obj,
2064                                      raising? stack : NULL,
2065                                      raising? NULL : stack);
2066
2067         /* obey compositor effects! */
2068         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
2069           evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
2070         stack_cb(cw->smart_obj, stack);
2071         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
2072           evas_object_data_del(cw->smart_obj, "client_restack");
2073         return;
2074      }
2075
2076    cw2 = evas_object_data_get(o, "comp_obj");
2077
2078    /* assume someone knew what they were doing during client init */
2079    if (cw->ec->new_client)
2080      layer = cw->ec->layer;
2081    else if ((cw2) && _e_comp_object_is_pending(cw2->ec))
2082      layer = cw2->ec->layer;
2083    else
2084      layer = evas_object_layer_get(stack);
2085    ecstack = e_client_below_get(cw->ec);
2086    if (layer != e_comp_canvas_layer_map_to(cw->layer))
2087      {
2088         /* some FOOL is trying to restack a layer marker */
2089         if (cw->smart_obj == e_comp->layers[cw->layer].obj) return;
2090         evas_object_layer_set(cw->smart_obj, layer);
2091         /* we got our layer wrangled, return now! */
2092         if (layer != e_comp_canvas_layer_map_to(cw->layer)) return;
2093      }
2094
2095    /* check if we're stacking below another client */
2096    while (!cw2)
2097      {
2098         /* check for non-client layer object */
2099         if (!e_util_strcmp(evas_object_name_get(o), "layer_obj"))
2100           break;
2101         /* find an existing client to use for layering
2102          * by walking up the object stack
2103          *
2104          * this is guaranteed to be pretty quick since we'll either:
2105          * - run out of client layers
2106          * - find a stacking client
2107          */
2108         o = evas_object_above_get(o);
2109         if ((!o) || (o == cw->smart_obj)) break;
2110         if (evas_object_layer_get(o) != layer)
2111           {
2112              /* reached the top client layer somehow
2113               * use top client object
2114               */
2115              o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR)].obj;
2116           }
2117         if (!o)
2118           /* top client layer window hasn't been stacked yet. this probably shouldn't happen?
2119            * return here since the top client layer window
2120            */
2121           {
2122              E_Client *ec;
2123
2124              ec = e_client_top_get();
2125              if (ec)
2126                o = ec->frame;
2127              //else //wat
2128           }
2129         if (o) cw2 = evas_object_data_get(o, "comp_obj");
2130      }
2131
2132    if (cw2 && cw->layer != cw2->layer)
2133      return;
2134
2135    /* remove existing layers */
2136    _e_comp_object_layers_remove(cw);
2137    if (cw2)
2138      {
2139         if (o == stack) //if stacking above, cw2 is above; else cw2 is below
2140           _e_comp_object_layers_add(cw, raising ? cw2 : NULL, raising ? NULL : cw2, 0);
2141         else if (o == cw->smart_obj) //prepend (lower) if not stacking above
2142           _e_comp_object_layers_add(cw, NULL, NULL, !raising);
2143         else //if no stacking objects found, either raise or lower
2144           _e_comp_object_layers_add(cw, raising ? NULL : cw2, raising ? cw2 : NULL, 0);
2145      }
2146    else
2147      _e_comp_object_layers_add(cw, NULL, NULL, 0);
2148
2149    /* find new object for stacking if cw2 is on state of layer_pending */
2150    if ((cw2) && _e_comp_object_is_pending(cw2->ec))
2151      {
2152         E_Client *new_stack = NULL, *current_ec = NULL;
2153         current_ec = cw2->ec;
2154         if (raising)
2155           {
2156              while ((new_stack = e_client_below_get(current_ec)))
2157                {
2158                   current_ec = new_stack;
2159                   if (new_stack == cw->ec) continue;
2160                   if (new_stack->layer != cw2->ec->layer) break;
2161                   if (!_e_comp_object_is_pending(new_stack)) break;
2162                }
2163              if ((new_stack) && (new_stack->layer == cw2->ec->layer))
2164                stack = new_stack->frame;
2165              else
2166                {
2167                   /* stack it above layer object */
2168                   int below_layer;
2169                   below_layer = (cw2->layer <= 0)? 0 : cw2->layer - 1 ;
2170                   stack = e_comp->layers[below_layer].obj;
2171                }
2172           }
2173         else
2174           {
2175              while ((new_stack = e_client_above_get(current_ec)))
2176                {
2177                   current_ec = new_stack;
2178                   if (new_stack == cw->ec) continue;
2179                   if (new_stack->layer != cw2->ec->layer) break;
2180                   if (!_e_comp_object_is_pending(new_stack)) break;
2181                }
2182              if ((new_stack) && (new_stack->layer == cw2->ec->layer))
2183                stack = new_stack->frame;
2184              else
2185                stack = e_comp->layers[cw2->layer].obj;
2186           }
2187      }
2188
2189    /* set restack if stacking has changed */
2190    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
2191      evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
2192    stack_cb(cw->smart_obj, stack);
2193    if (e_comp->layers[cw->layer].obj)
2194      if (evas_object_below_get(cw->smart_obj) == e_comp->layers[cw->layer].obj)
2195        {
2196           CRI("STACKING ERROR!!! ec:%p (cw->layer:%d, ec->layer:%d)", cw->ec, cw->layer, cw->ec->layer);
2197        }
2198    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
2199      evas_object_data_del(cw->smart_obj, "client_restack");
2200    if (!cw->visible) return;
2201    e_comp_render_queue();
2202 }
2203
2204 static void
2205 _e_comp_intercept_stack_above(void *data, Evas_Object *obj, Evas_Object *above)
2206 {
2207    EINA_SAFETY_ON_TRUE_RETURN(obj == above);
2208
2209    if (evas_object_below_get(obj) == above)
2210      {
2211         e_comp_object_layer_update(obj, above, NULL);
2212         return;
2213      }
2214
2215    TRACE_DS_BEGIN(COMP:INTERCEPT STACK ABOVE);
2216    _e_comp_intercept_stack_helper(data, above, _e_comp_object_stack_above);
2217    _e_comp_object_transform_obj_stack_update(obj);
2218    _e_comp_object_transform_obj_stack_update(above);
2219    TRACE_DS_END();
2220 }
2221
2222 static void
2223 _e_comp_intercept_stack_below(void *data, Evas_Object *obj, Evas_Object *below)
2224 {
2225    EINA_SAFETY_ON_TRUE_RETURN(obj == below);
2226    if (evas_object_above_get(obj) == below)
2227      {
2228         e_comp_object_layer_update(obj, NULL, below);
2229         return;
2230      }
2231
2232    TRACE_DS_BEGIN(COMP:INTERCEPT STACK BELOW);
2233    _e_comp_intercept_stack_helper(data, below, _e_comp_object_stack_below);
2234    if (evas_object_smart_smart_get(obj))
2235      _e_comp_object_transform_obj_stack_update(obj);
2236    if (evas_object_smart_smart_get(below))
2237      _e_comp_object_transform_obj_stack_update(below);
2238    TRACE_DS_END();
2239 }
2240
2241 static void
2242 _e_comp_intercept_lower(void *data, Evas_Object *obj)
2243 {
2244    E_Comp_Object *cw = data;
2245    Evas_Object *o;
2246
2247    TRACE_DS_BEGIN(COMP:INTERCEPT LOWER);
2248
2249    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
2250      {
2251         if (cw->ec->layer_pending)
2252           e_comp_object_layer_update(obj, NULL, obj);
2253
2254         _e_comp_object_lower(obj);
2255         goto end;
2256      }
2257    if (!EINA_INLIST_GET(cw->ec)->prev) goto end; //already lowest on layer
2258    o = evas_object_below_get(obj);
2259    _e_comp_object_layers_remove(cw);
2260    /* prepend to client list since this client should be the first item now */
2261    _e_comp_object_layers_add(cw, NULL, NULL, 1);
2262    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) goto end; //already at bottom!
2263    if (obj == e_comp->layers[cw->layer].obj) goto end; //never lower a layer marker!
2264    evas_object_data_set(obj, "client_restack", (void*)1);
2265    _e_comp_object_lower(obj);
2266    evas_object_data_del(obj, "client_restack");
2267    if (!cw->visible) goto end;
2268    e_comp_render_queue();
2269    _e_comp_object_transform_obj_stack_update(obj);
2270
2271 end:
2272    if (!cw->ec->post_lower)
2273      e_client_focus_stack_lower(cw->ec);
2274    TRACE_DS_END();
2275 }
2276
2277 static void
2278 _e_comp_intercept_raise(void *data, Evas_Object *obj)
2279 {
2280    E_Comp_Object *cw = data;
2281    Evas_Object *o;
2282
2283    TRACE_DS_BEGIN(COMP:INTERCEPT RAISE);
2284
2285    if ((cw->ec->layer_block) || (cw->ec->layer_pending))
2286      {
2287         if (cw->ec->layer_pending)
2288           {
2289              int obj_layer = evas_object_layer_get(obj);
2290              if (cw->ec->layer != obj_layer)
2291                e_comp_object_layer_update(obj, NULL, NULL);
2292           }
2293
2294         _e_comp_object_raise(obj);
2295         goto end;
2296      }
2297    if (!EINA_INLIST_GET(cw->ec)->next) goto end;//already highest on layer
2298    o = evas_object_above_get(obj);
2299    {
2300       E_Client *ecabove = e_client_above_get(cw->ec);
2301       if (ecabove && (ecabove->frame == e_comp->layers[cw->layer].obj) &&
2302           (ecabove->frame == o)) goto end; //highest below marker
2303    }
2304    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) goto end; //already at top!
2305    if (obj == e_comp->layers[cw->layer].obj) //never raise a non-layer marker!
2306      _e_comp_object_raise(obj);
2307    else
2308      {
2309         Evas_Object *op;
2310
2311         /* still stack below override below the layer marker */
2312         for (op = o = e_comp->layers[cw->layer].obj;
2313              o && o != e_comp->layers[cw->layer - 1].obj;
2314              op = o, o = evas_object_below_get(o))
2315           {
2316              if (evas_object_smart_smart_get(o))
2317                {
2318                   E_Client *ec;
2319
2320                   ec = e_comp_object_client_get(o);
2321                   if (ec && (!ec->override)) break;
2322                }
2323           }
2324         _e_comp_object_stack_below(obj, op);
2325         e_client_focus_defer_set(cw->ec);
2326      }
2327    if (!cw->visible) goto end;
2328    e_comp_render_queue();
2329    _e_comp_object_transform_obj_stack_update(obj);
2330
2331 end:
2332    TRACE_DS_END();
2333 }
2334
2335 static void
2336 _e_comp_intercept_hide(void *data, Evas_Object *obj)
2337 {
2338    E_Comp_Object *cw = data;
2339
2340 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2341    if( !_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_HIDE, cw->ec))
2342      {
2343         ELOGF("COMP", "Hide. intercepted", cw->ec);
2344         return;
2345      }
2346 #endif
2347
2348    if (cw->ec->launching == EINA_TRUE)
2349      {
2350         ELOGF("COMP", "Hide. Cancel launching flag", cw->ec);
2351         cw->ec->launching = EINA_FALSE;
2352      }
2353
2354    if (cw->ec->hidden)
2355      {
2356         /* hidden flag = just do it */
2357         ELOGF("COMP", "Hide hidden evas_object:%p", cw->ec, obj);
2358         evas_object_hide(obj);
2359         return;
2360      }
2361
2362    if (cw->ec->input_only)
2363      {
2364         /* input_only = who cares */
2365         ELOGF("COMP", "Hide input_only evas_object:%p", cw->ec, obj);
2366         evas_object_hide(obj);
2367         return;
2368      }
2369    /* already hidden or currently animating */
2370    if ((!cw->visible) || (cw->animating && cw->hiding && (!cw->ec->iconic)))
2371      {
2372         ELOGF("COMP", "Hide. but already hidden or currently animating", cw->ec);
2373         return;
2374      }
2375
2376    /* don't try hiding during shutdown */
2377    cw->defer_hide |= stopping;
2378    if (!cw->defer_hide)
2379      {
2380         if ((!cw->ec->iconic) && (!cw->ec->override))
2381           /* unset delete requested so the client doesn't break */
2382           cw->ec->delete_requested = 0;
2383         if ((!cw->animating) || (!cw->hiding) || cw->ec->iconic)
2384           {
2385              ELOGF("COMP", "Hide. but after iconify or hide animation, cw->animating:%d, cw->hiding:%d, iconic:%d",
2386                    cw->ec, cw->animating, cw->hiding, cw->ec->iconic);
2387
2388              if (cw->ec->iconic)
2389                e_comp_object_signal_emit(obj, "e,action,iconify", "e");
2390              else
2391                {
2392                   e_comp_object_signal_emit(obj, "e,state,hidden", "e");
2393                   if (!cw->showing)
2394                     _e_comp_object_animating_begin(cw);
2395                   if (!_e_comp_object_effect_visibility_start(cw, 0)) return;
2396                }
2397              evas_object_smart_callback_call(obj, "hiding", cw->ec);
2398              cw->defer_hide = !!cw->animating;
2399              if (!cw->animating)
2400                e_comp_object_effect_set(obj, NULL);
2401           }
2402      }
2403    if (cw->animating) return;
2404    /* if we have no animations running, go ahead and hide */
2405    cw->defer_hide = 0;
2406    ELOGF("COMP", "Hide normal object:%p", cw->ec, obj);
2407    evas_object_hide(obj);
2408 }
2409
2410 static void
2411 _e_comp_intercept_show_helper(E_Comp_Object *cw)
2412 {
2413    E_Client *ec = cw->ec;
2414    int w = 0, h = 0;
2415
2416    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
2417
2418    if (ec->show_pending.count > 0)
2419      {
2420         ELOGF("COMP", "show_helper. Show PENDING!!! show_pending:%d", ec, ec->show_pending.count);
2421         ec->show_pending.running = EINA_TRUE;
2422         return;
2423      }
2424
2425 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2426    if (!_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, ec))
2427      {
2428         ELOGF("COMP", "show_helper. intercepted", cw->ec);
2429         return;
2430      }
2431 #endif
2432
2433    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,
2434          cw->visible, cw->animating, cw->defer_hide, cw->content_type, cw->updates, cw->w, cw->h,
2435          ec->iconic, ec->exp_iconify.by_client, ec->exp_iconify.type, ec->input_only, ec->ignored, ec->new_client);
2436
2437    if (ec->sticky)
2438      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
2439    if (cw->visible)
2440      {
2441         if (ec->iconic && cw->animating)
2442           {
2443              /* triggered during iconify animation */
2444              e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
2445              cw->defer_hide = 0;
2446           }
2447         ELOGF("COMP", "show_helper. return. already cw->visible", ec);
2448         return;
2449      }
2450    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE ||
2451        cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE)
2452      {
2453         evas_object_move(cw->smart_obj, ec->x, ec->y);
2454         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2455         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2456
2457         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2458           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2459
2460         cw->real_hid = 0;
2461         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2462         evas_object_show(cw->smart_obj);
2463
2464         if (!ec->iconic)
2465           e_client_focus_defer_set(ec);
2466
2467         return;
2468      }
2469    if ((!cw->updates) && (!ec->input_only) && (!ec->ignored))
2470      {
2471         int pw, ph;
2472
2473         pw = ec->client.w, ph = ec->client.h;
2474         if ((!pw) || (!ph))
2475           if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
2476             {
2477                ec->changes.visible = !ec->hidden;
2478                ec->visible = 1;
2479                EC_CHANGED(ec);
2480                ELOGF("COMP", "show_helper. return. no pixmap size", ec);
2481                return;
2482             }
2483
2484         cw->updates = eina_tiler_new(pw, ph);
2485         if (!cw->updates)
2486           {
2487              ec->changes.visible = !ec->hidden;
2488              ec->visible = 1;
2489              EC_CHANGED(ec);
2490              ELOGF("COMP", "show_helper. return. no cw->updates", ec);
2491              return;
2492           }
2493      }
2494    if (cw->updates)
2495      eina_tiler_tile_size_set(cw->updates, 1, 1);
2496    if (ec->new_client)
2497      {
2498         /* ignore until client idler first run */
2499         ec->changes.visible = !ec->hidden;
2500         ec->visible = 1;
2501         EC_CHANGED(ec);
2502         ELOGF("COMP", "show_helper. return. new_client", ec);
2503         return;
2504      }
2505    if (ec->input_only)
2506      {
2507         /* who cares */
2508         cw->real_hid = 0;
2509         evas_object_move(cw->smart_obj, ec->x, ec->y);
2510         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2511         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2512         evas_object_show(cw->smart_obj);
2513         return;
2514      }
2515    if (ec->netwm.type == E_WINDOW_TYPE_DND && !e_comp_wl->drag_client)
2516      {
2517         /* start_drag not received */
2518         ec->changes.visible = 1;
2519         ec->visible = 1;
2520         EC_CHANGED(ec);
2521         ELOGF("COMP", "show_helper. return. start_drag not received yet", ec);
2522         return;
2523      }
2524    /* re-set geometry */
2525    evas_object_move(cw->smart_obj, ec->x, ec->y);
2526    /* force resize in case it hasn't happened yet, or just to update size */
2527    evas_object_resize(cw->smart_obj, ec->w, ec->h);
2528    if ((cw->w < 1) || (cw->h < 1))
2529      {
2530         /* if resize didn't go through, try again */
2531         ec->visible = ec->changes.visible = 1;
2532         EC_CHANGED(ec);
2533         ELOGF("COMP", "show_helper. return. cw_size(%d,%d)", ec, cw->w, cw->h);
2534         return;
2535      }
2536    /* if pixmap not available, clear pixmap since we're going to fetch it again */
2537    if (!e_pixmap_size_get(ec->pixmap, &w, &h))
2538      e_pixmap_clear(ec->pixmap);
2539
2540    if (cw->real_hid && w && h)
2541      {
2542         cw->real_hid = 0;
2543         /* force comp theming in case it didn't happen already */
2544         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2545         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2546           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2547      }
2548
2549    /* only do the show if show is allowed */
2550    if (!cw->real_hid)
2551      {
2552         if (ec->internal) //internal clients render when they feel like it
2553           e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2554
2555         if (!e_client_is_iconified_by_client(ec)||
2556             e_policy_visibility_client_is_uniconic(ec))
2557           {
2558              ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2559              evas_object_show(cw->smart_obj);
2560
2561              /* if comp object is shown in idle enterer before(E_CLIENT_HOOK_EVAL_FETCH),
2562                 it is rendered in idle callback without native surface and
2563                 compositor shows an empty frame if other objects aren't shown
2564                 because job callback of e_comp called at the next loop.
2565                 it causes a visual defect when windows are switched.
2566               */
2567              if (cw->redirected)
2568                {
2569                   e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2570                   e_comp_object_dirty(cw->smart_obj);
2571                   e_comp_object_render(cw->smart_obj);
2572                }
2573
2574              if (!ec->iconic ||
2575                  e_policy_visibility_client_is_uniconic(ec))
2576                {
2577                   if (ec->exp_iconify.not_raise &&
2578                       e_client_check_above_focused(ec))
2579                     e_client_focus_stack_append_current_focused(ec);
2580                   else
2581                     e_client_focus_defer_set(ec);
2582                }
2583           }
2584      }
2585 }
2586
2587 static void
2588 _e_comp_intercept_show(void *data, Evas_Object *obj EINA_UNUSED)
2589 {
2590    E_Comp_Object *cw = data;
2591    E_Client *ec = cw->ec;
2592    Eina_List *l;
2593    E_Input_Rect_Data *input_rect_data;
2594    E_Input_Rect_Smart_Data *input_rect_sd;
2595    int tw, th;
2596
2597    if (ec->ignored) return;
2598
2599    if (cw->effect_obj)
2600      {
2601         //INF("SHOW2 %p", ec);
2602         _e_comp_intercept_show_helper(cw);
2603         return;
2604      }
2605    //INF("SHOW %p", ec);
2606    if (ec->input_only)
2607      {
2608         cw->effect_obj = evas_object_rectangle_add(e_comp->evas);
2609         evas_object_color_set(cw->effect_obj, 0, 0, 0, 0);
2610         evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
2611         evas_object_name_set(cw->effect_obj, "cw->effect_obj::input_only");
2612      }
2613    else
2614      {
2615         if ((!cw->obj) && (cw->external_content))
2616           {
2617              ERR("cw->obj for external content is not created! ec:%p", cw->ec);
2618              return;
2619           }
2620
2621         _e_comp_object_setup(cw);
2622         if (!cw->obj)
2623           {
2624              cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
2625              cw->obj = evas_object_image_filled_add(e_comp->evas);
2626              evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
2627              e_util_size_debug_set(cw->obj, 1);
2628              evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
2629              evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
2630              evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
2631              evas_object_name_set(cw->obj, "cw->obj");
2632              evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
2633           }
2634         _e_comp_object_alpha_set(cw);
2635 #ifdef BORDER_ZOOMAPS
2636         e_comp_object_zoomap_set(o, 1);
2637 #else
2638         cw->zoomap_disabled = 1;
2639 #endif
2640         cw->redirected = 1;
2641         evas_object_color_set(cw->clip, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity);
2642      }
2643
2644    _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
2645    evas_object_geometry_set(cw->effect_obj, cw->x, cw->y, tw, th);
2646    if (cw->input_obj)
2647      {
2648         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2649         if (input_rect_sd)
2650           {
2651              EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2652                {
2653                   if (input_rect_data->obj)
2654                     {
2655                        evas_object_geometry_set(input_rect_data->obj,
2656                          cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2657                          cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2658                          input_rect_data->rect.w, input_rect_data->rect.h);
2659                     }
2660                }
2661           }
2662      }
2663
2664    if (cw->mask.obj)
2665      evas_object_resize(cw->mask.obj, cw->w, cw->h);
2666
2667    _e_comp_intercept_show_helper(cw);
2668 }
2669
2670 static void
2671 _e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus)
2672 {
2673    E_Comp_Object *cw = data;
2674    E_Client *ec;
2675
2676    ec = cw->ec;
2677    /* note: this is here as it seems there are enough apps that do not even
2678     * expect us to emulate a look of focus but not actually set x input
2679     * focus as we do - so simply abort any focus set on such windows */
2680    /* be strict about accepting focus hint */
2681    /* be strict about accepting focus hint */
2682    if ((!ec->icccm.accepts_focus) &&
2683        (!ec->icccm.take_focus))
2684      {
2685         if (!focus)
2686           {
2687              if (e_client_focused_get() == ec)
2688                 e_client_focused_set(NULL);
2689
2690              ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2691              evas_object_focus_set(obj, focus);
2692           }
2693         return;
2694      }
2695    if (focus && ec->lock_focus_out) return;
2696    if (e_object_is_del(E_OBJECT(ec)) && focus)
2697      CRI("CAN'T FOCUS DELETED CLIENT! ec:%p", ec);
2698
2699    /* filter focus setting based on current state */
2700    if (focus)
2701      {
2702         if (ec->focused)
2703           {
2704              ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2705              evas_object_focus_set(obj, focus);
2706              return;
2707           }
2708         if ((ec->iconic) && (!ec->deskshow))
2709           {
2710              if (!e_policy_visibility_client_is_uniconify_render_running(ec))
2711                {
2712                   /* don't focus an iconified window. that's silly! */
2713                   ELOGF("FOCUS", "Do uniconify to set focus", ec);
2714                   e_client_uniconify(ec);
2715                   if (e_client_focus_track_enabled())
2716                     e_client_focus_latest_set(ec);
2717                   return;
2718                }
2719           }
2720         if (!ec->visible)
2721           {
2722              return;
2723           }
2724         if ((!ec->sticky) && (ec->desk) && (!ec->desk->visible))
2725           {
2726              if (ec->desk->animate_count) return;
2727              e_desk_show(ec->desk);
2728              if (!ec->desk->visible) return;
2729           }
2730      }
2731
2732    if (focus)
2733      {
2734         /* check for dialog children that steal focus */
2735         if ((ec->modal) && (ec->modal != ec) &&
2736             (ec->modal->visible) && (!e_object_is_del(E_OBJECT(ec->modal))))
2737           {
2738              if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
2739                {
2740                   ELOGF("FOCUS", "focus set   | intercept focus to modal", ec->modal);
2741                   e_client_frame_focus_set(ec->modal, focus);
2742                }
2743              return;
2744           }
2745         else if ((ec->leader) && (ec->leader->modal) &&
2746                  (ec->leader->modal != ec) && ec->leader->modal->visible &&
2747                  (!e_object_is_del(E_OBJECT(ec->leader->modal))))
2748           {
2749              if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
2750                {
2751                   ELOGF("FOCUS", "focus set   | intercept focus to leader->modal", ec->leader->modal);
2752                   e_client_frame_focus_set(ec->leader->modal, focus);
2753                }
2754              return;
2755           }
2756         if (!cw->visible)
2757           {
2758              /* not yet visible, wait till the next time... */
2759              ec->want_focus = !ec->hidden;
2760              if (ec->want_focus)
2761                EC_CHANGED(ec);
2762              return;
2763           }
2764         e_client_focused_set(ec);
2765      }
2766    else
2767      {
2768         if (e_client_focused_get() == ec)
2769           e_client_focused_set(NULL);
2770      }
2771
2772    if (focus)
2773      ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2774    else
2775      ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2776
2777    evas_object_focus_set(obj, focus);
2778 }
2779
2780 static void
2781 _e_comp_intercept_color_set(void *data, Evas_Object *obj, int r, int g, int b, int a)
2782 {
2783    E_Comp_Object *cw = data;
2784
2785    if (cw->transparent.set)
2786      {
2787         cw->transparent.user_r = r;
2788         cw->transparent.user_g = g;
2789         cw->transparent.user_b = b;
2790         cw->transparent.user_a = a;
2791
2792         ELOGF("COMP", "Transparent user_color(%d,%d,%d,%d)",
2793               cw->ec,
2794               cw->transparent.user_r,
2795               cw->transparent.user_g,
2796               cw->transparent.user_b,
2797               cw->transparent.user_a);
2798      }
2799    else
2800      {
2801         evas_object_color_set(obj, r, g, b, a);
2802      }
2803 }
2804 ////////////////////////////////////////////////////
2805
2806 static void
2807 _e_comp_object_frame_recalc(E_Comp_Object *cw)
2808 {
2809    int w, h, ox, oy, ow, oh;
2810    Eina_List *l;
2811    Eina_Bool pass_event_flag = EINA_FALSE;
2812    E_Input_Rect_Data *input_rect_data;
2813    E_Input_Rect_Smart_Data *input_rect_sd;
2814
2815    if (cw->frame_object)
2816      {
2817         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
2818         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
2819         /* set a fixed size, force edje calc, check size difference */
2820         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
2821         edje_object_message_signal_process(cw->frame_object);
2822         edje_object_calc_force(cw->frame_object);
2823         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
2824         cw->client_inset.l = ox;
2825         cw->client_inset.r = MAX(w, 50) - (ox + ow);
2826         cw->client_inset.t = oy;
2827         cw->client_inset.b = MAX(h, 50) - (oy + oh);
2828         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
2829         evas_object_resize(cw->frame_object, w, h);
2830
2831         if (cw->input_obj)
2832           {
2833              input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2834              if (input_rect_sd)
2835                {
2836                   EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2837                     {
2838                        if (input_rect_data->obj)
2839                          {
2840                             pass_event_flag = EINA_TRUE;
2841                             break;
2842                          }
2843                     }
2844                }
2845           }
2846         evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
2847         evas_object_pass_events_set(cw->obj, pass_event_flag);
2848      }
2849    else
2850      {
2851         cw->client_inset.l = 0;
2852         cw->client_inset.r = 0;
2853         cw->client_inset.t = 0;
2854         cw->client_inset.b = 0;
2855      }
2856    cw->client_inset.calc = !!cw->frame_object;
2857 }
2858
2859 static void
2860 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2861 {
2862    E_Comp_Object *cw = data;
2863    int w, h, pw, ph;
2864
2865    /* - get current size
2866     * - calc new size
2867     * - readjust for new frame size
2868     */
2869
2870    w = cw->ec->w, h = cw->ec->h;
2871    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
2872
2873    _e_comp_object_frame_recalc(cw);
2874
2875    if (!cw->ec->fullscreen)
2876      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
2877
2878    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2879    if (cw->ec->shading || cw->ec->shaded) return;
2880    if (cw->ec->fullscreen)
2881      evas_object_resize(cw->ec->frame, cw->ec->zone->w, cw->ec->zone->h);
2882    else if (cw->ec->new_client)
2883      {
2884         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
2885         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
2886         evas_object_resize(cw->ec->frame, w, h);
2887      }
2888    else if ((w != cw->ec->w) || (h != cw->ec->h))
2889      evas_object_resize(cw->ec->frame, w, h);
2890 }
2891
2892 static void
2893 _e_comp_smart_cb_shading(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2894 {
2895    E_Comp_Object *cw = data;
2896
2897    if (!cw->ec) return; //NYI
2898    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2899
2900    cw->shade.x = cw->x;
2901    cw->shade.y = cw->y;
2902    e_comp_object_signal_emit(cw->smart_obj, "e,state,shading", "e");
2903 }
2904
2905 static void
2906 _e_comp_smart_cb_shaded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2907 {
2908    E_Comp_Object *cw = data;
2909
2910    if (!cw->ec) return; //NYI
2911    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2912
2913    e_comp_object_signal_emit(cw->smart_obj, "e,state,shaded", "e");
2914 }
2915
2916 static void
2917 _e_comp_smart_cb_unshading(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2918 {
2919    E_Comp_Object *cw = data;
2920
2921    if (!cw->ec) return; //NYI
2922    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2923
2924    e_comp_object_signal_emit(cw->smart_obj, "e,state,unshading", "e");
2925 }
2926
2927 static void
2928 _e_comp_smart_cb_unshaded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2929 {
2930    E_Comp_Object *cw = data;
2931
2932    if (!cw->ec) return; //NYI
2933    E_FREE_FUNC(cw->shade.anim, ecore_timer_del);
2934
2935    e_comp_object_signal_emit(cw->smart_obj, "e,state,unshaded", "e");
2936 }
2937
2938 static void
2939 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2940 {
2941    E_Comp_Object *cw = data;
2942
2943    _e_comp_object_shadow_setup(cw);
2944    if (cw->frame_object)
2945      {
2946         _e_comp_object_shadow(cw);
2947         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2948         _e_comp_object_frame_recalc(cw);
2949         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2950      }
2951 }
2952
2953 static void
2954 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2955 {
2956    E_Comp_Object *cw = data;
2957
2958    if (_e_comp_object_shadow_setup(cw))
2959      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2960    if (cw->frame_object)
2961      {
2962         _e_comp_object_shadow(cw);
2963         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2964         _e_comp_object_frame_recalc(cw);
2965         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2966      }
2967 }
2968
2969 static void
2970 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2971 {
2972    E_Comp_Object *cw = data;
2973
2974    if (cw->frame_object)
2975      {
2976         _e_comp_object_shadow(cw);
2977         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2978         _e_comp_object_frame_recalc(cw);
2979         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2980      }
2981 }
2982
2983 static void
2984 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2985 {
2986    E_Comp_Object *cw = data;
2987
2988    if (_e_comp_object_shadow_setup(cw))
2989      {
2990         EC_CHANGED(cw->ec);
2991         cw->ec->changes.size = 1;
2992      }
2993    if (cw->frame_object)
2994      {
2995         _e_comp_object_shadow(cw);
2996         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
2997         _e_comp_object_frame_recalc(cw);
2998         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2999      }
3000 }
3001
3002 static void
3003 _e_comp_smart_cb_sticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3004 {
3005    e_comp_object_signal_emit(obj, "e,state,sticky", "e");
3006 }
3007
3008 static void
3009 _e_comp_smart_cb_unsticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3010 {
3011    e_comp_object_signal_emit(obj, "e,state,unsticky", "e");
3012 }
3013
3014 static void
3015 _e_comp_smart_cb_unhung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3016 {
3017    E_Comp_Object *cw = data;
3018
3019    if (!cw->ec) return; //NYI
3020    e_comp_object_signal_emit(cw->smart_obj, "e,state,unhung", "e");
3021 }
3022
3023 static void
3024 _e_comp_smart_cb_hung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3025 {
3026    E_Comp_Object *cw = data;
3027
3028    if (!cw->ec) return; //NYI
3029    e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
3030 }
3031
3032 static void
3033 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3034 {
3035    e_comp_object_signal_emit(obj, "e,state,focused", "e");
3036 }
3037
3038 static void
3039 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3040 {
3041    E_Comp_Object *cw = data;
3042
3043    if (!e_object_is_del(E_OBJECT(cw->ec)))
3044      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
3045 }
3046
3047 static void
3048 _e_comp_input_obj_smart_add(Evas_Object *obj)
3049 {
3050    E_Input_Rect_Smart_Data *input_rect_sd;
3051    input_rect_sd = E_NEW(E_Input_Rect_Smart_Data, 1);
3052
3053    if (!input_rect_sd) return;
3054    evas_object_smart_data_set(obj, input_rect_sd);
3055 }
3056
3057 static void
3058 _e_comp_input_obj_smart_del(Evas_Object *obj)
3059 {
3060    E_Input_Rect_Smart_Data *input_rect_sd;
3061    E_Input_Rect_Data *input_rect_data;
3062
3063    input_rect_sd = evas_object_smart_data_get(obj);
3064    if (!input_rect_sd) return;
3065
3066    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
3067      {
3068         if (input_rect_data->obj)
3069           {
3070              evas_object_smart_member_del(input_rect_data->obj);
3071              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
3072           }
3073         E_FREE(input_rect_data);
3074      }
3075    E_FREE(input_rect_sd);
3076 }
3077
3078 static void
3079 _e_comp_input_obj_smart_move(Evas_Object *obj, int x, int y)
3080 {
3081    E_Input_Rect_Smart_Data *input_rect_sd;
3082    E_Input_Rect_Data *input_rect_data;
3083    Eina_List *l;
3084    E_Comp_Object *cw;
3085
3086    input_rect_sd = evas_object_smart_data_get(obj);
3087    if (!input_rect_sd) return;
3088
3089    cw = input_rect_sd->cw;
3090    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3091      {
3092         if (input_rect_data->obj)
3093           {
3094              evas_object_geometry_set(input_rect_data->obj,
3095                x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3096                y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3097                input_rect_data->rect.w, input_rect_data->rect.h);
3098           }
3099      }
3100 }
3101
3102 static void
3103 _e_comp_input_obj_smart_resize(Evas_Object *obj, int w, int h)
3104 {
3105    E_Input_Rect_Smart_Data *input_rect_sd;
3106    E_Input_Rect_Data *input_rect_data;
3107    Eina_List *l;
3108    E_Comp_Object *cw;
3109
3110    input_rect_sd = evas_object_smart_data_get(obj);
3111    if (!input_rect_sd) return;
3112
3113    cw = input_rect_sd->cw;
3114    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3115      {
3116         if (input_rect_data->obj)
3117           {
3118              evas_object_geometry_set(input_rect_data->obj,
3119                cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3120                cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3121                input_rect_data->rect.w, input_rect_data->rect.h);
3122           }
3123      }
3124 }
3125
3126 static void
3127 _e_comp_input_obj_smart_show(Evas_Object *obj)
3128 {
3129    E_Input_Rect_Smart_Data *input_rect_sd;
3130    E_Input_Rect_Data *input_rect_data;
3131    Eina_List *l;
3132
3133    input_rect_sd = evas_object_smart_data_get(obj);
3134    if (!input_rect_sd) return;
3135
3136    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3137      {
3138         if (input_rect_data->obj)
3139           {
3140              evas_object_show(input_rect_data->obj);
3141           }
3142      }
3143 }
3144
3145 static void
3146 _e_comp_input_obj_smart_hide(Evas_Object *obj)
3147 {
3148    E_Input_Rect_Smart_Data *input_rect_sd;
3149    E_Input_Rect_Data *input_rect_data;
3150    Eina_List *l;
3151
3152    input_rect_sd = evas_object_smart_data_get(obj);
3153    if (!input_rect_sd) return;
3154
3155    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3156      {
3157         if (input_rect_data->obj)
3158           {
3159              evas_object_hide(input_rect_data->obj);
3160           }
3161      }
3162 }
3163
3164 static void
3165 _e_comp_input_obj_smart_init(void)
3166 {
3167    if (_e_comp_input_obj_smart) return;
3168    {
3169       static const Evas_Smart_Class sc =
3170       {
3171          INPUT_OBJ_SMART_NAME,
3172          EVAS_SMART_CLASS_VERSION,
3173          _e_comp_input_obj_smart_add,
3174          _e_comp_input_obj_smart_del,
3175          _e_comp_input_obj_smart_move,
3176          _e_comp_input_obj_smart_resize,
3177          _e_comp_input_obj_smart_show,
3178          _e_comp_input_obj_smart_hide,
3179          NULL,
3180          NULL,
3181          NULL,
3182          NULL,
3183          NULL,
3184          NULL,
3185
3186          NULL,
3187          NULL,
3188          NULL,
3189          NULL
3190       };
3191       _e_comp_input_obj_smart = evas_smart_class_new(&sc);
3192    }
3193 }
3194
3195
3196 static void
3197 _e_comp_smart_add(Evas_Object *obj)
3198 {
3199    E_Comp_Object *cw;
3200
3201    cw = E_NEW(E_Comp_Object, 1);
3202    EINA_SAFETY_ON_NULL_RETURN(cw);
3203
3204    cw->smart_obj = obj;
3205    cw->x = cw->y = cw->w = cw->h = -1;
3206    evas_object_smart_data_set(obj, cw);
3207    cw->opacity = 255.0;
3208    cw->external_content = 0;
3209    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
3210    cw->transform_bg_color.r = 0;
3211    cw->transform_bg_color.g = 0;
3212    cw->transform_bg_color.b = 0;
3213    cw->transform_bg_color.a = 255;
3214    evas_object_data_set(obj, "comp_obj", cw);
3215    evas_object_move(obj, -1, -1);
3216    /* intercept ALL the callbacks! */
3217    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
3218    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
3219    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
3220    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
3221    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
3222    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
3223    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
3224    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
3225    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
3226    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
3227    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_color_set, cw);
3228
3229    evas_object_smart_callback_add(obj, "shading", _e_comp_smart_cb_shading, cw);
3230    evas_object_smart_callback_add(obj, "shaded", _e_comp_smart_cb_shaded, cw);
3231    evas_object_smart_callback_add(obj, "unshading", _e_comp_smart_cb_unshading, cw);
3232    evas_object_smart_callback_add(obj, "unshaded", _e_comp_smart_cb_unshaded, cw);
3233
3234    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
3235    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
3236    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
3237    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
3238
3239    evas_object_smart_callback_add(obj, "stick", _e_comp_smart_cb_sticky, cw);
3240    evas_object_smart_callback_add(obj, "unstick", _e_comp_smart_cb_unsticky, cw);
3241
3242    evas_object_smart_callback_add(obj, "hung", _e_comp_smart_cb_hung, cw);
3243    evas_object_smart_callback_add(obj, "unhung", _e_comp_smart_cb_unhung, cw);
3244
3245    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
3246
3247    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
3248    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
3249 }
3250
3251 static void
3252 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3253 {
3254    INTERNAL_ENTRY;
3255    evas_object_color_set(cw->clip, r, g, b, a);
3256    evas_object_smart_callback_call(obj, "color_set", NULL);
3257 }
3258
3259
3260 static void
3261 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3262 {
3263    INTERNAL_ENTRY;
3264    evas_object_clip_set(cw->clip, clip);
3265 }
3266
3267 static void
3268 _e_comp_smart_clip_unset(Evas_Object *obj)
3269 {
3270    INTERNAL_ENTRY;
3271    evas_object_clip_unset(cw->clip);
3272 }
3273
3274 static void
3275 _e_comp_smart_hide(Evas_Object *obj)
3276 {
3277    TRACE_DS_BEGIN(COMP:SMART HIDE);
3278
3279    INTERNAL_ENTRY;
3280    cw->visible = 0;
3281    cw->hiding = 0;
3282    evas_object_hide(cw->clip);
3283    if (cw->input_obj) evas_object_hide(cw->input_obj);
3284    evas_object_hide(cw->effect_obj);
3285    if (cw->default_input_obj) evas_object_hide(cw->default_input_obj);
3286    if (cw->transform_bg_obj) evas_object_hide(cw->transform_bg_obj);
3287    if (cw->transform_tranp_obj) evas_object_hide(cw->transform_tranp_obj);
3288    if (stopping)
3289      {
3290         TRACE_DS_END();
3291         return;
3292      }
3293
3294    /* unset native surface if current displaying buffer was destroied */
3295    if (!cw->buffer_destroy_listener.notify)
3296      {
3297         Evas_Native_Surface *ns;
3298         ns = evas_object_image_native_surface_get(cw->obj);
3299         if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
3300           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
3301      }
3302
3303    if (!cw->ec->input_only)
3304      {
3305         edje_object_freeze(cw->effect_obj);
3306         edje_object_freeze(cw->shobj);
3307         edje_object_play_set(cw->shobj, 0);
3308         if (cw->frame_object)
3309           edje_object_play_set(cw->frame_object, 0);
3310      }
3311    /* ensure focus-out */
3312    if (cw->ec->focused &&
3313        (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK))
3314      {
3315         ELOGF("FOCUS", "focus unset | smart_hide", cw->ec);
3316         e_client_frame_focus_set(cw->ec, EINA_FALSE);
3317         e_client_focus_defer_unset(cw->ec);
3318      }
3319    e_comp_render_queue(); //force nocomp recheck
3320
3321    TRACE_DS_END();
3322 }
3323
3324 static void
3325 _e_comp_smart_show(Evas_Object *obj)
3326 {
3327    E_Client *tmp;
3328    Eina_List *l;
3329
3330    INTERNAL_ENTRY;
3331    cw->defer_hide = 0;
3332    cw->visible = 1;
3333    if ((cw->w < 0) || (cw->h < 0))
3334      CRI("ACK! ec:%p", cw->ec);
3335
3336    TRACE_DS_BEGIN(COMP:SMART SHOW);
3337
3338    e_comp_object_map_update(obj);
3339
3340    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
3341      evas_object_show(tmp->frame);
3342
3343    evas_object_show(cw->clip);
3344    if (cw->input_obj) evas_object_show(cw->input_obj);
3345    if (!cw->ec->input_only)
3346      {
3347         edje_object_thaw(cw->effect_obj);
3348         edje_object_thaw(cw->shobj);
3349         edje_object_play_set(cw->shobj, 1);
3350         if (cw->frame_object)
3351           edje_object_play_set(cw->frame_object, 1);
3352      }
3353    evas_object_show(cw->effect_obj);
3354    if (cw->mask.obj) evas_object_show(cw->mask.obj);
3355    if (cw->transform_bg_obj) evas_object_show(cw->transform_bg_obj);
3356    if (cw->transform_tranp_obj) evas_object_show(cw->transform_tranp_obj);
3357    if (cw->default_input_obj) evas_object_show(cw->default_input_obj);
3358    e_comp_render_queue();
3359    if (cw->ec->input_only)
3360      {
3361         TRACE_DS_END();
3362         return;
3363      }
3364    if (cw->ec->iconic && (!cw->ec->new_client))
3365      {
3366         if (e_client_is_iconified_by_client(cw->ec))
3367           {
3368              ELOGF("COMP", "Set launching flag..", cw->ec);
3369              cw->ec->launching = EINA_TRUE;
3370           }
3371
3372         e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
3373      }
3374    else if (!cw->showing) /* if set, client was ec->hidden during show animation */
3375      {
3376         cw->showing = 1;
3377         ELOGF("COMP", "Set launching flag..", cw->ec);
3378         cw->ec->launching = EINA_TRUE;
3379
3380         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
3381         _e_comp_object_animating_begin(cw);
3382         if (!_e_comp_object_effect_visibility_start(cw, 1))
3383           {
3384              TRACE_DS_END();
3385              return;
3386           }
3387      }
3388    /* ensure some random effect doesn't lock the client offscreen */
3389    if (!cw->animating)
3390      {
3391         cw->showing = 0;
3392         e_comp_object_effect_set(obj, NULL);
3393      }
3394
3395    _e_comp_object_dim_update(cw);
3396
3397    TRACE_DS_END();
3398 }
3399
3400 static void
3401 _e_comp_smart_del(Evas_Object *obj)
3402 {
3403    Eina_List *l;
3404
3405    INTERNAL_ENTRY;
3406
3407    if (cw->buffer_destroy_listener.notify)
3408      {
3409         wl_list_remove(&cw->buffer_destroy_listener.link);
3410         cw->buffer_destroy_listener.notify = NULL;
3411      }
3412
3413    if (cw->tbm_surface)
3414      {
3415         tbm_surface_internal_unref(cw->tbm_surface);
3416         cw->tbm_surface = NULL;
3417      }
3418
3419    if (cw->render_update_lock.buffer_ref.buffer)
3420      {
3421         ELOGF("COMP", "Clear buffer_ref of render_update_lock:%d",
3422               cw->ec, cw->render_update_lock.lock);
3423         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
3424      }
3425
3426    e_comp_object_render_update_del(cw->smart_obj);
3427    E_FREE_FUNC(cw->updates, eina_tiler_free);
3428    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
3429    free(cw->ns);
3430
3431    if (cw->obj_mirror)
3432      {
3433         Evas_Object *o;
3434
3435         EINA_LIST_FREE(cw->obj_mirror, o)
3436           {
3437              evas_object_image_data_set(o, NULL);
3438              evas_object_freeze_events_set(o, 1);
3439              evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
3440              evas_object_del(o);
3441           }
3442      }
3443    _e_comp_object_layers_remove(cw);
3444    l = evas_object_data_get(obj, "comp_object-to_del");
3445    E_FREE_LIST(l, evas_object_del);
3446    _e_comp_object_mouse_event_callback_unset(cw);
3447    evas_object_del(cw->clip);
3448    evas_object_del(cw->effect_obj);
3449    evas_object_del(cw->shobj);
3450    evas_object_del(cw->frame_object);
3451    evas_object_del(cw->zoomobj);
3452    evas_object_del(cw->input_obj);
3453    evas_object_del(cw->obj);
3454    evas_object_del(cw->mask.obj);
3455    if (cw->dim.mask_obj) evas_object_del(cw->dim.mask_obj);
3456    evas_object_del(cw->transform_bg_obj);
3457    evas_object_del(cw->transform_tranp_obj);
3458    evas_object_del(cw->default_input_obj);
3459    eina_stringshare_del(cw->frame_theme);
3460    eina_stringshare_del(cw->frame_name);
3461    if (cw->animating)
3462      {
3463         cw->animating = 0;
3464         e_comp->animating--;
3465         UNREFD(cw->ec, 2);
3466         e_object_unref(E_OBJECT(cw->ec));
3467      }
3468    cw->ec->frame = NULL;
3469    free(cw);
3470 }
3471
3472 static void
3473 _e_comp_smart_move(Evas_Object *obj, int x, int y)
3474 {
3475    INTERNAL_ENTRY;
3476
3477    cw->x = x, cw->y = y;
3478    evas_object_move(cw->effect_obj, x, y);
3479    evas_object_move(cw->default_input_obj, x, y);
3480    if (cw->input_obj) evas_object_move(cw->input_obj, x, y);
3481
3482    e_comp_object_map_update(obj);
3483 }
3484
3485 static void
3486 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
3487 {
3488    Eina_Bool first = EINA_FALSE;
3489    int tw, th;
3490
3491    INTERNAL_ENTRY;
3492
3493    if (!cw->effect_obj) CRI("ACK! ec:%p", cw->ec);
3494
3495    TRACE_DS_BEGIN(COMP:SMART RESIZE);
3496
3497    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
3498
3499    if (cw->w != w || cw->h != h)
3500      e_comp_object_map_update(obj);
3501
3502    first = ((cw->w < 1) || (cw->h < 1));
3503    cw->w = w, cw->h = h;
3504    if ((!cw->ec->shading) && (!cw->ec->shaded))
3505      {
3506         int ww, hh, pw, ph;
3507
3508         if (cw->frame_object)
3509           e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
3510         else
3511           ww = w, hh = h;
3512         /* verify pixmap:object size */
3513         if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
3514           {
3515              if ((ww != pw) || (hh != ph))
3516                ELOGF("COMP", "CW RSZ: %dx%d || PX: %dx%d.", cw->ec, ww, hh, pw, ph);
3517           }
3518         evas_object_resize(cw->effect_obj, tw, th);
3519         evas_object_resize(cw->default_input_obj, w, h);
3520         if (cw->zoomobj) e_zoomap_child_resize(cw->zoomobj, pw, ph);
3521         if (cw->input_obj)
3522           evas_object_resize(cw->input_obj, w, h);
3523         if (cw->mask.obj)
3524           evas_object_resize(cw->mask.obj, w, h);
3525         /* resize render update tiler */
3526         if (!first)
3527           {
3528              RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
3529              cw->updates_full = 0;
3530              if (cw->updates) eina_tiler_clear(cw->updates);
3531           }
3532         else
3533           {
3534              RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3535              if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3536           }
3537      }
3538    else
3539      {
3540         evas_object_resize(cw->effect_obj, tw, th);
3541         evas_object_resize(cw->default_input_obj, w, h);
3542      }
3543    if (!cw->visible)
3544      {
3545         TRACE_DS_END();
3546         return;
3547      }
3548    e_comp_render_queue();
3549
3550    TRACE_DS_END();
3551 }
3552
3553 static void
3554 _e_comp_smart_init(void)
3555 {
3556    if (_e_comp_smart) return;
3557    {
3558       static const Evas_Smart_Class sc =
3559       {
3560          SMART_NAME,
3561          EVAS_SMART_CLASS_VERSION,
3562          _e_comp_smart_add,
3563          _e_comp_smart_del,
3564          _e_comp_smart_move,
3565          _e_comp_smart_resize,
3566          _e_comp_smart_show,
3567          _e_comp_smart_hide,
3568          _e_comp_smart_color_set,
3569          _e_comp_smart_clip_set,
3570          _e_comp_smart_clip_unset,
3571          NULL,
3572          NULL,
3573          NULL,
3574
3575          NULL,
3576          NULL,
3577          NULL,
3578          NULL
3579       };
3580       _e_comp_smart = evas_smart_class_new(&sc);
3581    }
3582 }
3583
3584 EINTERN void
3585 e_comp_object_init(void)
3586 {
3587    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
3588    E_EVENT_COMP_OBJECT_IMG_RENDER = ecore_event_type_new();
3589    E_EVENT_COMP_OBJECT_EFFECT_START = ecore_event_type_new();
3590    E_EVENT_COMP_OBJECT_EFFECT_END = ecore_event_type_new();
3591 }
3592
3593 EINTERN void
3594 e_comp_object_shutdown(void)
3595 {
3596
3597 }
3598
3599 E_API void
3600 e_comp_object_zoomap_set(Evas_Object *obj, Eina_Bool enabled)
3601 {
3602    API_ENTRY;
3603
3604    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
3605
3606    enabled = !enabled;
3607    if (cw->zoomap_disabled == enabled) return;
3608    if (enabled)
3609      {
3610         cw->zoomobj = e_zoomap_add(e_comp->evas);
3611         e_zoomap_smooth_set(cw->zoomobj, e_comp_config_get()->smooth_windows);
3612         e_zoomap_child_set(cw->zoomobj, cw->frame_object);
3613         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->zoomobj);
3614         e_zoomap_child_edje_solid_setup(cw->zoomobj);
3615         if (cw->ec->override)
3616           evas_object_name_set(cw->zoomobj, "cw->zoomobj::WINDOW");
3617         else if (!cw->ec->input_only)
3618           evas_object_name_set(cw->zoomobj, "cw->zoomobj::CLIENT");
3619      }
3620    else
3621      {
3622         edje_object_part_unswallow(cw->shobj, cw->zoomobj);
3623         E_FREE_FUNC(cw->zoomobj, evas_object_del);
3624         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
3625      }
3626    cw->zoomap_disabled = enabled;
3627 }
3628
3629 EINTERN Eina_Bool
3630 e_comp_object_mirror_visibility_check(Evas_Object *obj)
3631 {
3632    API_ENTRY EINA_FALSE;
3633    return !!cw->force_visible;
3634 }
3635 /////////////////////////////////////////////////////////
3636
3637 static void
3638 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3639 {
3640    Eina_List *l;
3641    Eina_Bool comp_object;
3642
3643    comp_object = !!evas_object_data_get(obj, "comp_object");
3644    if (comp_object)
3645      {
3646         Evas_Object *o;
3647
3648         o = edje_object_part_swallow_get(obj, "e.swallow.content");
3649         evas_object_del(o);
3650         e_comp_render_queue();
3651      }
3652    l = evas_object_data_get(obj, "comp_object-to_del");
3653    E_FREE_LIST(l, evas_object_del);
3654 }
3655
3656 static void
3657 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3658 {
3659    if (e_comp_util_object_is_above_nocomp(obj) &&
3660        (!evas_object_data_get(obj, "comp_override")))
3661      {
3662         evas_object_data_set(obj, "comp_override", (void*)1);
3663         e_comp_override_add();
3664      }
3665 }
3666
3667 static void
3668 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
3669 {
3670    Eina_Bool ref = EINA_TRUE;
3671    if (evas_object_visible_get(obj))
3672      {
3673         void *d;
3674
3675         d = evas_object_data_del(obj, "comp_hiding");
3676         if (d)
3677           /* currently trying to hide */
3678           ref = EINA_FALSE;
3679         else
3680           /* already visible */
3681           return;
3682      }
3683
3684    evas_object_show(obj);
3685    if (ref)
3686      {
3687         evas_object_ref(obj);
3688         evas_object_data_set(obj, "comp_ref", (void*)1);
3689      }
3690    edje_object_signal_emit(obj, "e,state,visible", "e");
3691    evas_object_data_set(obj, "comp_showing", (void*)1);
3692    if (e_comp_util_object_is_above_nocomp(obj))
3693      {
3694         evas_object_data_set(obj, "comp_override", (void*)1);
3695         e_comp_override_add();
3696      }
3697 }
3698
3699 static void
3700 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
3701 {
3702    if (!evas_object_visible_get(obj)) return;
3703    /* already hiding */
3704    if (evas_object_data_get(obj, "comp_hiding")) return;
3705    if (!evas_object_data_del(obj, "comp_showing"))
3706      {
3707         evas_object_ref(obj);
3708         evas_object_data_set(obj, "comp_ref", (void*)1);
3709      }
3710    edje_object_signal_emit(obj, "e,state,hidden", "e");
3711    evas_object_data_set(obj, "comp_hiding", (void*)1);
3712
3713    if (evas_object_data_del(obj, "comp_override"))
3714      e_comp_override_timed_pop();
3715 }
3716
3717 static void
3718 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
3719 {
3720    if (!e_util_strcmp(emission, "e,action,hide,done"))
3721      {
3722         if (!evas_object_data_del(obj, "comp_hiding")) return;
3723         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
3724         evas_object_hide(obj);
3725         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
3726      }
3727    else
3728      evas_object_data_del(obj, "comp_showing");
3729    if (evas_object_data_del(obj, "comp_ref"))
3730      evas_object_unref(obj);
3731 }
3732
3733 static void
3734 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3735 {
3736    if (data)
3737      {
3738         int w, h;
3739
3740         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3741         e_zoomap_child_resize(data, w, h);
3742      }
3743 }
3744
3745 E_API E_Comp_Object_Hook *
3746 e_comp_object_hook_add(E_Comp_Object_Hook_Point hookpoint, E_Comp_Object_Hook_Cb func, const void *data)
3747 {
3748    E_Comp_Object_Hook *ch;
3749
3750    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_HOOK_LAST, NULL);
3751    ch = E_NEW(E_Comp_Object_Hook, 1);
3752    if (!ch) return NULL;
3753    ch->hookpoint = hookpoint;
3754    ch->func = func;
3755    ch->data = (void*)data;
3756    _e_comp_object_hooks[hookpoint] = eina_inlist_append(_e_comp_object_hooks[hookpoint], EINA_INLIST_GET(ch));
3757    return ch;
3758 }
3759
3760 E_API void
3761 e_comp_object_hook_del(E_Comp_Object_Hook *ch)
3762 {
3763    ch->delete_me = 1;
3764    if (_e_comp_object_hooks_walking == 0)
3765      {
3766         _e_comp_object_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3767         free(ch);
3768      }
3769    else
3770      _e_comp_object_hooks_delete++;
3771 }
3772
3773 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
3774 E_API E_Comp_Object_Intercept_Hook *
3775 e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data)
3776 {
3777    E_Comp_Object_Intercept_Hook *ch;
3778
3779    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_INTERCEPT_HOOK_LAST, NULL);
3780    ch = E_NEW(E_Comp_Object_Intercept_Hook, 1);
3781    if (!ch) return NULL;
3782    ch->hookpoint = hookpoint;
3783    ch->func = func;
3784    ch->data = (void*)data;
3785    _e_comp_object_intercept_hooks[hookpoint] = eina_inlist_append(_e_comp_object_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3786    return ch;
3787 }
3788
3789 E_API void
3790 e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch)
3791 {
3792    ch->delete_me = 1;
3793    if (_e_comp_object_intercept_hooks_walking == 0)
3794      {
3795         _e_comp_object_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3796         free(ch);
3797      }
3798    else
3799      _e_comp_object_intercept_hooks_delete++;
3800 }
3801 #endif
3802
3803 EINTERN Evas_Object *
3804 e_comp_object_util_add(Evas_Object *obj, E_Comp_Object_Type type)
3805 {
3806    Evas_Object *o, *z = NULL;
3807    const char *name;
3808    Eina_List *l, *list = NULL;
3809    E_Comp_Config *conf = e_comp_config_get();
3810    Eina_Bool skip = EINA_FALSE, fast = EINA_FALSE, shadow = EINA_FALSE;
3811    E_Comp_Match *m;
3812    char buf[1024];
3813    int ok = 0;
3814    int x, y, w, h;
3815    Eina_Bool vis;
3816
3817    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
3818
3819    switch (type)
3820      {
3821       case E_COMP_OBJECT_TYPE_MENU:
3822         list = conf->match.menus;
3823         skip = conf->match.disable_menus;
3824         fast = conf->fast_menus;
3825         shadow = EINA_TRUE;
3826         break;
3827       case E_COMP_OBJECT_TYPE_POPUP:
3828         list = conf->match.popups;
3829         skip = conf->match.disable_popups;
3830         fast = conf->fast_popups;
3831         break;
3832       default:
3833         list = conf->match.objects;
3834         skip = conf->match.disable_objects;
3835         fast = conf->fast_objects;
3836      }
3837    name = evas_object_name_get(obj);
3838    vis = evas_object_visible_get(obj);
3839    o = edje_object_add(e_comp->evas);
3840    evas_object_data_set(o, "comp_object", (void*)1);
3841    if (name && (!skip))
3842      skip = (!strncmp(name, "noshadow", 8));
3843    if (skip)
3844      evas_object_data_set(o, "comp_object_skip", (void*)1);
3845    else if (list)
3846      {
3847         EINA_LIST_FOREACH(list, l, m)
3848           {
3849              if (((m->name) && (!name)) ||
3850                  ((name) && (m->name) && (!e_util_glob_match(name, m->name))))
3851                continue;
3852              if (!m->shadow_style) continue;
3853              if (fast)
3854                {
3855                   snprintf(buf, sizeof(buf), "e/comp/frame/%s/fast", m->shadow_style);
3856                   ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3857                }
3858              if (!ok)
3859                {
3860                   snprintf(buf, sizeof(buf), "e/comp/frame/%s", m->shadow_style);
3861                   ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3862                }
3863              if (ok)
3864                {
3865                   shadow = !m->no_shadow;
3866                   break;
3867                }
3868           }
3869      }
3870    else
3871      skip = EINA_TRUE;
3872    while (!ok)
3873      {
3874         if (skip)
3875           ok = e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/none");
3876         if (ok) break;
3877         if (conf->shadow_style)
3878           {
3879              if (fast)
3880                {
3881                   snprintf(buf, sizeof(buf), "e/comp/frame/%s/fast", conf->shadow_style);
3882                   ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3883                }
3884              if (!ok)
3885                {
3886                   snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
3887                   ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3888                }
3889              if (ok) break;
3890           }
3891         if (fast)
3892           ok = e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default/fast");
3893         if (!ok)
3894           ok = e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default");
3895         break;
3896      }
3897    if (shadow && (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow"))))
3898      edje_object_signal_emit(o, "e,state,shadow,on", "e");
3899    else
3900      edje_object_signal_emit(o, "e,state,shadow,off", "e");
3901
3902    evas_object_geometry_get(obj, &x, &y, &w, &h);
3903    evas_object_geometry_set(o, x, y, w, h);
3904    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
3905
3906    if (list)
3907      {
3908         z = e_zoomap_add(e_comp->evas);
3909         e_zoomap_child_edje_solid_setup(z);
3910         e_zoomap_smooth_set(z, conf->smooth_windows);
3911         e_zoomap_child_set(z, obj);
3912         e_zoomap_child_resize(z, w, h);
3913         evas_object_show(z);
3914      }
3915    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, z);
3916
3917    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, z);
3918    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, z);
3919    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, z);
3920    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, z);
3921    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, z);
3922    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, z);
3923
3924    e_comp_object_signal_emit(o, "e,state,hidden", "e");
3925
3926    edje_object_part_swallow(o, "e.swallow.content", z ?: obj);
3927
3928    _e_comp_object_event_add(o);
3929
3930    if (vis)
3931      evas_object_show(o);
3932
3933    return o;
3934 }
3935
3936 /* utility functions for deleting objects when their "owner" is deleted */
3937 EINTERN void
3938 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
3939 {
3940    Eina_List *l;
3941
3942    SOFT_ENTRY();
3943    EINA_SAFETY_ON_NULL_RETURN(to_del);
3944    l = evas_object_data_get(obj, "comp_object-to_del");
3945    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
3946    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
3947    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3948 }
3949
3950 EINTERN void
3951 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3952 {
3953    Eina_List *l;
3954
3955    SOFT_ENTRY();
3956    EINA_SAFETY_ON_NULL_RETURN(to_del);
3957    l = evas_object_data_get(obj, "comp_object-to_del");
3958    if (l)
3959      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3960 }
3961
3962 /////////////////////////////////////////////////////////
3963
3964 EINTERN Evas_Object *
3965 e_comp_object_client_add(E_Client *ec)
3966 {
3967    Evas_Object *o;
3968    E_Comp_Object *cw;
3969
3970    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3971    if (ec->frame) return NULL;
3972    _e_comp_smart_init();
3973    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3974    cw = evas_object_smart_data_get(o);
3975    if (!cw) return NULL;
3976    evas_object_data_set(o, "E_Client", ec);
3977    cw->ec = ec;
3978    ec->frame = o;
3979    evas_object_data_set(o, "comp_object", (void*)1);
3980
3981    _e_comp_object_event_add(o);
3982
3983    return o;
3984 }
3985
3986 /* utility functions for getting client inset */
3987 EINTERN void
3988 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3989 {
3990    API_ENTRY;
3991    if (!cw->client_inset.calc)
3992      {
3993         if (ax) *ax = x;
3994         if (ay) *ay = y;
3995         return;
3996      }
3997    if (ax) *ax = x - cw->client_inset.l;
3998    if (ay) *ay = y - cw->client_inset.t;
3999 }
4000
4001 E_API void
4002 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
4003 {
4004    API_ENTRY;
4005    if (!cw->client_inset.calc)
4006      {
4007         if (ax) *ax = x;
4008         if (ay) *ay = y;
4009         return;
4010      }
4011    if (ax) *ax = x + cw->client_inset.l;
4012    if (ay) *ay = y + cw->client_inset.t;
4013 }
4014
4015 EINTERN void
4016 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
4017 {
4018    API_ENTRY;
4019    if (!cw->client_inset.calc)
4020      {
4021         if (aw) *aw = w;
4022         if (ah) *ah = h;
4023         return;
4024      }
4025    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
4026    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
4027 }
4028
4029 E_API void
4030 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
4031 {
4032    API_ENTRY;
4033    if (!cw->client_inset.calc)
4034      {
4035         if (aw) *aw = w;
4036         if (ah) *ah = h;
4037         return;
4038      }
4039    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
4040    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
4041 }
4042
4043 E_API E_Client *
4044 e_comp_object_client_get(Evas_Object *obj)
4045 {
4046    Evas_Object *o;
4047
4048    SOFT_ENTRY(NULL);
4049    /* FIXME: remove this when eo is used */
4050    o = evas_object_data_get(obj, "comp_smart_obj");
4051    if (o)
4052      return e_comp_object_client_get(o);
4053    return cw ? cw->ec : NULL;
4054 }
4055
4056 EINTERN void
4057 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
4058 {
4059    API_ENTRY;
4060    if (cw->frame_extends)
4061      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
4062    else
4063      {
4064         if (x) *x = 0;
4065         if (y) *y = 0;
4066         if (w) *w  = cw->ec->w;
4067         if (h) *h  = cw->ec->h;
4068      }
4069 }
4070
4071 EINTERN E_Zone *
4072 e_comp_object_util_zone_get(Evas_Object *obj)
4073 {
4074    E_Zone *zone = NULL;
4075
4076    SOFT_ENTRY(NULL);
4077    if (cw)
4078      zone = cw->ec->zone;
4079    if (!zone)
4080      {
4081         int x, y;
4082
4083         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
4084         zone = e_comp_zone_xy_get(x, y);
4085      }
4086    return zone;
4087 }
4088
4089 EINTERN void
4090 e_comp_object_util_center(Evas_Object *obj)
4091 {
4092    int x, y, w, h, ow, oh;
4093    E_Zone *zone;
4094
4095    SOFT_ENTRY();
4096
4097    zone = e_comp_object_util_zone_get(obj);
4098    EINA_SAFETY_ON_NULL_RETURN(zone);
4099    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
4100    if (cw && (cw->ec->changes.size || cw->ec->new_client))
4101      ow = cw->ec->w, oh = cw->ec->h;
4102    else
4103      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4104    x = x + (w - ow) / 2;
4105    y = y + (h - oh) / 2;
4106    evas_object_move(obj, x, y);
4107 }
4108
4109 EINTERN void
4110 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
4111 {
4112    int x, y, w, h, ow, oh;
4113
4114    SOFT_ENTRY();
4115    EINA_SAFETY_ON_NULL_RETURN(on);
4116    evas_object_geometry_get(on, &x, &y, &w, &h);
4117    if (cw && (cw->ec->changes.size || cw->ec->new_client))
4118      ow = cw->ec->w, oh = cw->ec->h;
4119    else
4120      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4121    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
4122 }
4123
4124 EINTERN void
4125 e_comp_object_util_fullscreen(Evas_Object *obj)
4126 {
4127    SOFT_ENTRY();
4128
4129    if (cw)
4130      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
4131    else
4132      {
4133         evas_object_move(obj, 0, 0);
4134         evas_object_resize(obj, e_comp->w, e_comp->h);
4135      }
4136 }
4137
4138 EINTERN void
4139 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
4140 {
4141    E_Zone *zone;
4142    int zx, zy, zw, zh;
4143    int ow, oh;
4144    SOFT_ENTRY();
4145
4146    if (cw)
4147      ow = cw->w, oh = cw->h;
4148    else
4149      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4150    zone = e_comp_object_util_zone_get(obj);
4151    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
4152    if (x) *x = zx + (zw - ow) / 2;
4153    if (y) *y = zy + (zh - oh) / 2;
4154 }
4155
4156 EINTERN void
4157 e_comp_object_input_objs_del(Evas_Object *obj)
4158 {
4159    API_ENTRY;
4160    E_Input_Rect_Data *input_rect_data;
4161    E_Input_Rect_Smart_Data *input_rect_sd;
4162
4163    if (!cw->input_obj)
4164      return;
4165
4166    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4167    if (!input_rect_sd) return;
4168
4169    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
4170      {
4171         if (input_rect_data->obj)
4172           {
4173              evas_object_smart_member_del(input_rect_data->obj);
4174              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
4175           }
4176         E_FREE(input_rect_data);
4177      }
4178 }
4179
4180 E_API void
4181 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
4182 {
4183    API_ENTRY;
4184    E_Input_Rect_Data *input_rect_data = NULL;
4185    E_Input_Rect_Smart_Data *input_rect_sd;
4186    int client_w, client_h;
4187
4188    if (cw->ec->client.w)
4189      client_w = cw->ec->client.w;
4190    else
4191      client_w = cw->ec->w;
4192
4193    if (cw->ec->client.h)
4194      client_h = cw->ec->client.h;
4195    else
4196      client_h = cw->ec->h;
4197
4198    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
4199
4200    if (!cw->input_obj)
4201      {
4202         _e_comp_input_obj_smart_init();
4203         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
4204         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
4205         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4206
4207         if (input_rect_sd)
4208           input_rect_sd->cw = cw;
4209      }
4210
4211    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4212    if (input_rect_sd)
4213      {
4214         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
4215         if (input_rect_data)
4216           {
4217              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
4218              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
4219           }
4220      }
4221
4222    if ((input_rect_data) &&
4223        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
4224      {
4225         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
4226         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
4227         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
4228         evas_object_clip_set(input_rect_data->obj, cw->clip);
4229         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
4230         evas_object_geometry_set(input_rect_data->obj,
4231           MAX(cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l), 0) + x,
4232           MAX(cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t), 0) + y, w, h);
4233         evas_object_pass_events_set(cw->default_input_obj, 1);
4234         evas_object_pass_events_set(cw->obj, 1);
4235         if (cw->visible)
4236           {
4237              evas_object_show(input_rect_data->obj);
4238              evas_object_show(cw->input_obj);
4239           }
4240      }
4241    else
4242      {
4243         evas_object_smart_member_del(cw->input_obj);
4244         E_FREE_FUNC(cw->input_obj, evas_object_del);
4245         evas_object_pass_events_set(cw->default_input_obj, 0);
4246         evas_object_pass_events_set(cw->obj, 0);
4247      }
4248 }
4249
4250 EINTERN void
4251 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4252 {
4253    API_ENTRY;
4254    E_Input_Rect_Smart_Data *input_rect_sd;
4255    E_Input_Rect_Data *input_rect_data;
4256    Eina_List *l;
4257
4258    if (!cw->input_obj) return;
4259
4260    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4261    if (input_rect_sd)
4262      {
4263         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4264           {
4265              *list = eina_list_append(*list, &input_rect_data->rect);
4266           }
4267      }
4268 }
4269
4270 EINTERN void
4271 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4272 {
4273    API_ENTRY;
4274    if (l) *l = cw->client_inset.l;
4275    if (r) *r = cw->client_inset.r;
4276    if (t) *t = cw->client_inset.t;
4277    if (b) *b = cw->client_inset.b;
4278 }
4279
4280 /* set geometry for CSD */
4281 EINTERN void
4282 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4283 {
4284    Eina_Bool calc;
4285    int tx, ty, tw, th;
4286
4287    API_ENTRY;
4288    if (cw->frame_object)
4289      CRI("ACK! ec:%p", cw->ec);
4290    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4291        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4292    calc = cw->client_inset.calc;
4293    cw->client_inset.calc = l || r || t || b;
4294    eina_stringshare_replace(&cw->frame_theme, "borderless");
4295    if (cw->client_inset.calc)
4296      {
4297         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4298         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4299         e_client_size_set(cw->ec, tw, th);
4300      }
4301    else if (cw->ec->maximized || cw->ec->fullscreen)
4302      {
4303         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4304         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4305      }
4306    if (!cw->ec->new_client)
4307      {
4308         if (calc && cw->client_inset.calc)
4309           {
4310              tx = cw->ec->x - (l - cw->client_inset.l);
4311              ty = cw->ec->y - (t - cw->client_inset.t);
4312              e_client_pos_set(cw->ec, tx, ty);
4313           }
4314         cw->ec->changes.pos = cw->ec->changes.size = 1;
4315         EC_CHANGED(cw->ec);
4316      }
4317    cw->client_inset.l = l;
4318    cw->client_inset.r = r;
4319    cw->client_inset.t = t;
4320    cw->client_inset.b = b;
4321 }
4322
4323 EINTERN Eina_Bool
4324 e_comp_object_frame_allowed(Evas_Object *obj)
4325 {
4326    API_ENTRY EINA_FALSE;
4327    return (!cw->ec->mwm.borderless) && (cw->frame_object || (!cw->client_inset.calc));
4328 }
4329
4330 EINTERN Eina_Bool
4331 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
4332 {
4333    API_ENTRY EINA_FALSE;
4334    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
4335    eina_stringshare_replace(&cw->frame_name, name);
4336    if (cw->frame_object)
4337      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
4338    return EINA_TRUE;
4339 }
4340
4341 EINTERN Eina_Bool
4342 e_comp_object_frame_exists(Evas_Object *obj)
4343 {
4344    API_ENTRY EINA_FALSE;
4345    return !!cw->frame_object;
4346 }
4347
4348 EINTERN Eina_Bool
4349 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4350 {
4351    Evas_Object *o, *pbg;
4352    char buf[4096];
4353    int ok;
4354    Eina_Stringshare *theme;
4355
4356    API_ENTRY EINA_FALSE;
4357
4358    if (!e_util_strcmp(cw->frame_theme, name))
4359     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4360    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4361      return _e_comp_object_shadow_setup(cw);
4362    pbg = cw->frame_object;
4363    theme = eina_stringshare_add(name);
4364
4365    if (cw->frame_object)
4366      {
4367         int w, h;
4368
4369         w = cw->ec->w, h = cw->ec->h;
4370         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4371         if ((cw->ec->w != w) || (cw->ec->h != h))
4372           {
4373              cw->ec->changes.size = 1;
4374              EC_CHANGED(cw->ec);
4375           }
4376         E_FREE_FUNC(cw->frame_object, evas_object_del);
4377         if (!name) goto reshadow;
4378      }
4379    o = edje_object_add(e_comp->evas);
4380    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4381    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4382    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4383      {
4384         cw->frame_object = NULL;
4385         evas_object_del(o);
4386         eina_stringshare_del(cw->frame_theme);
4387         cw->frame_theme = theme;
4388         goto reshadow;
4389      }
4390    if (!ok)
4391      {
4392         if (theme != e_config->theme_default_border_style)
4393           {
4394              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4395              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4396           }
4397         if (!ok)
4398           {
4399              ok = e_theme_edje_object_set(o, "base/theme/border",
4400                                           "e/widgets/border/default/border");
4401              if (ok && (theme == e_config->theme_default_border_style))
4402                {
4403                   /* Reset default border style to default */
4404                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4405                   e_config_save_queue();
4406                }
4407           }
4408      }
4409
4410    if (ok)
4411      {
4412         cw->frame_object = o;
4413         eina_stringshare_del(cw->frame_theme);
4414         cw->frame_theme = theme;
4415         evas_object_name_set(o, "cw->frame_object");
4416
4417         if (cw->frame_name)
4418           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4419
4420         if (!pbg)
4421           {
4422              cw->ec->changes.icon = 1;
4423              EC_CHANGED(cw->ec);
4424           }
4425      }
4426    else
4427      {
4428         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4429         evas_object_del(o);
4430      }
4431 reshadow:
4432    if (cw->shobj)
4433      _e_comp_object_shadow_setup(cw);
4434    do
4435      {
4436         int old_x, old_y, new_x = 0, new_y = 0;
4437
4438         old_x = cw->x, old_y = cw->y;
4439
4440         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4441         if (pbg)
4442           new_x = cw->ec->x, new_y = cw->ec->y;
4443         else if (cw->ec->placed || (!cw->ec->new_client))
4444           {
4445              /* if no previous frame:
4446               * - reapply client_inset
4447               * - clamp to zone
4448               */
4449              int x, y;
4450
4451              if (cw->ec->changes.size)
4452                {
4453                   x = cw->ec->x;
4454                   y = cw->ec->y;
4455                }
4456              else
4457                {
4458                   x = cw->ec->client.x, y = cw->ec->client.y;
4459                   x = MAX(cw->ec->zone->x, cw->ec->client.x - cw->client_inset.l);
4460                   y = MAX(cw->ec->zone->y, cw->ec->client.y - cw->client_inset.t);
4461                }
4462              new_x = x, new_y = y;
4463           }
4464
4465         if (old_x != new_x || old_y != new_y)
4466           {
4467              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4468              cw->y = cw->x = -99999;
4469              evas_object_move(obj, new_x, new_y);
4470           }
4471      } while (0);
4472
4473    if (cw->ec->maximized)
4474      {
4475         cw->ec->changes.need_maximize = 1;
4476         EC_CHANGED(cw->ec);
4477      }
4478    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4479    if (cw->frame_object)
4480      {
4481         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4482      }
4483    else
4484      cw->frame_extends = 0;
4485    evas_object_del(pbg);
4486    return EINA_TRUE;
4487 }
4488
4489 E_API void
4490 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4491 {
4492    E_Comp_Object_Mover *prov;
4493
4494    API_ENTRY;
4495    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4496    edje_object_signal_emit(cw->shobj, sig, src);
4497    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4498    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4499        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4500      return;
4501    /* start with highest priority callback first */
4502    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4503      {
4504         if (!e_util_glob_match(sig, prov->sig)) continue;
4505         if (prov->func(prov->data, obj, sig)) break;
4506      }
4507 }
4508
4509 E_API void
4510 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4511 {
4512    /* FIXME: at some point I guess this should use eo to inherit
4513     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4514     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4515     */
4516    API_ENTRY;
4517    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4518 }
4519
4520 E_API void
4521 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4522 {
4523    API_ENTRY;
4524    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4525 }
4526
4527 E_API void
4528 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4529 {
4530    API_ENTRY;
4531    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4532 }
4533
4534 E_API void
4535 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4536 {
4537    int tw, th;
4538    Eina_Rectangle rect;
4539    API_ENTRY;
4540
4541    if (cw->ec->input_only || (!cw->updates)) return;
4542    if (cw->nocomp) return;
4543    rect.x = x, rect.y = y;
4544    rect.w = w, rect.h = h;
4545    evas_object_smart_callback_call(obj, "damage", &rect);
4546
4547    if (e_comp_is_on_overlay(cw->ec))
4548      {
4549         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4550         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4551         * E module attempts to block screen update due to the particular policy.
4552         */
4553         if (e_pixmap_resource_get(cw->ec->pixmap))
4554           cw->hwc_need_update = EINA_TRUE;
4555      }
4556
4557    /* ignore overdraw */
4558    if (cw->updates_full)
4559      {
4560         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4561         e_comp_object_render_update_add(obj);
4562
4563         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4564           evas_object_show(cw->smart_obj);
4565
4566         return;
4567      }
4568    /* clip rect to client surface */
4569    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4570    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4571    /* if rect is the total size of the client after clip, clear the updates
4572     * since this is guaranteed to be the whole region anyway
4573     */
4574    eina_tiler_area_size_get(cw->updates, &tw, &th);
4575    if ((w > tw) || (h > th))
4576      {
4577         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4578         eina_tiler_clear(cw->updates);
4579         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4580         x = 0, y = 0;
4581         tw = cw->ec->client.w, th = cw->ec->client.h;
4582      }
4583    if ((!x) && (!y) && (w == tw) && (h == th))
4584      {
4585         eina_tiler_clear(cw->updates);
4586         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4587         cw->updates_full = 1;
4588         cw->update_count = 0;
4589      }
4590    cw->update_count++;
4591    if (cw->update_count > UPDATE_MAX)
4592      {
4593         /* this is going to get really dumb, so just update the whole thing */
4594         eina_tiler_clear(cw->updates);
4595         cw->update_count = cw->updates_full = 1;
4596         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4597         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4598      }
4599    else
4600      {
4601         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4602         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4603      }
4604    cw->updates_exist = 1;
4605    e_comp_object_render_update_add(obj);
4606
4607    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4608      evas_object_show(cw->smart_obj);
4609 }
4610
4611 EINTERN Eina_Bool
4612 e_comp_object_damage_exists(Evas_Object *obj)
4613 {
4614    API_ENTRY EINA_FALSE;
4615    return cw->updates_exist;
4616 }
4617
4618 EINTERN void
4619 e_comp_object_render_update_add(Evas_Object *obj)
4620 {
4621    API_ENTRY;
4622
4623    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4624    if (cw->render_update_lock.lock) return;
4625    if (e_object_is_del(E_OBJECT(cw->ec)))
4626      CRI("CAN'T RENDER A DELETED CLIENT!!! ec:%p", cw->ec);
4627    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4628    if (!cw->update)
4629      {
4630         cw->update = 1;
4631         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4632      }
4633    e_comp_render_queue();
4634 }
4635
4636 EINTERN void
4637 e_comp_object_render_update_del(Evas_Object *obj)
4638 {
4639    API_ENTRY;
4640
4641    if (cw->ec->input_only || (!cw->updates)) return;
4642    if (!cw->update) return;
4643    cw->update = 0;
4644    /* this gets called during comp animating to clear the update flag */
4645    if (e_comp->grabbed) return;
4646    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4647    if (!e_comp->updates)
4648      {
4649         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4650         if (e_comp->render_animator)
4651           ecore_animator_freeze(e_comp->render_animator);
4652      }
4653 }
4654
4655 EINTERN void
4656 e_comp_object_shape_apply(Evas_Object *obj)
4657 {
4658    Eina_List *l;
4659    Evas_Object *o;
4660    unsigned int i, *pix, *p;
4661    int w, h, px, py;
4662
4663    API_ENTRY;
4664    if (!cw->ec) return; //NYI
4665    if (cw->external_content) return;
4666    if (cw->ec->shaped)
4667      {
4668         if ((cw->ec->shape_rects_num >= 1) &&
4669             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4670            return;
4671      }
4672    if (cw->native)
4673      {
4674         ERR("BUGGER: shape with native surface? cw=%p", cw);
4675         return;
4676      }
4677    evas_object_image_size_get(cw->obj, &w, &h);
4678    if ((w < 1) || (h < 1)) return;
4679
4680    if (cw->ec->shaped)
4681      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4682    _e_comp_object_alpha_set(cw);
4683    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4684       evas_object_image_alpha_set(o, 1);
4685
4686    p = pix = evas_object_image_data_get(cw->obj, 1);
4687    if (!pix)
4688      {
4689         evas_object_image_data_set(cw->obj, pix);
4690         return;
4691      }
4692    if (cw->ec->shaped)
4693      {
4694         unsigned char *spix, *sp;
4695
4696         spix = calloc(w * h, sizeof(unsigned char));
4697         if (!spix) return;
4698         for (i = 0; i < cw->ec->shape_rects_num; i++)
4699           {
4700              int rx, ry, rw, rh;
4701
4702              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4703              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4704              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4705              sp = spix + (w * ry) + rx;
4706              for (py = 0; py < rh; py++)
4707                {
4708                   for (px = 0; px < rw; px++)
4709                     {
4710                        *sp = 0xff; sp++;
4711                     }
4712                   sp += w - rw;
4713                }
4714           }
4715         sp = spix;
4716         for (py = 0; py < h; py++)
4717           {
4718              for (px = 0; px < w; px++)
4719                {
4720                   unsigned int mask, imask;
4721
4722                   mask = ((unsigned int)(*sp)) << 24;
4723                   imask = mask >> 8;
4724                   imask |= imask >> 8;
4725                   imask |= imask >> 8;
4726                   *p = mask | (*p & imask);
4727                   //if (*sp) *p = 0xff000000 | *p;
4728                   //else *p = 0x00000000;
4729                   sp++;
4730                   p++;
4731                }
4732           }
4733         free(spix);
4734      }
4735    else
4736       {
4737          for (py = 0; py < h; py++)
4738            {
4739               for (px = 0; px < w; px++)
4740                 *p |= 0xff000000;
4741            }
4742       }
4743    evas_object_image_data_set(cw->obj, pix);
4744    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4745    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4746      {
4747         evas_object_image_data_set(o, pix);
4748         evas_object_image_data_update_add(o, 0, 0, w, h);
4749      }
4750 // don't need to fix alpha chanel as blending
4751 // should be totally off here regardless of
4752 // alpha channel content
4753 }
4754
4755 static void
4756 _e_comp_object_clear(E_Comp_Object *cw)
4757 {
4758    Eina_List *l;
4759    Evas_Object *o;
4760
4761    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4762
4763    if (cw->render_update_lock.lock) return;
4764
4765    if (cw->ec->pixmap)
4766      e_pixmap_clear(cw->ec->pixmap);
4767    if (cw->native)
4768      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4769    evas_object_image_size_set(cw->obj, 1, 1);
4770    evas_object_image_data_set(cw->obj, NULL);
4771    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4772      {
4773         evas_object_image_size_set(o, 1, 1);
4774         evas_object_image_data_set(o, NULL);
4775      }
4776    cw->native = 0;
4777    e_comp_object_render_update_del(cw->smart_obj);
4778 }
4779
4780 static Eina_Bool
4781 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4782 {
4783     int r, g, b, a;
4784
4785     API_ENTRY EINA_FALSE;
4786
4787     if (cw->transparent.set == set)
4788        return EINA_TRUE;
4789
4790     if (set)
4791       {
4792          evas_object_color_get(obj, &r, &g, &b, &a);
4793          evas_object_color_set(obj, 0, 0, 0, 0);
4794
4795          cw->transparent.user_r = r;
4796          cw->transparent.user_g = g;
4797          cw->transparent.user_b = b;
4798          cw->transparent.user_a = a;
4799
4800          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4801                cw->ec,
4802                cw->transparent.user_r,
4803                cw->transparent.user_g,
4804                cw->transparent.user_b,
4805                cw->transparent.user_a);
4806
4807          cw->transparent.set = EINA_TRUE;
4808       }
4809     else
4810       {
4811          cw->transparent.set = EINA_FALSE;
4812
4813          evas_object_color_set(obj,
4814                                cw->transparent.user_r,
4815                                cw->transparent.user_g,
4816                                cw->transparent.user_b,
4817                                cw->transparent.user_a);
4818
4819          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4820                cw->ec,
4821                cw->transparent.user_r,
4822                cw->transparent.user_g,
4823                cw->transparent.user_b,
4824                cw->transparent.user_a);
4825       }
4826
4827    return EINA_TRUE;
4828 }
4829
4830 /* helper function to simplify toggling of redirection for display servers which support it */
4831 EINTERN void
4832 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4833 {
4834    API_ENTRY;
4835
4836    set = !!set;
4837    if (cw->redirected == set) return;
4838    cw->redirected = set;
4839    if (cw->external_content) return;
4840
4841    e_comp_object_map_update(obj);
4842
4843    if (set)
4844      {
4845         if (cw->updates_exist)
4846           e_comp_object_render_update_add(obj);
4847         else
4848           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4849
4850         _e_comp_object_transparent_set(obj, EINA_FALSE);
4851         evas_object_smart_callback_call(obj, "redirected", NULL);
4852      }
4853    else
4854      {
4855         _e_comp_object_clear(cw);
4856         _e_comp_object_transparent_set(obj, EINA_TRUE);
4857         evas_object_smart_callback_call(obj, "unredirected", NULL);
4858      }
4859 }
4860
4861 static void
4862 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4863 {
4864    E_Comp_Object *cw;
4865    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4866
4867    if (cw->buffer_destroy_listener.notify)
4868      {
4869         cw->buffer_destroy_listener.notify = NULL;
4870         wl_list_remove(&cw->buffer_destroy_listener.link);
4871      }
4872
4873    if (e_object_is_del(E_OBJECT(cw->ec)))
4874      {
4875         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4876           return;
4877      }
4878    else
4879      {
4880         /* if it's current displaying buffer, do not remove its content */
4881         if (!evas_object_visible_get(cw->ec->frame))
4882           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4883      }
4884 }
4885
4886 static void
4887 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4888 {
4889    Eina_List *l;
4890    Evas_Object *o;
4891
4892    if (cw->buffer_destroy_listener.notify)
4893      {
4894         wl_list_remove(&cw->buffer_destroy_listener.link);
4895         cw->buffer_destroy_listener.notify = NULL;
4896      }
4897
4898    if (cw->tbm_surface)
4899      {
4900         tbm_surface_internal_unref(cw->tbm_surface);
4901         cw->tbm_surface = NULL;
4902      }
4903
4904    if (ns)
4905      {
4906         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4907           {
4908              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4909              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4910           }
4911         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4912           {
4913              tbm_surface_internal_ref(ns->data.tbm.buffer);
4914              cw->tbm_surface = ns->data.tbm.buffer;
4915           }
4916      }
4917
4918    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4919    evas_object_image_native_surface_set(cw->obj, ns);
4920    TRACE_DS_END();
4921    if (with_mirror)
4922      {
4923         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4924           {
4925              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4926              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4927              evas_object_image_native_surface_set(o, ns);
4928              TRACE_DS_END();
4929           }
4930      }
4931 }
4932
4933 EINTERN void
4934 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4935 {
4936    Evas_Native_Surface ns;
4937
4938    API_ENTRY;
4939    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4940    if (cw->ec->input_only) return;
4941    if (cw->external_content) return;
4942    if (cw->render_update_lock.lock) return;
4943    set = !!set;
4944
4945    memset(&ns, 0, sizeof(Evas_Native_Surface));
4946
4947    if (set)
4948      {
4949         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4950         set = (!cw->ec->shaped);
4951         if (set)
4952           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4953      }
4954    cw->native = set;
4955
4956    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4957 }
4958
4959 EINTERN void
4960 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4961 {
4962    API_ENTRY;
4963    if (cw->ec->input_only) return;
4964    E_FREE(cw->ns);
4965    if (ns)
4966      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4967    _e_comp_object_alpha_set(cw);
4968    if (cw->native)
4969      e_comp_object_native_surface_set(obj, cw->native);
4970    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4971 }
4972
4973 EINTERN void
4974 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4975 {
4976    API_ENTRY;
4977
4978    set = !!set;
4979
4980    if (cw->blanked == set) return;
4981    cw->blanked = set;
4982    _e_comp_object_alpha_set(cw);
4983    if (set)
4984      {
4985         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4986         evas_object_image_data_set(cw->obj, NULL);
4987         return;
4988      }
4989    if (cw->native)
4990      e_comp_object_native_surface_set(obj, 1);
4991    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4992 }
4993
4994 static void
4995 _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)
4996 {
4997    Evas_Object *o;
4998    int obj_x, obj_y;
4999
5000    if (!_damage_trace) return;
5001
5002    API_ENTRY;
5003
5004    if (!evas_object_visible_get(cw->obj)) return;
5005
5006    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
5007
5008    o = evas_object_rectangle_add(e_comp->evas);
5009    evas_object_layer_set(o, E_LAYER_MAX);
5010    evas_object_name_set(o, "damage_trace");
5011    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
5012    evas_object_resize(o, dmg_w, dmg_h);
5013    evas_object_color_set(o, 0, 128, 0, 128);
5014    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5015    evas_object_pass_events_set(o, EINA_TRUE);
5016    evas_object_show(o);
5017
5018    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
5019          cw->ec,
5020          dmg_w, dmg_h, dmg_x, dmg_y,
5021          origin->w, origin->h, origin->x, origin->y);
5022
5023    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
5024 }
5025
5026 /* mark an object as dirty and setup damages */
5027 EINTERN void
5028 e_comp_object_dirty(Evas_Object *obj)
5029 {
5030    Eina_Iterator *it;
5031    Eina_Rectangle *rect;
5032    Eina_List *ll;
5033    Evas_Object *o;
5034    int w, h, tw, th;
5035    Eina_Bool dirty, visible;
5036    E_Map *m = NULL;
5037
5038    API_ENTRY;
5039    if (cw->external_content) return;
5040    if (!cw->redirected) return;
5041    if (cw->render_update_lock.lock)
5042      {
5043         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5044         return;
5045      }
5046    /* only actually dirty if pixmap is available */
5047    if (!e_pixmap_resource_get(cw->ec->pixmap))
5048      {
5049         // e_pixmap_size_get returns last attached buffer size
5050         // eventhough it is destroyed
5051         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
5052         return;
5053      }
5054    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
5055    visible = cw->visible;
5056    if (!dirty) w = h = 1;
5057    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
5058    if (!dirty)
5059      evas_object_image_data_set(cw->obj, NULL);
5060    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5061    evas_object_image_size_set(cw->obj, tw, th);
5062    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
5063    if (cw->pending_updates)
5064      eina_tiler_area_size_set(cw->pending_updates, w, h);
5065    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
5066      {
5067         evas_object_image_pixels_dirty_set(o, dirty);
5068         if (!dirty)
5069           evas_object_image_data_set(o, NULL);
5070         evas_object_image_size_set(o, tw, th);
5071         visible |= evas_object_visible_get(o);
5072      }
5073    if (!dirty)
5074      {
5075         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
5076         return;
5077      }
5078
5079    e_comp_object_native_surface_set(obj, 1);
5080
5081    m = _e_comp_object_map_damage_transform_get(cw->ec);
5082    it = eina_tiler_iterator_new(cw->updates);
5083    EINA_ITERATOR_FOREACH(it, rect)
5084      {
5085         /* evas converts damage according to rotation of ecore_evas in damage_region_set
5086          * of evas engine and doesn't convert damage according to evas_map.
5087          * so damage of evas_object_image use surface coordinate.
5088          */
5089         if (m)
5090           {
5091              int damage_x, damage_y, damage_w, damage_h;
5092
5093              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
5094                                                       &damage_x, &damage_y, &damage_w, &damage_h);
5095              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
5096              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
5097           }
5098         else
5099           {
5100              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
5101              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
5102           }
5103
5104         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
5105           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
5106         if (cw->pending_updates)
5107           eina_tiler_rect_add(cw->pending_updates, rect);
5108      }
5109    eina_iterator_free(it);
5110    if (m) e_map_free(m);
5111    if (cw->pending_updates)
5112      eina_tiler_clear(cw->updates);
5113    else
5114      {
5115         cw->pending_updates = cw->updates;
5116         cw->updates = eina_tiler_new(w, h);
5117         eina_tiler_tile_size_set(cw->updates, 1, 1);
5118      }
5119    cw->update_count = cw->updates_full = cw->updates_exist = 0;
5120    evas_object_smart_callback_call(obj, "dirty", NULL);
5121    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
5122    /* force render if main object is hidden but mirrors are visible */
5123    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
5124    e_comp_object_render(obj);
5125 }
5126
5127 EINTERN Eina_Bool
5128 e_comp_object_render(Evas_Object *obj)
5129 {
5130    Eina_List *l;
5131    Evas_Object *o;
5132    int pw, ph;
5133    unsigned int *pix;
5134
5135    API_ENTRY EINA_FALSE;
5136
5137    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5138    if (cw->ec->input_only) return EINA_TRUE;
5139    if (cw->external_content) return EINA_TRUE;
5140    if (cw->native) return EINA_FALSE;
5141    /* if comp object is not redirected state, comp object should not be set by newly committed data
5142       because image size of comp object is 1x1 and it should not be shown on canvas */
5143    if (!cw->redirected) return EINA_TRUE;
5144    if (cw->render_update_lock.lock)
5145      {
5146         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5147         return EINA_TRUE;
5148      }
5149    e_comp_object_render_update_del(obj);
5150    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
5151
5152    if (!cw->pending_updates)
5153      {
5154         WRN("RENDER [%p]: NO RECTS!", cw->ec);
5155         evas_object_image_data_set(cw->obj, NULL);
5156         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5157           evas_object_image_data_set(o, NULL);
5158         return EINA_FALSE;
5159      }
5160
5161    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
5162
5163    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
5164
5165    pix = e_pixmap_image_data_get(cw->ec->pixmap);
5166    if (!pix)
5167      {
5168         e_pixmap_image_refresh(cw->ec->pixmap);
5169         pix = e_pixmap_image_data_get(cw->ec->pixmap);
5170      }
5171
5172    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
5173      e_pixmap_image_data_ref(cw->ec->pixmap);
5174
5175    /* set pixel data */
5176    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
5177    _e_comp_object_alpha_set(cw);
5178    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5179      {
5180         evas_object_image_data_set(o, pix);
5181         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5182         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
5183      }
5184
5185    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
5186
5187    e_comp_client_post_update_add(cw->ec);
5188
5189    return EINA_TRUE;
5190 }
5191
5192 /* create a duplicate of an evas object */
5193 EINTERN Evas_Object *
5194 e_comp_object_util_mirror_add(Evas_Object *obj)
5195 {
5196    Evas_Object *o;
5197    int w, h, tw, th;
5198    unsigned int *pix = NULL;
5199    Eina_Bool argb = EINA_FALSE;
5200
5201    SOFT_ENTRY(NULL);
5202
5203    if (!cw)
5204      cw = evas_object_data_get(obj, "comp_mirror");
5205    if (!cw)
5206      {
5207         o = evas_object_image_filled_add(evas_object_evas_get(obj));
5208         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5209         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5210         evas_object_image_alpha_set(o, 1);
5211         evas_object_image_source_set(o, obj);
5212         return o;
5213      }
5214    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
5215    if (cw->external_content)
5216      {
5217         ERR("%p of client %p is external content.", obj, cw->ec);
5218         return NULL;
5219      }
5220    o = evas_object_image_filled_add(evas_object_evas_get(obj));
5221    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5222    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5223    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
5224    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
5225    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
5226    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
5227    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
5228    evas_object_data_set(o, "comp_mirror", cw);
5229
5230    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5231    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5232
5233    evas_object_image_size_set(o, tw, th);
5234
5235    if (cw->ec->shaped)
5236      pix = evas_object_image_data_get(cw->obj, 0);
5237    else
5238      {
5239         if (cw->native)
5240           {
5241              if (cw->ns)
5242                evas_object_image_native_surface_set(o, cw->ns);
5243              else
5244                {
5245                   Evas_Native_Surface ns;
5246                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5247                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5248                     evas_object_image_native_surface_set(o, &ns);
5249                }
5250           }
5251         else
5252           {
5253              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5254              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5255              if ((argb) &&
5256                  (e_pixmap_image_exists(cw->ec->pixmap)))
5257                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5258              else
5259                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5260           }
5261      }
5262    if (pix)
5263      {
5264       Eina_Bool dirty;
5265
5266       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5267       evas_object_image_pixels_dirty_set(o, dirty);
5268       evas_object_image_data_set(o, pix);
5269       evas_object_image_data_set(cw->obj, pix);
5270       if (dirty)
5271         evas_object_image_data_update_add(o, 0, 0, tw, th);
5272    }
5273    return o;
5274 }
5275
5276 //////////////////////////////////////////////////////
5277
5278 EINTERN Eina_Bool
5279 e_comp_object_effect_allowed_get(Evas_Object *obj)
5280 {
5281    API_ENTRY EINA_FALSE;
5282
5283    if (!cw->shobj) return EINA_FALSE;
5284    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5285    return !e_comp_config_get()->match.disable_borders;
5286 }
5287
5288 /* setup an api effect for a client */
5289 E_API Eina_Bool
5290 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5291 {
5292    char buf[4096];
5293    Eina_Stringshare *grp;
5294    E_Comp_Config *config;
5295    Eina_Bool loaded = EINA_FALSE;
5296
5297    API_ENTRY EINA_FALSE;
5298    if (!cw->shobj) return EINA_FALSE; //input window
5299
5300    if (!effect) effect = "none";
5301    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5302
5303    config = e_comp_config_get();
5304    if ((config) && (config->effect_file))
5305      {
5306         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5307           {
5308              cw->effect_set = EINA_TRUE;
5309              loaded = EINA_TRUE;
5310           }
5311      }
5312
5313    if (!loaded)
5314      {
5315         edje_object_file_get(cw->effect_obj, NULL, &grp);
5316         cw->effect_set = !eina_streq(effect, "none");
5317         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5318         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5319           {
5320              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5321              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5322                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5323                  {
5324                     if (cw->effect_running)
5325                       {
5326                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5327                            return EINA_FALSE;
5328                       }
5329                     cw->effect_set = EINA_FALSE;
5330                     return cw->effect_set;
5331                  }
5332           }
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    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5340    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5341    if (cw->effect_clip)
5342      {
5343         evas_object_clip_unset(cw->clip);
5344         cw->effect_clip = 0;
5345      }
5346    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5347
5348    _e_comp_object_dim_update(cw);
5349
5350    return cw->effect_set;
5351 }
5352
5353 /* set params for embryo scripts in effect */
5354 E_API void
5355 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5356 {
5357    Edje_Message_Int_Set *msg;
5358    unsigned int x;
5359
5360    API_ENTRY;
5361    EINA_SAFETY_ON_NULL_RETURN(params);
5362    EINA_SAFETY_ON_FALSE_RETURN(count);
5363    if (!cw->effect_set) return;
5364
5365    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5366    msg->count = (int)count;
5367    for (x = 0; x < count; x++)
5368       msg->val[x] = params[x];
5369    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5370    edje_object_message_signal_process(cw->effect_obj);
5371 }
5372
5373 static void
5374 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5375 {
5376    Edje_Signal_Cb end_cb;
5377    void *end_data;
5378    E_Comp_Object *cw = data;
5379
5380    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5381    cw->effect_running = 0;
5382    if (!_e_comp_object_animating_end(cw)) return;
5383
5384    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5385      {
5386         evas_object_data_del(cw->smart_obj, "effect_running");
5387         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5388         e_client_visibility_calculate();
5389      }
5390
5391    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5392    if (!end_cb) return;
5393    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5394    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5395    end_cb(end_data, cw->smart_obj, emission, source);
5396 }
5397
5398 /* clip effect to client's zone */
5399 EINTERN void
5400 e_comp_object_effect_clip(Evas_Object *obj)
5401 {
5402    API_ENTRY;
5403    if (!cw->ec->zone) return;
5404    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5405    if (!cw->effect_clip_able) return;
5406    evas_object_clip_set(cw->smart_obj, cw->ec->zone->bg_clip_object);
5407    cw->effect_clip = 1;
5408 }
5409
5410 /* unclip effect from client's zone */
5411 EINTERN void
5412 e_comp_object_effect_unclip(Evas_Object *obj)
5413 {
5414    API_ENTRY;
5415    if (!cw->effect_clip) return;
5416    evas_object_clip_unset(cw->smart_obj);
5417    cw->effect_clip = 0;
5418 }
5419
5420 /* start effect, running end_cb after */
5421 E_API Eina_Bool
5422 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5423 {
5424    API_ENTRY EINA_FALSE;
5425    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5426    if (!cw->effect_set) return EINA_FALSE;
5427
5428    if (cw->effect_running)
5429      {
5430         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5431      }
5432
5433    e_comp_object_effect_clip(obj);
5434    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5435
5436    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5437    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5438    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5439    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5440
5441    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5442    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5443
5444    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5445    _e_comp_object_animating_begin(cw);
5446    cw->effect_running = 1;
5447    return EINA_TRUE;
5448 }
5449
5450 /* stop a currently-running effect immediately */
5451 E_API Eina_Bool
5452 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5453 {
5454    int ret = 0;
5455    Edje_Signal_Cb end_cb_before = NULL;
5456    void *end_data_before = NULL;
5457    API_ENTRY EINA_FALSE;
5458
5459    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5460    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5461
5462    if (end_cb_before != end_cb) return EINA_TRUE;
5463    e_comp_object_effect_unclip(obj);
5464    if (cw->effect_clip)
5465      {
5466         evas_object_clip_unset(cw->effect_obj);
5467         cw->effect_clip = 0;
5468      }
5469    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5470    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5471
5472    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5473      {
5474         evas_object_data_del(cw->smart_obj, "effect_running");
5475         e_client_visibility_calculate();
5476      }
5477
5478    cw->effect_running = 0;
5479    ret = _e_comp_object_animating_end(cw);
5480
5481    if ((ret) && (end_cb_before))
5482      {
5483         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5484         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5485      }
5486
5487    return ret;
5488 }
5489
5490 static int
5491 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5492 {
5493    return a->pri - b->pri;
5494 }
5495
5496 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5497 E_API E_Comp_Object_Mover *
5498 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5499 {
5500    E_Comp_Object_Mover *prov;
5501
5502    prov = E_NEW(E_Comp_Object_Mover, 1);
5503    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5504    prov->func = provider;
5505    prov->data = (void*)data;
5506    prov->pri = pri;
5507    prov->sig = sig;
5508    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5509      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5510    return prov;
5511 }
5512
5513 E_API void
5514 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5515 {
5516    EINA_SAFETY_ON_NULL_RETURN(prov);
5517    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5518    free(prov);
5519 }
5520
5521 E_API Evas_Object *
5522 e_comp_object_effect_object_get(Evas_Object *obj)
5523 {
5524    API_ENTRY NULL;
5525
5526    return cw->effect_obj;
5527 }
5528
5529 EINTERN Eina_Bool
5530 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5531 {
5532    API_ENTRY EINA_FALSE;
5533    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5534    if (!cw->effect_set) return EINA_FALSE;
5535
5536    cw->hiding = set;
5537
5538    return EINA_TRUE;
5539 }
5540
5541 ////////////////////////////////////
5542
5543 static void
5544 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5545 {
5546    if (e_comp->autoclose.obj)
5547      {
5548         e_comp_ungrab_input(0, 1);
5549         if (e_comp->autoclose.del_cb)
5550           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5551         else if (!already_del)
5552           {
5553              evas_object_hide(e_comp->autoclose.obj);
5554              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5555           }
5556         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5557      }
5558    e_comp->autoclose.obj = NULL;
5559    e_comp->autoclose.data = NULL;
5560    e_comp->autoclose.del_cb = NULL;
5561    e_comp->autoclose.key_cb = NULL;
5562    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5563 }
5564
5565 static void
5566 _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)
5567 {
5568    _e_comp_object_autoclose_cleanup(0);
5569 }
5570
5571 static void
5572 _e_comp_object_autoclose_setup(Evas_Object *obj)
5573 {
5574    if (!e_comp->autoclose.rect)
5575      {
5576         /* create rect just below autoclose object to catch mouse events */
5577         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5578         evas_object_move(e_comp->autoclose.rect, 0, 0);
5579         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5580         evas_object_show(e_comp->autoclose.rect);
5581         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5582         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5583         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5584         e_comp_grab_input(0, 1);
5585      }
5586    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5587    evas_object_focus_set(obj, 1);
5588 }
5589
5590 static void
5591 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5592 {
5593    _e_comp_object_autoclose_setup(obj);
5594    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5595 }
5596
5597 static void
5598 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5599 {
5600    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5601    _e_comp_object_autoclose_cleanup(1);
5602    if (e_client_focused_get()) return;
5603    if (e_config->focus_policy != E_FOCUS_MOUSE)
5604      e_client_refocus();
5605 }
5606
5607 EINTERN void
5608 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5609 {
5610    SOFT_ENTRY();
5611
5612    if (e_comp->autoclose.obj)
5613      {
5614         if (e_comp->autoclose.obj == obj) return;
5615         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5616         e_comp->autoclose.obj = obj;
5617         e_comp->autoclose.del_cb = del_cb;
5618         e_comp->autoclose.key_cb = cb;
5619         e_comp->autoclose.data = (void*)data;
5620         if (evas_object_visible_get(obj))
5621           _e_comp_object_autoclose_setup(obj);
5622         else
5623           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5624         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5625         return;
5626      }
5627    e_comp->autoclose.obj = obj;
5628    e_comp->autoclose.del_cb = del_cb;
5629    e_comp->autoclose.key_cb = cb;
5630    e_comp->autoclose.data = (void*)data;
5631    if (evas_object_visible_get(obj))
5632      _e_comp_object_autoclose_setup(obj);
5633    else
5634      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5635    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5636 }
5637
5638 E_API unsigned int
5639 e_comp_object_is_animating(Evas_Object *obj)
5640 {
5641    API_ENTRY 0;
5642
5643    return cw->animating;
5644 }
5645
5646 E_API void
5647 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5648 {
5649    API_ENTRY;
5650
5651    if ((cw->external_content) &&
5652        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5653      {
5654         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5655             "But current external content is %d object for %p.",
5656             cw->content_type, cw->ec);
5657         return;
5658      }
5659
5660    cw->user_alpha_set = EINA_TRUE;
5661    cw->user_alpha = alpha;
5662
5663    if (!cw->obj) return;
5664
5665    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5666
5667    evas_object_image_alpha_set(cw->obj, alpha);
5668
5669    if ((!cw->native) && (!cw->external_content))
5670      evas_object_image_data_set(cw->obj, NULL);
5671 }
5672
5673 EINTERN Eina_Bool
5674 e_comp_object_alpha_get(Evas_Object *obj)
5675 {
5676    API_ENTRY EINA_FALSE;
5677
5678    return evas_object_image_alpha_get(cw->obj);
5679 }
5680
5681 E_API void
5682 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5683 {
5684    Eina_Bool mask_set = EINA_FALSE;
5685    Evas_Object *o;
5686
5687    API_ENTRY;
5688    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5689    if (cw->ec->input_only) return;
5690    mask_set = !!set;
5691
5692    if (mask_set)
5693      {
5694         if (!cw->mask.obj)
5695           {
5696              o = evas_object_rectangle_add(e_comp->evas);
5697              evas_object_color_set(o, 0, 0, 0, 0);
5698              evas_object_clip_set(o, cw->clip);
5699              evas_object_smart_member_add(o, obj);
5700              evas_object_move(o, 0, 0);
5701              evas_object_resize(o, cw->w, cw->h);
5702              /* save render op value to restore when clear a mask.
5703               *
5704               * NOTE: DO NOT change the render op on ec->frame while mask object
5705               * is set. it will overwrite the changed op value. */
5706              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5707              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5708              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5709              if (cw->visible) evas_object_show(o);
5710
5711              cw->mask.obj = o;
5712              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5713              ELOGF("COMP", "         |mask_obj", cw->ec);
5714              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5715           }
5716      }
5717    else
5718      {
5719         if (cw->mask.obj)
5720           {
5721              evas_object_smart_member_del(cw->mask.obj);
5722              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5723
5724              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5725              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5726           }
5727      }
5728 }
5729
5730 E_API Eina_Bool
5731 e_comp_object_mask_has(Evas_Object *obj)
5732 {
5733    API_ENTRY EINA_FALSE;
5734
5735    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5736 }
5737
5738 EINTERN void
5739 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5740 {
5741    int tw, th;
5742    API_ENTRY;
5743
5744    if ((cw->external_content) &&
5745        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5746      {
5747         WRN("Can set up size to ONLY evas \"image\" object. "
5748             "But current external content is %d object for %p.",
5749             cw->content_type, cw->ec);
5750         return;
5751      }
5752
5753    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5754
5755    evas_object_image_size_set(cw->obj, tw, th);
5756 }
5757
5758 E_API void
5759 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5760 {
5761    Eina_Bool transform_set = EINA_FALSE;
5762    API_ENTRY;
5763    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5764    if (cw->ec->input_only) return;
5765
5766    transform_set = !!set;
5767
5768    if (transform_set)
5769      {
5770         if (!cw->transform_bg_obj)
5771           {
5772              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5773              evas_object_move(o, 0, 0);
5774              evas_object_resize(o, 1, 1);
5775              if (cw->transform_bg_color.a >= 255)
5776                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5777              else
5778                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5779              evas_object_color_set(o,
5780                                    cw->transform_bg_color.r,
5781                                    cw->transform_bg_color.g,
5782                                    cw->transform_bg_color.b,
5783                                    cw->transform_bg_color.a);
5784              if (cw->visible) evas_object_show(o);
5785
5786              cw->transform_bg_obj = o;
5787              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5788           }
5789         _e_comp_object_transform_obj_stack_update(obj);
5790      }
5791    else
5792      {
5793         if (cw->transform_bg_obj)
5794           {
5795              evas_object_smart_member_del(cw->transform_bg_obj);
5796              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5797           }
5798      }
5799 }
5800
5801 E_API void
5802 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5803 {
5804    API_ENTRY;
5805
5806    cw->transform_bg_color.r = r;
5807    cw->transform_bg_color.g = g;
5808    cw->transform_bg_color.b = b;
5809    cw->transform_bg_color.a = a;
5810
5811    if (cw->transform_bg_obj)
5812      {
5813         evas_object_color_set(cw->transform_bg_obj,
5814                               cw->transform_bg_color.r,
5815                               cw->transform_bg_color.g,
5816                               cw->transform_bg_color.b,
5817                               cw->transform_bg_color.a);
5818      }
5819 }
5820
5821 EINTERN void
5822 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5823 {
5824    API_ENTRY;
5825    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5826    if (cw->ec->input_only) return;
5827    if (!cw->transform_bg_obj) return;
5828
5829    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5830 }
5831
5832 EINTERN void
5833 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5834 {
5835    API_ENTRY;
5836    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5837    if (cw->ec->input_only) return;
5838    if (!cw->transform_bg_obj) return;
5839
5840    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5841 }
5842
5843 EINTERN void
5844 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5845 {
5846    Eina_Bool transform_set = EINA_FALSE;
5847    API_ENTRY;
5848    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5849    if (cw->ec->input_only) return;
5850
5851    transform_set = !!set;
5852
5853    if (transform_set)
5854      {
5855         if (!cw->transform_tranp_obj)
5856           {
5857              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5858              evas_object_move(o, 0, 0);
5859              evas_object_resize(o, 1, 1);
5860              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5861              evas_object_color_set(o, 0, 0, 0, 0);
5862              if (cw->visible) evas_object_show(o);
5863
5864              cw->transform_tranp_obj = o;
5865              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5866           }
5867         _e_comp_object_transform_obj_stack_update(obj);
5868      }
5869    else
5870      {
5871         if (cw->transform_tranp_obj)
5872           {
5873              evas_object_smart_member_del(cw->transform_tranp_obj);
5874              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5875           }
5876      }
5877 }
5878
5879 EINTERN void
5880 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5881 {
5882    API_ENTRY;
5883    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5884    if (cw->ec->input_only) return;
5885    if (!cw->transform_tranp_obj) return;
5886
5887    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5888 }
5889
5890 EINTERN void
5891 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5892 {
5893    API_ENTRY;
5894    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5895    if (cw->ec->input_only) return;
5896    if (!cw->transform_tranp_obj) return;
5897
5898    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5899 }
5900
5901 EINTERN void
5902 e_comp_object_layer_update(Evas_Object *obj,
5903                            Evas_Object *above, Evas_Object *below)
5904 {
5905    E_Comp_Object *cw2 = NULL;
5906    Evas_Object *o = NULL;
5907    short layer;
5908
5909    API_ENTRY;
5910
5911    if (cw->ec->layer_block) return;
5912    if ((above) && (below))
5913      {
5914         ERR("Invalid layer update request! cw=%p", cw);
5915         return;
5916      }
5917
5918    o = above?:below;
5919
5920    if (o)
5921      {
5922         layer = evas_object_layer_get(o);
5923         cw2 = evas_object_data_get(o, "comp_obj");
5924         while (!cw2)
5925           {
5926              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5927
5928              o = evas_object_above_get(o);
5929              if ((!o) || (o == cw->smart_obj)) break;
5930              if (evas_object_layer_get(o) != layer)
5931                {
5932                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5933                }
5934              if (!o)
5935                {
5936                   E_Client *ec;
5937                   ec = e_client_top_get();
5938                   if (ec) o = ec->frame;
5939                }
5940
5941              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5942           }
5943      }
5944
5945    _e_comp_object_layers_remove(cw);
5946    if (cw2)
5947      {
5948         if (cw2->layer > cw->layer)
5949           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5950         else if (cw2->layer == cw->layer)
5951           {
5952              if (above)
5953                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5954              else if (o == obj)
5955                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5956              else if (below)
5957                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5958           }
5959         else
5960           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5961      }
5962    else
5963      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5964 }
5965
5966 EINTERN int
5967 e_comp_object_layer_get(Evas_Object *obj)
5968 {
5969    API_ENTRY -1;
5970    return cw->layer;
5971 }
5972
5973 E_API Eina_Bool
5974 e_comp_object_content_set(Evas_Object *obj,
5975                           Evas_Object *content,
5976                           E_Comp_Object_Content_Type type)
5977 {
5978    API_ENTRY EINA_FALSE;
5979
5980    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5981    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5982    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5983
5984    if (cw->obj)
5985      {
5986         ERR("Can't set e.swallow.content to requested content. "
5987             "Previous comp object should not be changed at all.");
5988         return EINA_FALSE;
5989      }
5990
5991    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5992
5993    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5994        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5995      {
5996         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5997             type, content, cw->ec, cw->ec->pixmap);
5998         return EINA_FALSE;
5999      }
6000
6001    cw->external_content = EINA_TRUE;
6002
6003    cw->obj = content;
6004    cw->content_type = type;
6005    e_util_size_debug_set(cw->obj, 1);
6006    evas_object_name_set(cw->obj, "cw->obj");
6007    _e_comp_object_alpha_set(cw);
6008
6009    if (cw->shobj)
6010      _e_comp_object_shadow_setup(cw);
6011
6012    return EINA_TRUE;
6013 }
6014
6015 EINTERN Eina_Bool
6016 e_comp_object_content_unset(Evas_Object *obj)
6017 {
6018    API_ENTRY EINA_FALSE;
6019
6020    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6021    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
6022
6023    if (!cw->obj && !cw->ec->visible)
6024      {
6025         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
6026         return EINA_TRUE;
6027      }
6028
6029    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
6030      {
6031         ELOGF("COMP", "has been set to internal image object already", cw->ec);
6032         return EINA_TRUE;
6033      }
6034
6035    if (cw->obj)
6036      {
6037         if (cw->frame_object)
6038           edje_object_part_unswallow(cw->frame_object, cw->obj);
6039         else if (cw->shobj)
6040           edje_object_part_unswallow(cw->shobj, cw->obj);
6041
6042         evas_object_del(cw->obj);
6043         evas_object_hide(cw->obj);
6044         cw->obj = NULL;
6045      }
6046
6047    cw->external_content = EINA_FALSE;
6048    if (cw->ec->is_cursor)
6049      {
6050         int pw, ph;
6051         DBG("%p is cursor surface..", cw->ec);
6052         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
6053           pw = ph = 1;
6054         evas_object_resize(cw->ec->frame, pw, ph);
6055         evas_object_hide(cw->ec->frame);
6056         return EINA_TRUE;
6057      }
6058
6059
6060    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
6061    cw->obj = evas_object_image_filled_add(e_comp->evas);
6062    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
6063    e_util_size_debug_set(cw->obj, 1);
6064    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
6065    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
6066    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
6067    evas_object_name_set(cw->obj, "cw->obj");
6068    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
6069    _e_comp_object_alpha_set(cw);
6070
6071    if (cw->shobj)
6072      _e_comp_object_shadow_setup(cw);
6073
6074    if (cw->visible)
6075      {
6076         cw->visible = 0;
6077         _e_comp_intercept_show_helper(cw);
6078         cw->visible = 1;
6079      }
6080
6081    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
6082    e_comp_object_dirty(cw->smart_obj);
6083    e_comp_object_render(cw->smart_obj);
6084    e_comp_object_render_update_add(obj);
6085
6086    return EINA_TRUE;
6087 }
6088
6089 EINTERN Evas_Object *
6090 e_comp_object_content_get(Evas_Object *obj)
6091 {
6092    API_ENTRY NULL;
6093
6094    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
6095
6096    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
6097      {
6098         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
6099         return NULL;
6100      }
6101
6102    return cw->obj;
6103 }
6104
6105 E_API E_Comp_Object_Content_Type
6106 e_comp_object_content_type_get(Evas_Object *obj)
6107 {
6108    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
6109
6110    return cw->content_type;
6111 }
6112
6113 E_API void
6114 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
6115 {
6116    API_ENTRY;
6117    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6118    E_Comp_Config *conf = e_comp_config_get();
6119    if (cw->ec->input_only) return;
6120    if (!conf->dim_rect_enable) return;
6121
6122    cw->dim.mask_set = mask_set;
6123    cw->dim.mask_x = x;
6124    cw->dim.mask_y = y;
6125    cw->dim.mask_w = w;
6126    cw->dim.mask_h = h;
6127
6128    if (!cw->dim.enable) return;
6129    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
6130 }
6131
6132 EINTERN void
6133 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
6134 {
6135    Eina_Bool mask_set = EINA_FALSE;
6136    Evas_Object *o;
6137
6138    API_ENTRY;
6139    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6140    E_Comp_Config *conf = e_comp_config_get();
6141    if (cw->ec->input_only) return;
6142    if (!conf->dim_rect_enable) return;
6143
6144    mask_set = !!set;
6145
6146    if (mask_set)
6147      {
6148         if (cw->dim.mask_obj)
6149           {
6150              evas_object_smart_member_del(cw->dim.mask_obj);
6151              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6152           }
6153
6154         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);
6155         o = evas_object_rectangle_add(e_comp->evas);
6156         evas_object_color_set(o, 0, 0, 0, 0);
6157         evas_object_smart_member_add(o, obj);
6158         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
6159         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
6160
6161         evas_object_render_op_set(o, EVAS_RENDER_COPY);
6162         if (cw->visible) evas_object_show(o);
6163
6164         cw->dim.mask_obj = o;
6165         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
6166
6167         evas_object_layer_set(cw->dim.mask_obj, 9998);
6168      }
6169    else
6170      {
6171         if (cw->dim.mask_obj)
6172           {
6173              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
6174              evas_object_smart_member_del(cw->dim.mask_obj);
6175              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6176           }
6177      }
6178 }
6179
6180 E_API void
6181 e_comp_object_dim_client_set(E_Client *ec)
6182 {
6183    E_Comp_Config *conf = e_comp_config_get();
6184
6185    if (!conf->dim_rect_enable) return ;
6186    if (dim_client == ec) return;
6187
6188    Eina_Bool prev_dim = EINA_FALSE;
6189    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
6190
6191    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
6192       prev_dim = EINA_TRUE;
6193
6194    if (prev_dim && dim_client->visible && ec)
6195      {
6196         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
6197         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
6198      }
6199    else
6200      {
6201         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
6202         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
6203      }
6204    dim_client = ec;
6205 }
6206
6207 EINTERN E_Client *
6208 e_comp_object_dim_client_get(void)
6209 {
6210    E_Comp_Config *conf = e_comp_config_get();
6211
6212    if (!conf->dim_rect_enable ) return NULL;
6213
6214    return dim_client;
6215 }
6216
6217 static void
6218 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6219 {
6220    API_ENTRY;
6221    char emit[32] = "\0";
6222    E_Comp_Config *conf = e_comp_config_get();
6223
6224    if (!ec) return;
6225    if (!conf->dim_rect_enable) return;
6226    if (!cw->effect_obj) return;
6227    if (enable == cw->dim.enable) return;
6228
6229    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6230    if (noeffect || !conf->dim_rect_effect)
6231      {
6232         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6233      }
6234    else
6235      {
6236         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6237      }
6238
6239    cw->dim.enable = enable;
6240
6241    if (cw->dim.mask_set && !enable)
6242      {
6243         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6244         edje_object_signal_emit(cw->effect_obj, emit, "e");
6245      }
6246    else if (cw->dim.mask_set && enable)
6247      {
6248         edje_object_signal_emit(cw->effect_obj, emit, "e");
6249         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6250      }
6251    else
6252      {
6253         edje_object_signal_emit(cw->effect_obj, emit, "e");
6254      }
6255 }
6256
6257 static Eina_Bool
6258 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6259 {
6260    API_ENTRY EINA_FALSE;
6261    E_Comp_Config *conf = e_comp_config_get();
6262
6263    if (!ec) return EINA_FALSE;
6264    if (!conf->dim_rect_enable) return EINA_FALSE;
6265
6266    if (cw->dim.enable) return EINA_TRUE;
6267
6268    return EINA_FALSE;
6269 }
6270
6271 static void
6272 _e_comp_object_dim_update(E_Comp_Object *cw)
6273 {
6274    E_Comp_Config *conf = e_comp_config_get();
6275
6276    if (!cw) return;
6277    if (!conf->dim_rect_enable) return;
6278    if (!cw->effect_obj) return;
6279    if (cw->dim.enable)
6280      {
6281         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6282         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6283
6284         if (cw->dim.mask_set)
6285           {
6286              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6287           }
6288      }
6289 }
6290
6291 EINTERN void
6292 e_comp_object_clear(Evas_Object *obj)
6293 {
6294    API_ENTRY;
6295
6296    _e_comp_object_clear(cw);
6297 }
6298
6299 EINTERN Eina_Bool
6300 e_comp_object_hwc_update_exists(Evas_Object *obj)
6301 {
6302    API_ENTRY EINA_FALSE;
6303    return cw->hwc_need_update;
6304 }
6305
6306 // will remove out
6307 E_API void
6308 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6309 {
6310    API_ENTRY;
6311    cw->hwc_need_update = set;
6312 }
6313
6314 EINTERN Eina_Bool
6315 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6316 {
6317    API_ENTRY EINA_FALSE;
6318    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6319 }
6320
6321 EINTERN void
6322 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6323 {
6324    API_ENTRY;
6325    if (cw->indicator.obj != indicator)
6326      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6327    cw->indicator.obj = indicator;
6328    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6329 }
6330
6331 EINTERN void
6332 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6333 {
6334    API_ENTRY;
6335    if (cw->indicator.obj != indicator) return;
6336    cw->indicator.obj = NULL;
6337    edje_object_part_unswallow(cw->shobj, indicator);
6338 }
6339
6340 EINTERN void
6341 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6342 {
6343    API_ENTRY;
6344    Edje_Message_Int_Set *msg;
6345
6346    if (!cw->indicator.obj) return;
6347
6348    cw->indicator.w = w;
6349    cw->indicator.h = h;
6350
6351    if (!cw->shobj) return;
6352
6353    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6354    msg->count = 2;
6355    msg->val[0] = w;
6356    msg->val[1] = h;
6357    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6358    edje_object_message_signal_process(cw->shobj);
6359 }
6360
6361 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6362 EINTERN void
6363 e_comp_object_map_update(Evas_Object *obj)
6364 {
6365    API_ENTRY;
6366    E_Client *ec = cw->ec;
6367    E_Comp_Wl_Client_Data *cdata;
6368    E_Map *map;
6369    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6370    char buffer[128];
6371    char *p = buffer;
6372    int l, remain = sizeof buffer;
6373
6374    if (!ec) return;
6375    if (e_object_is_del(E_OBJECT(ec))) return;
6376    cdata = e_client_cdata_get(ec);
6377    if (!cdata) return;
6378
6379    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6380     * when new buffer is attached.
6381     */
6382    if (!cdata->buffer_ref.buffer) return;
6383
6384    if ((!cw->redirected) ||
6385        (e_client_video_hw_composition_check(ec)) ||
6386        (!e_comp_wl_output_buffer_transform_get(ec) &&
6387         cdata->scaler.buffer_viewport.buffer.scale == 1))
6388      {
6389         if (evas_object_map_enable_get(cw->effect_obj))
6390           {
6391              ELOGF("TRANSFORM", "map: disable", cw->ec);
6392              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6393              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6394              evas_object_resize(cw->effect_obj, tw, th);
6395           }
6396
6397         return;
6398      }
6399
6400    map = e_map_new();
6401    EINA_SAFETY_ON_NULL_RETURN(map);
6402
6403    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6404
6405    x1 = y1 = 0;
6406    x2 = bw;
6407    y2 = bh;
6408
6409    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6410
6411    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6412    e_map_point_image_uv_set(map, 0, x, y);
6413    l = snprintf(p, remain, "%d,%d", x, y);
6414    p += l, remain -= l;
6415
6416    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6417    e_map_point_image_uv_set(map, 1, x, y);
6418    l = snprintf(p, remain, " %d,%d", x, y);
6419    p += l, remain -= l;
6420
6421    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6422    e_map_point_image_uv_set(map, 2, 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, x1, y2, &x, &y);
6427    e_map_point_image_uv_set(map, 3, x, y);
6428    l = snprintf(p, remain, " %d,%d", x, y);
6429    p += l, remain -= l;
6430
6431    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6432          cw->ec,
6433          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6434
6435    e_comp_object_map_set(cw->effect_obj, map);
6436    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6437
6438    e_map_free(map);
6439
6440    /* if there's screen rotation with comp mode, then ec->effect_obj and
6441     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6442     */
6443    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6444    evas_object_resize(cw->effect_obj, tw, th);
6445 }
6446
6447 EINTERN Eina_Bool
6448 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6449 {
6450    API_ENTRY EINA_FALSE;
6451
6452    cw->render_trace = set;
6453
6454    return EINA_TRUE;
6455 }
6456
6457 EINTERN Eina_Bool
6458 e_comp_object_native_usable_get(Evas_Object *obj)
6459 {
6460    API_ENTRY EINA_FALSE;
6461    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6462
6463    if (cw->ec->input_only) return EINA_FALSE;
6464    if (cw->external_content) return EINA_FALSE;
6465    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6466
6467    /* just return true value, if it is normal case */
6468    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6469
6470    /* abnormal case */
6471    Evas_Native_Surface *ns;
6472    ns = evas_object_image_native_surface_get(cw->obj);
6473
6474    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6475    if (ns)
6476      {
6477         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6478         return EINA_TRUE;
6479      }
6480
6481    return EINA_FALSE;
6482 }
6483
6484 EINTERN Eina_Bool
6485 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6486 {
6487    API_ENTRY EINA_FALSE;
6488    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6489    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6490    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6491
6492    switch (filter)
6493      {
6494       case E_COMP_IMAGE_FILTER_BLUR:
6495          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6496          break;
6497       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6498          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6499          break;
6500       case E_COMP_IMAGE_FILTER_INVERSE:
6501          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6502          break;
6503       case E_COMP_IMAGE_FILTER_NONE:
6504       default:
6505          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6506          break;
6507      }
6508
6509    cw->image_filter = filter;
6510
6511    return EINA_TRUE;
6512 }
6513
6514 EINTERN E_Comp_Image_Filter
6515 e_comp_object_image_filter_get(Evas_Object *obj)
6516 {
6517    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6518    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6519    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6520    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6521
6522    return cw->image_filter;
6523 }
6524
6525 static void
6526 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6527 {
6528    Evas_Object *obj;
6529
6530    if (!_damage_trace) return;
6531
6532    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6533      evas_object_del(obj);
6534
6535    _damage_trace_post_objs = NULL;
6536 }
6537
6538 static void
6539 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6540 {
6541    if (!_damage_trace) return;
6542
6543    _damage_trace_post_objs = _damage_trace_objs;
6544    _damage_trace_objs = NULL;
6545 }
6546
6547 EINTERN void
6548 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6549 {
6550    if (_damage_trace == onoff) return;
6551
6552    if (onoff)
6553      {
6554         evas_event_callback_add(e_comp->evas,
6555                                 EVAS_CALLBACK_RENDER_PRE,
6556                                 _e_comp_object_damage_trace_render_pre_cb,
6557                                 NULL);
6558
6559         evas_event_callback_add(e_comp->evas,
6560                                 EVAS_CALLBACK_RENDER_POST,
6561                                 _e_comp_object_damage_trace_render_post_cb,
6562                                 NULL);
6563      }
6564    else
6565      {
6566         Evas_Object *obj;
6567
6568         EINA_LIST_FREE(_damage_trace_objs, obj)
6569           evas_object_del(obj);
6570
6571         _damage_trace_objs = NULL;
6572
6573         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6574           evas_object_del(obj);
6575
6576         _damage_trace_post_objs = NULL;
6577
6578         evas_event_callback_del(e_comp->evas,
6579                                 EVAS_CALLBACK_RENDER_PRE,
6580                                 _e_comp_object_damage_trace_render_pre_cb);
6581
6582         evas_event_callback_del(e_comp->evas,
6583                                 EVAS_CALLBACK_RENDER_POST,
6584                                 _e_comp_object_damage_trace_render_post_cb);
6585      }
6586
6587    _damage_trace = onoff;
6588 }
6589
6590 EINTERN Eina_Bool
6591 e_comp_object_redirected_get(Evas_Object *obj)
6592 {
6593    API_ENTRY EINA_FALSE;
6594    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6595
6596    return cw->redirected;
6597 }
6598
6599 EINTERN Eina_Bool
6600 e_comp_object_color_visible_get(Evas_Object *obj)
6601 {
6602    API_ENTRY EINA_FALSE;
6603    int a;
6604
6605    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6606
6607    e_comp_object_color_get(obj, NULL, NULL, NULL, &a);
6608    if (a <= 0)
6609      return EINA_FALSE;
6610
6611    evas_object_color_get(cw->effect_obj, NULL, NULL, NULL, &a);
6612    if (a <= 0)
6613      return EINA_FALSE;
6614
6615    evas_object_color_get(cw->shobj, NULL, NULL, NULL, &a);
6616    if (a <= 0)
6617      return EINA_FALSE;
6618
6619    evas_object_color_get(cw->obj, NULL, NULL, NULL, &a);
6620    if (a <= 0)
6621      return EINA_FALSE;
6622
6623    return EINA_TRUE;
6624 }
6625
6626 E_API Eina_Bool
6627 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6628 {
6629    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6630
6631    return e_map_set_to_comp_object(em, obj);
6632 }
6633
6634 EINTERN E_Map *
6635 e_comp_object_map_get(const Evas_Object *obj)
6636 {
6637    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6638
6639    return e_map_get_from_comp_object(obj);
6640 }
6641
6642 E_API Eina_Bool
6643 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6644 {
6645    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6646
6647    evas_object_map_enable_set(obj, enable);
6648
6649    return EINA_TRUE;
6650 }
6651
6652 E_API Eina_Bool
6653 e_comp_object_render_update_lock(Evas_Object *obj)
6654 {
6655    API_ENTRY EINA_FALSE;
6656
6657    if (cw->render_update_lock.lock == 0)
6658      {
6659         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6660         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref,
6661                                    e_pixmap_resource_get(cw->ec->pixmap));
6662         e_comp_object_render_update_del(obj);
6663         ELOGF("COMP", "Render update lock enabled", cw->ec);
6664      }
6665
6666    cw->render_update_lock.lock++;
6667
6668    return EINA_TRUE;
6669 }
6670
6671 E_API void
6672 e_comp_object_render_update_unlock(Evas_Object *obj)
6673 {
6674    API_ENTRY;
6675
6676    if (cw->render_update_lock.lock == 0)
6677      return;
6678
6679    cw->render_update_lock.lock--;
6680
6681    if (cw->render_update_lock.lock == 0)
6682      {
6683
6684         if (cw->render_update_lock.pending_move_set)
6685           {
6686              evas_object_move(obj,
6687                               cw->render_update_lock.pending_move_x,
6688                               cw->render_update_lock.pending_move_y);
6689              cw->render_update_lock.pending_move_x = 0;
6690              cw->render_update_lock.pending_move_y = 0;
6691              cw->render_update_lock.pending_move_set = EINA_FALSE;
6692           }
6693
6694         if (cw->render_update_lock.pending_resize_set)
6695           {
6696              evas_object_resize(obj,
6697                                 cw->render_update_lock.pending_resize_w,
6698                                 cw->render_update_lock.pending_resize_h);
6699              cw->render_update_lock.pending_resize_w = 0;
6700              cw->render_update_lock.pending_resize_h = 0;
6701              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6702           }
6703
6704         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6705
6706         if ((cw->ec->exp_iconify.buffer_flush) &&
6707             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6708             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6709           e_comp_object_clear(obj);
6710         else
6711           e_comp_object_render_update_add(obj);
6712
6713         ELOGF("COMP", "Render update lock disabled", cw->ec);
6714      }
6715 }
6716
6717 E_API Eina_Bool
6718 e_comp_object_render_update_lock_get(Evas_Object *obj)
6719 {
6720    API_ENTRY EINA_FALSE;
6721
6722    if (cw->render_update_lock.lock > 0)
6723      return EINA_TRUE;
6724
6725    return EINA_FALSE;
6726 }
6727
6728 E_API void
6729 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6730 {
6731    API_ENTRY;
6732
6733    if (cw->transparent.set)
6734      {
6735         if (r) *r = cw->transparent.user_r;
6736         if (g) *g = cw->transparent.user_g;
6737         if (b) *b = cw->transparent.user_b;
6738         if (a) *a = cw->transparent.user_a;
6739      }
6740    else
6741      {
6742         evas_object_color_get(obj, r, g, b, a);
6743      }
6744 }