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