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