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