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