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