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