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