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"
20 #include <sys/xattr.h>
21 #include <sys/types.h>
26 //////////////////////////////////////////////////////////////////////////
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
37 //////////////////////////////////////////////////////////////////////////
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;
46 static E_Comp_Config *conf = NULL;
47 static E_Config_DD *conf_edd = NULL;
48 static E_Config_DD *conf_match_edd = NULL;
50 static Ecore_Timer *action_timeout = NULL;
51 static Eina_Bool gl_avail = EINA_FALSE;
53 static double ecore_frametime = 0;
55 static int _e_comp_log_dom = -1;
57 static int _e_comp_hooks_delete = 0;
58 static int _e_comp_hooks_walking = 0;
60 static Eina_Bool _e_calc_visibility = EINA_FALSE;
62 static Eina_Inlist *_e_comp_hooks[] =
64 [E_COMP_HOOK_PREPARE_PLANE] = NULL,
67 E_API int E_EVENT_COMPOSITOR_DISABLE = -1;
68 E_API int E_EVENT_COMPOSITOR_ENABLE = -1;
70 //////////////////////////////////////////////////////////////////////////
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__)
84 _e_comp_fps_update(void)
86 static double rtime = 0.0;
87 static double rlapse = 0.0;
88 static int frames = 0;
89 static int flapse = 0;
91 double tim = ecore_time_get();
94 dt = tim - e_comp->frametimes[0];
95 e_comp->frametimes[0] = tim;
105 else if ((tim - rlapse) >= 0.5)
107 e_comp->fps = (frames - flapse) / (tim - rlapse);
115 if (e_comp->fps_bg && e_comp->fps_fg)
118 Evas_Coord x = 0, y = 0, w = 0, h = 0;
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);
125 evas_object_geometry_get(e_comp->fps_fg, NULL, NULL, &w, &h);
128 z = e_zone_current_get();
131 switch (conf->fps_corner)
133 case 3: // bottom-right
138 case 2: // bottom-left
147 default: // 0 // top-left
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);
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);
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);
178 E_FREE_FUNC(e_comp->fps_fg, evas_object_del);
179 E_FREE_FUNC(e_comp->fps_bg, evas_object_del);
184 _e_comp_hooks_clean(void)
190 for (x = 0; x < E_COMP_HOOK_LAST; x++)
191 EINA_INLIST_FOREACH_SAFE(_e_comp_hooks[x], l, ch)
193 if (!ch->delete_me) continue;
194 _e_comp_hooks[x] = eina_inlist_remove(_e_comp_hooks[x],
195 EINA_INLIST_GET(ch));
201 e_comp_hook_call(E_Comp_Hook_Point hookpoint, void *data EINA_UNUSED)
205 _e_comp_hooks_walking++;
206 EINA_INLIST_FOREACH(_e_comp_hooks[hookpoint], ch)
208 if (ch->delete_me) continue;
209 ch->func(ch->data, NULL);
211 _e_comp_hooks_walking--;
212 if ((_e_comp_hooks_walking == 0) && (_e_comp_hooks_delete > 0))
213 _e_comp_hooks_clean();
217 _e_comp_cb_update(void)
224 if (!e_comp) return EINA_FALSE;
226 TRACE_DS_BEGIN(COMP:UPDATE CB);
228 if (e_comp->update_job)
229 e_comp->update_job = NULL;
231 ecore_animator_freeze(e_comp->render_animator);
235 if (conf->grab && (!e_comp->grabbed))
237 if (e_comp->grab_cb) e_comp->grab_cb();
241 e_comp->updates = NULL;
242 EINA_LIST_FREE(l, ec)
244 /* clear update flag */
245 e_comp_object_render_update_del(ec->frame);
247 if (e_object_is_del(E_OBJECT(ec))) continue;
248 if (e_comp->hwc && e_comp_is_on_overlay(ec)) continue;
251 e_pixmap_size_get(ec->pixmap, &pw, &ph);
253 if (e_pixmap_dirty_get(ec->pixmap))
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))
259 e_pixmap_image_clear(ec->pixmap, 0);
261 else if (!e_pixmap_size_get(ec->pixmap, NULL, NULL))
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. */
269 res = e_pixmap_size_get(ec->pixmap, &pw, &ph);
272 e_pixmap_image_refresh(ec->pixmap);
273 e_comp_object_dirty(ec->frame);
276 if (conf->grab && e_comp->grabbed)
278 if (e_comp->grab_cb) e_comp->grab_cb();
281 if (e_comp->updates && (!e_comp->update_job))
282 ecore_animator_thaw(e_comp->render_animator);
286 return ECORE_CALLBACK_RENEW;
290 _e_comp_cb_job(void *data EINA_UNUSED)
292 DBG("UPDATE ALL JOB...");
297 _e_comp_cb_animator(void *data EINA_UNUSED)
299 return _e_comp_cb_update();
303 _e_comp_signal_user(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Event_Signal_User *ev)
307 // e uses this to pop up config panel
309 else if (ev->number == 2)
311 e_comp_canvas_fps_toggle();
313 return ECORE_CALLBACK_PASS_ON;
316 //////////////////////////////////////////////////////////////////////////
319 _e_comp_free(E_Comp *c)
324 EINA_LIST_FOREACH_SAFE(c->zones, l, ll, zone)
326 e_object_del(E_OBJECT(zone));
329 e_comp_canvas_clear();
331 ecore_evas_free(c->ee);
332 eina_stringshare_del(c->name);
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);
342 //////////////////////////////////////////////////////////////////////////
345 _e_comp_object_add(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
347 return ECORE_CALLBACK_RENEW;
351 _e_comp_override_expire(void *data EINA_UNUSED)
353 e_comp->nocomp_override_timer = NULL;
354 e_comp->nocomp_override--;
356 if (e_comp->nocomp_override <= 0)
358 e_comp->nocomp_override = 0;
359 e_comp_render_queue();
364 //////////////////////////////////////////////////////////////////////////
367 _e_comp_screensaver_on(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
369 return ECORE_CALLBACK_PASS_ON;
373 _e_comp_screensaver_off(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
375 return ECORE_CALLBACK_PASS_ON;
378 //////////////////////////////////////////////////////////////////////////
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);
386 ecore_frametime = ecore_animator_frametime_get();
388 E_EVENT_COMPOSITOR_DISABLE = ecore_event_type_new();
389 E_EVENT_COMPOSITOR_ENABLE = ecore_event_type_new();
391 ignores = eina_hash_pointer_new(NULL);
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");
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");
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");
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)
412 switch (conf->version)
415 // going from version 0 we should disable grab for smoothness
421 e_config_save_queue();
422 conf->version = E_COMP_VERSION;
425 e_comp_object_init();
428 /* conf->hwc configuration has to be check before e_comp_screen_init() */
430 e_comp->hwc = EINA_TRUE; // activate hwc policy on the primary output
432 if (conf->avoid_afill) e_comp->avoid_afill = EINA_TRUE;
433 if (conf->hwc_prefer_gbm) e_comp->hwc_prefer_gbm = EINA_TRUE;
435 e_main_ts_begin("\tE_Comp_Screen Init");
436 if (!e_comp_screen_init())
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);
444 e_main_ts_end("\tE_Comp_Screen Init Done");
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;
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;
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;
461 if (conf->canvas_render_delay_after_boot) e_comp->canvas_render_delayed = EINA_TRUE;
463 if ((conf->commit_handler_timer.use) && (conf->commit_handler_timer.interval))
465 e_comp->commit_handler_timer.use = EINA_TRUE;
466 e_comp->commit_handler_timer.interval = conf->commit_handler_timer.interval;
469 #ifdef REFACTOR_DESK_AREA
471 e_comp_canvas_fake_layers_init();
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);
479 g_rec_mutex_init(&e_comp->ec_list_mutex);
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;
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);
499 e_comp_internal_save(void)
501 return e_config_domain_save("e_comp", conf_edd, conf);
505 e_comp_shutdown(void)
510 E_FREE_FUNC(action_timeout, ecore_timer_del);
511 EINA_LIST_FOREACH_SAFE(e_comp->clients, l, ll, ec)
514 e_object_del(E_OBJECT(ec));
517 e_comp_wl_shutdown();
518 e_comp_screen_shutdown();
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);
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);
531 conf_match_edd = NULL;
534 E_FREE_FUNC(ignores, eina_hash_free);
536 g_rec_mutex_clear(&e_comp->ec_list_mutex);
542 e_comp_deferred_job(void)
545 e_main_ts_begin("\tE_BG_Zone Update");
547 zone = e_zone_current_get();
548 EINA_SAFETY_ON_NULL_GOTO(zone, comp_wl_job);
550 e_bg_zone_update(zone, E_BG_TRANSITION_DESK);
552 e_bg_zone_update(zone, E_BG_TRANSITION_START);
553 e_main_ts_end("\tE_BG_Zone Update Done");
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");
562 e_comp_render_queue(void)
564 if (e_comp->update_job)
566 DBG("UPDATE JOB DEL...");
567 E_FREE_FUNC(e_comp->update_job, ecore_job_del);
569 DBG("UPDATE JOB ADD...");
570 e_comp->update_job = ecore_job_add(_e_comp_cb_job, e_comp);
574 e_comp_client_post_update_add(E_Client *ec)
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);
580 e_object_ref(E_OBJECT(ec));
584 e_comp_client_render_list_add(E_Client *ec)
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);
590 e_object_ref(E_OBJECT(ec));
593 E_API E_Comp_Config *
594 e_comp_config_get(void)
600 e_comp_shadows_reset(void)
604 _e_comp_fps_update();
605 E_LIST_FOREACH(e_comp->zones, e_comp_canvas_zone_update);
607 e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
611 e_comp_top_window_at_xy_get(Evas_Coord x, Evas_Coord y)
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;
625 e_comp_util_wins_print(void)
629 o = evas_object_top_get(e_comp->evas);
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));
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);
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);
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);
656 e_comp_ignore_win_add(E_Pixmap_Type type, Ecore_Window win)
660 eina_hash_add(ignores, &win, (void*)1);
661 ec = e_pixmap_find_client(type, win);
664 if (ec->visible) evas_object_hide(ec->frame);
668 e_comp_ignore_win_del(E_Pixmap_Type type, Ecore_Window win)
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;
676 if (ec->visible) evas_object_show(ec->frame);
680 e_comp_ignore_win_find(Ecore_Window win)
682 return !!eina_hash_find(ignores, &win);
686 e_comp_override_del()
688 e_comp->nocomp_override--;
689 if (e_comp->nocomp_override <= 0)
691 e_comp->nocomp_override = 0;
692 e_comp_render_queue();
697 e_comp_override_add()
699 e_comp->nocomp_override++;
700 if (e_comp->nocomp_override > 0)
702 // go full compositing
703 e_comp_hwc_end(__FUNCTION__);
708 e_comp_client_override_del(E_Client *ec)
713 if (ec->comp_override <= 0)
715 ec->comp_override = 0;
716 e_comp_render_queue();
721 e_comp_client_override_add(E_Client *ec)
726 if (ec->comp_override > 0)
727 e_comp_hwc_client_end(ec, __FUNCTION__);
731 e_comp_find_by_window(Ecore_Window win)
733 if ((e_comp->win == win) || (e_comp->ee_win == win) || (e_comp->root == win)) return e_comp;
738 e_comp_override_timed_pop(void)
740 if (e_comp->nocomp_override <= 0) return;
741 if (e_comp->nocomp_override_timer)
742 e_comp->nocomp_override--;
744 e_comp->nocomp_override_timer = ecore_timer_add(1.0, _e_comp_override_expire, NULL);
748 e_comp_layer_name_get(unsigned int layer, char *buff, int buff_size)
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;
790 e_comp_grab_input(Eina_Bool mouse, Eina_Bool kbd)
792 Eina_Bool ret = EINA_FALSE;
793 Ecore_Window mwin = 0, kwin = 0;
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))
806 e_comp->input_mouse_grabs += mouse;
807 e_comp->input_key_grabs += kbd;
814 e_comp_ungrab_input(Eina_Bool mouse, Eina_Bool kbd)
816 Ecore_Window mwin = 0, kwin = 0;
820 if (e_comp->input_mouse_grabs)
821 e_comp->input_mouse_grabs -= mouse;
823 if (e_comp->input_key_grabs)
824 e_comp->input_key_grabs -= kbd;
826 if (mouse && (!e_comp->input_mouse_grabs))
827 mwin = e_comp->ee_win;
829 if (kbd && (!e_comp->input_key_grabs))
830 kwin = e_comp->ee_win;
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;
839 E_Zone *zone = e_zone_current_get();
842 e_zone_focus_reset(zone);
846 e_comp_util_kbd_grabbed(void)
848 return e_client_action_get() || e_grabinput_key_win_get();
852 e_comp_util_mouse_grabbed(void)
854 return e_client_action_get() || e_grabinput_mouse_win_get();
858 e_comp_gl_set(Eina_Bool set)
870 e_comp_button_bindings_ungrab_all(void)
872 if (e_comp->bindings_ungrab_cb)
873 e_comp->bindings_ungrab_cb();
877 e_comp_button_bindings_grab_all(void)
879 if (e_comp->bindings_grab_cb)
880 e_comp->bindings_grab_cb();
884 e_comp_util_object_is_above_nocomp(Evas_Object *obj)
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))
901 o = evas_object_above_get(o);
902 } while (o && (evas_object_layer_get(o) == cl));
910 e_comp_hook_add(E_Comp_Hook_Point hookpoint, E_Comp_Hook_Cb func, const void *data)
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;
919 ch->data = (void*)data;
920 _e_comp_hooks[hookpoint] = eina_inlist_append(_e_comp_hooks[hookpoint],
921 EINA_INLIST_GET(ch));
926 e_comp_hook_del(E_Comp_Hook *ch)
929 if (_e_comp_hooks_walking == 0)
931 _e_comp_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_hooks[ch->hookpoint],
932 EINA_INLIST_GET(ch));
936 _e_comp_hooks_delete++;
940 e_comp_is_on_overlay(E_Client *ec)
945 E_Hwc_Window *hwc_window;
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);
953 eout = e_output_find(zone->output_id);
954 if (!eout) return EINA_FALSE;
956 if (e_hwc_policy_get(eout->hwc) == E_HWC_POLICY_PLANES)
958 if (!e_hwc_mode_get(eout->hwc)) return EINA_FALSE;
960 EINA_LIST_FOREACH_SAFE(eout->planes, l, ll, ep)
962 E_Client *overlay_ec = ep->ec;
963 if (overlay_ec == ec) return EINA_TRUE;
968 hwc_window = ec->hwc_window;
969 if (!hwc_window) return EINA_FALSE;
971 if (e_hwc_window_is_on_hw_overlay(hwc_window)) return EINA_TRUE;
978 e_comp_zone_find(const char *output_id)
983 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
984 EINA_SAFETY_ON_NULL_RETURN_VAL(output_id, NULL);
986 EINA_LIST_FOREACH(e_comp->zones, l, zone)
989 if (!strcmp(zone->output_id, output_id)) return zone;
997 e_comp_vis_ec_list_get(E_Zone *zone)
999 Eina_List *ec_list = NULL;
1003 E_OBJECT_CHECK_RETURN(zone, NULL);
1004 E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
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))
1012 ec = evas_object_data_get(o, "E_Client");
1014 if (e_object_is_del(E_OBJECT(ec))) continue;
1016 if (e_comp_zone_find_by_ec(ec) != zone) continue;
1018 // check clients to skip composite
1019 if (e_client_util_ignored_get(ec) || (!evas_object_visible_get(ec->frame)))
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))
1028 if (evas_object_data_get(ec->frame, "comp_skip"))
1031 ec_list = eina_list_append(ec_list, ec);
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))
1047 e_getpwnam_r(const char *name)
1050 struct passwd *u_res;
1057 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1058 if (buflen == -1) /* Value was indeterminate */
1059 buflen = BUFLEN; /* Should be more than enough */
1062 buf = malloc(buflen);
1065 ERR("failed to create buffer");
1069 u = malloc(sizeof(struct passwd));
1072 ERR("failed to create password struct");
1077 ret = getpwnam_r(name, u, buf, buflen, &u_res);
1081 ERR("password not found");
1083 ERR("errno returned by getpwnam_r is %d", ret);
1095 e_getgrnam_r(const char *name)
1098 struct group *grp_res;
1104 buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1105 if (buflen == -1) /* Value was indeterminate */
1106 buflen = BUFLEN; /* Should be more than enough */
1109 buf = malloc(buflen);
1112 ERR("failed to create buffer");
1116 g = malloc(sizeof(struct group));
1119 ERR("failed to create group struct");
1124 ret = getgrnam_r(name, g, buf, buflen, &grp_res);
1125 if (grp_res == NULL)
1128 ERR("Group not found");
1130 ERR("errno returned by getpwnam_r is %d", ret);
1144 e_comp_socket_init(const char *name)
1147 char socket_path[108];
1151 E_Config_Socket_Access *sa = NULL;
1152 Eina_List *l = NULL;
1154 #undef STRERR_BUFSIZE
1155 #define STRERR_BUFSIZE 1024
1156 char buf[STRERR_BUFSIZE];
1158 if (!name) return EINA_FALSE;
1160 dir = e_util_env_get("XDG_RUNTIME_DIR");
1161 if (!dir) return EINA_FALSE;
1163 /* check whether buffer size is less than concatenated string which
1164 * is made of XDG_RUNTIME_DIR, '/', socket name and NULL.
1166 l_dir = strlen(dir);
1167 l_name = strlen(name);
1168 if ((l_dir + l_name + 2) > STRERR_BUFSIZE)
1170 ERR("Size of buffer is not enough. dir:%s name:%s",
1176 snprintf(socket_path, sizeof(socket_path), "%s/%s", dir, name);
1179 EINA_LIST_FOREACH(e_config->sock_accesses, l, sa)
1181 if (strcmp(sa->sock_access.name, name)) continue;
1182 if (!sa->sock_access.use) break;
1184 if ((sa->sock_access.owner) &&
1185 (sa->sock_access.group))
1187 uid = e_getpwnam_r(sa->sock_access.owner);
1189 gid = e_getgrnam_r(sa->sock_access.group);
1191 DBG("socket path: %s owner: %s (%d) group: %s (%d) permissions: %o",
1193 sa->sock_access.owner, uid,
1194 sa->sock_access.group, gid,
1195 sa->sock_access.permissions);
1197 res = chmod(socket_path, sa->sock_access.permissions);
1200 ERR("Could not change modes of socket file:%s (%s)",
1202 strerror_r(errno, buf, STRERR_BUFSIZE));
1204 PRCTL("[Winsys] Could not chane modes of socket file: %s", socket_path);
1208 res = chown(socket_path, uid, gid);
1211 ERR("Could not change owner of socket file:%s (%s)",
1213 strerror_r(errno, buf, STRERR_BUFSIZE));
1215 PRCTL("[Winsys] Could not change owner of socket file: %s", socket_path);
1220 if (sa->sock_access.smack.use)
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);
1229 ERR("Could not change smack variable for socket file: %s (%s)",
1231 strerror_r(errno, buf, STRERR_BUFSIZE));
1233 PRCTL("[Winsys] Could not change smack variable for socket file: %s", socket_path);
1238 if (sa->sock_symlink_access.use)
1240 res = symlink(socket_path,
1241 sa->sock_symlink_access.link_name);
1244 ERR("Could not make symbolic link: %s (%s)",
1245 sa->sock_symlink_access.link_name,
1246 strerror_r(errno, buf, STRERR_BUFSIZE));
1248 PRCTL("[Winsys] Could not make symbolic link: %s", sa->sock_symlink_access.link_name);
1249 if (errno != EEXIST)
1253 uid = e_getpwnam_r(sa->sock_symlink_access.owner);
1255 gid = e_getgrnam_r(sa->sock_symlink_access.group);
1257 res = lchown(sa->sock_symlink_access.link_name, uid, gid);
1260 ERR("chown -h owner:users %s failed! (%s)", sa->sock_symlink_access.link_name,
1261 strerror_r(errno, buf, STRERR_BUFSIZE));
1263 PRCTL("[Winsys] chown -h owner:users %s failed!", sa->sock_symlink_access.link_name);
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);
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));
1277 PRCTL("[Winsys] Chould not change smack variable for symbolic link: %s", sa->sock_symlink_access.link_name);
1287 /* set the deactive value to the only primary output */
1289 e_comp_hwc_deactive_set(Eina_Bool set)
1291 E_Output *output = NULL;
1293 EINA_SAFETY_ON_NULL_RETURN(e_comp);
1294 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1296 output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1297 EINA_SAFETY_ON_NULL_RETURN(output);
1299 e_hwc_deactive_set(output->hwc, set);
1302 /* get the deactive value to the only primary output */
1304 e_comp_hwc_deactive_get(void)
1306 E_Output *output = NULL;
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);
1311 output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1312 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1314 return e_hwc_deactive_get(output->hwc);
1317 /* set the multi_plane value to the only primary output */
1319 e_comp_hwc_multi_plane_set(Eina_Bool set)
1321 E_Output *output = NULL;
1323 EINA_SAFETY_ON_NULL_RETURN(e_comp);
1324 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1326 output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1327 EINA_SAFETY_ON_NULL_RETURN(output);
1329 e_hwc_planes_multi_plane_set(output->hwc, EINA_TRUE);
1332 /* get the multi_plane value to the only primary output */
1334 e_comp_hwc_multi_plane_get(void)
1336 E_Output *output = NULL;
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);
1341 output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1342 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1344 return e_hwc_planes_multi_plane_get(output->hwc);
1347 /* end the hwc policy at the primary output */
1349 e_comp_hwc_end(const char *location)
1351 E_Output *output = NULL;
1354 EINA_SAFETY_ON_NULL_RETURN(e_comp);
1355 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1357 output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
1358 EINA_SAFETY_ON_NULL_RETURN(output);
1361 EINA_SAFETY_ON_NULL_RETURN(hwc);
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);
1370 e_comp_hwc_client_end(E_Client *ec, const char *location)
1372 E_Zone *zone = NULL;
1373 E_Output *output = NULL;
1375 E_Hwc_Window *hwc_window = NULL;
1377 EINA_SAFETY_ON_NULL_RETURN(ec);
1379 zone = e_comp_zone_find_by_ec(ec);
1380 EINA_SAFETY_ON_NULL_RETURN(zone);
1382 output = e_output_find(zone->output_id);
1383 EINA_SAFETY_ON_NULL_RETURN(output);
1386 EINA_SAFETY_ON_NULL_RETURN(hwc);
1388 if (hwc->hwc_policy == E_HWC_POLICY_PLANES)
1390 e_hwc_planes_client_end(output->hwc, ec, location);
1392 else if (hwc->hwc_policy == E_HWC_POLICY_WINDOWS)
1394 hwc_window = ec->hwc_window;
1395 EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1397 e_hwc_window_client_type_override(hwc_window);
1402 e_comp_util_client_is_fullscreen(const E_Client *ec)
1404 if ((!ec->visible) || (ec->input_only))
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)
1414 e_comp_image_filter_set(E_Comp_Image_Filter filter)
1418 if (e_comp->image_filter == filter) return EINA_TRUE;
1419 E_CLIENT_FOREACH(ec)
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);
1427 e_comp->image_filter = filter;
1431 E_API E_Comp_Image_Filter
1432 e_comp_image_filter_get(void)
1434 return e_comp->image_filter;
1438 e_comp_zone_find_by_ec(E_Client *ec)
1443 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
1445 EINA_LIST_FOREACH(e_comp->zones, l, zone)
1447 if (!zone) continue;
1448 if (e_zone_has_ec(zone, ec)) return zone;
1455 e_comp_desk_find_by_ec(E_Client *ec)
1459 zone = e_comp_zone_find_by_ec(ec);
1460 EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
1462 return e_zone_desk_find_by_ec(zone, ec);
1465 #ifdef REFACTOR_DESK_AREA
1467 e_comp_desk_area_find_by_ec(E_Client *ec)
1471 desk = e_comp_desk_find_by_ec(ec);
1472 EINA_SAFETY_ON_NULL_RETURN_VAL(desk, NULL);
1474 return e_desk_desk_area_find_by_ec(desk, ec);
1479 e_comp_client_zone_is_displaying(E_Client *ec)
1483 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1485 zone = e_comp_zone_find_by_ec(ec);
1486 if (!zone) return EINA_FALSE;
1488 return e_zone_is_displaying(zone);
1492 e_comp_idler_before(void)
1494 Eina_Bool check_focus = EINA_FALSE;
1497 Eina_Bool e_visibility_changed = EINA_FALSE;
1499 // TODO: call e_zone_idle_before() for each zone
1500 e_client_idler_before(&check_focus);
1502 if (e_comp_canvas_norender_get() <= 0)
1504 EINA_LIST_FOREACH(e_comp->zones, zl, zone)
1506 if (e_comp_visibility_calculation_get())
1507 e_visibility_changed = e_zone_visibility_calculate(zone);
1510 (e_client_focused_get() == NULL) ||
1511 (e_comp_visibility_calculation_get()) ||
1512 (e_visibility_changed))
1514 // FIXME: Only the default zone(screen) update the focus.
1515 // Multi-zones(Multi-screens) are not supported yet.
1516 if (!zone->focus) continue;
1518 e_focus_update(zone->focus);
1521 e_comp_visibility_calculation_set(EINA_FALSE);
1526 e_comp_visibility_calculation_set(Eina_Bool set)
1528 if (_e_calc_visibility != set)
1529 _e_calc_visibility = set;
1533 e_comp_visibility_calculation_get(void)
1535 return _e_calc_visibility;
1539 e_comp_focused_ec_get(void)
1541 E_Client *focused_ec;
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)
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;