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