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