cc9f2f1d9c6ec0308bfd907c3dc2348c6dc332ad
[platform/upstream/enlightenment.git] / src / bin / e_comp.c
1 #include "e_comp_intern.h"
2 #include "e_bg_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_screen_intern.h"
7 #include "e_comp_wl_intern.h"
8 #include "e_client_intern.h"
9 #include "e_hwc_intern.h"
10 #include "e_hwc_window_intern.h"
11 #include "e_hwc_windows_intern.h"
12 #include "e_grabinput_intern.h"
13 #include "e_focus_intern.h"
14 #include "e_comp_object_intern.h"
15 #include "e_zone_intern.h"
16 #include "e_config_intern.h"
17 #include "e_screensaver_intern.h"
18 #include "e_hwc_planes_intern.h"
19
20 #include <sys/xattr.h>
21 #include <sys/types.h>
22 #include <grp.h>
23 #include <pwd.h>
24
25 #define OVER_FLOW 1
26 //////////////////////////////////////////////////////////////////////////
27 //
28 // TODO (no specific order):
29 //   1. abstract evas object and compwin so we can duplicate the object N times
30 //      in N canvases - for winlist, everything, pager etc. too
31 //   2. implement "unmapped composite cache" -> N pixels worth of unmapped
32 //      windows to be fully composited. only the most active/recent.
33 //   3. for unmapped windows - when window goes out of unmapped comp cache
34 //      make a miniature copy (1/4 width+height?) and set property on window
35 //      with pixmap id
36 //
37 //////////////////////////////////////////////////////////////////////////
38
39 static Eina_List *handlers = NULL;
40 static Eina_List *hooks = NULL;
41 E_API E_Comp *e_comp = NULL;
42 E_API E_Comp_Wl_Data *e_comp_wl = NULL;
43 static Eina_Hash *ignores = NULL;
44 static Eina_List *actions = NULL;
45
46 static E_Comp_Config *conf = NULL;
47 static E_Config_DD *conf_edd = NULL;
48 static E_Config_DD *conf_match_edd = NULL;
49
50 static Ecore_Timer *action_timeout = NULL;
51 static Eina_Bool gl_avail = EINA_FALSE;
52
53 static double ecore_frametime = 0;
54
55 static int _e_comp_log_dom = -1;
56
57 static int _e_comp_hooks_delete = 0;
58 static int _e_comp_hooks_walking = 0;
59
60 static Eina_Bool _e_calc_visibility = EINA_FALSE;
61
62 static Eina_Inlist *_e_comp_hooks[] =
63 {
64    [E_COMP_HOOK_PREPARE_PLANE] = NULL,
65 };
66
67 E_API int E_EVENT_COMPOSITOR_DISABLE = -1;
68 E_API int E_EVENT_COMPOSITOR_ENABLE = -1;
69
70 //////////////////////////////////////////////////////////////////////////
71 #undef DBG
72 #undef INF
73 #undef WRN
74 #undef ERR
75 #undef CRI
76
77 #define DBG(...)            EINA_LOG_DOM_DBG(_e_comp_log_dom, __VA_ARGS__)
78 #define INF(...)            EINA_LOG_DOM_INFO(_e_comp_log_dom, __VA_ARGS__)
79 #define WRN(...)            EINA_LOG_DOM_WARN(_e_comp_log_dom, __VA_ARGS__)
80 #define ERR(...)            EINA_LOG_DOM_ERR(_e_comp_log_dom, __VA_ARGS__)
81 #define CRI(...)            EINA_LOG_DOM_CRIT(_e_comp_log_dom, __VA_ARGS__)
82
83 static void
84 _e_comp_fps_update(void)
85 {
86    static double rtime = 0.0;
87    static double rlapse = 0.0;
88    static int frames = 0;
89    static int flapse = 0;
90    double dt;
91    double tim = ecore_time_get();
92
93    /* calculate fps */
94    dt = tim - e_comp->frametimes[0];
95    e_comp->frametimes[0] = tim;
96
97    rtime += dt;
98    frames++;
99
100    if (rlapse == 0.0)
101      {
102         rlapse = tim;
103         flapse = frames;
104      }
105    else if ((tim - rlapse) >= 0.5)
106      {
107         e_comp->fps = (frames - flapse) / (tim - rlapse);
108         rlapse = tim;
109         flapse = frames;
110         rtime = 0.0;
111      }
112
113    if (conf->fps_show)
114      {
115         if (e_comp->fps_bg && e_comp->fps_fg)
116           {
117              char buf[128];
118              Evas_Coord x = 0, y = 0, w = 0, h = 0;
119              E_Zone *z;
120
121              if (e_comp->fps > 0.0) snprintf(buf, sizeof(buf), "FPS: %1.1f", e_comp->fps);
122              else snprintf(buf, sizeof(buf), "N/A");
123              evas_object_text_text_set(e_comp->fps_fg, buf);
124
125              evas_object_geometry_get(e_comp->fps_fg, NULL, NULL, &w, &h);
126              w += 8;
127              h += 8;
128              z = e_zone_current_get();
129              if (z)
130                {
131                   switch (conf->fps_corner)
132                     {
133                      case 3: // bottom-right
134                         x = z->x + z->w - w;
135                         y = z->y + z->h - h;
136                         break;
137
138                      case 2: // bottom-left
139                         x = z->x;
140                         y = z->y + z->h - h;
141                         break;
142
143                      case 1: // top-right
144                         x = z->x + z->w - w;
145                         y = z->y;
146                         break;
147                      default: // 0 // top-left
148                         x = z->x;
149                         y = z->y;
150                         break;
151                     }
152                }
153              evas_object_move(e_comp->fps_bg, x, y);
154              evas_object_resize(e_comp->fps_bg, w, h);
155              evas_object_move(e_comp->fps_fg, x + 4, y + 4);
156           }
157         else
158           {
159              e_comp->fps_bg = evas_object_rectangle_add(e_comp->evas);
160              evas_object_color_set(e_comp->fps_bg, 0, 0, 0, 128);
161              evas_object_layer_set(e_comp->fps_bg, E_LAYER_MAX);
162              evas_object_name_set(e_comp->fps_bg, "e_comp->fps_bg");
163              evas_object_lower(e_comp->fps_bg);
164              evas_object_show(e_comp->fps_bg);
165
166              e_comp->fps_fg = evas_object_text_add(e_comp->evas);
167              evas_object_text_font_set(e_comp->fps_fg, "Sans", 10);
168              evas_object_text_text_set(e_comp->fps_fg, "???");
169              evas_object_color_set(e_comp->fps_fg, 255, 255, 255, 255);
170              evas_object_layer_set(e_comp->fps_fg, E_LAYER_MAX);
171              evas_object_name_set(e_comp->fps_bg, "e_comp->fps_fg");
172              evas_object_stack_above(e_comp->fps_fg, e_comp->fps_bg);
173              evas_object_show(e_comp->fps_fg);
174           }
175      }
176    else
177      {
178         E_FREE_FUNC(e_comp->fps_fg, evas_object_del);
179         E_FREE_FUNC(e_comp->fps_bg, evas_object_del);
180      }
181 }
182
183 static void
184 _e_comp_hooks_clean(void)
185 {
186    Eina_Inlist *l;
187    E_Comp_Hook *ch;
188    unsigned int x;
189
190    for (x = 0; x < E_COMP_HOOK_LAST; x++)
191      EINA_INLIST_FOREACH_SAFE(_e_comp_hooks[x], l, ch)
192        {
193           if (!ch->delete_me) continue;
194           _e_comp_hooks[x] = eina_inlist_remove(_e_comp_hooks[x],
195                                                 EINA_INLIST_GET(ch));
196           free(ch);
197        }
198 }
199
200 EINTERN void
201 e_comp_hook_call(E_Comp_Hook_Point hookpoint, void *data EINA_UNUSED)
202 {
203    E_Comp_Hook *ch;
204
205    _e_comp_hooks_walking++;
206    EINA_INLIST_FOREACH(_e_comp_hooks[hookpoint], ch)
207      {
208         if (ch->delete_me) continue;
209         ch->func(ch->data, NULL);
210      }
211    _e_comp_hooks_walking--;
212    if ((_e_comp_hooks_walking == 0) && (_e_comp_hooks_delete > 0))
213      _e_comp_hooks_clean();
214 }
215
216 static Eina_Bool
217 _e_comp_cb_update(void)
218 {
219    E_Client *ec;
220    Eina_List *l;
221    int pw, ph, w, h;
222    Eina_Bool res;
223
224    if (!e_comp) return EINA_FALSE;
225
226    TRACE_DS_BEGIN(COMP:UPDATE CB);
227
228    if (e_comp->update_job)
229      e_comp->update_job = NULL;
230    else
231      ecore_animator_freeze(e_comp->render_animator);
232
233    DBG("UPDATE ALL");
234
235    if (conf->grab && (!e_comp->grabbed))
236      {
237         if (e_comp->grab_cb) e_comp->grab_cb();
238         e_comp->grabbed = 1;
239      }
240    l = e_comp->updates;
241    e_comp->updates = NULL;
242    EINA_LIST_FREE(l, ec)
243      {
244         /* clear update flag */
245         e_comp_object_render_update_del(ec->frame);
246
247         if (e_object_is_del(E_OBJECT(ec))) continue;
248         if (e_comp->hwc && e_comp_is_on_overlay(ec)) continue;
249
250         /* update client */
251         e_pixmap_size_get(ec->pixmap, &pw, &ph);
252
253         if (e_pixmap_dirty_get(ec->pixmap))
254           {
255              if (e_pixmap_refresh(ec->pixmap) &&
256                  e_pixmap_size_get(ec->pixmap, &w, &h) &&
257                  e_pixmap_size_changed(ec->pixmap, pw, ph))
258                {
259                   e_pixmap_image_clear(ec->pixmap, 0);
260                }
261              else if (!e_pixmap_size_get(ec->pixmap, NULL, NULL))
262                {
263                   WRN("FAIL %p", ec);
264                   /* if client pixmap is not valid while checking updates list in job cb handler
265                      than let evas object as it is and make no updats on. */
266                }
267           }
268
269         res = e_pixmap_size_get(ec->pixmap, &pw, &ph);
270         if (!res) continue;
271
272         e_pixmap_image_refresh(ec->pixmap);
273         e_comp_object_dirty(ec->frame);
274      }
275
276    if (conf->grab && e_comp->grabbed)
277      {
278         if (e_comp->grab_cb) e_comp->grab_cb();
279         e_comp->grabbed = 0;
280      }
281    if (e_comp->updates && (!e_comp->update_job))
282      ecore_animator_thaw(e_comp->render_animator);
283
284    TRACE_DS_END();
285
286    return ECORE_CALLBACK_RENEW;
287 }
288
289 static void
290 _e_comp_cb_job(void *data EINA_UNUSED)
291 {
292    DBG("UPDATE ALL JOB...");
293    _e_comp_cb_update();
294 }
295
296 static Eina_Bool
297 _e_comp_cb_animator(void *data EINA_UNUSED)
298 {
299    return _e_comp_cb_update();
300 }
301
302 static Eina_Bool
303 _e_comp_signal_user(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Event_Signal_User *ev)
304 {
305    if (ev->number == 1)
306      {
307         // e uses this to pop up config panel
308      }
309    else if (ev->number == 2)
310      {
311         e_comp_canvas_fps_toggle();
312      }
313    return ECORE_CALLBACK_PASS_ON;
314 }
315
316 //////////////////////////////////////////////////////////////////////////
317
318 static void
319 _e_comp_free(E_Comp *c)
320 {
321    Eina_List *l, *ll;
322    E_Zone *zone;
323
324    EINA_LIST_FOREACH_SAFE(c->zones, l, ll, zone)
325      {
326         e_object_del(E_OBJECT(zone));
327      }
328
329    e_comp_canvas_clear();
330
331    ecore_evas_free(c->ee);
332    eina_stringshare_del(c->name);
333
334    if (c->render_animator) ecore_animator_del(c->render_animator);
335    if (c->update_job) ecore_job_del(c->update_job);
336    if (c->nocomp_delay_timer) ecore_timer_del(c->nocomp_delay_timer);
337    if (c->nocomp_override_timer) ecore_timer_del(c->nocomp_override_timer);
338
339    free(c);
340 }
341
342 //////////////////////////////////////////////////////////////////////////
343
344 static Eina_Bool
345 _e_comp_object_add(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
346 {
347    return ECORE_CALLBACK_RENEW;
348 }
349
350 static Eina_Bool
351 _e_comp_override_expire(void *data EINA_UNUSED)
352 {
353    e_comp->nocomp_override_timer = NULL;
354    e_comp->nocomp_override--;
355
356    if (e_comp->nocomp_override <= 0)
357      {
358         e_comp->nocomp_override = 0;
359         e_comp_render_queue();
360      }
361    return EINA_FALSE;
362 }
363
364 //////////////////////////////////////////////////////////////////////////
365
366 static Eina_Bool
367 _e_comp_screensaver_on(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
368 {
369    return ECORE_CALLBACK_PASS_ON;
370 }
371
372 static Eina_Bool
373 _e_comp_screensaver_off(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
374 {
375    return ECORE_CALLBACK_PASS_ON;
376 }
377
378 //////////////////////////////////////////////////////////////////////////
379
380 EINTERN Eina_Bool
381 e_comp_init(void)
382 {
383    _e_comp_log_dom = eina_log_domain_register("e_comp", EINA_COLOR_YELLOW);
384    eina_log_domain_level_set("e_comp", EINA_LOG_LEVEL_INFO);
385
386    ecore_frametime = ecore_animator_frametime_get();
387
388    E_EVENT_COMPOSITOR_DISABLE = ecore_event_type_new();
389    E_EVENT_COMPOSITOR_ENABLE = ecore_event_type_new();
390
391    ignores = eina_hash_pointer_new(NULL);
392
393    e_main_ts_begin("\tE_Comp_Data Init");
394    e_comp_cfdata_edd_init(&conf_edd, &conf_match_edd);
395    e_main_ts_end("\tE_Comp_Data Init Done");
396
397    e_main_ts_begin("\tE_Comp_Data Load");
398    conf = e_config_domain_load("e_comp", conf_edd);
399    e_main_ts_end("\tE_Comp_Data Load Done");
400
401    if (!conf)
402      {
403         e_main_ts_begin("\tE_Comp_Data New");
404         conf = e_comp_cfdata_config_new();
405         e_main_ts_end("\tE_Comp_Data New Done");
406      }
407
408    // comp config versioning - add this in. over time add epochs etc. if
409    // necessary, but for now a simple version number will do
410    if (conf->version < E_COMP_VERSION)
411      {
412         switch (conf->version)
413           {
414            case 0:
415              // going from version 0 we should disable grab for smoothness
416              conf->grab = 0;
417              /* fallthrough */
418            default:
419              break;
420           }
421         e_config_save_queue();
422         conf->version = E_COMP_VERSION;
423      }
424
425    e_comp_object_init();
426    e_comp_new();
427
428    /* conf->hwc configuration has to be check before e_comp_screen_init() */
429    if (conf->hwc)
430      e_comp->hwc = EINA_TRUE; // activate hwc policy on the primary output
431
432    if (conf->avoid_afill) e_comp->avoid_afill = EINA_TRUE;
433    if (conf->hwc_prefer_gbm) e_comp->hwc_prefer_gbm = EINA_TRUE;
434
435    e_main_ts_begin("\tE_Comp_Screen Init");
436    if (!e_comp_screen_init())
437      {
438         e_main_ts_end("\tE_Comp_Screen Init Failed");
439         ERR("Fail to init e_comp_screen");
440         e_object_del(E_OBJECT(e_comp));
441         E_FREE_FUNC(ignores, eina_hash_free);
442         return EINA_FALSE;
443      }
444    e_main_ts_end("\tE_Comp_Screen Init Done");
445
446    if (e_comp->hwc)
447      {
448         if (conf->hwc_deactive) e_comp_hwc_deactive_set(EINA_TRUE);
449         if (conf->hwc_reuse_cursor_buffer) e_comp->hwc_reuse_cursor_buffer = EINA_TRUE;
450
451         if (conf->hwc_use_multi_plane) e_comp_hwc_multi_plane_set(EINA_TRUE);
452         if (conf->hwc_sync_mode_change) e_comp->hwc_sync_mode_change = EINA_TRUE;
453         if (conf->hwc_use_detach) e_comp->hwc_use_detach = EINA_TRUE;
454         if (conf->hwc_ignore_primary) e_comp->hwc_ignore_primary = EINA_TRUE;
455         if (conf->hwc_send_redraw_request) e_comp->hwc_send_redraw_request = EINA_TRUE;
456      }
457
458    // use wl_surface instead of tbm_surface for the e_comp_wl_buffer
459    if (conf->use_native_type_buffer) e_comp->use_native_type_buffer = EINA_TRUE;
460
461    if (conf->canvas_render_delay_after_boot) e_comp->canvas_render_delayed = EINA_TRUE;
462
463    if ((conf->commit_handler_timer.use) && (conf->commit_handler_timer.interval))
464      {
465         e_comp->commit_handler_timer.use = EINA_TRUE;
466         e_comp->commit_handler_timer.interval = conf->commit_handler_timer.interval;
467      }
468
469 #ifdef REFACTOR_DESK_AREA
470 #else
471    e_comp_canvas_fake_layers_init();
472 #endif
473
474    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON,  _e_comp_screensaver_on,  NULL);
475    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_OFF, _e_comp_screensaver_off, NULL);
476    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_SIGNAL_USER, _e_comp_signal_user,     NULL);
477    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _e_comp_object_add,      NULL);
478
479    g_rec_mutex_init(&e_comp->ec_list_mutex);
480
481    return EINA_TRUE;
482 }
483
484 EINTERN E_Comp *
485 e_comp_new(void)
486 {
487    if (e_comp)
488      CRI("CANNOT REPLACE EXISTING COMPOSITOR");
489    e_comp = E_OBJECT_ALLOC(E_Comp, E_COMP_TYPE, _e_comp_free);
490    if (!e_comp) return NULL;
491
492    e_comp->name = eina_stringshare_add(_("Compositor"));
493    e_comp->render_animator = ecore_animator_add(_e_comp_cb_animator, NULL);
494    ecore_animator_freeze(e_comp->render_animator);
495    return e_comp;
496 }
497
498 EINTERN int
499 e_comp_internal_save(void)
500 {
501    return e_config_domain_save("e_comp", conf_edd, conf);
502 }
503
504 EINTERN int
505 e_comp_shutdown(void)
506 {
507    Eina_List *l, *ll;
508    E_Client *ec;
509
510    E_FREE_FUNC(action_timeout, ecore_timer_del);
511    EINA_LIST_FOREACH_SAFE(e_comp->clients, l, ll, ec)
512      {
513         DELD(ec, 99999);
514         e_object_del(E_OBJECT(ec));
515      }
516
517    e_comp_wl_shutdown();
518    e_comp_screen_shutdown();
519
520    e_object_del(E_OBJECT(e_comp));
521    e_comp_object_shutdown();
522    E_FREE_LIST(handlers, ecore_event_handler_del);
523    E_FREE_LIST(actions, e_object_del);
524    E_FREE_LIST(hooks, e_client_hook_del);
525
526    gl_avail = EINA_FALSE;
527    e_comp_cfdata_config_free(conf);
528    E_CONFIG_DD_FREE(conf_match_edd);
529    E_CONFIG_DD_FREE(conf_edd);
530    conf = NULL;
531    conf_match_edd = NULL;
532    conf_edd = NULL;
533
534    E_FREE_FUNC(ignores, eina_hash_free);
535
536    g_rec_mutex_clear(&e_comp->ec_list_mutex);
537
538    return 1;
539 }
540
541 EINTERN void
542 e_comp_deferred_job(void)
543 {
544    /* Bg update */
545    e_main_ts_begin("\tE_BG_Zone Update");
546    E_Zone *zone = NULL;
547    zone = e_zone_current_get();
548    EINA_SAFETY_ON_NULL_GOTO(zone, comp_wl_job);
549    if (zone->bg_object)
550      e_bg_zone_update(zone, E_BG_TRANSITION_DESK);
551    else
552      e_bg_zone_update(zone, E_BG_TRANSITION_START);
553    e_main_ts_end("\tE_BG_Zone Update Done");
554
555 comp_wl_job:
556    e_main_ts_begin("\tE_Comp_Wl_Deferred");
557    e_comp_wl_deferred_job();
558    e_main_ts_end("\tE_Comp_Wl_Deferred Done");
559 }
560
561 E_API void
562 e_comp_render_queue(void)
563 {
564    if (e_comp->update_job)
565       {
566          DBG("UPDATE JOB DEL...");
567          E_FREE_FUNC(e_comp->update_job, ecore_job_del);
568       }
569    DBG("UPDATE JOB ADD...");
570    e_comp->update_job = ecore_job_add(_e_comp_cb_job, e_comp);
571 }
572
573 EINTERN void
574 e_comp_client_post_update_add(E_Client *ec)
575 {
576    if (ec->on_post_updates) return;
577    ec->on_post_updates = EINA_TRUE;
578    e_comp->post_updates = eina_list_append(e_comp->post_updates, ec);
579    REFD(ec, 111);
580    e_object_ref(E_OBJECT(ec));
581 }
582
583 EINTERN void
584 e_comp_client_render_list_add(E_Client *ec)
585 {
586    if (ec->on_render_list) return;
587    ec->on_render_list = EINA_TRUE;
588    e_comp->render_list = eina_list_append(e_comp->render_list, ec);
589    REFD(ec, 111);
590    e_object_ref(E_OBJECT(ec));
591 }
592
593 E_API E_Comp_Config *
594 e_comp_config_get(void)
595 {
596    return conf;
597 }
598
599 EINTERN void
600 e_comp_shadows_reset(void)
601 {
602    E_Client *ec;
603
604    _e_comp_fps_update();
605    E_LIST_FOREACH(e_comp->zones, e_comp_canvas_zone_update);
606    E_CLIENT_FOREACH(ec)
607      e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
608 }
609
610 EINTERN Ecore_Window
611 e_comp_top_window_at_xy_get(Evas_Coord x, Evas_Coord y)
612 {
613    E_Client *ec;
614    Evas_Object *o;
615
616    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, 0);
617    o = evas_object_top_at_xy_get(e_comp->evas, x, y, 0, 0);
618    if (!o) return e_comp->ee_win;
619    ec = evas_object_data_get(o, "E_Client");
620    if (ec) return e_client_util_pwin_get(ec);
621    return e_comp->ee_win;
622 }
623
624 EINTERN void
625 e_comp_util_wins_print(void)
626 {
627    Evas_Object *o;
628
629    o = evas_object_top_get(e_comp->evas);
630    while (o)
631      {
632         E_Client *ec;
633         int x, y, w, h;
634
635         ec = evas_object_data_get(o, "E_Client");
636         evas_object_geometry_get(o, &x, &y, &w, &h);
637         fprintf(stderr, "LAYER %d  ", evas_object_layer_get(o));
638         if (ec)
639 #if defined(__cplusplus) || defined(c_plusplus)
640           fprintf(stderr, "EC%s%s:  %p - '%s:%s' || %d,%d @ %dx%d\n",
641                   ec->override ? "O" : "", ec->focused ? "*" : "", ec,
642                   e_client_util_name_get(ec) ?: ec->icccm.name, ec->icccm.cpp_class, x, y, w, h);
643 #else
644           fprintf(stderr, "EC%s%s:  %p - '%s:%s' || %d,%d @ %dx%d\n",
645                   ec->override ? "O" : "", ec->focused ? "*" : "", ec,
646                   e_client_util_name_get(ec) ?: ec->icccm.name, ec->icccm.class, x, y, w, h);
647 #endif
648        else
649           fprintf(stderr, "OBJ: %p - %s || %d,%d @ %dx%d\n", o, evas_object_name_get(o), x, y, w, h);
650         o = evas_object_below_get(o);
651      }
652    fputc('\n', stderr);
653 }
654
655 EINTERN void
656 e_comp_ignore_win_add(E_Pixmap_Type type, Ecore_Window win)
657 {
658    E_Client *ec;
659
660    eina_hash_add(ignores, &win, (void*)1);
661    ec = e_pixmap_find_client(type, win);
662    if (!ec) return;
663    ec->ignored = 1;
664    if (ec->visible) evas_object_hide(ec->frame);
665 }
666
667 EINTERN void
668 e_comp_ignore_win_del(E_Pixmap_Type type, Ecore_Window win)
669 {
670    E_Client *ec;
671
672    eina_hash_del_by_key(ignores, &win);
673    ec = e_pixmap_find_client(type, win);
674    if ((!ec) || (e_object_is_del(E_OBJECT(ec)))) return;
675    ec->ignored = 0;
676    if (ec->visible) evas_object_show(ec->frame);
677 }
678
679 EINTERN Eina_Bool
680 e_comp_ignore_win_find(Ecore_Window win)
681 {
682    return !!eina_hash_find(ignores, &win);
683 }
684
685 E_API void
686 e_comp_override_del()
687 {
688    e_comp->nocomp_override--;
689    if (e_comp->nocomp_override <= 0)
690      {
691         e_comp->nocomp_override = 0;
692         e_comp_render_queue();
693      }
694 }
695
696 E_API void
697 e_comp_override_add()
698 {
699    e_comp->nocomp_override++;
700    if (e_comp->nocomp_override > 0)
701      {
702         // go full compositing
703         e_comp_hwc_end(__FUNCTION__);
704      }
705 }
706
707 E_API void
708 e_comp_client_override_del(E_Client *ec)
709 {
710    if (!ec) return;
711
712    ec->comp_override--;
713    if (ec->comp_override <= 0)
714      {
715         ec->comp_override = 0;
716         e_comp_render_queue();
717      }
718 }
719
720 E_API void
721 e_comp_client_override_add(E_Client *ec)
722 {
723    if (!ec) return;
724
725    ec->comp_override++;
726    if (ec->comp_override > 0)
727      e_comp_hwc_client_end(ec, __FUNCTION__);
728 }
729
730 EINTERN E_Comp *
731 e_comp_find_by_window(Ecore_Window win)
732 {
733    if ((e_comp->win == win) || (e_comp->ee_win == win) || (e_comp->root == win)) return e_comp;
734    return NULL;
735 }
736
737 EINTERN void
738 e_comp_override_timed_pop(void)
739 {
740    if (e_comp->nocomp_override <= 0) return;
741    if (e_comp->nocomp_override_timer)
742      e_comp->nocomp_override--;
743    else
744      e_comp->nocomp_override_timer = ecore_timer_add(1.0, _e_comp_override_expire, NULL);
745 }
746
747 E_API void
748 e_comp_layer_name_get(unsigned int layer, char *buff, int buff_size)
749 {
750    if (!buff) return;
751
752    switch(layer)
753      {
754       case E_LAYER_BOTTOM: strncpy(buff, "E_LAYER_BOTTOM", buff_size); break;
755       case E_LAYER_BG: strncpy(buff, "E_LAYER_BG", buff_size); break;
756       case E_LAYER_DESKTOP: strncpy(buff, "E_LAYER_DESKTOP", buff_size); break;
757       case E_LAYER_DESKTOP_TOP: strncpy(buff, "E_LAYER_DESKTOP_TOP", buff_size); break;
758       case E_LAYER_CLIENT_DESKTOP: strncpy(buff, "E_LAYER_CLIENT_DESKTOP", buff_size); break;
759       case E_LAYER_CLIENT_BELOW: strncpy(buff, "E_LAYER_CLIENT_BELOW", buff_size); break;
760       case E_LAYER_CLIENT_NORMAL: strncpy(buff, "E_LAYER_CLIENT_NORMAL", buff_size); break;
761       case E_LAYER_CLIENT_ABOVE: strncpy(buff, "E_LAYER_CLIENT_ABOVE", buff_size); break;
762       case E_LAYER_CLIENT_EDGE: strncpy(buff, "E_LAYER_CLIENT_EDGE", buff_size); break;
763       case E_LAYER_CLIENT_FULLSCREEN: strncpy(buff, "E_LAYER_CLIENT_FULLSCREEN", buff_size); break;
764       case E_LAYER_CLIENT_EDGE_FULLSCREEN: strncpy(buff, "E_LAYER_CLIENT_EDGE_FULLSCREEN", buff_size); break;
765       case E_LAYER_CLIENT_POPUP: strncpy(buff, "E_LAYER_CLIENT_POPUP", buff_size); break;
766       case E_LAYER_CLIENT_TOP: strncpy(buff, "E_LAYER_CLIENT_TOP", buff_size); break;
767       case E_LAYER_CLIENT_PRIO: strncpy(buff, "E_LAYER_CLIENT_PRIO", buff_size); break;
768       case E_LAYER_CLIENT_NOTIFICATION_LOW: strncpy(buff, "E_LAYER_CLIENT_NOTIFICATION_LOW", buff_size); break;
769       case E_LAYER_CLIENT_NOTIFICATION_NORMAL: strncpy(buff, "E_LAYER_CLIENT_NOTIFICATION_NORMAL", buff_size); break;
770       case E_LAYER_CLIENT_NOTIFICATION_HIGH: strncpy(buff, "E_LAYER_CLIENT_NOTIFICATION_HIGH", buff_size); break;
771       case E_LAYER_CLIENT_NOTIFICATION_TOP: strncpy(buff, "E_LAYER_CLIENT_NOTIFICATION_TOP", buff_size); break;
772       case E_LAYER_CLIENT_ALERT_LOW: strncpy(buff, "E_LAYER_CLIENT_ALERT_LOW", buff_size); break;
773       case E_LAYER_CLIENT_ALERT: strncpy(buff, "E_LAYER_CLIENT_ALERT", buff_size); break;
774       case E_LAYER_CLIENT_ALERT_HIGH: strncpy(buff, "E_LAYER_CLIENT_ALERT_HIGH", buff_size); break;
775       case E_LAYER_CLIENT_DRAG: strncpy(buff, "E_LAYER_CLIENT_DRAG", buff_size); break;
776       case E_LAYER_CLIENT_CURSOR: strncpy(buff, "E_LAYER_CLIENT_CURSOR", buff_size); break;
777       case E_LAYER_POPUP: strncpy(buff, "E_LAYER_POPUP", buff_size); break;
778       case E_LAYER_EFFECT: strncpy(buff, "E_LAYER_EFFECT", buff_size); break;
779       case E_LAYER_DESK_OBJECT_BELOW: strncpy(buff, "E_LAYER_DESK_OBJECT_BELOW", buff_size); break;
780       case E_LAYER_DESK_OBJECT: strncpy(buff, "E_LAYER_DESK_OBJECT", buff_size); break;
781       case E_LAYER_DESK_OBJECT_ABOVE: strncpy(buff, "E_LAYER_DESK_OBJECT_ABOVE", buff_size); break;
782       case E_LAYER_MENU: strncpy(buff, "E_LAYER_MENU", buff_size); break;
783       case E_LAYER_DESKLOCK: strncpy(buff, "E_LAYER_DESKLOCK", buff_size); break;
784       case E_LAYER_MAX: strncpy(buff, "E_LAYER_MAX", buff_size); break;
785       default:strncpy(buff, "E_LAYER_NONE", buff_size); break;
786      }
787 }
788
789 E_API Eina_Bool
790 e_comp_grab_input(Eina_Bool mouse, Eina_Bool kbd)
791 {
792    Eina_Bool ret = EINA_FALSE;
793    Ecore_Window mwin = 0, kwin = 0;
794
795    mouse = !!mouse;
796    kbd = !!kbd;
797    if (mouse || e_comp->input_mouse_grabs)
798      mwin = e_comp->ee_win;
799    if (kbd || e_comp->input_mouse_grabs)
800      kwin = e_comp->ee_win;
801    //e_comp_override_add(); //nocomp condition
802    if ((e_comp->input_mouse_grabs && e_comp->input_key_grabs) ||
803        e_grabinput_get(mwin, 0, kwin))
804      {
805         ret = EINA_TRUE;
806         e_comp->input_mouse_grabs += mouse;
807         e_comp->input_key_grabs += kbd;
808      }
809
810    return ret;
811 }
812
813 E_API void
814 e_comp_ungrab_input(Eina_Bool mouse, Eina_Bool kbd)
815 {
816    Ecore_Window mwin = 0, kwin = 0;
817
818    mouse = !!mouse;
819    kbd = !!kbd;
820    if (e_comp->input_mouse_grabs)
821      e_comp->input_mouse_grabs -= mouse;
822
823    if (e_comp->input_key_grabs)
824      e_comp->input_key_grabs -= kbd;
825
826    if (mouse && (!e_comp->input_mouse_grabs))
827      mwin = e_comp->ee_win;
828
829    if (kbd && (!e_comp->input_key_grabs))
830      kwin = e_comp->ee_win;
831
832    //e_comp_override_timed_pop(); //nocomp condition
833    if ((!mwin) && (!kwin)) return;
834    e_grabinput_release(mwin, kwin);
835    evas_event_feed_mouse_out(e_comp->evas, 0, NULL);
836    evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
837    if (e_client_focused_get()) return;
838
839    E_Zone *zone = e_zone_current_get();
840    if (!zone) return;
841
842    e_zone_focus_reset(zone);
843 }
844
845 EINTERN Eina_Bool
846 e_comp_util_kbd_grabbed(void)
847 {
848    return e_client_action_get() || e_grabinput_key_win_get();
849 }
850
851 EINTERN Eina_Bool
852 e_comp_util_mouse_grabbed(void)
853 {
854    return e_client_action_get() || e_grabinput_mouse_win_get();
855 }
856
857 EINTERN void
858 e_comp_gl_set(Eina_Bool set)
859 {
860    gl_avail = !!set;
861 }
862
863 EINTERN Eina_Bool
864 e_comp_gl_get(void)
865 {
866    return gl_avail;
867 }
868
869 EINTERN void
870 e_comp_button_bindings_ungrab_all(void)
871 {
872    if (e_comp->bindings_ungrab_cb)
873      e_comp->bindings_ungrab_cb();
874 }
875
876 EINTERN void
877 e_comp_button_bindings_grab_all(void)
878 {
879    if (e_comp->bindings_grab_cb)
880      e_comp->bindings_grab_cb();
881 }
882
883 EINTERN Eina_Bool
884 e_comp_util_object_is_above_nocomp(Evas_Object *obj)
885 {
886    Evas_Object *o;
887    int cl, ol;
888
889    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
890    if (!evas_object_visible_get(obj)) return EINA_FALSE;
891    if (!e_comp->nocomp_ec) return EINA_FALSE;
892    cl = evas_object_layer_get(e_comp->nocomp_ec->frame);
893    ol = evas_object_layer_get(obj);
894    if (cl > ol) return EINA_FALSE;
895    o = evas_object_above_get(e_comp->nocomp_ec->frame);
896    if ((cl == ol) && (evas_object_layer_get(o) == cl))
897      {
898         do {
899            if (o == obj)
900              return EINA_TRUE;
901            o = evas_object_above_get(o);
902         } while (o && (evas_object_layer_get(o) == cl));
903      }
904    else
905      return EINA_TRUE;
906    return EINA_FALSE;
907 }
908
909 E_API E_Comp_Hook *
910 e_comp_hook_add(E_Comp_Hook_Point hookpoint, E_Comp_Hook_Cb func, const void *data)
911 {
912    E_Comp_Hook *ch;
913
914    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_HOOK_LAST, NULL);
915    ch = E_NEW(E_Comp_Hook, 1);
916    EINA_SAFETY_ON_NULL_RETURN_VAL(ch, NULL);
917    ch->hookpoint = hookpoint;
918    ch->func = func;
919    ch->data = (void*)data;
920    _e_comp_hooks[hookpoint] = eina_inlist_append(_e_comp_hooks[hookpoint],
921                                                  EINA_INLIST_GET(ch));
922    return ch;
923 }
924
925 E_API void
926 e_comp_hook_del(E_Comp_Hook *ch)
927 {
928    ch->delete_me = 1;
929    if (_e_comp_hooks_walking == 0)
930      {
931         _e_comp_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_hooks[ch->hookpoint],
932                                                           EINA_INLIST_GET(ch));
933         free(ch);
934      }
935    else
936      _e_comp_hooks_delete++;
937 }
938
939 EINTERN Eina_Bool
940 e_comp_is_on_overlay(E_Client *ec)
941 {
942    Eina_List *l, *ll;
943    E_Output *eout;
944    E_Plane *ep;
945    E_Hwc_Window *hwc_window;
946    E_Zone *zone;
947
948    EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec, EINA_FALSE);
949    zone = e_comp_zone_find_by_ec(ec);
950    EINA_SAFETY_ON_TRUE_RETURN_VAL(!zone, EINA_FALSE);
951    EINA_SAFETY_ON_TRUE_RETURN_VAL(!zone->output_id, EINA_FALSE);
952
953    eout = e_output_find(zone->output_id);
954    if (!eout) return EINA_FALSE;
955
956    if (e_hwc_policy_get(eout->hwc) == E_HWC_POLICY_PLANES)
957      {
958         if (!e_hwc_mode_get(eout->hwc)) return EINA_FALSE;
959
960         EINA_LIST_FOREACH_SAFE(eout->planes, l, ll, ep)
961           {
962              E_Client *overlay_ec = ep->ec;
963              if (overlay_ec == ec) return EINA_TRUE;
964           }
965      }
966    else
967      {
968         hwc_window = ec->hwc_window;
969         if (!hwc_window) return EINA_FALSE;
970
971         if (e_hwc_window_is_on_hw_overlay(hwc_window)) return EINA_TRUE;
972      }
973
974    return EINA_FALSE;
975 }
976
977 EINTERN E_Zone *
978 e_comp_zone_find(const char *output_id)
979 {
980    Eina_List *l = NULL;
981    E_Zone *zone = NULL;
982
983    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
984    EINA_SAFETY_ON_NULL_RETURN_VAL(output_id, NULL);
985
986    EINA_LIST_FOREACH(e_comp->zones, l, zone)
987      {
988         if (!zone) continue;
989         if (!strcmp(zone->output_id, output_id)) return zone;
990      }
991
992    return NULL;
993 }
994
995
996 E_API Eina_List *
997 e_comp_vis_ec_list_get(E_Zone *zone)
998 {
999    Eina_List *ec_list = NULL;
1000    E_Client  *ec;
1001    Evas_Object *o;
1002
1003    E_OBJECT_CHECK_RETURN(zone, NULL);
1004    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
1005
1006    // TODO: check if eout is available to use hwc policy
1007    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
1008      {
1009         int x, y, w, h;
1010         int scr_w, scr_h;
1011
1012         ec = evas_object_data_get(o, "E_Client");
1013         if (!ec) continue;
1014         if (e_object_is_del(E_OBJECT(ec))) continue;
1015
1016         if (e_comp_zone_find_by_ec(ec) != zone) continue;
1017
1018         // check clients to skip composite
1019         if (e_client_util_ignored_get(ec) || (!evas_object_visible_get(ec->frame)))
1020           continue;
1021
1022         // check geometry if located out of screen such as quick panel
1023         ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &scr_w, &scr_h);
1024         if (!E_INTERSECTS(0, 0, scr_w, scr_h,
1025                           ec->client.x, ec->client.y, ec->client.w, ec->client.h))
1026           continue;
1027
1028         if (evas_object_data_get(ec->frame, "comp_skip"))
1029           continue;
1030
1031         ec_list = eina_list_append(ec_list, ec);
1032
1033         // find full opaque win and excludes below wins from the visible list.
1034         e_client_geometry_get(ec, &x, &y, &w, &h);
1035         if (!E_CONTAINS(x, y, w, h,
1036                         0, 0, scr_w, scr_h))
1037            continue;
1038
1039         if (!ec->argb)
1040           break;
1041      }
1042
1043    return ec_list;
1044 }
1045
1046 static int
1047 e_getpwnam_r(const char *name)
1048 {
1049    struct passwd *u;
1050    struct passwd *u_res;
1051    char* buf;
1052    size_t buflen;
1053    int ret;
1054 #undef BUFLEN
1055 #define BUFLEN 2048
1056
1057    buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1058    if (buflen == -1)          /* Value was indeterminate */
1059      buflen = BUFLEN;        /* Should be more than enough */
1060 #undef BUFLEN
1061
1062    buf = malloc(buflen);
1063    if (buf == NULL)
1064      {
1065         ERR("failed to create buffer");
1066         return 0;
1067      }
1068
1069    u = malloc(sizeof(struct passwd));
1070    if (!u)
1071      {
1072         ERR("failed to create password struct");
1073         free(buf);
1074         return 0;
1075      }
1076
1077    ret = getpwnam_r(name, u, buf, buflen, &u_res);
1078    if (u_res == NULL)
1079      {
1080         if (ret == 0)
1081           ERR("password not found");
1082         else
1083           ERR("errno returned by getpwnam_r is %d", ret);
1084         free(buf);
1085         free(u);
1086         return 0;
1087      }
1088    ret = u->pw_uid;
1089    free(buf);
1090    free(u);
1091    return ret;
1092 }
1093
1094 static int
1095 e_getgrnam_r(const char *name)
1096 {
1097    struct group *g;
1098    struct group *grp_res;
1099    char* buf;
1100    size_t buflen;
1101    int ret;
1102 #undef BUFLEN
1103 #define BUFLEN 2048
1104    buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1105    if (buflen == -1)          /* Value was indeterminate */
1106      buflen = BUFLEN;        /* Should be more than enough */
1107 #undef BUFLEN
1108
1109    buf = malloc(buflen);
1110    if (buf == NULL)
1111      {
1112         ERR("failed to create buffer");
1113         return 0;
1114      }
1115
1116    g = malloc(sizeof(struct group));
1117    if (!g)
1118      {
1119         ERR("failed to create group struct");
1120         free(buf);
1121         return 0;
1122      }
1123
1124    ret = getgrnam_r(name, g, buf, buflen, &grp_res);
1125    if (grp_res == NULL)
1126      {
1127         if (ret == 0)
1128           ERR("Group not found");
1129         else
1130           ERR("errno returned by getpwnam_r is %d", ret);
1131
1132         free(buf);
1133         free(g);
1134         return 0;
1135      }
1136
1137    ret = g->gr_gid;
1138    free(buf);
1139    free(g);
1140    return ret;
1141 }
1142
1143 EINTERN Eina_Bool
1144 e_comp_socket_init(const char *name)
1145 {
1146    char *dir = NULL;
1147    char socket_path[108];
1148    uid_t uid;
1149    gid_t gid;
1150    int res;
1151    E_Config_Socket_Access *sa = NULL;
1152    Eina_List *l = NULL;
1153    int l_dir, l_name;
1154 #undef STRERR_BUFSIZE
1155 #define STRERR_BUFSIZE 1024
1156    char buf[STRERR_BUFSIZE];
1157
1158    if (!name) return EINA_FALSE;
1159
1160    dir = e_util_env_get("XDG_RUNTIME_DIR");
1161    if (!dir) return EINA_FALSE;
1162
1163    /* check whether buffer size is less than concatenated string which
1164     * is made of XDG_RUNTIME_DIR, '/', socket name and NULL.
1165     */
1166    l_dir = strlen(dir);
1167    l_name = strlen(name);
1168    if ((l_dir + l_name + 2) > STRERR_BUFSIZE)
1169      {
1170         ERR("Size of buffer is not enough. dir:%s name:%s",
1171             dir, name);
1172                 free(dir);
1173         return EINA_FALSE;
1174      }
1175
1176    snprintf(socket_path, sizeof(socket_path), "%s/%s", dir, name);
1177    free(dir);
1178
1179    EINA_LIST_FOREACH(e_config->sock_accesses, l, sa)
1180      {
1181         if (strcmp(sa->sock_access.name, name)) continue;
1182         if (!sa->sock_access.use) break;
1183
1184         if ((sa->sock_access.owner) &&
1185             (sa->sock_access.group))
1186           {
1187              uid = e_getpwnam_r(sa->sock_access.owner);
1188
1189              gid = e_getgrnam_r(sa->sock_access.group);
1190
1191              DBG("socket path: %s owner: %s (%d) group: %s (%d) permissions: %o",
1192                  socket_path,
1193                  sa->sock_access.owner, uid,
1194                  sa->sock_access.group, gid,
1195                  sa->sock_access.permissions);
1196
1197              res = chmod(socket_path, sa->sock_access.permissions);
1198              if (res < 0)
1199                {
1200                   ERR("Could not change modes of socket file:%s (%s)",
1201                       socket_path,
1202                       strerror_r(errno, buf, STRERR_BUFSIZE));
1203
1204                   PRCTL("[Winsys] Could not chane modes of socket file: %s", socket_path);
1205                   return EINA_FALSE;
1206                }
1207
1208              res = chown(socket_path, uid, gid);
1209              if (res < 0)
1210                {
1211                   ERR("Could not change owner of socket file:%s (%s)",
1212                       socket_path,
1213                       strerror_r(errno, buf, STRERR_BUFSIZE));
1214
1215                   PRCTL("[Winsys] Could not change owner of socket file: %s", socket_path);
1216                   return EINA_FALSE;
1217                }
1218           }
1219
1220         if (sa->sock_access.smack.use)
1221           {
1222              res = setxattr(socket_path,
1223                             sa->sock_access.smack.name,
1224                             sa->sock_access.smack.value,
1225                             strlen(sa->sock_access.smack.value),
1226                             sa->sock_access.smack.flags);
1227              if (res < 0)
1228                {
1229                   ERR("Could not change smack variable for socket file: %s (%s)",
1230                       socket_path,
1231                       strerror_r(errno, buf, STRERR_BUFSIZE));
1232
1233                   PRCTL("[Winsys] Could not change smack variable for socket file: %s", socket_path);
1234                   return EINA_FALSE;
1235                }
1236           }
1237
1238         if (sa->sock_symlink_access.use)
1239           {
1240              res = symlink(socket_path,
1241                            sa->sock_symlink_access.link_name);
1242              if (res < 0)
1243                {
1244                   ERR("Could not make symbolic link: %s (%s)",
1245                       sa->sock_symlink_access.link_name,
1246                       strerror_r(errno, buf, STRERR_BUFSIZE));
1247
1248                   PRCTL("[Winsys] Could not make symbolic link: %s", sa->sock_symlink_access.link_name);
1249                   if (errno != EEXIST)
1250                     return EINA_FALSE;
1251                }
1252
1253              uid = e_getpwnam_r(sa->sock_symlink_access.owner);
1254
1255              gid = e_getgrnam_r(sa->sock_symlink_access.group);
1256
1257              res = lchown(sa->sock_symlink_access.link_name, uid, gid);
1258              if (res < 0)
1259                {
1260                   ERR("chown -h owner:users %s failed! (%s)", sa->sock_symlink_access.link_name,
1261                       strerror_r(errno, buf, STRERR_BUFSIZE));
1262
1263                   PRCTL("[Winsys] chown -h owner:users %s failed!", sa->sock_symlink_access.link_name);
1264                   return EINA_FALSE;
1265                }
1266
1267              res = setxattr(sa->sock_symlink_access.link_name,
1268                             sa->sock_symlink_access.smack.name,
1269                             sa->sock_symlink_access.smack.value,
1270                             strlen(sa->sock_symlink_access.smack.value),
1271                             sa->sock_symlink_access.smack.flags);
1272              if (res < 0)
1273                {
1274                   ERR("Chould not change smack variable for symbolic link: %s (%s)", sa->sock_symlink_access.link_name,
1275                       strerror_r(errno, buf, STRERR_BUFSIZE));
1276
1277                   PRCTL("[Winsys] Chould not change smack variable for symbolic link: %s", sa->sock_symlink_access.link_name);
1278                   return EINA_FALSE;
1279                }
1280           }
1281         break;
1282      }
1283
1284    return EINA_TRUE;
1285 }
1286
1287 /* set the deactive value to the only primary output */
1288 EINTERN void
1289 e_comp_hwc_deactive_set(Eina_Bool set)
1290 {
1291    E_Output *output = NULL;
1292
1293    EINA_SAFETY_ON_NULL_RETURN(e_comp);
1294    EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1295
1296    output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1297    EINA_SAFETY_ON_NULL_RETURN(output);
1298
1299    e_hwc_deactive_set(output->hwc, set);
1300 }
1301
1302 /* get the deactive value to the only primary output */
1303 EINTERN Eina_Bool
1304 e_comp_hwc_deactive_get(void)
1305 {
1306    E_Output *output = NULL;
1307
1308    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1309    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
1310
1311    output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1312    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1313
1314    return e_hwc_deactive_get(output->hwc);
1315 }
1316
1317 /* set the multi_plane value to the only primary output */
1318 EINTERN void
1319 e_comp_hwc_multi_plane_set(Eina_Bool set)
1320 {
1321    E_Output *output = NULL;
1322
1323    EINA_SAFETY_ON_NULL_RETURN(e_comp);
1324    EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1325
1326    output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1327    EINA_SAFETY_ON_NULL_RETURN(output);
1328
1329    e_hwc_planes_multi_plane_set(output->hwc, EINA_TRUE);
1330 }
1331
1332 /* get the multi_plane value to the only primary output */
1333 EINTERN Eina_Bool
1334 e_comp_hwc_multi_plane_get(void)
1335 {
1336    E_Output *output = NULL;
1337
1338    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1339    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
1340
1341    output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1342    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1343
1344    return e_hwc_planes_multi_plane_get(output->hwc);
1345 }
1346
1347 /* end the hwc policy at the primary output */
1348 EINTERN void
1349 e_comp_hwc_end(const char *location)
1350 {
1351    E_Output *output = NULL;
1352    E_Hwc *hwc = NULL;
1353
1354    EINA_SAFETY_ON_NULL_RETURN(e_comp);
1355    EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1356
1357    output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1358    EINA_SAFETY_ON_NULL_RETURN(output);
1359
1360    hwc = output->hwc;
1361    EINA_SAFETY_ON_NULL_RETURN(hwc);
1362
1363    if (hwc->hwc_policy == E_HWC_POLICY_PLANES)
1364      e_hwc_planes_end(output->hwc, location);
1365    else if (hwc->hwc_policy == E_HWC_POLICY_WINDOWS)
1366      e_hwc_windows_client_type_override(output->hwc);
1367 }
1368
1369 EINTERN void
1370 e_comp_hwc_client_end(E_Client *ec, const char *location)
1371 {
1372    E_Zone *zone = NULL;
1373    E_Output *output = NULL;
1374    E_Hwc *hwc = NULL;
1375    E_Hwc_Window *hwc_window = NULL;
1376
1377    EINA_SAFETY_ON_NULL_RETURN(ec);
1378
1379    zone = e_comp_zone_find_by_ec(ec);
1380    EINA_SAFETY_ON_NULL_RETURN(zone);
1381
1382    output = e_output_find(zone->output_id);
1383    EINA_SAFETY_ON_NULL_RETURN(output);
1384
1385    hwc = output->hwc;
1386    EINA_SAFETY_ON_NULL_RETURN(hwc);
1387
1388    if (hwc->hwc_policy == E_HWC_POLICY_PLANES)
1389      {
1390         e_hwc_planes_client_end(output->hwc, ec, location);
1391      }
1392    else if (hwc->hwc_policy == E_HWC_POLICY_WINDOWS)
1393      {
1394         hwc_window = ec->hwc_window;
1395         EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1396
1397         e_hwc_window_client_type_override(hwc_window);
1398      }
1399 }
1400
1401 EINTERN Eina_Bool
1402 e_comp_util_client_is_fullscreen(const E_Client *ec)
1403 {
1404    if ((!ec->visible) || (ec->input_only))
1405      return EINA_FALSE;
1406    return ((ec->client.x == 0) && (ec->client.y == 0) &&
1407        ((ec->client.w) >= e_comp->w) &&
1408        ((ec->client.h) >= e_comp->h) &&
1409        (!ec->argb) && (!ec->shaped)
1410        );
1411 }
1412
1413 E_API Eina_Bool
1414 e_comp_image_filter_set(E_Comp_Image_Filter filter)
1415 {
1416    E_Client *ec;
1417
1418    if (e_comp->image_filter == filter) return EINA_TRUE;
1419    E_CLIENT_FOREACH(ec)
1420      {
1421         e_comp_object_image_filter_set(ec->frame, filter);
1422         e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1423         e_comp_object_dirty(ec->frame);
1424         e_comp_object_render(ec->frame);
1425      }
1426
1427    e_comp->image_filter = filter;
1428    return EINA_FALSE;
1429 }
1430
1431 E_API E_Comp_Image_Filter
1432 e_comp_image_filter_get(void)
1433 {
1434    return e_comp->image_filter;
1435 }
1436
1437 E_API E_Zone *
1438 e_comp_zone_find_by_ec(E_Client *ec)
1439 {
1440    Eina_List *l;
1441    E_Zone *zone;
1442
1443    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
1444
1445    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1446      {
1447         if (!zone) continue;
1448         if (e_zone_has_ec(zone, ec)) return zone;
1449      }
1450
1451    return NULL;
1452 }
1453
1454 E_API E_Desk *
1455 e_comp_desk_find_by_ec(E_Client *ec)
1456 {
1457    E_Zone *zone;
1458
1459    zone = e_comp_zone_find_by_ec(ec);
1460    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
1461
1462    return e_zone_desk_find_by_ec(zone, ec);
1463 }
1464
1465 #ifdef REFACTOR_DESK_AREA
1466 E_API E_Desk_Area *
1467 e_comp_desk_area_find_by_ec(E_Client *ec)
1468 {
1469    E_Desk *desk;
1470
1471    desk = e_comp_desk_find_by_ec(ec);
1472    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, NULL);
1473
1474    return e_desk_desk_area_find_by_ec(desk, ec);
1475 }
1476 #endif
1477
1478 EINTERN Eina_Bool
1479 e_comp_client_zone_is_displaying(E_Client *ec)
1480 {
1481    E_Zone *zone;
1482
1483    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1484
1485    zone = e_comp_zone_find_by_ec(ec);
1486    if (!zone) return EINA_FALSE;
1487
1488    return e_zone_is_displaying(zone);
1489 }
1490
1491 EINTERN void
1492 e_comp_idler_before(void)
1493 {
1494    Eina_Bool check_focus = EINA_FALSE;
1495    E_Zone *zone;
1496    Eina_List *zl;
1497    Eina_Bool e_visibility_changed = EINA_FALSE;
1498
1499    // TODO: call e_zone_idle_before() for each zone
1500    e_client_idler_before(&check_focus);
1501
1502    if (e_comp_canvas_norender_get() <= 0)
1503      {
1504         EINA_LIST_FOREACH(e_comp->zones, zl, zone)
1505            {
1506               if (e_comp_visibility_calculation_get())
1507                 e_visibility_changed = e_zone_visibility_calculate(zone);
1508
1509               if (check_focus ||
1510                   (e_client_focused_get() == NULL) ||
1511                   (e_comp_visibility_calculation_get()) ||
1512                   (e_visibility_changed))
1513                 {
1514                   // FIXME: Only the default zone(screen) update the focus.
1515                   //        Multi-zones(Multi-screens) are not supported yet.
1516                   if (!zone->focus) continue;
1517
1518                    e_focus_update(zone->focus);
1519                 }
1520            }
1521         e_comp_visibility_calculation_set(EINA_FALSE);
1522      }
1523 }
1524
1525 EINTERN void
1526 e_comp_visibility_calculation_set(Eina_Bool set)
1527 {
1528    if (_e_calc_visibility != set)
1529       _e_calc_visibility = set;
1530 }
1531
1532 EINTERN Eina_Bool
1533 e_comp_visibility_calculation_get(void)
1534 {
1535    return _e_calc_visibility;
1536 }
1537
1538 EINTERN E_Client *
1539 e_comp_focused_ec_get(void)
1540 {
1541    E_Client *focused_ec;
1542    Eina_List *l;
1543    E_Zone *zone;
1544
1545    // e20 compositor support only one focused_ec,
1546    // therefore find the focused_ec from the zone and return it
1547    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1548      {
1549         if (!zone) continue;
1550         if (!zone->focus) continue;
1551         focused_ec = e_focus_focused_ec_get(zone->focus);
1552         if (focused_ec) return focused_ec;
1553      }
1554
1555    return NULL;
1556 }