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