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