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