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