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