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