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