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