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