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