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