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