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