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