e_comp_wl: replace "client_resize" smart call into resize signal
[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              evas_object_smart_callback_call(obj, "hiding", cw->ec);
2475              cw->defer_hide = !!cw->animating;
2476              if (!cw->animating)
2477                e_comp_object_effect_set(obj, NULL);
2478           }
2479      }
2480    if (cw->animating) return;
2481    /* if we have no animations running, go ahead and hide */
2482    cw->defer_hide = 0;
2483    ELOGF("COMP", "Hide normal object:%p", cw->ec, obj);
2484    evas_object_hide(obj);
2485
2486    wl_signal_emit(&cw->events.hide, NULL);
2487 }
2488
2489 static void
2490 _e_comp_intercept_show_helper(E_Comp_Object *cw)
2491 {
2492    E_Client *ec = cw->ec;
2493    int w = 0, h = 0;
2494
2495    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
2496
2497    if (ec->show_pending.count > 0)
2498      {
2499         ELOGF("COMP", "show_helper. Show PENDING!!! show_pending:%d", ec, ec->show_pending.count);
2500         ec->show_pending.running = EINA_TRUE;
2501         return;
2502      }
2503
2504 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
2505    if (!_e_comp_object_intercept_hook_call(E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, ec))
2506      {
2507         ELOGF("COMP", "show_helper. intercepted", cw->ec);
2508         return;
2509      }
2510 #endif
2511
2512    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,
2513          cw->visible, cw->animating, cw->defer_hide, cw->content_type, cw->updates, cw->w, cw->h,
2514          ec->iconic, ec->exp_iconify.by_client, ec->exp_iconify.type, ec->input_only, ec->ignored, ec->new_client);
2515
2516    if (cw->visible)
2517      {
2518         if (ec->iconic && cw->animating)
2519           {
2520              /* triggered during iconify animation */
2521              e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
2522              cw->defer_hide = 0;
2523           }
2524         ELOGF("COMP", "show_helper. return. already cw->visible", ec);
2525         return;
2526      }
2527    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE ||
2528        cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE)
2529      {
2530         evas_object_move(cw->smart_obj, ec->x, ec->y);
2531         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2532         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2533
2534         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2535           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2536
2537         cw->real_hid = 0;
2538         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2539         evas_object_show(cw->smart_obj);
2540
2541         if (!ec->iconic)
2542           e_client_focus_defer_set(ec);
2543
2544         return;
2545      }
2546    if ((!cw->updates) && (!ec->input_only) && (!ec->ignored))
2547      {
2548         int pw, ph;
2549
2550         pw = ec->client.w, ph = ec->client.h;
2551         if ((!pw) || (!ph))
2552           if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
2553             {
2554                ec->changes.visible = !ec->hidden;
2555                ec->visible = 1;
2556                EC_CHANGED(ec);
2557                ELOGF("COMP", "show_helper. return. no pixmap size", ec);
2558                return;
2559             }
2560
2561         cw->updates = eina_tiler_new(pw, ph);
2562         if (!cw->updates)
2563           {
2564              ec->changes.visible = !ec->hidden;
2565              ec->visible = 1;
2566              EC_CHANGED(ec);
2567              ELOGF("COMP", "show_helper. return. no cw->updates", ec);
2568              return;
2569           }
2570      }
2571    if (cw->updates)
2572      eina_tiler_tile_size_set(cw->updates, 1, 1);
2573    if (ec->new_client)
2574      {
2575         /* ignore until client idler first run */
2576         ec->changes.visible = !ec->hidden;
2577         ec->visible = 1;
2578         EC_CHANGED(ec);
2579         ELOGF("COMP", "show_helper. return. new_client", ec);
2580         return;
2581      }
2582    if (ec->input_only)
2583      {
2584         /* who cares */
2585         cw->real_hid = 0;
2586         evas_object_move(cw->smart_obj, ec->x, ec->y);
2587         evas_object_resize(cw->smart_obj, ec->w, ec->h);
2588         ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2589         evas_object_show(cw->smart_obj);
2590         return;
2591      }
2592    if (ec->netwm.type == E_WINDOW_TYPE_DND && !e_comp_wl->drag_client)
2593      {
2594         /* start_drag not received */
2595         ec->changes.visible = 1;
2596         ec->visible = 1;
2597         EC_CHANGED(ec);
2598         ELOGF("COMP", "show_helper. return. start_drag not received yet", ec);
2599         return;
2600      }
2601    /* re-set geometry */
2602    evas_object_move(cw->smart_obj, ec->x, ec->y);
2603    /* force resize in case it hasn't happened yet, or just to update size */
2604    evas_object_resize(cw->smart_obj, ec->w, ec->h);
2605    if ((cw->w < 1) || (cw->h < 1))
2606      {
2607         /* if resize didn't go through, try again */
2608         ec->visible = ec->changes.visible = 1;
2609         EC_CHANGED(ec);
2610         ELOGF("COMP", "show_helper. return. cw_size(%d,%d)", ec, cw->w, cw->h);
2611         return;
2612      }
2613    /* if pixmap not available, clear pixmap since we're going to fetch it again */
2614    if (!e_pixmap_size_get(ec->pixmap, &w, &h))
2615      e_pixmap_clear(ec->pixmap);
2616
2617    if (cw->real_hid && w && h)
2618      {
2619         cw->real_hid = 0;
2620         /* force comp theming in case it didn't happen already */
2621         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
2622         if (e_comp->image_filter != E_COMP_IMAGE_FILTER_NONE)
2623           e_comp_object_image_filter_set(cw->smart_obj, e_comp->image_filter);
2624      }
2625
2626    /* only do the show if show is allowed */
2627    if (!cw->real_hid)
2628      {
2629         if (ec->internal) //internal clients render when they feel like it
2630           e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2631
2632         if (!e_client_is_iconified_by_client(ec)||
2633             e_policy_visibility_client_is_uniconic(ec))
2634           {
2635              ELOGF("COMP", "show_helper. evas_object_show!!!", ec);
2636              evas_object_show(cw->smart_obj);
2637
2638              /* if comp object is shown in idle enterer before(E_CLIENT_HOOK_EVAL_FETCH),
2639                 it is rendered in idle callback without native surface and
2640                 compositor shows an empty frame if other objects aren't shown
2641                 because job callback of e_comp called at the next loop.
2642                 it causes a visual defect when windows are switched.
2643               */
2644              if (cw->redirected)
2645                {
2646                   e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
2647                   e_comp_object_dirty(cw->smart_obj);
2648                   e_comp_object_render(cw->smart_obj);
2649                }
2650           }
2651      }
2652
2653    wl_signal_emit(&cw->events.show, NULL);
2654 }
2655
2656 static void
2657 _e_comp_intercept_show(void *data, Evas_Object *obj EINA_UNUSED)
2658 {
2659    E_Comp_Object *cw = data;
2660    E_Client *ec = cw->ec;
2661    Eina_List *l;
2662    E_Input_Rect_Data *input_rect_data;
2663    E_Input_Rect_Smart_Data *input_rect_sd;
2664    int tw, th;
2665
2666    if (ec->ignored) return;
2667
2668    if (cw->effect_obj)
2669      {
2670         //INF("SHOW2 %p", ec);
2671         _e_comp_intercept_show_helper(cw);
2672         return;
2673      }
2674    //INF("SHOW %p", ec);
2675    if (ec->input_only)
2676      {
2677         cw->effect_obj = evas_object_rectangle_add(e_comp->evas);
2678         evas_object_color_set(cw->effect_obj, 0, 0, 0, 0);
2679         evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
2680         evas_object_name_set(cw->effect_obj, "cw->effect_obj::input_only");
2681      }
2682    else
2683      {
2684         if ((!cw->obj) && (cw->external_content))
2685           {
2686              ERR("cw->obj for external content is not created! ec:%p", cw->ec);
2687              return;
2688           }
2689
2690         _e_comp_object_setup(cw);
2691         if (!cw->obj)
2692           {
2693              cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
2694              cw->obj = evas_object_image_filled_add(e_comp->evas);
2695              evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
2696              e_util_size_debug_set(cw->obj, 1);
2697              evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
2698              evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
2699              evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
2700              evas_object_name_set(cw->obj, "cw->obj");
2701              evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
2702              evas_object_intercept_color_set_callback_add(cw->obj, _e_comp_intercept_obj_color_set, cw);
2703           }
2704         _e_comp_object_alpha_set(cw);
2705
2706         cw->redirected = 1;
2707         evas_object_color_set(cw->clip, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity);
2708      }
2709
2710    _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
2711    evas_object_geometry_set(cw->effect_obj, cw->x, cw->y, tw, th);
2712    if (cw->input_obj)
2713      {
2714         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2715         if (input_rect_sd)
2716           {
2717              EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2718                {
2719                   if (input_rect_data->obj)
2720                     {
2721                        evas_object_geometry_set(input_rect_data->obj,
2722                          cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
2723                          cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
2724                          input_rect_data->rect.w, input_rect_data->rect.h);
2725                     }
2726                }
2727           }
2728      }
2729
2730    if (cw->mask.obj)
2731      evas_object_resize(cw->mask.obj, cw->w, cw->h);
2732
2733    _e_comp_intercept_show_helper(cw);
2734 }
2735
2736 static void
2737 _e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus)
2738 {
2739    E_Comp_Object *cw = data;
2740    E_Client *ec;
2741
2742    ec = cw->ec;
2743    /* note: this is here as it seems there are enough apps that do not even
2744     * expect us to emulate a look of focus but not actually set x input
2745     * focus as we do - so simply abort any focus set on such windows */
2746    /* be strict about accepting focus hint */
2747    /* be strict about accepting focus hint */
2748    if ((!ec->icccm.accepts_focus) &&
2749        (!ec->icccm.take_focus))
2750      {
2751         if (!focus)
2752           {
2753              if (e_client_focused_get() == ec)
2754                 e_client_focused_set(NULL);
2755
2756              ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2757              evas_object_focus_set(obj, focus);
2758           }
2759         return;
2760      }
2761    if (focus && ec->lock_focus_out) return;
2762    if (e_object_is_del(E_OBJECT(ec)) && focus)
2763      CRI("CAN'T FOCUS DELETED CLIENT! ec:%p", ec);
2764
2765    /* filter focus setting based on current state */
2766    if (focus)
2767      {
2768         if (ec->focused)
2769           {
2770              ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2771              evas_object_focus_set(obj, focus);
2772              return;
2773           }
2774         if ((ec->iconic) && (!ec->deskshow))
2775           {
2776              if (!e_policy_visibility_client_is_uniconify_render_running(ec))
2777                {
2778                   /* don't focus an iconified window. that's silly! */
2779                   ELOGF("FOCUS", "Do uniconify to set focus", ec);
2780                   e_client_uniconify(ec);
2781                   e_client_focus_latest_set(ec);
2782                   return;
2783                }
2784           }
2785         if (!ec->visible)
2786           {
2787              return;
2788           }
2789      }
2790
2791    if (focus)
2792      {
2793         /* check for modal child and set focus to modal child */
2794         E_Client *modal_child = e_client_modal_child_get(ec);
2795         if ((modal_child) && (modal_child != ec) &&
2796             (!e_client_is_iconified_by_client(modal_child)) &&
2797             (modal_child->visible) && (!e_object_is_del(E_OBJECT(modal_child))))
2798           {
2799              // add ec to latest focus stack
2800              e_client_focus_latest_set(ec);
2801
2802              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);
2803              //e_client_focused_set(modal_child);
2804              evas_object_focus_set(modal_child->frame, focus);
2805              return;
2806           }
2807         if (!cw->visible)
2808           {
2809              /* not yet visible, wait till the next time... */
2810              ec->want_focus = !ec->hidden;
2811              if (ec->want_focus)
2812                EC_CHANGED(ec);
2813              return;
2814           }
2815         e_client_focused_set(ec);
2816      }
2817    else
2818      {
2819         if (e_client_focused_get() == ec)
2820           e_client_focused_set(NULL);
2821      }
2822
2823    if (focus)
2824      ELOGF("FOCUS", "FOCUS SET   | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2825    else
2826      ELOGF("FOCUS", "FOCUS UNSET | evas_object(%p) (frame:%p)", ec, obj, ec->frame);
2827
2828    evas_object_focus_set(obj, focus);
2829 }
2830
2831 static void
2832 _e_comp_intercept_color_set(void *data, Evas_Object *obj, int r, int g, int b, int a)
2833 {
2834    E_Comp_Object *cw = data;
2835
2836    if (cw->transparent.set)
2837      {
2838         cw->transparent.user_r = r;
2839         cw->transparent.user_g = g;
2840         cw->transparent.user_b = b;
2841         cw->transparent.user_a = a;
2842
2843         ELOGF("COMP", "Transparent user_color(%d,%d,%d,%d)",
2844               cw->ec,
2845               cw->transparent.user_r,
2846               cw->transparent.user_g,
2847               cw->transparent.user_b,
2848               cw->transparent.user_a);
2849      }
2850    else
2851      {
2852         evas_object_color_set(obj, r, g, b, a);
2853      }
2854
2855    wl_signal_emit(&cw->events.color_set, NULL);
2856
2857    _e_comp_object_color_visible_update(cw);
2858 }
2859
2860 ////////////////////////////////////////////////////
2861
2862 static void
2863 _e_comp_object_frame_recalc(E_Comp_Object *cw)
2864 {
2865    int w, h, ox, oy, ow, oh;
2866    Eina_List *l;
2867    Eina_Bool pass_event_flag = EINA_FALSE;
2868    E_Input_Rect_Data *input_rect_data;
2869    E_Input_Rect_Smart_Data *input_rect_sd;
2870
2871    if (cw->frame_object)
2872      {
2873         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
2874         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
2875         /* set a fixed size, force edje calc, check size difference */
2876         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
2877         edje_object_message_signal_process(cw->frame_object);
2878         edje_object_calc_force(cw->frame_object);
2879         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
2880         cw->client_inset.l = ox;
2881         cw->client_inset.r = MAX(w, 50) - (ox + ow);
2882         cw->client_inset.t = oy;
2883         cw->client_inset.b = MAX(h, 50) - (oy + oh);
2884         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
2885         evas_object_resize(cw->frame_object, w, h);
2886
2887         if (cw->input_obj)
2888           {
2889              input_rect_sd = evas_object_smart_data_get(cw->input_obj);
2890              if (input_rect_sd)
2891                {
2892                   EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
2893                     {
2894                        if (input_rect_data->obj)
2895                          {
2896                             pass_event_flag = EINA_TRUE;
2897                             break;
2898                          }
2899                     }
2900                }
2901           }
2902         evas_object_pass_events_set(cw->default_input_obj, pass_event_flag);
2903         evas_object_pass_events_set(cw->obj, pass_event_flag);
2904      }
2905    else
2906      {
2907         cw->client_inset.l = 0;
2908         cw->client_inset.r = 0;
2909         cw->client_inset.t = 0;
2910         cw->client_inset.b = 0;
2911      }
2912    cw->client_inset.calc = !!cw->frame_object;
2913 }
2914
2915 static void
2916 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2917 {
2918    E_Comp_Object *cw = data;
2919    E_Zone *zone;
2920    int w, h, pw, ph;
2921
2922    /* - get current size
2923     * - calc new size
2924     * - readjust for new frame size
2925     */
2926
2927    w = cw->ec->w, h = cw->ec->h;
2928    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
2929
2930    _e_comp_object_frame_recalc(cw);
2931
2932    if (!cw->ec->fullscreen)
2933      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
2934
2935    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2936    if (cw->ec->fullscreen)
2937      {
2938         zone = e_comp_zone_find_by_ec(cw->ec);
2939         if (!zone) return;
2940         evas_object_resize(cw->ec->frame, zone->w, zone->h);
2941      }
2942    else if (cw->ec->new_client)
2943      {
2944         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
2945         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
2946         evas_object_resize(cw->ec->frame, w, h);
2947      }
2948    else if ((w != cw->ec->w) || (h != cw->ec->h))
2949      evas_object_resize(cw->ec->frame, w, h);
2950 }
2951
2952 static void
2953 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2954 {
2955    E_Comp_Object *cw = data;
2956
2957    _e_comp_object_shadow_setup(cw);
2958    if (cw->frame_object)
2959      {
2960         _e_comp_object_shadow(cw);
2961         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2962         _e_comp_object_frame_recalc(cw);
2963         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2964      }
2965 }
2966
2967 static void
2968 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2969 {
2970    E_Comp_Object *cw = data;
2971
2972    if (_e_comp_object_shadow_setup(cw))
2973      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2974    if (cw->frame_object)
2975      {
2976         _e_comp_object_shadow(cw);
2977         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2978         _e_comp_object_frame_recalc(cw);
2979         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2980      }
2981 }
2982
2983 static void
2984 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2985 {
2986    E_Comp_Object *cw = data;
2987
2988    if (cw->frame_object)
2989      {
2990         _e_comp_object_shadow(cw);
2991         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2992         _e_comp_object_frame_recalc(cw);
2993         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2994      }
2995 }
2996
2997 static void
2998 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2999 {
3000    E_Comp_Object *cw = data;
3001
3002    if (_e_comp_object_shadow_setup(cw))
3003      {
3004         EC_CHANGED(cw->ec);
3005         cw->ec->changes.size = 1;
3006      }
3007    if (cw->frame_object)
3008      {
3009         _e_comp_object_shadow(cw);
3010         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
3011         _e_comp_object_frame_recalc(cw);
3012         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
3013      }
3014 }
3015
3016 static void
3017 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3018 {
3019    e_comp_object_signal_emit(obj, "e,state,focused", "e");
3020 }
3021
3022 static void
3023 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3024 {
3025    E_Comp_Object *cw = data;
3026
3027    if (!e_object_is_del(E_OBJECT(cw->ec)))
3028      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
3029 }
3030
3031 static void
3032 _e_comp_input_obj_smart_add(Evas_Object *obj)
3033 {
3034    E_Input_Rect_Smart_Data *input_rect_sd;
3035    input_rect_sd = E_NEW(E_Input_Rect_Smart_Data, 1);
3036
3037    if (!input_rect_sd) return;
3038    evas_object_smart_data_set(obj, input_rect_sd);
3039 }
3040
3041 static void
3042 _e_comp_input_obj_smart_del(Evas_Object *obj)
3043 {
3044    E_Input_Rect_Smart_Data *input_rect_sd;
3045    E_Input_Rect_Data *input_rect_data;
3046
3047    input_rect_sd = evas_object_smart_data_get(obj);
3048    if (!input_rect_sd) return;
3049
3050    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
3051      {
3052         if (input_rect_data->obj)
3053           {
3054              evas_object_smart_member_del(input_rect_data->obj);
3055              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
3056           }
3057         E_FREE(input_rect_data);
3058      }
3059    E_FREE(input_rect_sd);
3060 }
3061
3062 static void
3063 _e_comp_input_obj_smart_move(Evas_Object *obj, int x, int y)
3064 {
3065    E_Input_Rect_Smart_Data *input_rect_sd;
3066    E_Input_Rect_Data *input_rect_data;
3067    Eina_List *l;
3068    E_Comp_Object *cw;
3069
3070    input_rect_sd = evas_object_smart_data_get(obj);
3071    if (!input_rect_sd) return;
3072
3073    cw = input_rect_sd->cw;
3074    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3075      {
3076         if (input_rect_data->obj)
3077           {
3078              evas_object_geometry_set(input_rect_data->obj,
3079                x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3080                y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3081                input_rect_data->rect.w, input_rect_data->rect.h);
3082           }
3083      }
3084 }
3085
3086 static void
3087 _e_comp_input_obj_smart_resize(Evas_Object *obj, int w, int h)
3088 {
3089    E_Input_Rect_Smart_Data *input_rect_sd;
3090    E_Input_Rect_Data *input_rect_data;
3091    Eina_List *l;
3092    E_Comp_Object *cw;
3093
3094    input_rect_sd = evas_object_smart_data_get(obj);
3095    if (!input_rect_sd) return;
3096
3097    cw = input_rect_sd->cw;
3098    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3099      {
3100         if (input_rect_data->obj)
3101           {
3102              evas_object_geometry_set(input_rect_data->obj,
3103                cw->x + input_rect_data->rect.x + (!!cw->frame_object * cw->client_inset.l),
3104                cw->y + input_rect_data->rect.y + (!!cw->frame_object * cw->client_inset.t),
3105                input_rect_data->rect.w, input_rect_data->rect.h);
3106           }
3107      }
3108 }
3109
3110 static void
3111 _e_comp_input_obj_smart_show(Evas_Object *obj)
3112 {
3113    E_Input_Rect_Smart_Data *input_rect_sd;
3114    E_Input_Rect_Data *input_rect_data;
3115    Eina_List *l;
3116
3117    input_rect_sd = evas_object_smart_data_get(obj);
3118    if (!input_rect_sd) return;
3119
3120    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3121      {
3122         if (input_rect_data->obj)
3123           {
3124              evas_object_show(input_rect_data->obj);
3125           }
3126      }
3127 }
3128
3129 static void
3130 _e_comp_input_obj_smart_hide(Evas_Object *obj)
3131 {
3132    E_Input_Rect_Smart_Data *input_rect_sd;
3133    E_Input_Rect_Data *input_rect_data;
3134    Eina_List *l;
3135
3136    input_rect_sd = evas_object_smart_data_get(obj);
3137    if (!input_rect_sd) return;
3138
3139    EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
3140      {
3141         if (input_rect_data->obj)
3142           {
3143              evas_object_hide(input_rect_data->obj);
3144           }
3145      }
3146 }
3147
3148 static void
3149 _e_comp_input_obj_smart_init(void)
3150 {
3151    if (_e_comp_input_obj_smart) return;
3152    {
3153       static const Evas_Smart_Class sc =
3154       {
3155          INPUT_OBJ_SMART_NAME,
3156          EVAS_SMART_CLASS_VERSION,
3157          _e_comp_input_obj_smart_add,
3158          _e_comp_input_obj_smart_del,
3159          _e_comp_input_obj_smart_move,
3160          _e_comp_input_obj_smart_resize,
3161          _e_comp_input_obj_smart_show,
3162          _e_comp_input_obj_smart_hide,
3163          NULL,
3164          NULL,
3165          NULL,
3166          NULL,
3167          NULL,
3168          NULL,
3169
3170          NULL,
3171          NULL,
3172          NULL,
3173          NULL
3174       };
3175       _e_comp_input_obj_smart = evas_smart_class_new(&sc);
3176    }
3177 }
3178
3179
3180 static void
3181 _e_comp_smart_add(Evas_Object *obj)
3182 {
3183    E_Comp_Object *cw;
3184
3185    cw = E_NEW(E_Comp_Object, 1);
3186    EINA_SAFETY_ON_NULL_RETURN(cw);
3187
3188    wl_signal_init(&cw->events.lower);
3189 #ifdef REFACTOR_DESK_AREA
3190    wl_signal_init(&cw->events.lower_done);
3191    wl_signal_init(&cw->events.raise);
3192 #endif
3193    wl_signal_init(&cw->events.show);
3194    wl_signal_init(&cw->events.hide);
3195 #ifdef REFACTOR_DESK_AREA
3196    wl_signal_init(&cw->events.set_layer);
3197    wl_signal_init(&cw->events.stack_above);
3198    wl_signal_init(&cw->events.stack_below);
3199 #endif
3200    wl_signal_init(&cw->events.image_filter_set);
3201    wl_signal_init(&cw->events.render_op_set);
3202    wl_signal_init(&cw->events.content_type_set);
3203    wl_signal_init(&cw->events.color_set);
3204    wl_signal_init(&cw->events.color_visible_set);
3205    wl_signal_init(&cw->events.resize);
3206
3207    cw->smart_obj = obj;
3208    cw->x = cw->y = cw->w = cw->h = -1;
3209    evas_object_smart_data_set(obj, cw);
3210    cw->opacity = 255.0;
3211    cw->external_content = 0;
3212    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
3213    cw->transform_bg_color.r = 0;
3214    cw->transform_bg_color.g = 0;
3215    cw->transform_bg_color.b = 0;
3216    cw->transform_bg_color.a = 255;
3217    cw->color_visible = EINA_TRUE;
3218    evas_object_data_set(obj, "comp_obj", cw);
3219    evas_object_move(obj, -1, -1);
3220    /* intercept ALL the callbacks! */
3221    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
3222    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
3223    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
3224    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
3225    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
3226    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
3227    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
3228    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
3229    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
3230    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
3231    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_color_set, cw);
3232
3233    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
3234    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
3235    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
3236    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
3237
3238    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
3239
3240    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
3241    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
3242 }
3243
3244 static void
3245 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3246 {
3247    INTERNAL_ENTRY;
3248    evas_object_color_set(cw->clip, r, g, b, a);
3249    evas_object_smart_callback_call(obj, "color_set", NULL);
3250 }
3251
3252
3253 static void
3254 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3255 {
3256    INTERNAL_ENTRY;
3257    evas_object_clip_set(cw->clip, clip);
3258 }
3259
3260 static void
3261 _e_comp_smart_clip_unset(Evas_Object *obj)
3262 {
3263    INTERNAL_ENTRY;
3264    evas_object_clip_unset(cw->clip);
3265 }
3266
3267 static void
3268 _e_comp_smart_hide(Evas_Object *obj)
3269 {
3270    TRACE_DS_BEGIN(COMP:SMART HIDE);
3271
3272    INTERNAL_ENTRY;
3273    cw->visible = 0;
3274    cw->hiding = 0;
3275    evas_object_hide(cw->clip);
3276    if (cw->input_obj) evas_object_hide(cw->input_obj);
3277    evas_object_hide(cw->effect_obj);
3278    if (cw->default_input_obj) evas_object_hide(cw->default_input_obj);
3279    if (cw->transform_bg_obj) evas_object_hide(cw->transform_bg_obj);
3280    if (cw->transform_tranp_obj) evas_object_hide(cw->transform_tranp_obj);
3281    if (stopping)
3282      {
3283         TRACE_DS_END();
3284         return;
3285      }
3286
3287    /* unset native surface if current displaying buffer was destroied */
3288    if (!cw->buffer_destroy_listener.notify)
3289      {
3290         Evas_Native_Surface *ns;
3291         ns = evas_object_image_native_surface_get(cw->obj);
3292         if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
3293           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
3294      }
3295
3296    if (!cw->ec->input_only)
3297      {
3298         edje_object_freeze(cw->effect_obj);
3299         edje_object_freeze(cw->shobj);
3300         edje_object_play_set(cw->shobj, 0);
3301         if (cw->frame_object)
3302           edje_object_play_set(cw->frame_object, 0);
3303      }
3304
3305    e_comp_render_queue(); //force nocomp recheck
3306
3307    TRACE_DS_END();
3308 }
3309
3310 static void
3311 _e_comp_smart_show(Evas_Object *obj)
3312 {
3313    E_Client *tmp;
3314    Eina_List *l;
3315
3316    INTERNAL_ENTRY;
3317    cw->defer_hide = 0;
3318    cw->visible = 1;
3319    if ((cw->w < 0) || (cw->h < 0))
3320      CRI("ACK! ec:%p", cw->ec);
3321
3322    TRACE_DS_BEGIN(COMP:SMART SHOW);
3323
3324    e_comp_object_map_update(obj);
3325
3326    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
3327      evas_object_show(tmp->frame);
3328
3329    evas_object_show(cw->clip);
3330    if (cw->input_obj) evas_object_show(cw->input_obj);
3331    if (!cw->ec->input_only)
3332      {
3333         edje_object_thaw(cw->effect_obj);
3334         edje_object_thaw(cw->shobj);
3335         edje_object_play_set(cw->shobj, 1);
3336         if (cw->frame_object)
3337           edje_object_play_set(cw->frame_object, 1);
3338      }
3339    evas_object_show(cw->effect_obj);
3340    if (cw->mask.obj) evas_object_show(cw->mask.obj);
3341    if (cw->transform_bg_obj) evas_object_show(cw->transform_bg_obj);
3342    if (cw->transform_tranp_obj) evas_object_show(cw->transform_tranp_obj);
3343    if (cw->default_input_obj) evas_object_show(cw->default_input_obj);
3344    e_comp_render_queue();
3345    if (cw->ec->input_only)
3346      {
3347         TRACE_DS_END();
3348         return;
3349      }
3350    if (cw->ec->iconic && (!cw->ec->new_client))
3351      {
3352         if (e_client_is_iconified_by_client(cw->ec))
3353           {
3354              ELOGF("COMP", "Set launching flag..", cw->ec);
3355              cw->ec->launching = EINA_TRUE;
3356           }
3357
3358         e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
3359      }
3360    else if (!cw->showing) /* if set, client was ec->hidden during show animation */
3361      {
3362         cw->showing = 1;
3363         ELOGF("COMP", "Set launching flag..", cw->ec);
3364         cw->ec->launching = EINA_TRUE;
3365
3366         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
3367         _e_comp_object_animating_begin(cw);
3368         if (!_e_comp_object_effect_visibility_start(cw, 1))
3369           {
3370              TRACE_DS_END();
3371              return;
3372           }
3373      }
3374    /* ensure some random effect doesn't lock the client offscreen */
3375    if (!cw->animating)
3376      {
3377         cw->showing = 0;
3378         e_comp_object_effect_set(obj, NULL);
3379      }
3380
3381    _e_comp_object_dim_update(cw);
3382
3383    TRACE_DS_END();
3384 }
3385
3386 static void
3387 _e_comp_smart_del(Evas_Object *obj)
3388 {
3389    Eina_List *l;
3390
3391    INTERNAL_ENTRY;
3392
3393    if (cw->buffer_destroy_listener.notify)
3394      {
3395         wl_list_remove(&cw->buffer_destroy_listener.link);
3396         cw->buffer_destroy_listener.notify = NULL;
3397      }
3398
3399    if (cw->tbm_surface)
3400      {
3401         tbm_surface_internal_unref(cw->tbm_surface);
3402         cw->tbm_surface = NULL;
3403      }
3404
3405    if (cw->render_update_lock.buffer_ref.buffer)
3406      {
3407         ELOGF("COMP", "Clear buffer_ref of render_update_lock:%d",
3408               cw->ec, cw->render_update_lock.lock);
3409         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
3410      }
3411
3412    e_comp_object_render_update_del(cw->smart_obj);
3413    E_FREE_FUNC(cw->updates, eina_tiler_free);
3414    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
3415    free(cw->ns);
3416
3417    if (cw->obj_mirror)
3418      {
3419         Evas_Object *o;
3420
3421         EINA_LIST_FREE(cw->obj_mirror, o)
3422           {
3423              evas_object_image_data_set(o, NULL);
3424              evas_object_freeze_events_set(o, 1);
3425              evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
3426              evas_object_del(o);
3427           }
3428      }
3429 #ifdef REFACTOR_DESK_AREA
3430 #else
3431    _e_comp_object_layers_remove(cw);
3432 #endif
3433    l = evas_object_data_get(obj, "comp_object-to_del");
3434    E_FREE_LIST(l, evas_object_del);
3435    _e_comp_object_mouse_event_callback_unset(cw);
3436    evas_object_del(cw->clip);
3437    evas_object_del(cw->obj);
3438    evas_object_del(cw->shobj);
3439    evas_object_del(cw->effect_obj);
3440    evas_object_del(cw->frame_object);
3441    evas_object_del(cw->input_obj);
3442    evas_object_del(cw->mask.obj);
3443    if (cw->dim.mask_obj) evas_object_del(cw->dim.mask_obj);
3444    evas_object_del(cw->transform_bg_obj);
3445    evas_object_del(cw->transform_tranp_obj);
3446    evas_object_del(cw->default_input_obj);
3447    eina_stringshare_del(cw->frame_theme);
3448    eina_stringshare_del(cw->frame_name);
3449    if (cw->animating)
3450      {
3451         cw->animating = 0;
3452         e_comp->animating--;
3453         UNREFD(cw->ec, 2);
3454         e_object_unref(E_OBJECT(cw->ec));
3455      }
3456    cw->ec->frame = NULL;
3457    free(cw);
3458 }
3459
3460 static void
3461 _e_comp_smart_move(Evas_Object *obj, int x, int y)
3462 {
3463    INTERNAL_ENTRY;
3464
3465    cw->x = x, cw->y = y;
3466    evas_object_move(cw->effect_obj, x, y);
3467    evas_object_move(cw->default_input_obj, x, y);
3468    if (cw->input_obj) evas_object_move(cw->input_obj, x, y);
3469
3470    e_comp_object_map_update(obj);
3471 }
3472
3473 static void
3474 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
3475 {
3476    Eina_Bool first = EINA_FALSE;
3477    int tw, th;
3478
3479    INTERNAL_ENTRY;
3480
3481    if (!cw->effect_obj) CRI("ACK! ec:%p", cw->ec);
3482
3483    TRACE_DS_BEGIN(COMP:SMART RESIZE);
3484
3485    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
3486
3487    if (cw->w != w || cw->h != h)
3488      e_comp_object_map_update(obj);
3489
3490    first = ((cw->w < 1) || (cw->h < 1));
3491    cw->w = w, cw->h = h;
3492
3493    int ww, hh, pw, ph;
3494
3495    if (cw->frame_object)
3496      e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
3497    else
3498      ww = w, hh = h;
3499    /* verify pixmap:object size */
3500    if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
3501      {
3502         if ((ww != pw) || (hh != ph))
3503           ELOGF("COMP", "CW RSZ: %dx%d || PX: %dx%d.", cw->ec, ww, hh, pw, ph);
3504      }
3505    evas_object_resize(cw->effect_obj, tw, th);
3506    evas_object_resize(cw->default_input_obj, w, h);
3507    if (cw->input_obj)
3508      evas_object_resize(cw->input_obj, w, h);
3509    if (cw->mask.obj)
3510      evas_object_resize(cw->mask.obj, w, h);
3511    /* resize render update tiler */
3512    if (!first)
3513      {
3514         RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
3515         cw->updates_full = 0;
3516         if (cw->updates) eina_tiler_clear(cw->updates);
3517      }
3518    else
3519      {
3520         RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3521         if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3522      }
3523
3524    if (!cw->visible)
3525      {
3526         TRACE_DS_END();
3527         return;
3528      }
3529    e_comp_render_queue();
3530
3531    TRACE_DS_END();
3532 }
3533
3534 static void
3535 _e_comp_smart_init(void)
3536 {
3537    if (_e_comp_smart) return;
3538    {
3539       static const Evas_Smart_Class sc =
3540       {
3541          SMART_NAME,
3542          EVAS_SMART_CLASS_VERSION,
3543          _e_comp_smart_add,
3544          _e_comp_smart_del,
3545          _e_comp_smart_move,
3546          _e_comp_smart_resize,
3547          _e_comp_smart_show,
3548          _e_comp_smart_hide,
3549          _e_comp_smart_color_set,
3550          _e_comp_smart_clip_set,
3551          _e_comp_smart_clip_unset,
3552          NULL,
3553          NULL,
3554          NULL,
3555
3556          NULL,
3557          NULL,
3558          NULL,
3559          NULL
3560       };
3561       _e_comp_smart = evas_smart_class_new(&sc);
3562    }
3563 }
3564
3565 EINTERN void
3566 e_comp_object_init(void)
3567 {
3568    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
3569    E_EVENT_COMP_OBJECT_IMG_RENDER = ecore_event_type_new();
3570    E_EVENT_COMP_OBJECT_EFFECT_START = ecore_event_type_new();
3571    E_EVENT_COMP_OBJECT_EFFECT_END = ecore_event_type_new();
3572 }
3573
3574 EINTERN void
3575 e_comp_object_shutdown(void)
3576 {
3577
3578 }
3579
3580 EINTERN Eina_Bool
3581 e_comp_object_mirror_visibility_check(Evas_Object *obj)
3582 {
3583    API_ENTRY EINA_FALSE;
3584    return !!cw->force_visible;
3585 }
3586 /////////////////////////////////////////////////////////
3587
3588 static void
3589 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3590 {
3591    Eina_List *l;
3592    Eina_Bool comp_object;
3593
3594    comp_object = !!evas_object_data_get(obj, "comp_object");
3595    if (comp_object)
3596      {
3597         Evas_Object *o;
3598
3599         o = edje_object_part_swallow_get(obj, "e.swallow.content");
3600         evas_object_del(o);
3601         e_comp_render_queue();
3602      }
3603    l = evas_object_data_get(obj, "comp_object-to_del");
3604    E_FREE_LIST(l, evas_object_del);
3605 }
3606
3607 static void
3608 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3609 {
3610    if (e_comp_util_object_is_above_nocomp(obj) &&
3611        (!evas_object_data_get(obj, "comp_override")))
3612      {
3613         evas_object_data_set(obj, "comp_override", (void*)1);
3614         e_comp_override_add();
3615      }
3616 }
3617
3618 static void
3619 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
3620 {
3621    Eina_Bool ref = EINA_TRUE;
3622    if (evas_object_visible_get(obj))
3623      {
3624         void *d;
3625
3626         d = evas_object_data_del(obj, "comp_hiding");
3627         if (d)
3628           /* currently trying to hide */
3629           ref = EINA_FALSE;
3630         else
3631           /* already visible */
3632           return;
3633      }
3634
3635    evas_object_show(obj);
3636    if (ref)
3637      {
3638         evas_object_ref(obj);
3639         evas_object_data_set(obj, "comp_ref", (void*)1);
3640      }
3641    edje_object_signal_emit(obj, "e,state,visible", "e");
3642    evas_object_data_set(obj, "comp_showing", (void*)1);
3643    if (e_comp_util_object_is_above_nocomp(obj))
3644      {
3645         evas_object_data_set(obj, "comp_override", (void*)1);
3646         e_comp_override_add();
3647      }
3648 }
3649
3650 static void
3651 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
3652 {
3653    if (!evas_object_visible_get(obj)) return;
3654    /* already hiding */
3655    if (evas_object_data_get(obj, "comp_hiding")) return;
3656    if (!evas_object_data_del(obj, "comp_showing"))
3657      {
3658         evas_object_ref(obj);
3659         evas_object_data_set(obj, "comp_ref", (void*)1);
3660      }
3661    edje_object_signal_emit(obj, "e,state,hidden", "e");
3662    evas_object_data_set(obj, "comp_hiding", (void*)1);
3663
3664    if (evas_object_data_del(obj, "comp_override"))
3665      e_comp_override_timed_pop();
3666 }
3667
3668 static void
3669 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
3670 {
3671    if (!e_util_strcmp(emission, "e,action,hide,done"))
3672      {
3673         if (!evas_object_data_del(obj, "comp_hiding")) return;
3674         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
3675         evas_object_hide(obj);
3676         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
3677      }
3678    else
3679      evas_object_data_del(obj, "comp_showing");
3680    if (evas_object_data_del(obj, "comp_ref"))
3681      evas_object_unref(obj);
3682 }
3683
3684 static void
3685 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3686 {
3687    if (data)
3688      {
3689         int w, h;
3690
3691         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3692      }
3693 }
3694
3695 E_API E_Comp_Object_Hook *
3696 e_comp_object_hook_add(E_Comp_Object_Hook_Point hookpoint, E_Comp_Object_Hook_Cb func, const void *data)
3697 {
3698    E_Comp_Object_Hook *ch;
3699
3700    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_HOOK_LAST, NULL);
3701    ch = E_NEW(E_Comp_Object_Hook, 1);
3702    if (!ch) return NULL;
3703    ch->hookpoint = hookpoint;
3704    ch->func = func;
3705    ch->data = (void*)data;
3706    _e_comp_object_hooks[hookpoint] = eina_inlist_append(_e_comp_object_hooks[hookpoint], EINA_INLIST_GET(ch));
3707    return ch;
3708 }
3709
3710 E_API void
3711 e_comp_object_hook_del(E_Comp_Object_Hook *ch)
3712 {
3713    ch->delete_me = 1;
3714    if (_e_comp_object_hooks_walking == 0)
3715      {
3716         _e_comp_object_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3717         free(ch);
3718      }
3719    else
3720      _e_comp_object_hooks_delete++;
3721 }
3722
3723 #ifdef _F_E_COMP_OBJECT_INTERCEPT_HOOK_
3724 E_API E_Comp_Object_Intercept_Hook *
3725 e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data)
3726 {
3727    E_Comp_Object_Intercept_Hook *ch;
3728
3729    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_OBJECT_INTERCEPT_HOOK_LAST, NULL);
3730    ch = E_NEW(E_Comp_Object_Intercept_Hook, 1);
3731    if (!ch) return NULL;
3732    ch->hookpoint = hookpoint;
3733    ch->func = func;
3734    ch->data = (void*)data;
3735    _e_comp_object_intercept_hooks[hookpoint] = eina_inlist_append(_e_comp_object_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3736    return ch;
3737 }
3738
3739 E_API void
3740 e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch)
3741 {
3742    ch->delete_me = 1;
3743    if (_e_comp_object_intercept_hooks_walking == 0)
3744      {
3745         _e_comp_object_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_object_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3746         free(ch);
3747      }
3748    else
3749      _e_comp_object_intercept_hooks_delete++;
3750 }
3751 #endif
3752
3753 E_API Evas_Object *
3754 e_comp_object_util_add(Evas_Object *obj)
3755 {
3756    Evas_Object *o;
3757    const char *name;
3758    E_Comp_Config *conf = e_comp_config_get();
3759    Eina_Bool skip = EINA_FALSE;
3760    char buf[1024];
3761    int ok = 0;
3762    int x, y, w, h;
3763    Eina_Bool vis;
3764
3765    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
3766
3767    name = evas_object_name_get(obj);
3768    vis = evas_object_visible_get(obj);
3769    o = edje_object_add(e_comp->evas);
3770    evas_object_data_set(o, "comp_object", (void*)1);
3771    if (name)
3772      skip = (!strncmp(name, "noshadow", 8));
3773    if (skip)
3774      evas_object_data_set(o, "comp_object_skip", (void*)1);
3775
3776    if (conf->shadow_style)
3777      {
3778         snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
3779         ok = e_theme_edje_object_set(o, "base/theme/comp", buf);
3780      }
3781    if (!ok)
3782      e_theme_edje_object_set(o, "base/theme/comp", "e/comp/frame/default");
3783    if (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow")))
3784      edje_object_signal_emit(o, "e,state,shadow,on", "e");
3785    else
3786      edje_object_signal_emit(o, "e,state,shadow,off", "e");
3787
3788    evas_object_geometry_get(obj, &x, &y, &w, &h);
3789    evas_object_geometry_set(o, x, y, w, h);
3790    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
3791
3792    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, NULL);
3793
3794    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, NULL);
3795    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, NULL);
3796    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, NULL);
3797    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3798    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, NULL);
3799    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, NULL);
3800
3801    e_comp_object_signal_emit(o, "e,state,hidden", "e");
3802
3803    edje_object_part_swallow(o, "e.swallow.content", obj);
3804
3805    _e_comp_object_event_add(o);
3806
3807    if (vis)
3808      evas_object_show(o);
3809
3810    return o;
3811 }
3812
3813 /* utility functions for deleting objects when their "owner" is deleted */
3814 EINTERN void
3815 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
3816 {
3817    Eina_List *l;
3818
3819    SOFT_ENTRY();
3820    EINA_SAFETY_ON_NULL_RETURN(to_del);
3821    l = evas_object_data_get(obj, "comp_object-to_del");
3822    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
3823    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
3824    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
3825 }
3826
3827 EINTERN void
3828 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3829 {
3830    Eina_List *l;
3831
3832    SOFT_ENTRY();
3833    EINA_SAFETY_ON_NULL_RETURN(to_del);
3834    l = evas_object_data_get(obj, "comp_object-to_del");
3835    if (l)
3836      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3837 }
3838
3839 /////////////////////////////////////////////////////////
3840
3841 EINTERN Evas_Object *
3842 e_comp_object_client_add(E_Client *ec)
3843 {
3844    Evas_Object *o;
3845    E_Comp_Object *cw;
3846
3847    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3848    if (ec->frame) return NULL;
3849    _e_comp_smart_init();
3850    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3851    cw = evas_object_smart_data_get(o);
3852    if (!cw) return NULL;
3853    evas_object_data_set(o, "E_Client", ec);
3854    cw->ec = ec;
3855    ec->frame = o;
3856    evas_object_data_set(o, "comp_object", (void*)1);
3857
3858    _e_comp_object_event_add(o);
3859
3860    return o;
3861 }
3862
3863 /* utility functions for getting client inset */
3864 E_API void
3865 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3866 {
3867    API_ENTRY;
3868    if (!cw->client_inset.calc)
3869      {
3870         if (ax) *ax = x;
3871         if (ay) *ay = y;
3872         return;
3873      }
3874    if (ax) *ax = x - cw->client_inset.l;
3875    if (ay) *ay = y - cw->client_inset.t;
3876 }
3877
3878 E_API void
3879 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3880 {
3881    API_ENTRY;
3882    if (!cw->client_inset.calc)
3883      {
3884         if (ax) *ax = x;
3885         if (ay) *ay = y;
3886         return;
3887      }
3888    if (ax) *ax = x + cw->client_inset.l;
3889    if (ay) *ay = y + cw->client_inset.t;
3890 }
3891
3892 E_API void
3893 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3894 {
3895    API_ENTRY;
3896    if (!cw->client_inset.calc)
3897      {
3898         if (aw) *aw = w;
3899         if (ah) *ah = h;
3900         return;
3901      }
3902    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
3903    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
3904 }
3905
3906 E_API void
3907 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3908 {
3909    API_ENTRY;
3910    if (!cw->client_inset.calc)
3911      {
3912         if (aw) *aw = w;
3913         if (ah) *ah = h;
3914         return;
3915      }
3916    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
3917    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
3918 }
3919
3920 E_API E_Client *
3921 e_comp_object_client_get(Evas_Object *obj)
3922 {
3923    Evas_Object *o;
3924
3925    SOFT_ENTRY(NULL);
3926    /* FIXME: remove this when eo is used */
3927    o = evas_object_data_get(obj, "comp_smart_obj");
3928    if (o)
3929      return e_comp_object_client_get(o);
3930    return cw ? cw->ec : NULL;
3931 }
3932
3933 EINTERN void
3934 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3935 {
3936    API_ENTRY;
3937    if (cw->frame_extends)
3938      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
3939    else
3940      {
3941         if (x) *x = 0;
3942         if (y) *y = 0;
3943         if (w) *w  = cw->ec->w;
3944         if (h) *h  = cw->ec->h;
3945      }
3946 }
3947
3948 EINTERN E_Zone *
3949 e_comp_object_util_zone_get(Evas_Object *obj)
3950 {
3951    E_Zone *zone = NULL;
3952
3953    SOFT_ENTRY(NULL);
3954    if (cw)
3955      zone = e_comp_zone_find_by_ec(cw->ec);
3956    if (!zone)
3957      {
3958         int x, y;
3959
3960         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3961         zone = e_comp_zone_xy_get(x, y);
3962      }
3963    return zone;
3964 }
3965
3966 EINTERN void
3967 e_comp_object_util_center(Evas_Object *obj)
3968 {
3969    int x, y, w, h, ow, oh;
3970    E_Zone *zone;
3971
3972    SOFT_ENTRY();
3973
3974    zone = e_comp_object_util_zone_get(obj);
3975    EINA_SAFETY_ON_NULL_RETURN(zone);
3976    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
3977    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3978      ow = cw->ec->w, oh = cw->ec->h;
3979    else
3980      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3981    x = x + (w - ow) / 2;
3982    y = y + (h - oh) / 2;
3983    evas_object_move(obj, x, y);
3984 }
3985
3986 EINTERN void
3987 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
3988 {
3989    int x, y, w, h, ow, oh;
3990
3991    SOFT_ENTRY();
3992    EINA_SAFETY_ON_NULL_RETURN(on);
3993    evas_object_geometry_get(on, &x, &y, &w, &h);
3994    if (cw && (cw->ec->changes.size || cw->ec->new_client))
3995      ow = cw->ec->w, oh = cw->ec->h;
3996    else
3997      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3998    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
3999 }
4000
4001 EINTERN void
4002 e_comp_object_util_fullscreen(Evas_Object *obj)
4003 {
4004    SOFT_ENTRY();
4005
4006    if (cw)
4007      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
4008    else
4009      {
4010         evas_object_move(obj, 0, 0);
4011         evas_object_resize(obj, e_comp->w, e_comp->h);
4012      }
4013 }
4014
4015 EINTERN void
4016 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
4017 {
4018    E_Zone *zone;
4019    int zx, zy, zw, zh;
4020    int ow, oh;
4021    SOFT_ENTRY();
4022
4023    if (cw)
4024      ow = cw->w, oh = cw->h;
4025    else
4026      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
4027    zone = e_comp_object_util_zone_get(obj);
4028    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
4029    if (x) *x = zx + (zw - ow) / 2;
4030    if (y) *y = zy + (zh - oh) / 2;
4031 }
4032
4033 EINTERN void
4034 e_comp_object_input_objs_del(Evas_Object *obj)
4035 {
4036    API_ENTRY;
4037    E_Input_Rect_Data *input_rect_data;
4038    E_Input_Rect_Smart_Data *input_rect_sd;
4039
4040    if (!cw->input_obj)
4041      return;
4042
4043    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4044    if (!input_rect_sd) return;
4045
4046    EINA_LIST_FREE(input_rect_sd->input_rect_data_list, input_rect_data)
4047      {
4048         if (input_rect_data->obj)
4049           {
4050              evas_object_smart_member_del(input_rect_data->obj);
4051              E_FREE_FUNC(input_rect_data->obj, evas_object_del);
4052           }
4053         E_FREE(input_rect_data);
4054      }
4055 }
4056
4057 E_API void
4058 e_comp_object_input_area_set(Evas_Object *obj, int x, int y, int w, int h)
4059 {
4060    API_ENTRY;
4061    E_Input_Rect_Data *input_rect_data = NULL;
4062    E_Input_Rect_Smart_Data *input_rect_sd;
4063    int client_w, client_h;
4064
4065    if (cw->ec->client.w)
4066      client_w = cw->ec->client.w;
4067    else
4068      client_w = cw->ec->w;
4069
4070    if (cw->ec->client.h)
4071      client_h = cw->ec->client.h;
4072    else
4073      client_h = cw->ec->h;
4074
4075    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, client_w, client_h);
4076
4077    if (!cw->input_obj)
4078      {
4079         _e_comp_input_obj_smart_init();
4080         cw->input_obj = evas_object_smart_add(e_comp->evas, _e_comp_input_obj_smart);
4081         evas_object_smart_member_add(cw->input_obj, cw->smart_obj);
4082         input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4083
4084         if (input_rect_sd)
4085           input_rect_sd->cw = cw;
4086      }
4087
4088    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4089    if (input_rect_sd)
4090      {
4091         input_rect_data = E_NEW(E_Input_Rect_Data, 1);
4092         if (input_rect_data)
4093           {
4094              EINA_RECTANGLE_SET(&input_rect_data->rect, x, y, w, h);
4095              input_rect_sd->input_rect_data_list = eina_list_append(input_rect_sd->input_rect_data_list, input_rect_data);
4096           }
4097      }
4098
4099    if ((input_rect_data) &&
4100        (x || y || (w != cw->ec->client.w) || (h != cw->ec->client.h)))
4101      {
4102         input_rect_data->obj = evas_object_rectangle_add(e_comp->evas);
4103         evas_object_name_set(input_rect_data->obj, "cw->input_obj");
4104         evas_object_color_set(input_rect_data->obj, 0, 0, 0, 0);
4105         evas_object_clip_set(input_rect_data->obj, cw->clip);
4106         evas_object_smart_member_add(input_rect_data->obj, cw->input_obj);
4107         evas_object_geometry_set(input_rect_data->obj,
4108           cw->ec->client.x + (!!cw->frame_object * cw->client_inset.l) + x,
4109           cw->ec->client.y + (!!cw->frame_object * cw->client_inset.t) + y, w, h);
4110         evas_object_pass_events_set(cw->default_input_obj, 1);
4111         evas_object_pass_events_set(cw->obj, 1);
4112         if (cw->visible)
4113           {
4114              evas_object_show(input_rect_data->obj);
4115              evas_object_show(cw->input_obj);
4116           }
4117      }
4118    else
4119      {
4120         evas_object_smart_member_del(cw->input_obj);
4121         E_FREE_FUNC(cw->input_obj, evas_object_del);
4122         evas_object_pass_events_set(cw->default_input_obj, 0);
4123         evas_object_pass_events_set(cw->obj, 0);
4124      }
4125 }
4126
4127 E_API void
4128 e_comp_object_input_rect_get(Evas_Object *obj, Eina_List **list)
4129 {
4130    API_ENTRY;
4131    E_Input_Rect_Smart_Data *input_rect_sd;
4132    E_Input_Rect_Data *input_rect_data;
4133    Eina_List *l;
4134
4135    if (!cw->input_obj) return;
4136
4137    input_rect_sd = evas_object_smart_data_get(cw->input_obj);
4138    if (input_rect_sd)
4139      {
4140         EINA_LIST_FOREACH(input_rect_sd->input_rect_data_list, l, input_rect_data)
4141           {
4142              *list = eina_list_append(*list, &input_rect_data->rect);
4143           }
4144      }
4145 }
4146
4147 EINTERN void
4148 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
4149 {
4150    API_ENTRY;
4151    if (l) *l = cw->client_inset.l;
4152    if (r) *r = cw->client_inset.r;
4153    if (t) *t = cw->client_inset.t;
4154    if (b) *b = cw->client_inset.b;
4155 }
4156
4157 /* set geometry for CSD */
4158 EINTERN void
4159 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
4160 {
4161    Eina_Bool calc;
4162    int tx, ty, tw, th;
4163
4164    API_ENTRY;
4165    if (cw->frame_object)
4166      CRI("ACK! ec:%p", cw->ec);
4167    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
4168        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
4169    calc = cw->client_inset.calc;
4170    cw->client_inset.calc = l || r || t || b;
4171    eina_stringshare_replace(&cw->frame_theme, "borderless");
4172    if (cw->client_inset.calc)
4173      {
4174         tw = cw->ec->w + ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4175         th = cw->ec->h + ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4176         e_client_size_set(cw->ec, tw, th);
4177      }
4178    else if (cw->ec->maximized || cw->ec->fullscreen)
4179      {
4180         cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
4181         cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
4182      }
4183    if (!cw->ec->new_client)
4184      {
4185         if (calc && cw->client_inset.calc)
4186           {
4187              tx = cw->ec->x - (l - cw->client_inset.l);
4188              ty = cw->ec->y - (t - cw->client_inset.t);
4189              e_client_pos_set(cw->ec, tx, ty);
4190           }
4191         cw->ec->changes.pos = cw->ec->changes.size = 1;
4192         EC_CHANGED(cw->ec);
4193      }
4194    cw->client_inset.l = l;
4195    cw->client_inset.r = r;
4196    cw->client_inset.t = t;
4197    cw->client_inset.b = b;
4198 }
4199
4200 EINTERN Eina_Bool
4201 e_comp_object_frame_allowed(Evas_Object *obj)
4202 {
4203    API_ENTRY EINA_FALSE;
4204    return (cw->frame_object || (!cw->client_inset.calc));
4205 }
4206
4207 EINTERN Eina_Bool
4208 e_comp_object_frame_exists(Evas_Object *obj)
4209 {
4210    API_ENTRY EINA_FALSE;
4211    return !!cw->frame_object;
4212 }
4213
4214 EINTERN Eina_Bool
4215 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
4216 {
4217    Evas_Object *o, *pbg;
4218    char buf[4096];
4219    int ok;
4220    Eina_Stringshare *theme;
4221
4222    API_ENTRY EINA_FALSE;
4223
4224    if (!e_util_strcmp(cw->frame_theme, name))
4225     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
4226    if (!e_util_strcmp(name, "COMP_RESHADOW"))
4227      return _e_comp_object_shadow_setup(cw);
4228    pbg = cw->frame_object;
4229    theme = eina_stringshare_add(name);
4230
4231    if (cw->frame_object)
4232      {
4233         int w, h;
4234
4235         w = cw->ec->w, h = cw->ec->h;
4236         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
4237         if ((cw->ec->w != w) || (cw->ec->h != h))
4238           {
4239              cw->ec->changes.size = 1;
4240              EC_CHANGED(cw->ec);
4241           }
4242         E_FREE_FUNC(cw->frame_object, evas_object_del);
4243         if (!name) goto reshadow;
4244      }
4245    o = edje_object_add(e_comp->evas);
4246    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
4247    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4248    if ((!ok) && (!e_util_strcmp(name, "borderless")))
4249      {
4250         cw->frame_object = NULL;
4251         evas_object_del(o);
4252         eina_stringshare_del(cw->frame_theme);
4253         cw->frame_theme = theme;
4254         goto reshadow;
4255      }
4256    if (!ok)
4257      {
4258         if (theme != e_config->theme_default_border_style)
4259           {
4260              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
4261              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
4262           }
4263         if (!ok)
4264           {
4265              ok = e_theme_edje_object_set(o, "base/theme/border",
4266                                           "e/widgets/border/default/border");
4267              if (ok && (theme == e_config->theme_default_border_style))
4268                {
4269                   /* Reset default border style to default */
4270                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
4271                   e_config_save_queue();
4272                }
4273           }
4274      }
4275
4276    if (ok)
4277      {
4278         cw->frame_object = o;
4279         eina_stringshare_del(cw->frame_theme);
4280         cw->frame_theme = theme;
4281         evas_object_name_set(o, "cw->frame_object");
4282
4283         if (cw->frame_name)
4284           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
4285
4286         if (!pbg)
4287           {
4288              cw->ec->changes.icon = 1;
4289              EC_CHANGED(cw->ec);
4290           }
4291      }
4292    else
4293      {
4294         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
4295         evas_object_del(o);
4296      }
4297 reshadow:
4298    if (cw->shobj)
4299      _e_comp_object_shadow_setup(cw);
4300    do
4301      {
4302         int old_x, old_y, new_x = 0, new_y = 0;
4303
4304         old_x = cw->x, old_y = cw->y;
4305
4306         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
4307         if (pbg)
4308           new_x = cw->ec->x, new_y = cw->ec->y;
4309         else if (cw->ec->placed || (!cw->ec->new_client))
4310           {
4311              /* if no previous frame:
4312               * - reapply client_inset
4313               * - clamp to zone
4314               */
4315              int x, y;
4316
4317              if (cw->ec->changes.size)
4318                {
4319                   x = cw->ec->x;
4320                   y = cw->ec->y;
4321                }
4322              else
4323                {
4324                   E_Zone *zone;
4325                   zone = e_comp_zone_find_by_ec(cw->ec);
4326                   if (!zone) break;
4327
4328                   x = cw->ec->client.x, y = cw->ec->client.y;
4329                   x = MAX(zone->x, cw->ec->client.x - cw->client_inset.l);
4330                   y = MAX(zone->y, cw->ec->client.y - cw->client_inset.t);
4331                }
4332              new_x = x, new_y = y;
4333           }
4334
4335         if (old_x != new_x || old_y != new_y)
4336           {
4337              /* this guarantees that we won't get blocked by the NOP check in the interceptor */
4338              cw->y = cw->x = -99999;
4339              evas_object_move(obj, new_x, new_y);
4340           }
4341      } while (0);
4342
4343    if (cw->ec->maximized)
4344      {
4345         cw->ec->changes.need_maximize = 1;
4346         EC_CHANGED(cw->ec);
4347      }
4348    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
4349    if (cw->frame_object)
4350      {
4351         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
4352      }
4353    else
4354      cw->frame_extends = 0;
4355    evas_object_del(pbg);
4356    return EINA_TRUE;
4357 }
4358
4359 E_API void
4360 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
4361 {
4362    E_Comp_Object_Mover *prov;
4363
4364    API_ENTRY;
4365    //INF("EMIT %p: %s %s", cw->ec, sig, src);
4366    edje_object_signal_emit(cw->shobj, sig, src);
4367    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
4368    if ((cw->ec->override && e_comp_config_get()->match.disable_overrides) ||
4369        ((!cw->ec->override) && e_comp_config_get()->match.disable_borders))
4370      return;
4371    /* start with highest priority callback first */
4372    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
4373      {
4374         if (!e_util_glob_match(sig, prov->sig)) continue;
4375         if (prov->func(prov->data, obj, sig)) break;
4376      }
4377 }
4378
4379 E_API void
4380 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4381 {
4382    /* FIXME: at some point I guess this should use eo to inherit
4383     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
4384     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
4385     */
4386    API_ENTRY;
4387    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
4388 }
4389
4390 E_API void
4391 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
4392 {
4393    API_ENTRY;
4394    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
4395 }
4396
4397 E_API void
4398 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
4399 {
4400    API_ENTRY;
4401    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
4402 }
4403
4404 E_API void
4405 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
4406 {
4407    int tw, th;
4408    Eina_Rectangle rect;
4409    API_ENTRY;
4410
4411    if (cw->ec->input_only || (!cw->updates)) return;
4412    if (cw->nocomp) return;
4413    rect.x = x, rect.y = y;
4414    rect.w = w, rect.h = h;
4415    evas_object_smart_callback_call(obj, "damage", &rect);
4416
4417    if (e_comp_is_on_overlay(cw->ec))
4418      {
4419         /* It will not set hwc_need_update value if E modules already cleanup pixmap
4420         * resource on the E_COMP_WL_HOOK_BUFFER_CHANGE hook function. It means that
4421         * E module attempts to block screen update due to the particular policy.
4422         */
4423         if (e_pixmap_resource_get(cw->ec->pixmap))
4424           cw->hwc_need_update = EINA_TRUE;
4425      }
4426
4427    /* ignore overdraw */
4428    if (cw->updates_full)
4429      {
4430         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
4431         e_comp_object_render_update_add(obj);
4432
4433         if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4434           evas_object_show(cw->smart_obj);
4435
4436         return;
4437      }
4438    /* clip rect to client surface */
4439    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
4440    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
4441    /* if rect is the total size of the client after clip, clear the updates
4442     * since this is guaranteed to be the whole region anyway
4443     */
4444    eina_tiler_area_size_get(cw->updates, &tw, &th);
4445    if ((w > tw) || (h > th))
4446      {
4447         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
4448         eina_tiler_clear(cw->updates);
4449         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
4450         x = 0, y = 0;
4451         tw = cw->ec->client.w, th = cw->ec->client.h;
4452      }
4453    if ((!x) && (!y) && (w == tw) && (h == th))
4454      {
4455         eina_tiler_clear(cw->updates);
4456         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
4457         cw->updates_full = 1;
4458         cw->update_count = 0;
4459      }
4460    cw->update_count++;
4461    if (cw->update_count > UPDATE_MAX)
4462      {
4463         /* this is going to get really dumb, so just update the whole thing */
4464         eina_tiler_clear(cw->updates);
4465         cw->update_count = cw->updates_full = 1;
4466         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
4467         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
4468      }
4469    else
4470      {
4471         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
4472         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
4473      }
4474    cw->updates_exist = 1;
4475    e_comp_object_render_update_add(obj);
4476
4477    if ((cw->ec->visible) && (!evas_object_visible_get(cw->smart_obj)) && (!cw->ec->iconic))
4478      evas_object_show(cw->smart_obj);
4479 }
4480
4481 EINTERN Eina_Bool
4482 e_comp_object_damage_exists(Evas_Object *obj)
4483 {
4484    API_ENTRY EINA_FALSE;
4485    return cw->updates_exist;
4486 }
4487
4488 EINTERN void
4489 e_comp_object_render_update_add(Evas_Object *obj)
4490 {
4491    API_ENTRY;
4492
4493    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
4494    if (cw->render_update_lock.lock) return;
4495    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
4496    if (!cw->update)
4497      {
4498         cw->update = 1;
4499         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
4500      }
4501    e_comp_render_queue();
4502 }
4503
4504 EINTERN void
4505 e_comp_object_render_update_del(Evas_Object *obj)
4506 {
4507    API_ENTRY;
4508
4509    if (cw->ec->input_only || (!cw->updates)) return;
4510    if (!cw->update) return;
4511    cw->update = 0;
4512    /* this gets called during comp animating to clear the update flag */
4513    if (e_comp->grabbed) return;
4514    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
4515    if (!e_comp->updates)
4516      {
4517         E_FREE_FUNC(e_comp->update_job, ecore_job_del);
4518         if (e_comp->render_animator)
4519           ecore_animator_freeze(e_comp->render_animator);
4520      }
4521 }
4522
4523 EINTERN void
4524 e_comp_object_shape_apply(Evas_Object *obj)
4525 {
4526    Eina_List *l;
4527    Evas_Object *o;
4528    unsigned int i, *pix, *p;
4529    int w, h, px, py;
4530
4531    API_ENTRY;
4532    if (!cw->ec) return; //NYI
4533    if (cw->external_content) return;
4534    if (cw->ec->shaped)
4535      {
4536         if ((cw->ec->shape_rects_num >= 1) &&
4537             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
4538            return;
4539      }
4540    if (cw->native)
4541      {
4542         ERR("BUGGER: shape with native surface? cw=%p", cw);
4543         return;
4544      }
4545    evas_object_image_size_get(cw->obj, &w, &h);
4546    if ((w < 1) || (h < 1)) return;
4547
4548    if (cw->ec->shaped)
4549      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4550    _e_comp_object_alpha_set(cw);
4551    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4552       evas_object_image_alpha_set(o, 1);
4553
4554    p = pix = evas_object_image_data_get(cw->obj, 1);
4555    if (!pix)
4556      {
4557         evas_object_image_data_set(cw->obj, pix);
4558         return;
4559      }
4560    if (cw->ec->shaped)
4561      {
4562         unsigned char *spix, *sp;
4563
4564         spix = calloc(w * h, sizeof(unsigned char));
4565         if (!spix) return;
4566         for (i = 0; i < cw->ec->shape_rects_num; i++)
4567           {
4568              int rx, ry, rw, rh;
4569
4570              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
4571              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
4572              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
4573              sp = spix + (w * ry) + rx;
4574              for (py = 0; py < rh; py++)
4575                {
4576                   for (px = 0; px < rw; px++)
4577                     {
4578                        *sp = 0xff; sp++;
4579                     }
4580                   sp += w - rw;
4581                }
4582           }
4583         sp = spix;
4584         for (py = 0; py < h; py++)
4585           {
4586              for (px = 0; px < w; px++)
4587                {
4588                   unsigned int mask, imask;
4589
4590                   mask = ((unsigned int)(*sp)) << 24;
4591                   imask = mask >> 8;
4592                   imask |= imask >> 8;
4593                   imask |= imask >> 8;
4594                   *p = mask | (*p & imask);
4595                   //if (*sp) *p = 0xff000000 | *p;
4596                   //else *p = 0x00000000;
4597                   sp++;
4598                   p++;
4599                }
4600           }
4601         free(spix);
4602      }
4603    else
4604       {
4605          for (py = 0; py < h; py++)
4606            {
4607               for (px = 0; px < w; px++)
4608                 *p |= 0xff000000;
4609            }
4610       }
4611    evas_object_image_data_set(cw->obj, pix);
4612    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
4613    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4614      {
4615         evas_object_image_data_set(o, pix);
4616         evas_object_image_data_update_add(o, 0, 0, w, h);
4617      }
4618 // don't need to fix alpha chanel as blending
4619 // should be totally off here regardless of
4620 // alpha channel content
4621 }
4622
4623 static void
4624 _e_comp_object_clear(E_Comp_Object *cw)
4625 {
4626    Eina_List *l;
4627    Evas_Object *o;
4628
4629    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4630
4631    if (cw->render_update_lock.lock) return;
4632
4633    if (cw->ec->pixmap)
4634      e_pixmap_clear(cw->ec->pixmap);
4635    if (cw->native)
4636      _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4637    evas_object_image_size_set(cw->obj, 1, 1);
4638    evas_object_image_data_set(cw->obj, NULL);
4639    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4640      {
4641         evas_object_image_size_set(o, 1, 1);
4642         evas_object_image_data_set(o, NULL);
4643      }
4644    cw->native = 0;
4645    e_comp_object_render_update_del(cw->smart_obj);
4646 }
4647
4648 static Eina_Bool
4649 _e_comp_object_transparent_set(Evas_Object *obj, Eina_Bool set)
4650 {
4651     int r, g, b, a;
4652
4653     API_ENTRY EINA_FALSE;
4654
4655     if (cw->transparent.set == set)
4656        return EINA_TRUE;
4657
4658     if (set)
4659       {
4660          evas_object_color_get(obj, &r, &g, &b, &a);
4661
4662          cw->transparent.user_r = r;
4663          cw->transparent.user_g = g;
4664          cw->transparent.user_b = b;
4665          cw->transparent.user_a = a;
4666
4667          cw->transparent.setting = EINA_TRUE;
4668          evas_object_color_set(obj, 0, 0, 0, 0);
4669          cw->transparent.setting = EINA_FALSE;
4670
4671          ELOGF("COMP", "Transparent enabled user_color(%d,%d,%d,%d)",
4672                cw->ec,
4673                cw->transparent.user_r,
4674                cw->transparent.user_g,
4675                cw->transparent.user_b,
4676                cw->transparent.user_a);
4677
4678          cw->transparent.set = EINA_TRUE;
4679       }
4680     else
4681       {
4682          cw->transparent.set = EINA_FALSE;
4683
4684          evas_object_color_set(obj,
4685                                cw->transparent.user_r,
4686                                cw->transparent.user_g,
4687                                cw->transparent.user_b,
4688                                cw->transparent.user_a);
4689
4690          ELOGF("COMP", "Transparent disabled user_color(%d,%d,%d,%d)",
4691                cw->ec,
4692                cw->transparent.user_r,
4693                cw->transparent.user_g,
4694                cw->transparent.user_b,
4695                cw->transparent.user_a);
4696       }
4697
4698    return EINA_TRUE;
4699 }
4700
4701 /* helper function to simplify toggling of redirection for display servers which support it */
4702 EINTERN void
4703 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
4704 {
4705    API_ENTRY;
4706
4707    set = !!set;
4708    if (cw->redirected == set) return;
4709    cw->redirected = set;
4710    if (cw->external_content) return;
4711
4712    e_comp_object_map_update(obj);
4713
4714    if (set)
4715      {
4716         if (cw->updates_exist)
4717           e_comp_object_render_update_add(obj);
4718         else
4719           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4720
4721         _e_comp_object_transparent_set(obj, EINA_FALSE);
4722         evas_object_smart_callback_call(obj, "redirected", NULL);
4723      }
4724    else
4725      {
4726         _e_comp_object_clear(cw);
4727         _e_comp_object_transparent_set(obj, EINA_TRUE);
4728         evas_object_smart_callback_call(obj, "unredirected", NULL);
4729      }
4730 }
4731
4732 static void
4733 _e_comp_object_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
4734 {
4735    E_Comp_Object *cw;
4736    cw = container_of(listener, E_Comp_Object, buffer_destroy_listener);
4737
4738    if (cw->buffer_destroy_listener.notify)
4739      {
4740         cw->buffer_destroy_listener.notify = NULL;
4741         wl_list_remove(&cw->buffer_destroy_listener.link);
4742      }
4743
4744    if (e_object_is_del(E_OBJECT(cw->ec)))
4745      {
4746         if (!e_object_delay_del_ref_get(E_OBJECT(cw->ec)))
4747           return;
4748      }
4749    else
4750      {
4751         /* if it's current displaying buffer, do not remove its content */
4752         if (!evas_object_visible_get(cw->ec->frame))
4753           _e_comp_object_native_surface_set(cw, NULL, EINA_TRUE);
4754      }
4755 }
4756
4757 static void
4758 _e_comp_object_native_surface_set(E_Comp_Object *cw, Evas_Native_Surface *ns, Eina_Bool with_mirror)
4759 {
4760    Eina_List *l;
4761    Evas_Object *o;
4762
4763    if (cw->buffer_destroy_listener.notify)
4764      {
4765         wl_list_remove(&cw->buffer_destroy_listener.link);
4766         cw->buffer_destroy_listener.notify = NULL;
4767      }
4768
4769    if (cw->tbm_surface)
4770      {
4771         tbm_surface_internal_unref(cw->tbm_surface);
4772         cw->tbm_surface = NULL;
4773      }
4774
4775    if (ns)
4776      {
4777         if ((ns->type == EVAS_NATIVE_SURFACE_WL) && (ns->data.wl.legacy_buffer))
4778           {
4779              cw->buffer_destroy_listener.notify = _e_comp_object_cb_buffer_destroy;
4780              wl_resource_add_destroy_listener((struct wl_resource *)ns->data.wl.legacy_buffer, &cw->buffer_destroy_listener);
4781           }
4782         else if ((ns->type == EVAS_NATIVE_SURFACE_TBM) && (ns->data.tbm.buffer))
4783           {
4784              tbm_surface_internal_ref(ns->data.tbm.buffer);
4785              cw->tbm_surface = ns->data.tbm.buffer;
4786           }
4787      }
4788
4789    TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4790    evas_object_image_native_surface_set(cw->obj, ns);
4791    TRACE_DS_END();
4792    if (with_mirror)
4793      {
4794         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4795           {
4796              evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
4797              TRACE_DS_BEGIN(NATIVE_SURFACE_SET);
4798              evas_object_image_native_surface_set(o, ns);
4799              TRACE_DS_END();
4800           }
4801      }
4802 }
4803
4804 EINTERN void
4805 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
4806 {
4807    Evas_Native_Surface ns;
4808
4809    API_ENTRY;
4810    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
4811    if (cw->ec->input_only) return;
4812    if (cw->external_content) return;
4813    if (cw->render_update_lock.lock) return;
4814    set = !!set;
4815
4816    memset(&ns, 0, sizeof(Evas_Native_Surface));
4817
4818    if (set)
4819      {
4820         /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
4821         set = (!cw->ec->shaped);
4822         if (set)
4823           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4824      }
4825    cw->native = set;
4826
4827    _e_comp_object_native_surface_set(cw, set && (!cw->blanked) ? (cw->ns ? cw->ns : &ns) : NULL, EINA_TRUE);
4828 }
4829
4830 EINTERN void
4831 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4832 {
4833    API_ENTRY;
4834    if (cw->ec->input_only) return;
4835    E_FREE(cw->ns);
4836    if (ns)
4837      cw->ns = (Evas_Native_Surface*)eina_memdup((unsigned char*)ns, sizeof(Evas_Native_Surface), 0);
4838    _e_comp_object_alpha_set(cw);
4839    if (cw->native)
4840      e_comp_object_native_surface_set(obj, cw->native);
4841    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4842 }
4843
4844 EINTERN void
4845 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4846 {
4847    API_ENTRY;
4848
4849    set = !!set;
4850
4851    if (cw->blanked == set) return;
4852    cw->blanked = set;
4853    _e_comp_object_alpha_set(cw);
4854    if (set)
4855      {
4856         _e_comp_object_native_surface_set(cw, NULL, EINA_FALSE);
4857         evas_object_image_data_set(cw->obj, NULL);
4858         return;
4859      }
4860    if (cw->native)
4861      e_comp_object_native_surface_set(obj, 1);
4862    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4863 }
4864
4865 static void
4866 _e_comp_object_damage_trace_rect_set(Evas_Object *obj, Eina_Rectangle *origin, int dmg_x, int dmg_y, int dmg_w, int dmg_h)
4867 {
4868    Evas_Object *o;
4869    int obj_x, obj_y;
4870
4871    if (!_damage_trace) return;
4872
4873    API_ENTRY;
4874
4875    if (!evas_object_visible_get(cw->obj)) return;
4876
4877    evas_object_geometry_get(cw->obj, &obj_x, &obj_y, NULL, NULL);
4878
4879    o = evas_object_rectangle_add(e_comp->evas);
4880    evas_object_layer_set(o, E_LAYER_MAX);
4881    evas_object_name_set(o, "damage_trace");
4882    evas_object_move(o, dmg_x + obj_x, dmg_y + obj_y);
4883    evas_object_resize(o, dmg_w, dmg_h);
4884    evas_object_color_set(o, 0, 128, 0, 128);
4885    evas_object_render_op_set(o, EVAS_RENDER_BLEND);
4886    evas_object_pass_events_set(o, EINA_TRUE);
4887    evas_object_show(o);
4888
4889    ELOGF("COMP", "add damage(%dx%d+%d+%d) origin(%dx%d+%d+%d)",
4890          cw->ec,
4891          dmg_w, dmg_h, dmg_x, dmg_y,
4892          origin->w, origin->h, origin->x, origin->y);
4893
4894    _damage_trace_objs = eina_list_append(_damage_trace_objs, o);
4895 }
4896
4897 /* mark an object as dirty and setup damages */
4898 E_API void
4899 e_comp_object_dirty(Evas_Object *obj)
4900 {
4901    Eina_Iterator *it;
4902    Eina_Rectangle *rect;
4903    Eina_List *ll;
4904    Evas_Object *o;
4905    int w, h, tw, th;
4906    Eina_Bool dirty, visible;
4907    E_Map *m = NULL;
4908
4909    API_ENTRY;
4910    if (cw->external_content) return;
4911    if (!cw->redirected) return;
4912    if (cw->render_update_lock.lock)
4913      {
4914         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
4915         return;
4916      }
4917    /* only actually dirty if pixmap is available */
4918    if (!e_pixmap_resource_get(cw->ec->pixmap))
4919      {
4920         // e_pixmap_size_get returns last attached buffer size
4921         // eventhough it is destroyed
4922         ERR("ERROR NO PIXMAP FOR ec:%p", cw->ec);
4923         return;
4924      }
4925    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4926    visible = cw->visible;
4927    if (!dirty) w = h = 1;
4928    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4929    if (!dirty)
4930      evas_object_image_data_set(cw->obj, NULL);
4931    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
4932    evas_object_image_size_set(cw->obj, tw, th);
4933    if (cw->mask.obj) evas_object_resize(cw->mask.obj, w, h);
4934    if (cw->pending_updates)
4935      eina_tiler_area_size_set(cw->pending_updates, w, h);
4936    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4937      {
4938         evas_object_image_pixels_dirty_set(o, dirty);
4939         if (!dirty)
4940           evas_object_image_data_set(o, NULL);
4941         evas_object_image_size_set(o, tw, th);
4942         visible |= evas_object_visible_get(o);
4943      }
4944    if (!dirty)
4945      {
4946         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4947         return;
4948      }
4949
4950    e_comp_object_native_surface_set(obj, 1);
4951
4952    m = _e_comp_object_map_damage_transform_get(cw->ec);
4953    it = eina_tiler_iterator_new(cw->updates);
4954    EINA_ITERATOR_FOREACH(it, rect)
4955      {
4956         /* evas converts damage according to rotation of ecore_evas in damage_region_set
4957          * of evas engine and doesn't convert damage according to evas_map.
4958          * so damage of evas_object_image use surface coordinate.
4959          */
4960         if (m)
4961           {
4962              int damage_x, damage_y, damage_w, damage_h;
4963
4964              _e_comp_object_map_damage_transform_rect(cw->ec, m, rect->x, rect->y, rect->w, rect->h,
4965                                                       &damage_x, &damage_y, &damage_w, &damage_h);
4966              evas_object_image_data_update_add(cw->obj, damage_x, damage_y, damage_w, damage_h);
4967              _e_comp_object_damage_trace_rect_set(obj, rect, damage_x, damage_y, damage_w, damage_h);
4968           }
4969         else
4970           {
4971              evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4972              _e_comp_object_damage_trace_rect_set(obj, rect, rect->x, rect->y, rect->w, rect->h);
4973           }
4974
4975         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4976           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4977         if (cw->pending_updates)
4978           eina_tiler_rect_add(cw->pending_updates, rect);
4979      }
4980    eina_iterator_free(it);
4981    if (m) e_map_free(m);
4982    if (cw->pending_updates)
4983      eina_tiler_clear(cw->updates);
4984    else
4985      {
4986         cw->pending_updates = cw->updates;
4987         cw->updates = eina_tiler_new(w, h);
4988         eina_tiler_tile_size_set(cw->updates, 1, 1);
4989      }
4990    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4991    evas_object_smart_callback_call(obj, "dirty", NULL);
4992    if (cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4993    /* force render if main object is hidden but mirrors are visible */
4994    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4995    e_comp_object_render(obj);
4996 }
4997
4998 E_API Eina_Bool
4999 e_comp_object_render(Evas_Object *obj)
5000 {
5001    Eina_List *l;
5002    Evas_Object *o;
5003    int pw, ph;
5004    unsigned int *pix;
5005
5006    API_ENTRY EINA_FALSE;
5007
5008    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5009    if (cw->ec->input_only) return EINA_TRUE;
5010    if (cw->external_content) return EINA_TRUE;
5011    if (cw->native) return EINA_FALSE;
5012    /* if comp object is not redirected state, comp object should not be set by newly committed data
5013       because image size of comp object is 1x1 and it should not be shown on canvas */
5014    if (!cw->redirected) return EINA_TRUE;
5015    if (cw->render_update_lock.lock)
5016      {
5017         ELOGF("COMP", "Render update locked:%d", cw->ec, cw->render_update_lock.lock);
5018         return EINA_TRUE;
5019      }
5020    e_comp_object_render_update_del(obj);
5021    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
5022
5023    if (!cw->pending_updates)
5024      {
5025         WRN("RENDER [%p]: NO RECTS!", cw->ec);
5026         evas_object_image_data_set(cw->obj, NULL);
5027         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5028           evas_object_image_data_set(o, NULL);
5029         return EINA_FALSE;
5030      }
5031
5032    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
5033
5034    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
5035
5036    pix = e_pixmap_image_data_get(cw->ec->pixmap);
5037    if (!pix)
5038      {
5039         e_pixmap_image_refresh(cw->ec->pixmap);
5040         pix = e_pixmap_image_data_get(cw->ec->pixmap);
5041      }
5042
5043    if ((pix) && ((!cw->blanked) || (cw->obj_mirror)))
5044      e_pixmap_image_data_ref(cw->ec->pixmap);
5045
5046    /* set pixel data */
5047    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
5048    _e_comp_object_alpha_set(cw);
5049    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
5050      {
5051         evas_object_image_data_set(o, pix);
5052         evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5053         evas_object_image_pixels_dirty_set(o, EINA_FALSE);
5054      }
5055
5056    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
5057
5058    e_comp_client_post_update_add(cw->ec);
5059
5060    return EINA_TRUE;
5061 }
5062
5063 /* create a duplicate of an evas object */
5064 E_API Evas_Object *
5065 e_comp_object_util_mirror_add(Evas_Object *obj)
5066 {
5067    Evas_Object *o;
5068    int w, h, tw, th;
5069    unsigned int *pix = NULL;
5070    Eina_Bool argb = EINA_FALSE;
5071
5072    SOFT_ENTRY(NULL);
5073
5074    if (!cw)
5075      cw = evas_object_data_get(obj, "comp_mirror");
5076    if (!cw)
5077      {
5078         o = evas_object_image_filled_add(evas_object_evas_get(obj));
5079         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5080         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5081         evas_object_image_alpha_set(o, 1);
5082         evas_object_image_source_set(o, obj);
5083         return o;
5084      }
5085    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
5086    if (cw->external_content)
5087      {
5088         ERR("%p of client %p is external content.", obj, cw->ec);
5089         return NULL;
5090      }
5091    o = evas_object_image_filled_add(evas_object_evas_get(obj));
5092    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
5093    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
5094    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
5095    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
5096    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
5097    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
5098    evas_object_data_set(o, "E_Client_Mirror", cw->ec);
5099    evas_object_data_set(o, "comp_mirror", cw);
5100
5101    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
5102    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5103
5104    evas_object_image_size_set(o, tw, th);
5105
5106    if (cw->ec->shaped)
5107      pix = evas_object_image_data_get(cw->obj, 0);
5108    else
5109      {
5110         if (cw->native)
5111           {
5112              if (cw->ns)
5113                evas_object_image_native_surface_set(o, cw->ns);
5114              else
5115                {
5116                   Evas_Native_Surface ns;
5117                   memset(&ns, 0, sizeof(Evas_Native_Surface));
5118                   if (e_pixmap_native_surface_init(cw->ec->pixmap, &ns))
5119                     evas_object_image_native_surface_set(o, &ns);
5120                }
5121           }
5122         else
5123           {
5124              /* FIXME: legacy code, please refer to commit 5e6831187a1 */
5125              argb = e_pixmap_image_is_argb(cw->ec->pixmap);
5126              if ((argb) &&
5127                  (e_pixmap_image_exists(cw->ec->pixmap)))
5128                pix = e_pixmap_image_data_get(cw->ec->pixmap);
5129              else
5130                pix = evas_object_image_data_get(cw->obj, EINA_FALSE);
5131           }
5132      }
5133    if (pix)
5134      {
5135       Eina_Bool dirty;
5136
5137       dirty = evas_object_image_pixels_dirty_get(cw->obj);
5138       evas_object_image_pixels_dirty_set(o, dirty);
5139       evas_object_image_data_set(o, pix);
5140       evas_object_image_data_set(cw->obj, pix);
5141       if (dirty)
5142         evas_object_image_data_update_add(o, 0, 0, tw, th);
5143    }
5144    return o;
5145 }
5146
5147 //////////////////////////////////////////////////////
5148
5149 EINTERN Eina_Bool
5150 e_comp_object_effect_allowed_get(Evas_Object *obj)
5151 {
5152    API_ENTRY EINA_FALSE;
5153
5154    if (!cw->shobj) return EINA_FALSE;
5155    if (cw->ec->override) return !e_comp_config_get()->match.disable_overrides;
5156    return !e_comp_config_get()->match.disable_borders;
5157 }
5158
5159 /* setup an api effect for a client */
5160 E_API Eina_Bool
5161 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
5162 {
5163    char buf[4096];
5164    Eina_Stringshare *grp;
5165    E_Comp_Config *config;
5166    Eina_Bool loaded = EINA_FALSE;
5167
5168    API_ENTRY EINA_FALSE;
5169    if (!cw->shobj) return EINA_FALSE; //input window
5170
5171    if (!effect) effect = "none";
5172    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
5173
5174    config = e_comp_config_get();
5175    if ((config) && (config->effect_file))
5176      {
5177         if (edje_object_file_set(cw->effect_obj, config->effect_file, buf))
5178           {
5179              cw->effect_set = EINA_TRUE;
5180              loaded = EINA_TRUE;
5181           }
5182      }
5183
5184    if (!loaded)
5185      {
5186         edje_object_file_get(cw->effect_obj, NULL, &grp);
5187         cw->effect_set = !eina_streq(effect, "none");
5188         if (!e_util_strcmp(buf, grp)) return cw->effect_set;
5189         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5190           {
5191              snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
5192              if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
5193                if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
5194                  {
5195                     if (cw->effect_running)
5196                       {
5197                          if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5198                            return EINA_FALSE;
5199                       }
5200                     cw->effect_set = EINA_FALSE;
5201                     return cw->effect_set;
5202                  }
5203           }
5204      }
5205    if (cw->effect_running)
5206      {
5207         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
5208           return EINA_FALSE;
5209      }
5210    ELOGF("COMP", "EFFECT Set GROUP[%s]", cw->ec, buf);
5211    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
5212    if (cw->effect_clip)
5213      {
5214         evas_object_clip_unset(cw->clip);
5215         cw->effect_clip = 0;
5216      }
5217    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
5218
5219    _e_comp_object_dim_update(cw);
5220
5221    return cw->effect_set;
5222 }
5223
5224 /* set params for embryo scripts in effect */
5225 E_API void
5226 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
5227 {
5228    Edje_Message_Int_Set *msg;
5229    unsigned int x;
5230
5231    API_ENTRY;
5232    EINA_SAFETY_ON_NULL_RETURN(params);
5233    EINA_SAFETY_ON_FALSE_RETURN(count);
5234    if (!cw->effect_set) return;
5235
5236    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
5237    msg->count = (int)count;
5238    for (x = 0; x < count; x++)
5239       msg->val[x] = params[x];
5240    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
5241    edje_object_message_signal_process(cw->effect_obj);
5242 }
5243
5244 static void
5245 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
5246 {
5247    Edje_Signal_Cb end_cb;
5248    void *end_data;
5249    E_Comp_Object *cw = data;
5250
5251    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
5252    cw->effect_running = 0;
5253    if (!_e_comp_object_animating_end(cw)) return;
5254
5255    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5256      {
5257         evas_object_data_del(cw->smart_obj, "effect_running");
5258         _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_END);
5259         e_comp_visibility_calculation_set(EINA_TRUE);
5260      }
5261
5262    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
5263    if (!end_cb) return;
5264    end_data = evas_object_data_get(obj, "_e_comp.end_data");
5265    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5266    end_cb(end_data, cw->smart_obj, emission, source);
5267 }
5268
5269 /* clip effect to client's zone */
5270 EINTERN void
5271 e_comp_object_effect_clip(Evas_Object *obj)
5272 {
5273    API_ENTRY;
5274    E_Zone *zone;
5275    zone = e_comp_zone_find_by_ec(cw->ec);
5276    if (!zone) return;
5277    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
5278    if (!cw->effect_clip_able) return;
5279    evas_object_clip_set(cw->smart_obj, zone->bg_clip_object);
5280    cw->effect_clip = 1;
5281 }
5282
5283 /* unclip effect from client's zone */
5284 EINTERN void
5285 e_comp_object_effect_unclip(Evas_Object *obj)
5286 {
5287    API_ENTRY;
5288    if (!cw->effect_clip) return;
5289    evas_object_clip_unset(cw->smart_obj);
5290    cw->effect_clip = 0;
5291 }
5292
5293 /* start effect, running end_cb after */
5294 E_API Eina_Bool
5295 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
5296 {
5297    API_ENTRY EINA_FALSE;
5298    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
5299    if (!cw->effect_set) return EINA_FALSE;
5300
5301    if (cw->effect_running)
5302      {
5303         e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb"));
5304      }
5305
5306    e_comp_object_effect_clip(obj);
5307    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
5308
5309    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5310    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
5311    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
5312    evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
5313
5314    _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_START, cw->ec);
5315    _e_comp_object_event_simple(obj, E_EVENT_COMP_OBJECT_EFFECT_START);
5316
5317    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
5318    _e_comp_object_animating_begin(cw);
5319    cw->effect_running = 1;
5320    return EINA_TRUE;
5321 }
5322
5323 /* stop a currently-running effect immediately */
5324 E_API Eina_Bool
5325 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
5326 {
5327    int ret = 0;
5328    Edje_Signal_Cb end_cb_before = NULL;
5329    void *end_data_before = NULL;
5330    API_ENTRY EINA_FALSE;
5331
5332    end_cb_before   = evas_object_data_get(cw->effect_obj, "_e_comp.end_cb");
5333    end_data_before = evas_object_data_get(cw->effect_obj, "_e_comp.end_data");
5334
5335    if (end_cb_before != end_cb) return EINA_TRUE;
5336    e_comp_object_effect_unclip(obj);
5337    if (cw->effect_clip)
5338      {
5339         evas_object_clip_unset(cw->effect_obj);
5340         cw->effect_clip = 0;
5341      }
5342    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
5343    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
5344
5345    if (evas_object_data_get(cw->smart_obj, "effect_running"))
5346      {
5347         evas_object_data_del(cw->smart_obj, "effect_running");
5348         e_comp_visibility_calculation_set(EINA_TRUE);
5349      }
5350
5351    cw->effect_running = 0;
5352    ret = _e_comp_object_animating_end(cw);
5353
5354    if ((ret) && (end_cb_before))
5355      {
5356         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_EFFECT_END, cw->ec);
5357         end_cb_before(end_data_before, cw->smart_obj, "e,action,done", "e");
5358      }
5359
5360    return ret;
5361 }
5362
5363 static int
5364 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
5365 {
5366    return a->pri - b->pri;
5367 }
5368
5369 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
5370 E_API E_Comp_Object_Mover *
5371 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
5372 {
5373    E_Comp_Object_Mover *prov;
5374
5375    prov = E_NEW(E_Comp_Object_Mover, 1);
5376    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
5377    prov->func = provider;
5378    prov->data = (void*)data;
5379    prov->pri = pri;
5380    prov->sig = sig;
5381    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
5382      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
5383    return prov;
5384 }
5385
5386 E_API void
5387 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
5388 {
5389    EINA_SAFETY_ON_NULL_RETURN(prov);
5390    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
5391    free(prov);
5392 }
5393
5394 E_API Evas_Object *
5395 e_comp_object_effect_object_get(Evas_Object *obj)
5396 {
5397    API_ENTRY NULL;
5398
5399    return cw->effect_obj;
5400 }
5401
5402 E_API Eina_Bool
5403 e_comp_object_effect_hiding_set(Evas_Object *obj, Eina_Bool set)
5404 {
5405    API_ENTRY EINA_FALSE;
5406    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5407    if (!cw->effect_set) return EINA_FALSE;
5408
5409    cw->hiding = set;
5410
5411    return EINA_TRUE;
5412 }
5413
5414 ////////////////////////////////////
5415
5416 static void
5417 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
5418 {
5419    if (e_comp->autoclose.obj)
5420      {
5421         e_comp_ungrab_input(0, 1);
5422         if (e_comp->autoclose.del_cb)
5423           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
5424         else if (!already_del)
5425           {
5426              evas_object_hide(e_comp->autoclose.obj);
5427              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
5428           }
5429         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
5430      }
5431    e_comp->autoclose.obj = NULL;
5432    e_comp->autoclose.data = NULL;
5433    e_comp->autoclose.del_cb = NULL;
5434    e_comp->autoclose.key_cb = NULL;
5435    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
5436 }
5437
5438 static void
5439 _e_comp_object_autoclose_mouse_up_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
5440 {
5441    _e_comp_object_autoclose_cleanup(0);
5442 }
5443
5444 static void
5445 _e_comp_object_autoclose_setup(Evas_Object *obj)
5446 {
5447    if (!e_comp->autoclose.rect)
5448      {
5449         /* create rect just below autoclose object to catch mouse events */
5450         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
5451         evas_object_move(e_comp->autoclose.rect, 0, 0);
5452         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
5453         evas_object_show(e_comp->autoclose.rect);
5454         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
5455         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
5456         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
5457         e_comp_grab_input(0, 1);
5458      }
5459    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
5460    evas_object_focus_set(obj, 1);
5461 }
5462
5463 static void
5464 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5465 {
5466    _e_comp_object_autoclose_setup(obj);
5467    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5468 }
5469
5470 static void
5471 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
5472 {
5473    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
5474    _e_comp_object_autoclose_cleanup(1);
5475    if (e_client_focused_get()) return;
5476
5477    E_Zone *zone = e_zone_current_get();
5478    if (!zone) return;
5479
5480    e_zone_focus_reset(zone);
5481 }
5482
5483 EINTERN void
5484 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
5485 {
5486    SOFT_ENTRY();
5487
5488    if (e_comp->autoclose.obj)
5489      {
5490         if (e_comp->autoclose.obj == obj) return;
5491         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5492         e_comp->autoclose.obj = obj;
5493         e_comp->autoclose.del_cb = del_cb;
5494         e_comp->autoclose.key_cb = cb;
5495         e_comp->autoclose.data = (void*)data;
5496         if (evas_object_visible_get(obj))
5497           _e_comp_object_autoclose_setup(obj);
5498         else
5499           evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5500         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5501         return;
5502      }
5503    e_comp->autoclose.obj = obj;
5504    e_comp->autoclose.del_cb = del_cb;
5505    e_comp->autoclose.key_cb = cb;
5506    e_comp->autoclose.data = (void*)data;
5507    if (evas_object_visible_get(obj))
5508      _e_comp_object_autoclose_setup(obj);
5509    else
5510      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
5511    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
5512 }
5513
5514 E_API unsigned int
5515 e_comp_object_is_animating(Evas_Object *obj)
5516 {
5517    API_ENTRY 0;
5518
5519    return cw->animating;
5520 }
5521
5522 E_API void
5523 e_comp_object_alpha_set(Evas_Object *obj, Eina_Bool alpha)
5524 {
5525    API_ENTRY;
5526
5527    if ((cw->external_content) &&
5528        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5529      {
5530         WRN("Can set up alpha value to ONLY evas \"image\" object. "
5531             "But current external content is %d object for %p.",
5532             cw->content_type, cw->ec);
5533         return;
5534      }
5535
5536    cw->user_alpha_set = EINA_TRUE;
5537    cw->user_alpha = alpha;
5538
5539    if (!cw->obj) return;
5540
5541    if (alpha == evas_object_image_alpha_get(cw->obj)) return;
5542
5543    evas_object_image_alpha_set(cw->obj, alpha);
5544
5545    if ((!cw->native) && (!cw->external_content))
5546      evas_object_image_data_set(cw->obj, NULL);
5547 }
5548
5549 EINTERN Eina_Bool
5550 e_comp_object_alpha_get(Evas_Object *obj)
5551 {
5552    API_ENTRY EINA_FALSE;
5553
5554    return evas_object_image_alpha_get(cw->obj);
5555 }
5556
5557 E_API void
5558 e_comp_object_mask_set(Evas_Object *obj, Eina_Bool set)
5559 {
5560    Eina_Bool mask_set = EINA_FALSE;
5561    Evas_Object *o;
5562
5563    API_ENTRY;
5564    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5565    if (cw->ec->input_only) return;
5566    mask_set = !!set;
5567
5568    if (mask_set)
5569      {
5570         if (!cw->mask.obj)
5571           {
5572              o = evas_object_rectangle_add(e_comp->evas);
5573              evas_object_color_set(o, 0, 0, 0, 0);
5574              evas_object_clip_set(o, cw->clip);
5575              evas_object_smart_member_add(o, obj);
5576              evas_object_move(o, 0, 0);
5577              evas_object_resize(o, cw->w, cw->h);
5578              /* save render op value to restore when clear a mask.
5579               *
5580               * NOTE: DO NOT change the render op on ec->frame while mask object
5581               * is set. it will overwrite the changed op value. */
5582              cw->mask.saved_render_op = evas_object_render_op_get(obj);
5583              evas_object_render_op_set(obj, EVAS_RENDER_COPY);
5584              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5585              if (cw->visible) evas_object_show(o);
5586
5587              cw->mask.obj = o;
5588              evas_object_name_set(cw->mask.obj, "cw->mask_obj");
5589              ELOGF("COMP", "         |mask_obj", cw->ec);
5590              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_SET, cw->ec);
5591           }
5592      }
5593    else
5594      {
5595         if (cw->mask.obj)
5596           {
5597              evas_object_smart_member_del(cw->mask.obj);
5598              E_FREE_FUNC(cw->mask.obj, evas_object_del);
5599
5600              evas_object_render_op_set(obj, cw->mask.saved_render_op);
5601              _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_MASK_OBJECT_UNSET, cw->ec);
5602           }
5603      }
5604 }
5605
5606 E_API Eina_Bool
5607 e_comp_object_mask_has(Evas_Object *obj)
5608 {
5609    API_ENTRY EINA_FALSE;
5610
5611    return (cw->mask.obj) ? EINA_TRUE : EINA_FALSE;
5612 }
5613
5614 EINTERN void
5615 e_comp_object_size_update(Evas_Object *obj, int w, int h)
5616 {
5617    int tw, th;
5618    API_ENTRY;
5619
5620    if ((cw->external_content) &&
5621        (cw->content_type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE))
5622      {
5623         WRN("Can set up size to ONLY evas \"image\" object. "
5624             "But current external content is %d object for %p.",
5625             cw->content_type, cw->ec);
5626         return;
5627      }
5628
5629    _e_comp_object_map_transform_rect(cw->ec, 0, 0, w, h, NULL, NULL, &tw, &th);
5630
5631    evas_object_image_size_set(cw->obj, tw, th);
5632 }
5633
5634 E_API void
5635 e_comp_object_transform_bg_set(Evas_Object *obj, Eina_Bool set)
5636 {
5637    Eina_Bool transform_set = EINA_FALSE;
5638    API_ENTRY;
5639    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5640    if (cw->ec->input_only) return;
5641
5642    transform_set = !!set;
5643
5644    if (transform_set)
5645      {
5646         if (!cw->transform_bg_obj)
5647           {
5648              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5649              evas_object_move(o, 0, 0);
5650              evas_object_resize(o, 1, 1);
5651              if (cw->transform_bg_color.a >= 255)
5652                evas_object_render_op_set(o, EVAS_RENDER_COPY);
5653              else
5654                evas_object_render_op_set(o, EVAS_RENDER_BLEND);
5655              evas_object_color_set(o,
5656                                    cw->transform_bg_color.r,
5657                                    cw->transform_bg_color.g,
5658                                    cw->transform_bg_color.b,
5659                                    cw->transform_bg_color.a);
5660              if (cw->visible) evas_object_show(o);
5661
5662              cw->transform_bg_obj = o;
5663              evas_object_name_set(cw->transform_bg_obj, "cw->transform_bg_obj");
5664           }
5665 #ifdef REFACTOR_DESK_AREA
5666         e_comp_object_transform_obj_stack_update(obj);
5667 #else
5668         _e_comp_object_transform_obj_stack_update(obj);
5669 #endif
5670      }
5671    else
5672      {
5673         if (cw->transform_bg_obj)
5674           {
5675              evas_object_smart_member_del(cw->transform_bg_obj);
5676              E_FREE_FUNC(cw->transform_bg_obj, evas_object_del);
5677           }
5678      }
5679 }
5680
5681 E_API void
5682 e_comp_object_transform_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
5683 {
5684    API_ENTRY;
5685
5686    cw->transform_bg_color.r = r;
5687    cw->transform_bg_color.g = g;
5688    cw->transform_bg_color.b = b;
5689    cw->transform_bg_color.a = a;
5690
5691    if (cw->transform_bg_obj)
5692      {
5693         evas_object_color_set(cw->transform_bg_obj,
5694                               cw->transform_bg_color.r,
5695                               cw->transform_bg_color.g,
5696                               cw->transform_bg_color.b,
5697                               cw->transform_bg_color.a);
5698      }
5699 }
5700
5701 EINTERN void
5702 e_comp_object_transform_bg_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5703 {
5704    API_ENTRY;
5705    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5706    if (cw->ec->input_only) return;
5707    if (!cw->transform_bg_obj) return;
5708
5709    _e_comp_object_transform_obj_map_set(cw->transform_bg_obj, vertices);
5710 }
5711
5712 EINTERN void
5713 e_comp_object_transform_bg_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5714 {
5715    API_ENTRY;
5716    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5717    if (cw->ec->input_only) return;
5718    if (!cw->transform_bg_obj) return;
5719
5720    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_bg_obj, vertices, zoom);
5721 }
5722
5723 E_API void
5724 e_comp_object_transform_transp_set(Evas_Object *obj, Eina_Bool set)
5725 {
5726    Eina_Bool transform_set = EINA_FALSE;
5727    API_ENTRY;
5728    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5729    if (cw->ec->input_only) return;
5730
5731    transform_set = !!set;
5732
5733    if (transform_set)
5734      {
5735         if (!cw->transform_tranp_obj)
5736           {
5737              Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
5738              evas_object_move(o, 0, 0);
5739              evas_object_resize(o, 1, 1);
5740              evas_object_render_op_set(o, EVAS_RENDER_COPY);
5741              evas_object_color_set(o, 0, 0, 0, 0);
5742              if (cw->visible) evas_object_show(o);
5743
5744              cw->transform_tranp_obj = o;
5745              evas_object_pass_events_set(cw->transform_tranp_obj, EINA_TRUE);
5746              ELOGF("TRANSFORM","transform set: TRUE", cw->ec);
5747              evas_object_name_set(cw->transform_tranp_obj, "cw->transform_trasp_obj");
5748           }
5749 #ifdef REFACTOR_DESK_AREA
5750         e_comp_object_transform_obj_stack_update(obj);
5751 #else
5752         _e_comp_object_transform_obj_stack_update(obj);
5753 #endif
5754      }
5755    else
5756      {
5757         if (cw->transform_tranp_obj)
5758           {
5759              ELOGF("TRANSFORM","transform set: FALSE", cw->ec);
5760              evas_object_smart_member_del(cw->transform_tranp_obj);
5761              E_FREE_FUNC(cw->transform_tranp_obj, evas_object_del);
5762           }
5763      }
5764 }
5765
5766 EINTERN void
5767 e_comp_object_transform_transp_vertices_set(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices)
5768 {
5769    API_ENTRY;
5770    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5771    if (cw->ec->input_only) return;
5772    if (!cw->transform_tranp_obj) return;
5773
5774    _e_comp_object_transform_obj_map_set(cw->transform_tranp_obj, vertices);
5775 }
5776
5777 EINTERN void
5778 e_comp_object_transform_transp_vertices_set_with_zoom(Evas_Object *obj, E_Util_Transform_Rect_Vertex *vertices, E_Util_Transform_Zoom zoom)
5779 {
5780    API_ENTRY;
5781    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
5782    if (cw->ec->input_only) return;
5783    if (!cw->transform_tranp_obj) return;
5784
5785    _e_comp_object_transform_obj_map_set_with_zoom(cw->transform_tranp_obj, vertices, zoom);
5786 }
5787
5788 #ifdef REFACTOR_DESK_AREA
5789 #else
5790 EINTERN void
5791 e_comp_object_layer_update(Evas_Object *obj,
5792                            Evas_Object *above, Evas_Object *below)
5793 {
5794    E_Comp_Object *cw2 = NULL;
5795    Evas_Object *o = NULL;
5796    short layer;
5797
5798    API_ENTRY;
5799
5800    if (cw->ec->layer_block) return;
5801    if ((above) && (below))
5802      {
5803         ERR("Invalid layer update request! cw=%p", cw);
5804         return;
5805      }
5806
5807    o = above?:below;
5808
5809    if (o)
5810      {
5811         layer = evas_object_layer_get(o);
5812         cw2 = evas_object_data_get(o, "comp_obj");
5813         while (!cw2)
5814           {
5815              if (!e_util_strcmp(evas_object_name_get(o), "layer_obj")) break;
5816
5817              o = evas_object_above_get(o);
5818              if ((!o) || (o == cw->smart_obj)) break;
5819              if (evas_object_layer_get(o) != layer)
5820                {
5821                   o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_ALERT)].obj;
5822                }
5823              if (!o)
5824                {
5825                   E_Client *ec;
5826                   ec = e_client_top_get();
5827                   if (ec) o = ec->frame;
5828                }
5829
5830              if (o) cw2 = evas_object_data_get(o, "comp_obj");
5831           }
5832      }
5833
5834    _e_comp_object_layers_remove(cw);
5835    if (cw2)
5836      {
5837         if (cw2->layer > cw->layer)
5838           _e_comp_object_layers_add(cw, NULL, NULL, 0);
5839         else if (cw2->layer == cw->layer)
5840           {
5841              if (above)
5842                _e_comp_object_layers_add(cw, cw2, NULL, 0);
5843              else if (o == obj)
5844                _e_comp_object_layers_add(cw, NULL, NULL, above? 0 : 1);
5845              else if (below)
5846                _e_comp_object_layers_add(cw, NULL, cw2, 0);
5847           }
5848         else
5849           _e_comp_object_layers_add(cw, NULL, NULL, 1);
5850      }
5851    else
5852      _e_comp_object_layers_add(cw, NULL, NULL, 0);
5853 }
5854 #endif
5855
5856 EINTERN int
5857 e_comp_object_layer_get(Evas_Object *obj)
5858 {
5859    API_ENTRY -1;
5860    return cw->layer;
5861 }
5862
5863 E_API Eina_Bool
5864 e_comp_object_content_set(Evas_Object *obj,
5865                           Evas_Object *content,
5866                           E_Comp_Object_Content_Type type)
5867 {
5868    API_ENTRY EINA_FALSE;
5869
5870    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5871    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5872    EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5873
5874    if (cw->obj)
5875      {
5876         ERR("Can't set e.swallow.content to requested content. "
5877             "Previous comp object should not be changed at all.");
5878         return EINA_FALSE;
5879      }
5880
5881    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_FALSE;
5882
5883    if ((type != E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) &&
5884        (type != E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
5885      {
5886         ERR("Content type %d for %p is not supported ec:%p pixmap:%p",
5887             type, content, cw->ec, cw->ec->pixmap);
5888         return EINA_FALSE;
5889      }
5890
5891    cw->external_content = EINA_TRUE;
5892
5893    cw->obj = content;
5894    cw->content_type = type;
5895    e_util_size_debug_set(cw->obj, 1);
5896    evas_object_name_set(cw->obj, "cw->obj");
5897    _e_comp_object_alpha_set(cw);
5898
5899    if (cw->shobj)
5900      _e_comp_object_shadow_setup(cw);
5901
5902    wl_signal_emit(&cw->events.content_type_set, NULL);
5903
5904    return EINA_TRUE;
5905 }
5906
5907 EINTERN Eina_Bool
5908 e_comp_object_content_unset(Evas_Object *obj)
5909 {
5910    API_ENTRY EINA_FALSE;
5911
5912    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
5913    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec->pixmap, EINA_FALSE);
5914
5915    if (!cw->obj && !cw->ec->visible)
5916      {
5917         ELOGF("COMP", "is not visible yet. no need to unset", cw->ec);
5918         return EINA_TRUE;
5919      }
5920
5921    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5922      {
5923         ELOGF("COMP", "has been set to internal image object already", cw->ec);
5924         return EINA_TRUE;
5925      }
5926
5927    if (cw->obj)
5928      {
5929         if (cw->frame_object)
5930           edje_object_part_unswallow(cw->frame_object, cw->obj);
5931         else if (cw->shobj)
5932           edje_object_part_unswallow(cw->shobj, cw->obj);
5933
5934         evas_object_del(cw->obj);
5935         evas_object_hide(cw->obj);
5936         cw->obj = NULL;
5937      }
5938
5939    cw->external_content = EINA_FALSE;
5940    if (cw->ec->is_cursor)
5941      {
5942         int pw, ph;
5943         DBG("%p is cursor surface..", cw->ec);
5944         if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))
5945           pw = ph = 1;
5946         evas_object_resize(cw->ec->frame, pw, ph);
5947         evas_object_hide(cw->ec->frame);
5948         return EINA_TRUE;
5949      }
5950
5951
5952    cw->content_type = E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE;
5953    cw->obj = evas_object_image_filled_add(e_comp->evas);
5954    evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
5955    e_util_size_debug_set(cw->obj, 1);
5956    evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
5957    evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
5958    evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
5959    evas_object_name_set(cw->obj, "cw->obj");
5960    evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
5961    evas_object_intercept_color_set_callback_add(obj, _e_comp_intercept_obj_color_set, cw);
5962    _e_comp_object_alpha_set(cw);
5963
5964    if (cw->shobj)
5965      _e_comp_object_shadow_setup(cw);
5966
5967    if (cw->visible)
5968      {
5969         cw->visible = 0;
5970         _e_comp_intercept_show_helper(cw);
5971         cw->visible = 1;
5972      }
5973
5974    e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
5975    e_comp_object_dirty(cw->smart_obj);
5976    e_comp_object_render(cw->smart_obj);
5977    e_comp_object_render_update_add(obj);
5978
5979    wl_signal_emit(&cw->events.content_type_set, NULL);
5980
5981    return EINA_TRUE;
5982 }
5983
5984 EINTERN Evas_Object *
5985 e_comp_object_content_get(Evas_Object *obj)
5986 {
5987    API_ENTRY NULL;
5988
5989    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, NULL);
5990
5991    if (cw->content_type == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
5992      {
5993         ELOGF("COMP", "has been set to internal image object. couldn't return internal image object", cw->ec);
5994         return NULL;
5995      }
5996
5997    return cw->obj;
5998 }
5999
6000 E_API E_Comp_Object_Content_Type
6001 e_comp_object_content_type_get(Evas_Object *obj)
6002 {
6003    API_ENTRY E_COMP_OBJECT_CONTENT_TYPE_NONE;
6004
6005    return cw->content_type;
6006 }
6007
6008 E_API void
6009 e_comp_object_dim_mask_update(Evas_Object *obj, Eina_Bool mask_set, int x, int y, int w, int h)
6010 {
6011    API_ENTRY;
6012    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6013    E_Comp_Config *conf = e_comp_config_get();
6014    if (cw->ec->input_only) return;
6015    if (!conf->dim_rect_enable) return;
6016
6017    cw->dim.mask_set = mask_set;
6018    cw->dim.mask_x = x;
6019    cw->dim.mask_y = y;
6020    cw->dim.mask_w = w;
6021    cw->dim.mask_h = h;
6022
6023    if (!cw->dim.enable) return;
6024    e_comp_object_dim_mask_set(cw->ec->frame, mask_set);
6025 }
6026
6027 EINTERN void
6028 e_comp_object_dim_mask_set(Evas_Object *obj, Eina_Bool set)
6029 {
6030    Eina_Bool mask_set = EINA_FALSE;
6031    Evas_Object *o;
6032
6033    API_ENTRY;
6034    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
6035    E_Comp_Config *conf = e_comp_config_get();
6036    if (cw->ec->input_only) return;
6037    if (!conf->dim_rect_enable) return;
6038
6039    mask_set = !!set;
6040
6041    if (mask_set)
6042      {
6043         if (cw->dim.mask_obj)
6044           {
6045              evas_object_smart_member_del(cw->dim.mask_obj);
6046              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6047           }
6048
6049         ELOGF("COMP", "DIM  |Mask applied on Dim rect mask_rect[%d %d %d %d]", cw->ec, cw->dim.mask_x, cw->dim.mask_y, cw->dim.mask_w, cw->dim.mask_h);
6050         o = evas_object_rectangle_add(e_comp->evas);
6051         evas_object_color_set(o, 0, 0, 0, 0);
6052         evas_object_smart_member_add(o, obj);
6053         evas_object_resize(o, cw->dim.mask_w, cw->dim.mask_h);
6054         evas_object_move(o, cw->dim.mask_x, cw->dim.mask_y);
6055
6056         evas_object_render_op_set(o, EVAS_RENDER_COPY);
6057         if (cw->visible) evas_object_show(o);
6058
6059         cw->dim.mask_obj = o;
6060         evas_object_name_set(cw->dim.mask_obj, "cw->dim_mask_obj");
6061
6062         evas_object_layer_set(cw->dim.mask_obj, 9998);
6063      }
6064    else
6065      {
6066         if (cw->dim.mask_obj)
6067           {
6068              ELOGF("COMP", "DIM  |Mask on Dim rect Removed", cw->ec);
6069              evas_object_smart_member_del(cw->dim.mask_obj);
6070              E_FREE_FUNC(cw->dim.mask_obj, evas_object_del);
6071           }
6072      }
6073 }
6074
6075 E_API void
6076 e_comp_object_dim_client_set(E_Client *ec)
6077 {
6078    E_Comp_Config *conf = e_comp_config_get();
6079
6080    if (!conf->dim_rect_enable) return ;
6081    if (dim_client == ec) return;
6082
6083    Eina_Bool prev_dim = EINA_FALSE;
6084    ELOGF("COMP", "DIM  |Client Set %p -> %p", ec, dim_client, ec);
6085
6086    if (dim_client && _e_comp_object_dim_enable_get(dim_client, dim_client->frame))
6087       prev_dim = EINA_TRUE;
6088
6089    if (prev_dim && dim_client->visible && ec)
6090      {
6091         _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_TRUE);
6092         _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_TRUE);
6093      }
6094    else
6095      {
6096         if (prev_dim) _e_comp_object_dim_enable_set(dim_client, dim_client->frame, EINA_FALSE, EINA_FALSE);
6097         if (ec)       _e_comp_object_dim_enable_set(ec, ec->frame, EINA_TRUE, EINA_FALSE);
6098      }
6099    dim_client = ec;
6100 }
6101
6102 EINTERN E_Client *
6103 e_comp_object_dim_client_get(void)
6104 {
6105    E_Comp_Config *conf = e_comp_config_get();
6106
6107    if (!conf->dim_rect_enable ) return NULL;
6108
6109    return dim_client;
6110 }
6111
6112 static void
6113 _e_comp_object_dim_enable_set(E_Client *ec, Evas_Object *obj, Eina_Bool enable, Eina_Bool noeffect)
6114 {
6115    API_ENTRY;
6116    char emit[32] = "\0";
6117    E_Comp_Config *conf = e_comp_config_get();
6118
6119    if (!ec) return;
6120    if (!conf->dim_rect_enable) return;
6121    if (!cw->effect_obj) return;
6122    if (enable == cw->dim.enable) return;
6123
6124    ELOGF("COMP", "DIM  |set on Client [%d]", ec, enable);
6125    if (noeffect || !conf->dim_rect_effect)
6126      {
6127         strncpy(emit, (enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), sizeof(emit) - 1);
6128      }
6129    else
6130      {
6131         strncpy(emit, (enable ? "e,state,dim,on" : "e,state,dim,off"), sizeof(emit) - 1);
6132      }
6133
6134    cw->dim.enable = enable;
6135
6136    if (cw->dim.mask_set && !enable)
6137      {
6138         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6139         edje_object_signal_emit(cw->effect_obj, emit, "e");
6140      }
6141    else if (cw->dim.mask_set && enable)
6142      {
6143         edje_object_signal_emit(cw->effect_obj, emit, "e");
6144         e_comp_object_dim_mask_set(cw->ec->frame, enable);
6145      }
6146    else
6147      {
6148         edje_object_signal_emit(cw->effect_obj, emit, "e");
6149      }
6150 }
6151
6152 static Eina_Bool
6153 _e_comp_object_dim_enable_get(E_Client *ec, Evas_Object *obj)
6154 {
6155    API_ENTRY EINA_FALSE;
6156    E_Comp_Config *conf = e_comp_config_get();
6157
6158    if (!ec) return EINA_FALSE;
6159    if (!conf->dim_rect_enable) return EINA_FALSE;
6160
6161    if (cw->dim.enable) return EINA_TRUE;
6162
6163    return EINA_FALSE;
6164 }
6165
6166 static void
6167 _e_comp_object_dim_update(E_Comp_Object *cw)
6168 {
6169    E_Comp_Config *conf = e_comp_config_get();
6170
6171    if (!cw) return;
6172    if (!conf->dim_rect_enable) return;
6173    if (!cw->effect_obj) return;
6174    if (cw->dim.enable)
6175      {
6176         edje_object_signal_emit(cw->effect_obj, (cw->dim.enable ? "e,state,dim,on,noeffect" : "e,state,dim,off,noeffect"), "e");
6177         ELOGF("COMP", "DIM  |Applied on Client dim.enable[%d]", cw->ec, cw->dim.enable);
6178
6179         if (cw->dim.mask_set)
6180           {
6181              e_comp_object_dim_mask_set(cw->ec->frame,  cw->dim.mask_set);
6182           }
6183      }
6184 }
6185
6186 EINTERN void
6187 e_comp_object_clear(Evas_Object *obj)
6188 {
6189    API_ENTRY;
6190
6191    _e_comp_object_clear(cw);
6192 }
6193
6194 EINTERN Eina_Bool
6195 e_comp_object_hwc_update_exists(Evas_Object *obj)
6196 {
6197    API_ENTRY EINA_FALSE;
6198    return cw->hwc_need_update;
6199 }
6200
6201 // will remove out
6202 E_API void
6203 e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
6204 {
6205    API_ENTRY;
6206    cw->hwc_need_update = set;
6207 }
6208
6209 E_API Eina_Bool
6210 e_comp_object_effect_object_part_swallow(Evas_Object *obj, const char *part_name, Evas_Object *swallow_obj)
6211 {
6212    API_ENTRY EINA_FALSE;
6213    return edje_object_part_swallow(cw->effect_obj, part_name, swallow_obj);
6214 }
6215
6216 EINTERN void
6217 e_comp_object_indicator_swallow(Evas_Object *obj, Evas_Object *indicator)
6218 {
6219    API_ENTRY;
6220    if (cw->indicator.obj != indicator)
6221      edje_object_part_unswallow(cw->shobj, cw->indicator.obj);
6222    cw->indicator.obj = indicator;
6223    edje_object_part_swallow(cw->shobj, "e.swallow.indicator", indicator);
6224 }
6225
6226 EINTERN void
6227 e_comp_object_indicator_unswallow(Evas_Object *obj, Evas_Object *indicator)
6228 {
6229    API_ENTRY;
6230    if (cw->indicator.obj != indicator) return;
6231    cw->indicator.obj = NULL;
6232    edje_object_part_unswallow(cw->shobj, indicator);
6233 }
6234
6235 EINTERN void
6236 e_comp_object_indicator_size_set(Evas_Object *obj, int w, int h)
6237 {
6238    API_ENTRY;
6239    Edje_Message_Int_Set *msg;
6240
6241    if (!cw->indicator.obj) return;
6242
6243    cw->indicator.w = w;
6244    cw->indicator.h = h;
6245
6246    if (!cw->shobj) return;
6247
6248    msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
6249    msg->count = 2;
6250    msg->val[0] = w;
6251    msg->val[1] = h;
6252    edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 0, msg);
6253    edje_object_message_signal_process(cw->shobj);
6254 }
6255
6256 /* buffer transform and scale are applied to e_comp_object and e_pixmap internaly */
6257 EINTERN void
6258 e_comp_object_map_update(Evas_Object *obj)
6259 {
6260    API_ENTRY;
6261    E_Client *ec = cw->ec;
6262    E_Comp_Wl_Client_Data *cdata;
6263    E_Map *map;
6264    int x1, y1, x2, y2, x, y, bw, bh, tw, th;
6265    char buffer[128];
6266    char *p = buffer;
6267    int l, remain = sizeof buffer;
6268
6269    if (!ec) return;
6270    if (e_object_is_del(E_OBJECT(ec))) return;
6271    cdata = e_client_cdata_get(ec);
6272    if (!cdata) return;
6273
6274    /* if buffer had been flushed, buffer could be NULL. Then map will be applied
6275     * when new buffer is attached.
6276     */
6277    if (!cdata->buffer_ref.buffer) return;
6278
6279    if ((!cw->redirected) ||
6280        (e_client_video_hw_composition_check(ec)) ||
6281        (!e_comp_wl_output_buffer_transform_get(ec) &&
6282         cdata->scaler.buffer_viewport.buffer.scale == 1))
6283      {
6284         if (evas_object_map_enable_get(cw->effect_obj))
6285           {
6286              ELOGF("TRANSFORM", "map: disable", cw->ec);
6287              evas_object_map_enable_set(cw->effect_obj, EINA_FALSE);
6288              _e_comp_object_map_transform_rect(cw->ec, 0, 0, cw->w, cw->h, NULL, NULL, &tw, &th);
6289              evas_object_resize(cw->effect_obj, tw, th);
6290           }
6291
6292         return;
6293      }
6294
6295    map = e_map_new();
6296    EINA_SAFETY_ON_NULL_RETURN(map);
6297
6298    e_pixmap_size_get(ec->pixmap, &bw, &bh);
6299
6300    x1 = y1 = 0;
6301    x2 = bw;
6302    y2 = bh;
6303
6304    e_map_util_points_populate_from_geometry(map, ec->x, ec->y, bw, bh, 0);
6305
6306    _e_comp_object_map_transform_pos(ec, x1, y1, &x, &y);
6307    e_map_point_image_uv_set(map, 0, x, y);
6308    l = snprintf(p, remain, "%d,%d", x, y);
6309    p += l, remain -= l;
6310
6311    _e_comp_object_map_transform_pos(ec, x2, y1, &x, &y);
6312    e_map_point_image_uv_set(map, 1, x, y);
6313    l = snprintf(p, remain, " %d,%d", x, y);
6314    p += l, remain -= l;
6315
6316    _e_comp_object_map_transform_pos(ec, x2, y2, &x, &y);
6317    e_map_point_image_uv_set(map, 2, x, y);
6318    l = snprintf(p, remain, " %d,%d", x, y);
6319    p += l, remain -= l;
6320
6321    _e_comp_object_map_transform_pos(ec, x1, y2, &x, &y);
6322    e_map_point_image_uv_set(map, 3, x, y);
6323    l = snprintf(p, remain, " %d,%d", x, y);
6324    p += l, remain -= l;
6325
6326    ELOGF("TRANSFORM", "map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d=>%s)",
6327          cw->ec,
6328          ec->x, ec->y, bw, bh, x1, y1, x2, y1, x2, y2, x1, y2, buffer);
6329
6330    e_comp_object_map_set(cw->effect_obj, map);
6331    e_comp_object_map_enable_set(cw->effect_obj, EINA_TRUE);
6332
6333    e_map_free(map);
6334
6335    /* if there's screen rotation with comp mode, then ec->effect_obj and
6336     * ec->obj should rotate. if not, in evas_map, update region is clipped.
6337     */
6338    _e_comp_object_map_transform_rect(cw->ec, 0, 0, bw, bh, NULL, NULL, &tw, &th);
6339    evas_object_resize(cw->effect_obj, tw, th);
6340 }
6341
6342 EINTERN Eina_Bool
6343 e_comp_object_render_trace_set(Evas_Object *obj, Eina_Bool set)
6344 {
6345    API_ENTRY EINA_FALSE;
6346
6347    cw->render_trace = set;
6348
6349    return EINA_TRUE;
6350 }
6351
6352 E_API Eina_Bool
6353 e_comp_object_native_usable_get(Evas_Object *obj)
6354 {
6355    API_ENTRY EINA_FALSE;
6356    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6357
6358    if (cw->ec->input_only) return EINA_FALSE;
6359    if (cw->external_content) return EINA_FALSE;
6360    if (e_comp_object_content_type_get(cw->ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) return EINA_FALSE;
6361
6362    /* just return true value, if it is normal case */
6363    if (e_pixmap_usable_get(cw->ec->pixmap)) return EINA_TRUE;
6364
6365    /* abnormal case */
6366    Evas_Native_Surface *ns;
6367    ns = evas_object_image_native_surface_get(cw->obj);
6368
6369    /* client pixmap is not usable but cw->obj is drawable due to it holds valid native surface*/
6370    if (ns)
6371      {
6372         ELOGF("COMP", "Client pixmap is Not usable but still holds valid native surface", cw->ec);
6373         return EINA_TRUE;
6374      }
6375
6376    return EINA_FALSE;
6377 }
6378
6379 EINTERN Eina_Bool
6380 e_comp_object_image_filter_set(Evas_Object *obj, E_Comp_Image_Filter filter)
6381 {
6382    API_ENTRY EINA_FALSE;
6383    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6384    if (e_object_is_del(E_OBJECT(cw->ec))) return EINA_FALSE;
6385    if (!e_client_cdata_get(cw->ec)) return EINA_FALSE;
6386
6387    if (cw->image_filter == filter) return EINA_TRUE;
6388
6389    switch (filter)
6390      {
6391       case E_COMP_IMAGE_FILTER_BLUR:
6392          efl_gfx_filter_program_set(cw->obj, "blur (20) padding_set (0)", "image_filter");
6393          break;
6394       case E_COMP_IMAGE_FILTER_GRAYSCALE:
6395          efl_gfx_filter_program_set(cw->obj, "grayscale ()", "image_filter");
6396          break;
6397       case E_COMP_IMAGE_FILTER_INVERSE:
6398          efl_gfx_filter_program_set(cw->obj, "inverse_color ()", "image_filter");
6399          break;
6400       case E_COMP_IMAGE_FILTER_NONE:
6401       default:
6402          efl_gfx_filter_program_set(cw->obj, NULL, "image_filter");
6403          break;
6404      }
6405
6406    cw->image_filter = filter;
6407
6408    wl_signal_emit(&cw->events.image_filter_set, NULL);
6409
6410    return EINA_TRUE;
6411 }
6412
6413 EINTERN E_Comp_Image_Filter
6414 e_comp_object_image_filter_get(Evas_Object *obj)
6415 {
6416    API_ENTRY E_COMP_IMAGE_FILTER_NONE;
6417    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, E_COMP_IMAGE_FILTER_NONE);
6418    if (e_object_is_del(E_OBJECT(cw->ec))) return E_COMP_IMAGE_FILTER_NONE;
6419    if (!e_client_cdata_get(cw->ec)) return E_COMP_IMAGE_FILTER_NONE;
6420
6421    return cw->image_filter;
6422 }
6423
6424 static void
6425 _e_comp_object_damage_trace_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6426 {
6427    Evas_Object *obj;
6428
6429    if (!_damage_trace) return;
6430
6431    EINA_LIST_FREE(_damage_trace_post_objs, obj)
6432      evas_object_del(obj);
6433
6434    _damage_trace_post_objs = NULL;
6435 }
6436
6437 static void
6438 _e_comp_object_damage_trace_render_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
6439 {
6440    if (!_damage_trace) return;
6441
6442    _damage_trace_post_objs = _damage_trace_objs;
6443    _damage_trace_objs = NULL;
6444 }
6445
6446 EINTERN void
6447 e_comp_object_damage_trace_debug(Eina_Bool onoff)
6448 {
6449    if (_damage_trace == onoff) return;
6450
6451    if (onoff)
6452      {
6453         evas_event_callback_add(e_comp->evas,
6454                                 EVAS_CALLBACK_RENDER_PRE,
6455                                 _e_comp_object_damage_trace_render_pre_cb,
6456                                 NULL);
6457
6458         evas_event_callback_add(e_comp->evas,
6459                                 EVAS_CALLBACK_RENDER_POST,
6460                                 _e_comp_object_damage_trace_render_post_cb,
6461                                 NULL);
6462      }
6463    else
6464      {
6465         Evas_Object *obj;
6466
6467         EINA_LIST_FREE(_damage_trace_objs, obj)
6468           evas_object_del(obj);
6469
6470         _damage_trace_objs = NULL;
6471
6472         EINA_LIST_FREE(_damage_trace_post_objs, obj)
6473           evas_object_del(obj);
6474
6475         _damage_trace_post_objs = NULL;
6476
6477         evas_event_callback_del(e_comp->evas,
6478                                 EVAS_CALLBACK_RENDER_PRE,
6479                                 _e_comp_object_damage_trace_render_pre_cb);
6480
6481         evas_event_callback_del(e_comp->evas,
6482                                 EVAS_CALLBACK_RENDER_POST,
6483                                 _e_comp_object_damage_trace_render_post_cb);
6484      }
6485
6486    _damage_trace = onoff;
6487 }
6488
6489 EINTERN Eina_Bool
6490 e_comp_object_redirected_get(Evas_Object *obj)
6491 {
6492    API_ENTRY EINA_FALSE;
6493    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
6494
6495    return cw->redirected;
6496 }
6497
6498 EINTERN Eina_Bool
6499 e_comp_object_color_visible_get(Evas_Object *obj)
6500 {
6501    API_ENTRY EINA_FALSE;
6502
6503    return cw->color_visible;
6504 }
6505
6506 E_API Eina_Bool
6507 e_comp_object_map_set(Evas_Object *obj, E_Map *em)
6508 {
6509    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6510
6511    return e_map_set_to_comp_object(em, obj);
6512 }
6513
6514 EINTERN E_Map *
6515 e_comp_object_map_get(const Evas_Object *obj)
6516 {
6517    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
6518
6519    return e_map_get_from_comp_object(obj);
6520 }
6521
6522 E_API Eina_Bool
6523 e_comp_object_map_enable_set(Evas_Object *obj, Eina_Bool enable)
6524 {
6525    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
6526
6527    evas_object_map_enable_set(obj, enable);
6528
6529    return EINA_TRUE;
6530 }
6531
6532 E_API Eina_Bool
6533 e_comp_object_render_update_lock(Evas_Object *obj)
6534 {
6535    E_Comp_Wl_Buffer *buffer;
6536    struct wayland_tbm_client_queue *cqueue;
6537
6538    API_ENTRY EINA_FALSE;
6539
6540    if (cw->render_update_lock.lock == 0)
6541      {
6542         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, cw->ec);
6543
6544         buffer = e_pixmap_resource_get(cw->ec->pixmap);
6545         if ((buffer) && (buffer->resource))
6546           {
6547              cqueue = e_comp_wl_tbm_client_queue_get(cw->ec);
6548              if (cqueue)
6549                wayland_tbm_server_client_queue_flush(cqueue);
6550           }
6551
6552         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, buffer);
6553         e_comp_object_render_update_del(obj);
6554
6555         ELOGF("COMP", "Render update lock enabled", cw->ec);
6556      }
6557
6558    cw->render_update_lock.lock++;
6559
6560    return EINA_TRUE;
6561 }
6562
6563 E_API void
6564 e_comp_object_render_update_unlock(Evas_Object *obj)
6565 {
6566    API_ENTRY;
6567
6568    if (cw->render_update_lock.lock == 0)
6569      return;
6570
6571    cw->render_update_lock.lock--;
6572
6573    if (cw->render_update_lock.lock == 0)
6574      {
6575
6576         if (cw->render_update_lock.pending_move_set)
6577           {
6578              evas_object_move(obj,
6579                               cw->render_update_lock.pending_move_x,
6580                               cw->render_update_lock.pending_move_y);
6581              cw->render_update_lock.pending_move_x = 0;
6582              cw->render_update_lock.pending_move_y = 0;
6583              cw->render_update_lock.pending_move_set = EINA_FALSE;
6584           }
6585
6586         if (cw->render_update_lock.pending_resize_set)
6587           {
6588              evas_object_resize(obj,
6589                                 cw->render_update_lock.pending_resize_w,
6590                                 cw->render_update_lock.pending_resize_h);
6591              cw->render_update_lock.pending_resize_w = 0;
6592              cw->render_update_lock.pending_resize_h = 0;
6593              cw->render_update_lock.pending_resize_set = EINA_FALSE;
6594           }
6595
6596         e_comp_wl_buffer_reference(&cw->render_update_lock.buffer_ref, NULL);
6597
6598         if ((cw->ec->exp_iconify.buffer_flush) &&
6599             (e_policy_visibility_client_is_iconic(cw->ec)) &&
6600             (cw->ec->comp_data) && (!cw->ec->comp_data->buffer_ref.buffer))
6601           e_comp_object_clear(obj);
6602         else
6603           e_comp_object_render_update_add(obj);
6604
6605         _e_comp_object_hook_call(E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_UNSET, cw->ec);
6606
6607         ELOGF("COMP", "Render update lock disabled", cw->ec);
6608      }
6609 }
6610
6611 E_API Eina_Bool
6612 e_comp_object_render_update_lock_get(Evas_Object *obj)
6613 {
6614    API_ENTRY EINA_FALSE;
6615
6616    if (cw->render_update_lock.lock > 0)
6617      return EINA_TRUE;
6618
6619    return EINA_FALSE;
6620 }
6621
6622 E_API void
6623 e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a)
6624 {
6625    API_ENTRY;
6626
6627    if ((cw->transparent.set) || (cw->transparent.setting))
6628      {
6629         if (r) *r = cw->transparent.user_r;
6630         if (g) *g = cw->transparent.user_g;
6631         if (b) *b = cw->transparent.user_b;
6632         if (a) *a = cw->transparent.user_a;
6633      }
6634    else
6635      {
6636         evas_object_color_get(obj, r, g, b, a);
6637      }
6638 }
6639
6640 EINTERN void
6641 e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op)
6642 {
6643    API_ENTRY;
6644
6645    evas_object_render_op_set(cw->obj, op);
6646
6647    wl_signal_emit(&cw->events.render_op_set, NULL);
6648 }
6649
6650 EINTERN Evas_Render_Op
6651 e_comp_object_render_op_get(Evas_Object *obj)
6652 {
6653    API_ENTRY EVAS_RENDER_BLEND;
6654
6655    return evas_object_render_op_get(cw->obj);
6656 }
6657
6658 EINTERN void
6659 e_comp_object_lower_listener_add(Evas_Object *obj, struct wl_listener *listener)
6660 {
6661    API_ENTRY;
6662    wl_signal_add(&cw->events.lower, listener);
6663 }
6664
6665 #ifdef REFACTOR_DESK_AREA
6666 EINTERN void
6667 e_comp_object_lower_done_listener_add(Evas_Object *obj, struct wl_listener *listener)
6668 {
6669    API_ENTRY;
6670    wl_signal_add(&cw->events.lower_done, listener);
6671 }
6672
6673 EINTERN void
6674 e_comp_object_raise_listener_add(Evas_Object *obj, struct wl_listener *listener)
6675 {
6676    API_ENTRY;
6677    wl_signal_add(&cw->events.raise, listener);
6678 }
6679 #endif
6680
6681 EINTERN void
6682 e_comp_object_show_listener_add(Evas_Object *obj, struct wl_listener *listener)
6683 {
6684    API_ENTRY;
6685    wl_signal_add(&cw->events.show, listener);
6686 }
6687
6688 EINTERN void
6689 e_comp_object_hide_listener_add(Evas_Object *obj, struct wl_listener *listener)
6690 {
6691    API_ENTRY;
6692    wl_signal_add(&cw->events.hide, listener);
6693 }
6694
6695 #ifdef REFACTOR_DESK_AREA
6696 EINTERN void
6697 e_comp_object_set_layer_listener_add(Evas_Object *obj, struct wl_listener *listener)
6698 {
6699    API_ENTRY;
6700    wl_signal_add(&cw->events.set_layer, listener);
6701 }
6702
6703 EINTERN void
6704 e_comp_object_stack_above_listener_add(Evas_Object *obj, struct wl_listener *listener)
6705 {
6706    API_ENTRY;
6707    wl_signal_add(&cw->events.stack_above, listener);
6708 }
6709
6710 EINTERN void
6711 e_comp_object_stack_below_listener_add(Evas_Object *obj, struct wl_listener *listener)
6712 {
6713    API_ENTRY;
6714    wl_signal_add(&cw->events.stack_below, listener);
6715 }
6716 #endif
6717
6718 EINTERN void
6719 e_comp_object_image_filter_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6720 {
6721    API_ENTRY;
6722    wl_signal_add(&cw->events.image_filter_set, listener);
6723 }
6724
6725 EINTERN void
6726 e_comp_object_render_op_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6727 {
6728    API_ENTRY;
6729    wl_signal_add(&cw->events.render_op_set, listener);
6730 }
6731
6732 EINTERN void
6733 e_comp_object_content_type_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6734 {
6735    API_ENTRY;
6736    wl_signal_add(&cw->events.content_type_set, listener);
6737 }
6738
6739 EINTERN void
6740 e_comp_object_color_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6741 {
6742    API_ENTRY;
6743    wl_signal_add(&cw->events.color_set, listener);
6744 }
6745
6746 EINTERN void
6747 e_comp_object_color_visible_set_listener_add(Evas_Object *obj, struct wl_listener *listener)
6748 {
6749    API_ENTRY;
6750    wl_signal_add(&cw->events.color_visible_set, listener);
6751 }
6752
6753 EINTERN void
6754 e_comp_object_resize_listener_add(Evas_Object *obj, struct wl_listener *listener)
6755 {
6756    API_ENTRY;
6757    wl_signal_add(&cw->events.resize, listener);
6758 }