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