diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index c3a552f6b..e64dcfb50 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -138,7 +138,7 @@ src/bin/e_place.h \ src/bin/e_pointer.h \ src/bin/e_powersave.h \ src/bin/e_prefix.h \ -src/bin/e_randr.h \ +src/bin/e_randr2.h \ src/bin/e_remember.h \ src/bin/e_resist.h \ src/bin/e_scale.h \ @@ -364,7 +364,7 @@ $(ENLIGHTENMENTHEADERS) if ! HAVE_WAYLAND_ONLY enlightenment_src += \ src/bin/e_comp_x.c \ -src/bin/e_randr.c \ +src/bin/e_randr2.c \ src/bin/e_xsettings.c endif diff --git a/src/bin/e_actions.c b/src/bin/e_actions.c index d420470cd..52725c257 100644 --- a/src/bin/e_actions.c +++ b/src/bin/e_actions.c @@ -2899,6 +2899,13 @@ ACT_FN_GO(module_toggle, ) else e_module_enable(m); } +ACT_FN_GO(screen_redo, __UNUSED__) +{ + printf("REDOOOOOOOOOOOOOOOOOOOOOOOOOOO\n"); + e_randr2_screeninfo_update(); + e_randr2_config_apply(); +} + /* local subsystem globals */ static Eina_Hash *actions = NULL; static Eina_List *action_list = NULL; @@ -3240,6 +3247,12 @@ e_actions_init(void) e_action_predef_name_set(N_("Screen"), N_("Backlight Down"), "backlight_adjust", "-10", NULL, 0); + /* screen setup */ + ACT_GO(screen_redo); + e_action_predef_name_set(N_("Screen"), + N_("Update and re-apply screen setup"), + "screen_redo", NULL, NULL, 0); + /* window_move_to_center */ ACT_GO(window_move_to_center); e_action_predef_name_set(N_("Window : Actions"), N_("Move To Center"), @@ -3426,6 +3439,7 @@ e_actions_init(void) e_action_predef_name_set(N_("Keyboard Layouts"), N_("Previous keyboard layout"), "kbd_layout_prev", NULL, NULL, 0); + return 1; } diff --git a/src/bin/e_comp_object.c b/src/bin/e_comp_object.c index 5ed948533..6b4df5aba 100644 --- a/src/bin/e_comp_object.c +++ b/src/bin/e_comp_object.c @@ -657,7 +657,7 @@ static void _e_comp_object_setup(E_Comp_Object *cw) { cw->clip = evas_object_rectangle_add(cw->comp->evas); - evas_object_resize(cw->clip, cw->comp->man->w, cw->comp->man->h); + evas_object_resize(cw->clip, 999999, 999999); evas_object_smart_member_add(cw->clip, cw->smart_obj); cw->effect_obj = edje_object_add(cw->comp->evas); evas_object_move(cw->effect_obj, cw->x, cw->y); diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index 6208d20e1..d8a5813a5 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -1334,7 +1334,8 @@ _e_comp_x_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_ c = e_comp_find_by_window(ev->win); if (c) { - e_manager_resize(c->man, ev->w, ev->h); + // do not handle this here - use randr events + //e_manager_resize(c->man, ev->w, ev->h); return ECORE_CALLBACK_RENEW; } ec = _e_comp_x_client_find_by_window(ev->win); @@ -4565,14 +4566,32 @@ _e_comp_x_pre_swap(void *data, Evas *e EINA_UNUSED) static Eina_Bool _e_comp_x_xinerama_setup(int rw, int rh) { - int n, i; + int i; E_Screen *screen; Eina_List *all_screens = NULL; + Eina_List *l; + E_Randr2_Screen *s; - /* first (and only) root window */ - /* get number of xinerama screens */ - n = ecore_x_xinerama_screen_count_get(); - if (n < 2) + i = 0; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if ((s->config.enabled) && + (s->config.geom.w > 0) && + (s->config.geom.h > 0)) + { + screen = E_NEW(E_Screen, 1); + screen->escreen = screen->screen = i; + screen->x = s->config.geom.x; + screen->y = s->config.geom.y; + screen->w = s->config.geom.w; + screen->h = s->config.geom.h; + all_screens = eina_list_append(all_screens, screen); + INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i", + i, i, screen->w, screen->h, screen->x, screen->y); + i++; + } + } + if (i == 0) { screen = E_NEW(E_Screen, 1); screen->escreen = screen->screen = 0; @@ -4582,32 +4601,35 @@ _e_comp_x_xinerama_setup(int rw, int rh) screen->h = rh; all_screens = eina_list_append(all_screens, screen); } - else - { - for (i = 0; i < n; i++) - { - int x, y, w, h; - - /* get each xinerama screen geometry */ - if (ecore_x_xinerama_screen_geometry_get(i, &x, &y, &w, &h)) - { - INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i", - i, i, w, h, x, y); - /* add it to our list */ - screen = E_NEW(E_Screen, 1); - screen->escreen = screen->screen = i; - screen->x = x; - screen->y = y; - screen->w = w; - screen->h = h; - all_screens = eina_list_append(all_screens, screen); - } - } - } e_xinerama_screens_set(all_screens); return EINA_TRUE; } +static Eina_Bool +_e_comp_x_randr_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info EINA_UNUSED) +{ + if ((e_comp->man->w != e_randr2->w) || + (e_comp->man->h != e_randr2->h)) + { + e_manager_resize(e_comp->man, e_randr2->w, e_randr2->h); + } + else + { + E_Client *ec; + + ecore_x_netwm_desk_size_set(e_comp->man->root, e_comp->man->w, e_comp->man->h); + _e_comp_x_xinerama_setup(e_comp->man->w, e_comp->man->h); + + e_comp_canvas_update(); + E_CLIENT_FOREACH(e_comp, ec) + { + if (!e_client_util_ignored_get(ec)) + _e_comp_x_client_zone_geometry_set(ec); + } + } + return ECORE_CALLBACK_RENEW; +} + static void _e_comp_x_ee_resize(Ecore_Evas *ee EINA_UNUSED) { @@ -5251,7 +5273,10 @@ e_comp_x_init(void) e_desklock_show_hook_add(_e_comp_x_desklock_show); e_desklock_hide_hook_add(_e_comp_x_desklock_hide); - if (!e_randr_init()) return 0; + + if (!e_randr2_init()) return 0; + E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE, _e_comp_x_randr_change, NULL); + if (!e_atoms_init()) return 0; if (!_e_comp_x_screens_setup()) return EINA_FALSE; if (!e_xsettings_init()) @@ -5274,7 +5299,7 @@ e_comp_x_shutdown(void) ecore_x_screensaver_custom_blanking_disable(); if (x_fatal) return; e_atoms_shutdown(); - e_randr_shutdown(); + e_randr2_shutdown(); /* ecore_x_ungrab(); */ ecore_x_focus_reset(); ecore_x_events_allow_all(); diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h index a39351e00..832a7d2a0 100644 --- a/src/bin/e_includes.h +++ b/src/bin/e_includes.h @@ -10,7 +10,7 @@ #include "e_auth.h" #ifdef NEED_X # include "e_comp_x.h" -# include "e_randr.h" +# include "e_randr2.h" #endif #include "e_pixmap.h" #include "e_comp_object.h" diff --git a/src/bin/e_init.c b/src/bin/e_init.c index 60c8a6143..e61b467b6 100644 --- a/src/bin/e_init.c +++ b/src/bin/e_init.c @@ -64,7 +64,6 @@ e_init_show(void) evas_object_name_set(o, "_e_init_extra_screen"); } evas_object_clip_set(o, zone->bg_clip_object); - fprintf(stderr, "zone %p: %i %i %ix%i\n", zone, zone->x, zone->y, zone->w, zone->h); evas_object_move(o, zone->x, zone->y); evas_object_resize(o, zone->w, zone->h); evas_object_layer_set(o, E_LAYER_MAX); diff --git a/src/bin/e_randr2.c b/src/bin/e_randr2.c new file mode 100644 index 000000000..781a55a4e --- /dev/null +++ b/src/bin/e_randr2.c @@ -0,0 +1,1581 @@ +#include "e.h" + +#define E_RANDR_CONFIG_VERSION 1 + +///////////////////////////////////////////////////////////////////////// +static void _animated_apply_abort(void); +static Eina_Bool _cb_delay_timer(void *data); +static Eina_Bool _cb_fade_animator(void *data); +static void _animated_apply(void); +static void _do_apply(void); +static void _info_free(E_Randr2 *r); +static E_Config_Randr2 *_config_load(void); +static void _config_free(E_Config_Randr2 *cfg); +static Eina_Bool _config_save(E_Randr2 *r, E_Config_Randr2 *cfg); +static void _config_update(E_Randr2 *r, E_Config_Randr2 *cfg); +static void _config_apply(E_Randr2 *r, E_Config_Randr2 *cfg); +static E_Config_Randr2_Screen *_config_screen_find(E_Randr2_Screen *s, E_Config_Randr2 *cfg); +static int _config_screen_match_count(E_Randr2 *r, E_Config_Randr2 *cfg); +static char *_screens_fingerprint(E_Randr2 *r); +static Eina_Bool _screens_differ(E_Randr2 *r1, E_Randr2 *r2); +static void _cb_acpi_handler_add(void *data); +static Eina_Bool _cb_screen_change_delay(void *data); +static void _screen_change_delay(void); +static Eina_Bool _cb_acpi(void *data, int type, void *event); +static E_Randr2_Screen *_screen_output_find(const char *out); +static E_Randr2_Screen *_screen_id_find(const char *id); +static void _screen_config_takeover(void); +static void _screen_config_do(E_Randr2_Screen *s); +static void _screen_config_eval(void); +static void _screen_config_maxsize(void); + +///////////////////////////////////////////////////////////////////////// +static E_Config_DD *_e_randr2_cfg_edd = NULL; +static E_Config_DD *_e_randr2_cfg_screen_edd = NULL; +static Eina_List *_ev_handlers = NULL; +static Eina_Bool _lid_is_closed = EINA_FALSE; +static Ecore_Job *_acpi_handler_add_job = NULL; +static Ecore_Timer *_screen_delay_timer = NULL; +static Eina_Bool event_screen = EINA_FALSE; +static Eina_Bool event_ignore = EINA_FALSE; + +///////////////////////////////////////////////////////////////////////// +EAPI E_Config_Randr2 *e_randr2_cfg = NULL; +EAPI E_Randr2 *e_randr2 = NULL; + +EAPI int E_EVENT_RANDR_CHANGE = 0; + +///////////////////////////////////////////////////////////////////////// +// X11 backend +static Eina_Bool _output_init(void); +static void _output_shutdown(void); +static void _output_events_listen(void); +static void _output_events_unlisten(void); +static char *_output_screen_get(Ecore_X_Window root, Ecore_X_Randr_Output o); +static Ecore_X_Randr_Edid_Display_Interface_Type _output_conn_type_get(Ecore_X_Window root, Ecore_X_Randr_Output o); +static char *_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output o); +static Eina_Bool _is_lid_name(const char *name); +static E_Randr2 *_info_get(void); +static Eina_Bool _cb_screen_change(void *data, int type, void *event); +static Eina_Bool _cb_crtc_change(void *data, int type, void *event); +static Eina_Bool _cb_output_change(void *data, int type, void *event); +static Eina_Bool _output_name_find(Ecore_X_Window root, const char *name, Ecore_X_Randr_Output *outputs, int outputs_num, Ecore_X_Randr_Output *out_ret); +static Eina_Bool _output_exists(Ecore_X_Randr_Output out, Ecore_X_Randr_Crtc_Info *info); +static Eina_Bool _rotation_exists(int rot, Ecore_X_Randr_Crtc_Info *info); +static Ecore_X_Randr_Mode _mode_screen_find(Ecore_X_Window root, E_Randr2_Screen *s, Ecore_X_Randr_Output out); +static void _screen_config_apply(void); + +///////////////////////////////////////////////////////////////////////// +EINTERN Eina_Bool +e_randr2_init(void) +{ + if (!_output_init()) return EINA_FALSE; + // create data descriptors for config storage + _e_randr2_cfg_screen_edd = + E_CONFIG_DD_NEW("E_Config_Randr2_Screen", E_Config_Randr2_Screen); +#undef T +#undef D +#define T E_Config_Randr2_Screen +#define D _e_randr2_cfg_screen_edd + E_CONFIG_VAL(D, T, id, STR); + E_CONFIG_VAL(D, T, rel_to, STR); + E_CONFIG_VAL(D, T, rel_align, DOUBLE); + E_CONFIG_VAL(D, T, mode_refresh, DOUBLE); + E_CONFIG_VAL(D, T, mode_w, UINT); + E_CONFIG_VAL(D, T, mode_h, INT); + E_CONFIG_VAL(D, T, rotation, INT); + E_CONFIG_VAL(D, T, priority, INT); + E_CONFIG_VAL(D, T, rel_mode, UCHAR); + E_CONFIG_VAL(D, T, enabled, UCHAR); + + _e_randr2_cfg_edd = E_CONFIG_DD_NEW("E_Config_Randr2", E_Config_Randr2); +#undef T +#undef D +#define T E_Config_Randr2 +#define D _e_randr2_cfg_edd + E_CONFIG_VAL(D, T, version, INT); + E_CONFIG_LIST(D, T, screens, _e_randr2_cfg_screen_edd); + E_CONFIG_VAL(D, T, restore, UCHAR); + + if (!E_EVENT_RANDR_CHANGE) E_EVENT_RANDR_CHANGE = ecore_event_type_new(); + // delay setting up acpi handler, as acpi is init'ed after randr + _acpi_handler_add_job = ecore_job_add(_cb_acpi_handler_add, NULL); + // get current lid status of a laptop + _lid_is_closed = (e_acpi_lid_status_get() == E_ACPI_LID_CLOSED); + // set up events from the driver + _output_events_listen(); + // get current screen info + e_randr2 = _info_get(); + // from screen info calculate screen max dimensions + _screen_config_maxsize(); + // load config and apply it + e_randr2_cfg = _config_load(); + // only apply if restore is set AND at least one configured screen + // matches one we have + if ((e_randr2_cfg->restore) && + (_config_screen_match_count(e_randr2, e_randr2_cfg) > 0)) + { +// _config_update(e_randr2, e_randr2_cfg); + _do_apply(); + } + else + { + _config_update(e_randr2, e_randr2_cfg); + e_randr2_config_save(); + } + return EINA_TRUE; +} + +EINTERN int +e_randr2_shutdown(void) +{ + _animated_apply_abort(); + // nuke any screen config delay handler + if (_screen_delay_timer) ecore_timer_del(_screen_delay_timer); + _screen_delay_timer = NULL; + // stop listening to driver info + _output_events_unlisten(); + // clean up acpi stuff + if (_acpi_handler_add_job) ecore_job_del(_acpi_handler_add_job); + _acpi_handler_add_job = NULL; + // clear up all event handlers + E_FREE_LIST(_ev_handlers, ecore_event_handler_del); + // free up screen info + _info_free(e_randr2); + e_randr2 = NULL; + _config_free(e_randr2_cfg); + e_randr2_cfg = NULL; + // free up data descriptors + E_CONFIG_DD_FREE(_e_randr2_cfg_edd); + E_CONFIG_DD_FREE(_e_randr2_cfg_screen_edd) + _output_shutdown(); + return 1; +} + +EAPI Eina_Bool +e_randr2_config_save(void) +{ + // save our config + return _config_save(e_randr2, e_randr2_cfg); +} + +EAPI void +e_randr2_config_apply(void) +{ + _animated_apply(); +} + +EAPI void +e_randr2_screeninfo_update(void) +{ + // re-fetch/update current screen info + _info_free(e_randr2); + e_randr2 = _info_get(); + _screen_config_maxsize(); +} + +///////////////////////////////////////////////////////////////////////// +static double _start_time = 0.0; +static Ecore_Animator *_fade_animator = NULL; +static Ecore_Timer *_apply_delay = NULL; +Eina_Bool _applying = EINA_FALSE; +static int _target_from = 0; +static int _target_to = 0; +static Evas_Object *_fade_obj = NULL; + +static void +_animated_apply_abort(void) +{ + if (_apply_delay) ecore_timer_del(_apply_delay); + if (_fade_animator) ecore_animator_del(_fade_animator); + _apply_delay = NULL; + _fade_animator = NULL; + _applying = EINA_FALSE; + _fade_obj = NULL; +} + +static Eina_Bool +_cb_delay_timer(void *data EINA_UNUSED) +{ + _apply_delay = NULL; + _target_from = 255; + _target_to = 0; + _start_time = ecore_loop_time_get(); + _fade_animator = ecore_animator_add(_cb_fade_animator, NULL); + return EINA_FALSE; +} + +static Eina_Bool +_cb_fade_animator(void *data EINA_UNUSED) +{ + double t = ecore_loop_time_get() - _start_time; + int v; + + t = t / 0.5; + if (t < 0.0) t = 0.0; + v = _target_from + ((_target_to - _target_from) * t); + if (t >= 1.0) v = _target_to; + evas_object_color_set(_fade_obj, 0, 0, 0, v); + if (v == _target_to) + { + if (_target_to == 255) + { + _apply_delay = ecore_timer_add(3.0, _cb_delay_timer, NULL); + _do_apply(); + } + else + { + evas_object_del(_fade_obj); + _fade_obj = NULL; + _applying = EINA_FALSE; + } + _fade_animator = NULL; + return EINA_FALSE; + } + return EINA_TRUE; +} + +static void +_animated_apply(void) +{ + Evas *e; + + // fade out, config, wait 3 seconds, fade back in + if (_applying) return; + _applying = EINA_TRUE; + _start_time = ecore_loop_time_get(); + e = e_comp_get(NULL)->evas; + _fade_obj = evas_object_rectangle_add(e); + evas_object_pass_events_set(_fade_obj, EINA_TRUE); + evas_object_color_set(_fade_obj, 0, 0, 0, 0); + evas_object_move(_fade_obj, 0, 0); + evas_object_resize(_fade_obj, 999999, 999999); + evas_object_layer_set(_fade_obj, EVAS_LAYER_MAX); + evas_object_show(_fade_obj); + _target_from = 0; + _target_to = 255; + _fade_animator = ecore_animator_add(_cb_fade_animator, NULL); +} + +static void +_do_apply(void) +{ + // take current screen config and apply it to the driver + printf("RRR: re-get info before applying..\n"); + _info_free(e_randr2); + e_randr2 = _info_get(); + _screen_config_maxsize(); + printf("RRR: apply config...\n"); + _config_apply(e_randr2, e_randr2_cfg); + printf("RRR: takeover config...\n"); + _screen_config_takeover(); + printf("RRR: eval config...\n"); + _screen_config_eval(); + printf("RRR: really apply config...\n"); + _screen_config_apply(); + printf("RRR: done config...\n"); +} + +static void +_info_free(E_Randr2 *r) +{ + E_Randr2_Screen *s; + E_Randr2_Mode *m; + + if (!r) return; + // free up our randr screen data + EINA_LIST_FREE(r->screens, s) + { + free(s->id); + free(s->info.screen); + free(s->info.name); + free(s->info.edid); + EINA_LIST_FREE(s->info.modes, m) free(m); + free(s->config.relative.to); + free(s); + } + free(r); +} + +static E_Config_Randr2 * +_config_load(void) +{ + E_Config_Randr2 *cfg; + + // load config and check if version is up to date + cfg = e_config_domain_load("e_randr2", _e_randr2_cfg_edd); + if (cfg) + { + if (cfg->version < E_RANDR_CONFIG_VERSION) + { + _config_free(cfg); + cfg = NULL; + } + else + { + printf("RRR: loaded existing config\n"); + return cfg; + } + } + + // need new config + cfg = calloc(1, sizeof(E_Config_Randr2)); + cfg->version = E_RANDR_CONFIG_VERSION; + cfg->screens = NULL; + cfg->restore = 1; + printf("RRR: fresh config\n"); + return cfg; +} + +static void +_config_free(E_Config_Randr2 *cfg) +{ + E_Config_Randr2_Screen *cs; + + if (!cfg) return; + // free config data + EINA_LIST_FREE(cfg->screens, cs) free(cs); + free(cfg); +} + +static Eina_Bool +_config_save(E_Randr2 *r, E_Config_Randr2 *cfg) +{ + if ((!r) || (!cfg)) return EINA_FALSE; + // save config struct to cfg file + return e_config_domain_save("e_randr2", _e_randr2_cfg_edd, cfg); +} + +static void +_config_update(E_Randr2 *r, E_Config_Randr2 *cfg) +{ + Eina_List *l; + E_Randr2_Screen *s; + E_Config_Randr2_Screen *cs; + + printf("--------------------------------------------------\n"); + EINA_LIST_FOREACH(r->screens, l, s) + { + printf("RRR: out id=%s: connected=%i\n", s->id, s->info.connected); + if ((!s->id) || (!s->info.connected)) continue; + cs = _config_screen_find(s, cfg); + if (!cs) + { + cs = calloc(1, sizeof(E_Config_Randr2_Screen)); + if (cs) + { + cs->id = strdup(s->id); + cfg->screens = eina_list_prepend(cfg->screens, cs); + } + } + if (cs) + { + if (s->config.relative.to) + cs->rel_to = strdup(s->config.relative.to); + cs->rel_align = s->config.relative.align; + cs->mode_refresh = s->config.mode.refresh; + cs->mode_w = s->config.mode.w; + cs->mode_h = s->config.mode.h; + cs->rotation = s->config.rotation; + cs->priority = s->config.priority; + cs->rel_mode = s->config.relative.mode; + cs->enabled = s->config.enabled; + } + } + printf("--------------------------------------------------\n"); +} + +static void +_config_apply(E_Randr2 *r, E_Config_Randr2 *cfg) +{ + Eina_List *l; + E_Randr2_Screen *s; + E_Config_Randr2_Screen *cs; + + if ((!r) || (!cfg)) return; + EINA_LIST_FOREACH(r->screens, l, s) + { + printf("RRR: apply '%s'...\n", s->info.name); + cs = NULL; + if (s->info.connected) cs = _config_screen_find(s, cfg); + printf("RRR: connected = %i\n", s->info.connected); + if ((cs) && (cs->enabled)) + { + printf("RRR: ... enabled\n"); + s->config.enabled = EINA_TRUE; + s->config.mode.w = cs->mode_w; + s->config.mode.h = cs->mode_h; + s->config.mode.refresh = cs->mode_refresh; + s->config.mode.preferred = EINA_FALSE; + s->config.rotation = cs->rotation; + s->config.priority = cs->priority; + free(s->config.relative.to); + if (cs->rel_to) s->config.relative.to = strdup(cs->rel_to); + else s->config.relative.to = NULL; + s->config.relative.mode = cs->rel_mode; + s->config.relative.align = cs->rel_align; + } + else + { + printf("RRR: ... disabled\n"); + s->config.enabled = EINA_FALSE; + s->config.geom.x = 0; + s->config.geom.y = 0; + s->config.geom.w = 0; + s->config.geom.h = 0; + s->config.mode.w = 0; + s->config.mode.h = 0; + s->config.mode.refresh = 0.0; + s->config.mode.preferred = EINA_FALSE; + s->config.rotation = 0; + s->config.priority = 0; + free(s->config.relative.to); + s->config.relative.to = NULL; + s->config.relative.mode = E_RANDR2_RELATIVE_NONE; + s->config.relative.align = 0.0; + } + s->config.configured = EINA_TRUE; + } +} + +static E_Config_Randr2_Screen * +_config_screen_find(E_Randr2_Screen *s, E_Config_Randr2 *cfg) +{ + Eina_List *l; + E_Config_Randr2_Screen *cs; + + if ((!s) || (!cfg)) return NULL; + if (!s->id) return NULL; + EINA_LIST_FOREACH(cfg->screens, l, cs) + { + if (!cs->id) continue; + if (!strcmp(cs->id, s->id)) return cs; + } + return NULL; +} + +static int +_config_screen_match_count(E_Randr2 *r, E_Config_Randr2 *cfg) +{ + Eina_List *l, *ll; + E_Randr2_Screen *s; + E_Config_Randr2_Screen *cs; + int count = 0; + + EINA_LIST_FOREACH(cfg->screens, l, cs) + { + if (!cs->id) continue; + EINA_LIST_FOREACH(r->screens, ll, s) + { + if ((!s->id) || (!s->info.connected)) continue; + if (!strcmp(cs->id, s->id)) count++; + } + } + return count; +} + +static void +_cb_acpi_handler_add(void *data EINA_UNUSED) +{ + // add acpi handler in delayed job + E_LIST_HANDLER_APPEND(_ev_handlers, E_EVENT_ACPI, _cb_acpi, NULL); + _acpi_handler_add_job = NULL; +} + +static char * +_screens_fingerprint(E_Randr2 *r) +{ + Eina_List *l; + E_Randr2_Screen *s; + Eina_Strbuf *buf; + char *str; + + buf = eina_strbuf_new(); + if (!buf) return NULL; + EINA_LIST_FOREACH(r->screens, l, s) + { + if (!s->id) eina_strbuf_append(buf, ":NULL:"); + else + { + eina_strbuf_append(buf, ":"); + eina_strbuf_append(buf, s->id); + eina_strbuf_append(buf, ":"); + } + } + str = eina_strbuf_string_steal(buf); + eina_strbuf_free(buf); + return str; +} + +static Eina_Bool +_screens_differ(E_Randr2 *r1, E_Randr2 *r2) +{ + char *s1, *s2; + Eina_Bool changed = EINA_FALSE; + Eina_List *l, *ll; + E_Randr2_Screen *s, *ss; + + // check monitor outputs and edids, plugged in things + s1 = _screens_fingerprint(r1); + s2 = _screens_fingerprint(r2); + if ((!s1) && (!s2)) return EINA_FALSE; + if ((s1) && (s2) && (strcmp(s1, s2))) changed = EINA_TRUE; + free(s1); + free(s2); + // check screen config + EINA_LIST_FOREACH(r2->screens, l, s) + { + if (!s->id) continue; + EINA_LIST_FOREACH(r2->screens, ll, ss) + { + if ((ss->id) && (!strcmp(s->id, ss->id))) break; + ss = NULL; + } + if (!ss) changed = EINA_TRUE; + else if ((s->config.geom.x != ss->config.geom.x) || + (s->config.geom.y != ss->config.geom.y) || + (s->config.geom.w != ss->config.geom.w) || + (s->config.geom.h != ss->config.geom.h) || + (s->config.mode.w != ss->config.mode.w) || + (s->config.mode.h != ss->config.mode.h) || + (s->config.enabled != ss->config.enabled) || + (s->config.rotation != ss->config.rotation)) + changed = EINA_TRUE; + } + return changed; +} + +static Eina_Bool +_cb_screen_change_delay(void *data EINA_UNUSED) +{ + _screen_delay_timer = NULL; + // if we had a screen plug/unplug etc. event and we shouldnt ignore it... + if ((event_screen) && (!event_ignore)) + { + E_Randr2 *rtemp; + Eina_Bool change = EINA_FALSE; + + printf("RRR: reconfigure screens due to event...\n"); + rtemp = _info_get(); + if (rtemp) + { + if (_screens_differ(e_randr2, rtemp)) change = EINA_TRUE; + _info_free(rtemp); + } + // we plugged or unplugged some monitor - re-apply config so + // known screens can be coonfigured + if (change) e_randr2_config_apply(); + } + // update screen info after the above apply or due to external changes + e_randr2_screeninfo_update(); + // tell the rest of e some screen reconfigure thing happened + ecore_event_add(E_EVENT_RANDR_CHANGE, NULL, NULL, NULL); + event_screen = EINA_FALSE; + event_ignore = EINA_FALSE; + return EINA_FALSE; +} + +static void +_screen_change_delay(void) +{ + // delay handling of screen shances as they can come in in a series over + // time and thus we can batch up responding to them by waiting 1.0 sec + if (_screen_delay_timer) ecore_timer_del(_screen_delay_timer); + _screen_delay_timer = ecore_timer_add(1.0, _cb_screen_change_delay, NULL); +} + +static Eina_Bool +_cb_acpi(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + E_Event_Acpi *ev = event; + Eina_Bool lid_closed; + + if (ev->type != E_ACPI_TYPE_LID) return EINA_TRUE; + lid_closed = (ev->status == E_ACPI_LID_CLOSED); + if (lid_closed == _lid_is_closed) return EINA_TRUE; + _lid_is_closed = lid_closed; + _screen_change_delay(); + return EINA_TRUE; +} + +static E_Randr2_Screen * +_screen_output_find(const char *out) +{ + E_Randr2_Screen *s; + Eina_List *l; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (!strcmp(s->info.name, out)) return s; + } + return NULL; +} + +static E_Randr2_Screen * +_screen_id_find(const char *id) +{ + E_Randr2_Screen *s; + Eina_List *l; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (!strcmp(s->id, id)) return s; + } + return NULL; +} + +static void +_screen_config_takeover(void) +{ + Eina_List *l; + E_Randr2_Screen *s; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + s->config.configured = EINA_TRUE; + } +} + +static int _config_do_recurse = 0; + +static void +_screen_config_do(E_Randr2_Screen *s) +{ + E_Randr2_Screen *s2 = NULL; + + _config_do_recurse++; + if (_config_do_recurse > 20) + { + ERR("screen config loop!"); + return; + } + // if screen has a dependency... + if ((s->config.relative.mode != E_RANDR2_RELATIVE_UNKNOWN) && + (s->config.relative.mode != E_RANDR2_RELATIVE_NONE) && + (s->config.relative.to)) + { + // if this screen is relative TO something (clone or left/right etc. + // then calculate what it is relative to first + s2 = _screen_id_find(s->config.relative.to); + printf("RRR: '%s' is relative to %p\n", s->info.name, s2); + if (!s2) + { + // strip out everythng in the string from / on as that is edid + // and fall back to finding just the output name in the rel + // to identifier, rather than the specific screen id + char *p, *str = alloca(strlen(s->config.relative.to) + 1); + strcpy(str, s->config.relative.to); + if ((p = strchr(str, '/'))) *p = 0; + s2 = _screen_output_find(str); + } + printf("RRR: '%s' is relative to %p\n", s->info.name, s2); + if (s2) _screen_config_do(s2); + } + s->config.geom.x = 0; + s->config.geom.y = 0; + if ((s->config.rotation == 0) || (s->config.rotation == 180)) + { + s->config.geom.w = s->config.mode.w; + s->config.geom.h = s->config.mode.h; + } + else + { + s->config.geom.w = s->config.mode.h; + s->config.geom.h = s->config.mode.w; + } + if (s2) + { + if (s->config.relative.mode == E_RANDR2_RELATIVE_CLONE) + { + printf("RRR: clone relative\n"); + s->config.geom.x = s2->config.geom.x; + s->config.geom.y = s2->config.geom.y; + s->config.geom.w = s2->config.geom.w; + s->config.geom.h = s2->config.geom.h; + s->config.mode.w = s2->config.mode.w; + s->config.mode.h = s2->config.mode.h; + s->config.rotation = s2->config.rotation; + s->config.mode.refresh = s2->config.mode.refresh; + } + else if (s->config.relative.mode == E_RANDR2_RELATIVE_TO_LEFT) + { + printf("RRR: to left relative\n"); + s->config.geom.x = s2->config.geom.x - s->config.geom.w; + s->config.geom.y = s2->config.geom.y + + ((s2->config.geom.h - s->config.geom.h) * + s->config.relative.align); + } + else if (s->config.relative.mode == E_RANDR2_RELATIVE_TO_RIGHT) + { + printf("RRR: to right relative\n"); + s->config.geom.x = s2->config.geom.x + s2->config.geom.w; + s->config.geom.y = s2->config.geom.y + + ((s2->config.geom.h - s->config.geom.h) * + s->config.relative.align); + } + else if (s->config.relative.mode == E_RANDR2_RELATIVE_TO_ABOVE) + { + printf("RRR: to above relative\n"); + s->config.geom.x = s2->config.geom.x + + ((s2->config.geom.w - s->config.geom.w) * + s->config.relative.align); + s->config.geom.y = s2->config.geom.y - s->config.geom.h; + } + else if (s->config.relative.mode == E_RANDR2_RELATIVE_TO_BELOW) + { + printf("RRR: to below relative\n"); + s->config.geom.x = s2->config.geom.x + + ((s2->config.geom.w - s->config.geom.w) * + s->config.relative.align); + s->config.geom.y = s2->config.geom.y + s2->config.geom.h; + } + } +} + +static void +_screen_config_eval(void) +{ + Eina_List *l; + E_Randr2_Screen *s; + int minx, miny, maxx, maxy; + + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (s->config.configured) _screen_config_do(s); + } + minx = 65535; + miny = 65535; + maxx = -65536; + maxy = -65536; + printf("RRR:--------------------------------\n"); + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (!s->config.enabled) continue; + if (s->config.geom.x < minx) minx = s->config.geom.x; + if (s->config.geom.y < miny) miny = s->config.geom.y; + if ((s->config.geom.x + s->config.geom.w) > maxx) + maxx = s->config.geom.x + s->config.geom.w; + if ((s->config.geom.y + s->config.geom.h) > maxy) + maxy = s->config.geom.y + s->config.geom.h; + printf("RRR: s: '%s' @ %i %i - %ix%i\n", + s->info.name, + s->config.geom.x, s->config.geom.y, + s->config.geom.w, s->config.geom.h); + } + printf("RRR:--- %i %i -> %i %i\n", minx, miny, maxx, maxy); + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + s->config.geom.x -= minx; + s->config.geom.y -= miny; + } + e_randr2->w = maxx - minx; + e_randr2->h = maxy - miny; +} + +static void +_screen_config_maxsize(void) +{ + Eina_List *l; + E_Randr2_Screen *s; + int maxx, maxy; + + maxx = -65536; + maxy = -65536; + printf("RRR:-------------------------------- 2\n"); + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (!s->config.enabled) continue; + if ((s->config.geom.x + s->config.geom.w) > maxx) + maxx = s->config.geom.x + s->config.geom.w; + if ((s->config.geom.y + s->config.geom.h) > maxy) + maxy = s->config.geom.y + s->config.geom.h; + printf("RRR: '%s': %i %i %ix%i\n", + s->info.name, + s->config.geom.x, s->config.geom.y, + s->config.geom.w, s->config.geom.h); + } + printf("RRR: result max: %ix%i\n", maxx, maxy); + e_randr2->w = maxx; + e_randr2->h = maxy; +} + +///////////////////////////////////////////////////////////////////////// +// X11 backend +static Eina_Bool +_output_init(void) +{ + // is randr extn there? + return ecore_x_randr_query(); +} + +static void +_output_shutdown(void) +{ +} + +static void +_output_events_listen(void) +{ + // add handler for randr screen change events + E_LIST_HANDLER_APPEND(_ev_handlers, ECORE_X_EVENT_SCREEN_CHANGE, + _cb_screen_change, NULL); + E_LIST_HANDLER_APPEND(_ev_handlers, ECORE_X_EVENT_RANDR_CRTC_CHANGE, + _cb_crtc_change, NULL); + E_LIST_HANDLER_APPEND(_ev_handlers, ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, + _cb_output_change, NULL); + // if it's 1.2 or better then we can select for these events + if (ecore_x_randr_version_get() >= E_RANDR_VERSION_1_2) + { + Ecore_X_Window root = ecore_x_window_root_first_get(); + ecore_x_randr_events_select(root, EINA_TRUE); + } +} + +static void +_output_events_unlisten(void) +{ + // clear up event listening + if (ecore_x_randr_version_get() >= E_RANDR_VERSION_1_2) + { + Ecore_X_Window root = ecore_x_window_root_first_get(); + ecore_x_randr_events_select(root, EINA_FALSE); + } +} + +static char * +_output_screen_get(Ecore_X_Window root, Ecore_X_Randr_Output o) +{ + // get the name of the screen - likely a model name or manufacturer name + char *name; + unsigned long len = 0; + unsigned char *edid = ecore_x_randr_output_edid_get(root, o, &len); + if (!edid) return NULL; + name = ecore_x_randr_edid_display_name_get(edid, len); + free(edid); + return name; +} + +static Ecore_X_Randr_Edid_Display_Interface_Type +_output_conn_type_get(Ecore_X_Window root, Ecore_X_Randr_Output o) +{ + // get what kind of connector (hdmi, dvi, displayport etc.) - vga is + Ecore_X_Randr_Edid_Display_Interface_Type type; + unsigned long len = 0; + unsigned char *edid = ecore_x_randr_output_edid_get(root, o, &len); + if (!edid) return ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_UNDEFINED; + type = ecore_x_randr_edid_display_interface_type_get(edid, len); + free(edid); + return type; +} + +static char * +_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output o) +{ + // get the output name - like connector (hdmi-0, dp1, dvi-0-1 etc.) + char *name = ecore_x_randr_output_name_get(root, o, NULL); + if (name) return name; + return _output_screen_get(root, o); +} + +static Eina_Bool +_is_lid_name(const char *name) +{ + // a fixed list of possible built in connector names - likely a laptop + // or device internal display + if (!name) return EINA_FALSE; + if (strstr(name, "LVDS")) return EINA_TRUE; + else if (strstr(name, "lvds")) return EINA_TRUE; + else if (strstr(name, "Lvds")) return EINA_TRUE; + else if (strstr(name, "LCD")) return EINA_TRUE; + else if (strstr(name, "eDP")) return EINA_TRUE; + else if (strstr(name, "edp")) return EINA_TRUE; + else if (strstr(name, "EDP")) return EINA_TRUE; + return EINA_FALSE; +} + +static char * +_edid_string_get(Ecore_X_Window root, Ecore_X_Randr_Output o) +{ + // convert the edid binary data into a hex string so we can use it as + // part of a name + unsigned char *edid = NULL; + unsigned long len = 0; + char *edid_str = NULL; + + edid = ecore_x_randr_output_edid_get(root, o, &len); + if (edid) + { + unsigned int k, kk; + + edid_str = malloc((len * 2) + 1); + if (edid_str) + { + const char *hexch = "0123456789abcdef"; + + for (kk = 0, k = 0; k < len; k++) + { + edid_str[kk ] = hexch[(edid[k] >> 4) & 0xf]; + edid_str[kk + 1] = hexch[ edid[k] & 0xf]; + kk += 2; + } + edid_str[kk] = 0; + } + free(edid); + } + return edid_str; +} + +static E_Randr2_Screen * +_info_unconf_primary_find(E_Randr2 *r) +{ + Eina_List *l; + E_Randr2_Screen *s, *s_primary = NULL; + int priority = 0; + + EINA_LIST_FOREACH(r->screens, l, s) + { + if (!((s->config.enabled) && + (s->config.mode.w > 0) && (s->config.mode.h > 0) && + (s->config.geom.w > 0) && (s->config.geom.h > 0))) + continue; + if (s->config.priority > priority) + { + s_primary = s; + priority = s->config.priority; + } + } + return s_primary; +} + +static E_Randr2_Screen * +_info_unconf_left_find(E_Randr2 *r) +{ + Eina_List *l; + E_Randr2_Screen *s, *s_left = NULL; + int left_x = 0x7fffffff; + int left_size = 0; + + EINA_LIST_FOREACH(r->screens, l, s) + { + if (!((s->config.enabled) && + (s->config.mode.w > 0) && (s->config.mode.h > 0) && + (s->config.geom.w > 0) && (s->config.geom.h > 0))) + continue; + if ((s->config.geom.x <= left_x) && + ((s->config.geom.w * s->config.geom.h) > left_size)) + { + left_size = s->config.geom.w * s->config.geom.h; + left_x = s->config.geom.x; + s_left = s; + } + } + return s_left; +} + +static E_Randr2_Screen * +_info_unconf_closest_find(E_Randr2 *r, E_Randr2_Screen *s2, Eina_Bool configured) +{ + Eina_List *l; + E_Randr2_Screen *s, *s_sel = NULL; + int dist = 0x7fffffff; + int dx, dy; + + EINA_LIST_FOREACH(r->screens, l, s) + { + if (s == s2) continue; + if (!((s->config.enabled) && + (s->config.mode.w > 0) && (s->config.mode.h > 0) && + (s->config.geom.w > 0) && (s->config.geom.h > 0))) + continue; + if ((!configured) && + (s->config.relative.mode != E_RANDR2_RELATIVE_UNKNOWN)) + continue; + else if ((configured) && + (s->config.relative.mode == E_RANDR2_RELATIVE_UNKNOWN)) + continue; + dx = (s->config.geom.x + (s->config.geom.w / 2)) - + (s2->config.geom.x + (s2->config.geom.w / 2)); + dy = (s->config.geom.y + (s->config.geom.h / 2)) - + (s2->config.geom.y + (s2->config.geom.h / 2)); + dx = sqrt((dx * dx) + (dy * dy)); + if (dx < dist) + { + s_sel = s; + dist = dx; + } + } + return s_sel; +} + +static void +_info_relative_fixup(E_Randr2 *r) +{ + E_Randr2_Screen *s, *s2; + int d, dx, dy; + + s = _info_unconf_primary_find(r); + if (s) s->config.relative.mode = E_RANDR2_RELATIVE_NONE; + else + { + s = _info_unconf_left_find(r); + if (!s) return; + s->config.relative.mode = E_RANDR2_RELATIVE_NONE; + } + for (;;) + { + // find the next screen that is closest to the last one we configured + /// that is still not configured yet + s = _info_unconf_closest_find(r, s, EINA_FALSE); + if (!s) break; + s2 = _info_unconf_closest_find(r, s, EINA_TRUE); + // fix up s->config.relative.mode, s->config.relative.to and + // s->config.relative.align to match (as closely as possible) + // the geometry given - config s relative to s2 + if (!s2) s->config.relative.mode = E_RANDR2_RELATIVE_NONE; + else + { + s->config.relative.to = strdup(s2->id); + s->config.relative.align = 0.0; + s->config.relative.mode = E_RANDR2_RELATIVE_NONE; + if ((s->config.geom.x + s->config.geom.w) <= + s2->config.geom.x) + { + s->config.relative.mode = E_RANDR2_RELATIVE_TO_LEFT; + d = s->config.geom.h - s2->config.geom.h; + dy = s2->config.geom.y - s->config.geom.y; + if (d != 0) + s->config.relative.align = ((double)dy) / ((double)d); + } + else if (s->config.geom.x >= + (s2->config.geom.x + s2->config.geom.w)) + { + s->config.relative.mode = E_RANDR2_RELATIVE_TO_RIGHT; + d = s->config.geom.h - s2->config.geom.h; + dy = s2->config.geom.y - s->config.geom.y; + if (d != 0) + s->config.relative.align = ((double)dy) / ((double)d); + } + else if ((s->config.geom.y + s->config.geom.h) <= + s2->config.geom.y) + { + s->config.relative.mode = E_RANDR2_RELATIVE_TO_ABOVE; + d = s->config.geom.w - s2->config.geom.w; + dx = s2->config.geom.x - s->config.geom.x; + if (d != 0) + s->config.relative.align = ((double)dx) / ((double)d); + } + else if (s->config.geom.y >= + (s2->config.geom.y + s2->config.geom.h)) + { + s->config.relative.mode = E_RANDR2_RELATIVE_TO_BELOW; + d = s->config.geom.w - s2->config.geom.w; + dx = s2->config.geom.x - s->config.geom.x; + if (d != 0) + s->config.relative.align = ((double)dx) / ((double)d); + } + else if ((s->config.geom.x == s2->config.geom.x) && + (s->config.geom.y == s2->config.geom.y) && + (s->config.geom.w == s2->config.geom.w) && + (s->config.geom.h == s2->config.geom.h)) + { + s->config.relative.mode = E_RANDR2_RELATIVE_CLONE; + } + // XXXL detect clone + if (s->config.relative.align < 0.0) + s->config.relative.align = 0.0; + else if (s->config.relative.align > 1.0) + s->config.relative.align = 1.0; + } + } +} + +static E_Randr2 * +_info_get(void) +{ + Ecore_X_Randr_Crtc *crtcs = NULL; + Ecore_X_Randr_Output *outputs = NULL; + int crtcs_num = 0, outputs_num = 0, i, j, k; + Ecore_X_Window root = ecore_x_window_root_first_get(); + E_Randr2 *r = calloc(1, sizeof(E_Randr2)); + if (!r) return NULL; + + printf("RRR: ................. info get!\n"); + // do this to force xrandr to update its content + ecore_x_randr_config_timestamp_get(root); + ecore_x_randr_screen_size_range_get(root, NULL, NULL, NULL, NULL); + ecore_x_sync(); + + crtcs = ecore_x_randr_crtcs_get(root, &crtcs_num); + outputs = ecore_x_randr_outputs_get(root, &outputs_num); + + for (i = 0; i < outputs_num; i++) + { + Ecore_X_Randr_Mode *modes; + Ecore_X_Randr_Edid_Display_Interface_Type conn; + int modes_num = 0, modes_pref = 0; + E_Randr2_Screen *s = calloc(1, sizeof(E_Randr2_Screen)); + if (!s) continue; + s->info.name = _output_name_get(root, outputs[i]); + printf("RRR: ...... out %s\n", s->info.name); + if (!s->info.name) + { + free(s); + continue; + } + s->info.screen = _output_screen_get(root, outputs[i]); + s->info.edid = _edid_string_get(root, outputs[i]); + if (s->info.edid) + s->id = malloc(strlen(s->info.name) + 1 + strlen(s->info.edid) + 1); + else + s->id = malloc(strlen(s->info.name) + 1 + 1); + if (!s->id) + { + free(s->info.screen); + free(s->info.edid); + free(s); + continue; + } + strcpy(s->id, s->info.name); + strcat(s->id, "/"); + if (s->info.edid) strcat(s->id, s->info.edid); + conn = _output_conn_type_get(root, outputs[i]); + if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_UNDEFINED) + s->info.connector = E_RANDR2_CONNECTOR_UNDEFINED; + else if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DVI) + s->info.connector = E_RANDR2_CONNECTOR_DVI; + else if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_HDMI_A) + s->info.connector = E_RANDR2_CONNECTOR_HDMI_A; + else if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_HDMI_B) + s->info.connector = E_RANDR2_CONNECTOR_HDMI_B; + else if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_MDDI) + s->info.connector = E_RANDR2_CONNECTOR_MDDI; + else if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT) + s->info.connector = E_RANDR2_CONNECTOR_DISPLAY_PORT; + s->info.is_lid = _is_lid_name(s->info.name); + if (ecore_x_randr_output_connection_status_get(root, outputs[i]) == + ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) + s->info.connected = EINA_TRUE; + printf("RRR: ...... connected %i\n", s->info.connected); + if (ecore_x_randr_output_backlight_level_get(root, outputs[i]) >= 0.0) + s->info.backlight = EINA_TRUE; + ecore_x_randr_output_size_mm_get(root, outputs[i], + &(s->info.size.w), &(s->info.size.h)); + modes = ecore_x_randr_output_modes_get(root, outputs[i], + &modes_num, &modes_pref); + printf("RRR: ...... modes %p\n", modes); + if (modes) + { + for (j = 0; j < modes_num; j++) + { + Ecore_X_Randr_Mode_Info *minfo = + ecore_x_randr_mode_info_get(root, modes[j]); + if (minfo) + { + E_Randr2_Mode *m = calloc(1, sizeof(E_Randr2_Mode)); + if (m) + { + m->w = minfo->width; + m->h = minfo->height; + m->refresh = + (double)minfo->dotClock / + (double)(minfo->hTotal * minfo->vTotal); + if (j == (modes_pref - 1)) + m->preferred = EINA_TRUE; + s->info.modes = eina_list_append(s->info.modes, m); + } + ecore_x_randr_mode_info_free(minfo); + } + } + free(modes); + } + if (ecore_x_randr_primary_output_get(root) == outputs[i]) + s->config.priority = 100; + for (j = 0; j < crtcs_num; j++) + { + Eina_Bool ok, possible; + Ecore_X_Randr_Crtc_Info *info = + ecore_x_randr_crtc_info_get(root, crtcs[j]); + if (info) + { + ok = EINA_FALSE; + possible = EINA_FALSE; + for (k = 0; k < info->noutput; k++) + { + if (info->outputs[k] == outputs[i]) + { + ok = EINA_TRUE; + break; + } + } + if (!ok) + { + for (k = 0; k < info->npossible; k++) + { + if (info->possible[k] == outputs[i]) + { + ok = EINA_TRUE; + possible = EINA_TRUE; + break; + } + } + } + if (ok) + { + if (!possible) + { + Ecore_X_Randr_Mode_Info *minfo; + + s->config.geom.x = info->x; + s->config.geom.y = info->y; + s->config.geom.w = info->width; + s->config.geom.h = info->height; + if (info->rotation & ECORE_X_RANDR_ORIENTATION_ROT_0) + s->config.rotation = 0; + else if (info->rotation & ECORE_X_RANDR_ORIENTATION_ROT_90) + s->config.rotation = 90; + else if (info->rotation & ECORE_X_RANDR_ORIENTATION_ROT_180) + s->config.rotation = 180; + else if (info->rotation & ECORE_X_RANDR_ORIENTATION_ROT_270) + s->config.rotation = 270; + minfo = ecore_x_randr_mode_info_get(root, + info->mode); + if (minfo) + { + s->config.enabled = EINA_TRUE; + s->config.mode.w = minfo->width; + s->config.mode.h = minfo->height; + s->config.mode.refresh = + (double)minfo->dotClock / + (double)(minfo->hTotal * minfo->vTotal); + ecore_x_randr_mode_info_free(minfo); + } + printf("RRR: '%s' %i %i %ix%i\n", + s->info.name, + s->config.geom.x, s->config.geom.y, + s->config.geom.w, s->config.geom.h); + } + if (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_0) + s->info.can_rot_0 = EINA_TRUE; + if (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_90) + s->info.can_rot_90 = EINA_TRUE; + if (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_180) + s->info.can_rot_180 = EINA_TRUE; + if (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_270) + s->info.can_rot_270 = EINA_TRUE; + } + ecore_x_randr_crtc_info_free(info); + } + } + r->screens = eina_list_append(r->screens, s); + } + + free(outputs); + free(crtcs); + + _info_relative_fixup(r); + return r; +} + +static Eina_Bool +_cb_screen_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Screen_Change *ev = event; + printf("RRR: CB screen change...\n"); + event_screen = EINA_TRUE; + ecore_x_randr_config_timestamp_get(ev->root); + ecore_x_randr_screen_current_size_get(ev->root, NULL, NULL, NULL, NULL); + ecore_x_sync(); + _screen_change_delay(); + return EINA_TRUE; +} + +static Eina_Bool +_cb_crtc_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Randr_Crtc_Change *ev = event; + printf("RRR: CB crtc change...\n"); + ecore_x_randr_config_timestamp_get(ev->win); + ecore_x_randr_screen_current_size_get(ev->win, NULL, NULL, NULL, NULL); + ecore_x_sync(); + _screen_change_delay(); + return EINA_TRUE; +} + +static Eina_Bool +_cb_output_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Randr_Output_Change *ev = event; + printf("RRR: CB output change...\n"); + event_screen = EINA_TRUE; + ecore_x_randr_config_timestamp_get(ev->win); + ecore_x_randr_screen_current_size_get(ev->win, NULL, NULL, NULL, NULL); + ecore_x_sync(); + _screen_change_delay(); + return EINA_TRUE; +} + +static Eina_Bool +_output_name_find(Ecore_X_Window root, const char *name, Ecore_X_Randr_Output *outputs, int outputs_num, Ecore_X_Randr_Output *out_ret) +{ + int i; + char *n; + + for (i = 0; i < outputs_num; i++) + { + n = _output_name_get(root, outputs[i]); + if ((n) && (!strcmp(n, name))) + { + free(n); + *out_ret = outputs[i]; + return EINA_TRUE; + } + free(n); + } + return EINA_FALSE; +} + +static Eina_Bool +_output_exists(Ecore_X_Randr_Output out, Ecore_X_Randr_Crtc_Info *info) +{ + int i; + + for (i = 0; i < info->npossible; i++) + { + if (out == info->possible[i]) return EINA_TRUE; + } + return EINA_FALSE; +} + +static Eina_Bool +_rotation_exists(int rot, Ecore_X_Randr_Crtc_Info *info) +{ + if ((rot == 0) && (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_0)) + return EINA_TRUE; + if ((rot == 90) && (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_90)) + return EINA_TRUE; + if ((rot == 180) && (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_180)) + return EINA_TRUE; + if ((rot == 270) && (info->rotations & ECORE_X_RANDR_ORIENTATION_ROT_270)) + return EINA_TRUE; + return EINA_FALSE; +} + +static Ecore_X_Randr_Mode +_mode_screen_find(Ecore_X_Window root, E_Randr2_Screen *s, Ecore_X_Randr_Output out) +{ + Ecore_X_Randr_Mode_Info *minfo; + Ecore_X_Randr_Mode mode = 0, *modes; + int modes_num = 0, modes_pref = 0, distance = 0x7fffffff; + int diff, i; + double refresh; + + modes = ecore_x_randr_output_modes_get(root, out, &modes_num, &modes_pref); + if (!modes) + { + printf("RRR: modes for '%s' FETCH FAILED!!!\n", s->info.name); +/* + for (i = 0; i < 500; i++) + { + printf("RRR: try %i\n", i); +// if (ecore_x_randr_output_connection_status_get(root, out) != +// ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) break; + ecore_x_sync(); + int n; + Ecore_X_Randr_Crtc *crtcs = ecore_x_randr_output_possible_crtcs_get(root, out, &n); + free(crtcs); + char *name = ecore_x_randr_output_name_get(root, out, &n); + free(name); + printf("RRR: conn: %i\n", ecore_x_randr_output_connection_status_get(root, out)); + int mw, mh; + ecore_x_randr_output_size_mm_get(root, out, &mw, &mh); + printf("RRR: bl: %1.2f\n", ecore_x_randr_output_backlight_level_get(root, out)); + ecore_x_randr_config_timestamp_get(root); + ecore_x_sync(); + ecore_x_randr_screen_current_size_get(root, NULL, NULL, NULL, NULL); + ecore_x_sync(); + modes = ecore_x_randr_output_modes_get(root, out, &modes_num, &modes_pref); + if (modes) break; + usleep(1000); + } + */ + } + printf("RRR: modes for '%s' are %p [%i]\n", s->info.name, modes, modes_num); + if (modes) + { + for (i = 0; i < modes_num; i++) + { + minfo = ecore_x_randr_mode_info_get(root, modes[i]); + if (!minfo) continue; + refresh = (double)minfo->dotClock / + (double)(minfo->hTotal * minfo->vTotal); + diff = + (100 * abs(s->config.mode.w - minfo->width)) + + (100 * abs(s->config.mode.h - minfo->height)) + + abs((100 * s->config.mode.refresh) - (100 * refresh)); + if (diff < distance) + { + mode = modes[i]; + distance = diff; + } + ecore_x_randr_mode_info_free(minfo); + } + free(modes); + } + return mode; +} + +static void +_screen_config_apply(void) +{ + Eina_List *l; + E_Randr2_Screen *s; + Ecore_X_Window root = ecore_x_window_root_first_get(); + int minw, minh, maxw, maxh, nw, nh, pw, ph, ww, hh; + Ecore_X_Randr_Crtc *crtcs = NULL; + Ecore_X_Randr_Output *outputs = NULL, out, *outconf; + E_Randr2_Screen **screenconf; + int crtcs_num = 0, outputs_num = 0, i; + Ecore_X_Randr_Crtc_Info *info; + int top_priority = 0; + + ecore_x_grab(); + // set virtual resolution + nw = e_randr2->w; + nh = e_randr2->h; + ecore_x_randr_screen_size_range_get(root, &minw, &minh, &maxw, &maxh); + ecore_x_randr_screen_current_size_get(root, &pw, &ph, NULL, NULL); + { + int ww = 0, hh = 0, ww2 = 0, hh2 = 0; + ecore_x_randr_screen_current_size_get(root, &ww, &hh, &ww2, &hh2); + printf("RRR: cur size: %ix%i\n", ww, hh); + } + printf("RRR: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh); + if (nw > maxw) nw = maxw; + if (nh > maxh) nh = maxh; + if (nw < minw) nw = minw; + if (nh < minh) nh = minh; + ww = nw; if (nw < pw) ww = pw; + hh = nh; if (nh < ph) hh = ph; + ecore_x_randr_screen_current_size_set(root, ww, hh, -1, -1); + { + int ww = 0, hh = 0, ww2 = 0, hh2 = 0; + ecore_x_randr_screen_current_size_get(root, &ww, &hh, &ww2, &hh2); + printf("RRR: cur size: %ix%i\n", ww, hh); + } + printf("RRR: set vsize: %ix%i\n", nw, nh); + + crtcs = ecore_x_randr_crtcs_get(root, &crtcs_num); + outputs = ecore_x_randr_outputs_get(root, &outputs_num); + + if ((crtcs) && (outputs)) + { + outconf = alloca(crtcs_num * sizeof(Ecore_X_Randr_Output)); + screenconf = alloca(crtcs_num * sizeof(E_Randr2_Screen *)); + memset(outconf, 0, crtcs_num * sizeof(Ecore_X_Randr_Output)); + memset(screenconf, 0, crtcs_num * sizeof(E_Randr2_Screen *)); + + // decide which outputs get which crtcs + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + printf("RRR: find output for '%s'\n", s->info.name); + // XXX: find clones and set them as outputs in an array + if ((s->config.configured) && + (_output_name_find(root, s->info.name, outputs, + outputs_num, &out))) + { + printf("RRR: enabled: %i\n", s->config.enabled); + if (s->config.enabled) + { + if (s->config.priority > top_priority) + top_priority = s->config.priority; + for (i = 0; i < crtcs_num; i++) + { + if (!outconf[i]) + { + printf("RRR: crtc slot empty: %i\n", i); + info = ecore_x_randr_crtc_info_get(root, + crtcs[i]); + if (info) + { + if (_output_exists(out, info) && + _rotation_exists(s->config.rotation, + info)) + { + printf("RRR: assign slot out: %x\n", out); + outconf[i] = out; + screenconf[i] = s; + ecore_x_randr_crtc_info_free(info); + break; + } + } + } + } + } + } + } + // set up a crtc to drive each output (or not) + for (i = 0; i < crtcs_num; i++) + { + // XXX: find clones and set them as outputs in an array + if (outconf[i]) + { + Ecore_X_Randr_Orientation orient = + ECORE_X_RANDR_ORIENTATION_ROT_0; + Ecore_X_Randr_Mode mode; + + mode = _mode_screen_find(root, screenconf[i], outconf[i]); + if (screenconf[i]->config.rotation == 0) + orient = ECORE_X_RANDR_ORIENTATION_ROT_0; + else if (screenconf[i]->config.rotation == 90) + orient = ECORE_X_RANDR_ORIENTATION_ROT_90; + else if (screenconf[i]->config.rotation == 180) + orient = ECORE_X_RANDR_ORIENTATION_ROT_180; + else if (screenconf[i]->config.rotation == 270) + orient = ECORE_X_RANDR_ORIENTATION_ROT_270; + printf("RRR: crtc on: %i = '%s' @ %i %i - %ix%i orient %i mode %x out %x\n", + i, screenconf[i]->info.name, + screenconf[i]->config.geom.x, + screenconf[i]->config.geom.y, + screenconf[i]->config.geom.w, + screenconf[i]->config.geom.h, + orient, mode, outconf[i]); + if (!ecore_x_randr_crtc_settings_set + (root, crtcs[i], &(outconf[i]), 1, + screenconf[i]->config.geom.x, + screenconf[i]->config.geom.y, + mode, orient)) + printf("RRR: failed to set crtc!!!!!!\n"); + ecore_x_randr_crtc_panning_area_set + (root, crtcs[i], + screenconf[i]->config.geom.x, + screenconf[i]->config.geom.y, + screenconf[i]->config.geom.w, + screenconf[i]->config.geom.h); + if (screenconf[i]->config.priority == top_priority) + { + ecore_x_randr_primary_output_set(root, outconf[i]); + top_priority = -1; + } + } + else + { + printf("RRR: crtc off: %i\n", i); + ecore_x_randr_crtc_settings_set + (root, crtcs[i], NULL, 0, 0, 0, 0, + ECORE_X_RANDR_ORIENTATION_ROT_0); + } + } + } + free(outputs); + free(crtcs); + + ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1); + { + int ww = 0, hh = 0, ww2 = 0, hh2 = 0; + ecore_x_randr_screen_current_size_get(root, &ww, &hh, &ww2, &hh2); + printf("RRR: cur size: %ix%i\n", ww, hh); + } + ecore_x_randr_screen_size_range_get(root, NULL, NULL, NULL, NULL); + ecore_x_ungrab(); + ecore_x_sync(); + + // ignore the next batch of randr events - we caused them ourselves + event_ignore = EINA_TRUE; +} diff --git a/src/bin/e_randr2.h b/src/bin/e_randr2.h new file mode 100644 index 000000000..70fd40f0c --- /dev/null +++ b/src/bin/e_randr2.h @@ -0,0 +1,121 @@ +#ifdef E_TYPEDEFS + +typedef struct _E_Randr2 E_Randr2; +typedef struct _E_Randr2_Screen E_Randr2_Screen; +typedef struct _E_Randr2_Mode E_Randr2_Mode; + +typedef struct _E_Config_Randr2 E_Config_Randr2; +typedef struct _E_Config_Randr2_Screen E_Config_Randr2_Screen; + +#else +#ifndef E_RANDR2_H +#define E_RAND2R_H + +#define E_RANDR_VERSION_1_1 ((1 << 16) | 1) +#define E_RANDR_VERSION_1_2 ((1 << 16) | 2) +#define E_RANDR_VERSION_1_3 ((1 << 16) | 3) +#define E_RANDR_VERSION_1_4 ((1 << 16) | 4) + +typedef enum _E_Randr2_Relative +{ + E_RANDR2_RELATIVE_UNKNOWN, + E_RANDR2_RELATIVE_NONE, + E_RANDR2_RELATIVE_CLONE, + E_RANDR2_RELATIVE_TO_LEFT, + E_RANDR2_RELATIVE_TO_RIGHT, + E_RANDR2_RELATIVE_TO_ABOVE, + E_RANDR2_RELATIVE_TO_BELOW +} E_Randr2_Relative; + +typedef enum _E_Randr2_Connector +{ + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_DVI, + E_RANDR2_CONNECTOR_HDMI_A, + E_RANDR2_CONNECTOR_HDMI_B, + E_RANDR2_CONNECTOR_MDDI, + E_RANDR2_CONNECTOR_DISPLAY_PORT +} E_Randr2_Connector; + +struct _E_Randr2 +{ + Eina_List *screens; // available screens + int w, h; // virtual resolution needed for screens (calculated) +}; + +struct _E_Randr2_Mode +{ + int w, h; // resolution width and height + double refresh; // refresh in hz + Eina_Bool preferred : 1; // is this the preferred mode for the device? +}; + +struct _E_Randr2_Screen +{ + char *id; // string id which is "name/edid"; + struct { + char *screen; // name of the screen device attached + char *name; // name of the output itself + char *edid; // full edid data + E_Randr2_Connector connector; // the connector type + Eina_Bool is_lid : 1; // is an internal screen + Eina_Bool connected : 1; // some screen is plugged in or not + Eina_Bool backlight : 1; // does it have backlight controls? + Eina_Bool can_rot_0 : 1; // can it do this rotation? + Eina_Bool can_rot_90 : 1; // can it do this rotation? + Eina_Bool can_rot_180 : 1; // can it do this rotation? + Eina_Bool can_rot_270 : 1; // can it do this rotation? + Eina_List *modes; // available screen modes here + struct { + int w, h; // physical width and height in mm + } size; + } info; + struct { + struct { + E_Randr2_Relative mode; // what relative mode to the screen below + char *to; // what screen this one is relative to + double align; // alignment along the edge + } relative; + Eina_Rectangle geom; // the geometry that is set (as a result) + E_Randr2_Mode mode; // screen res/refresh to use + int rotation; // 0, 90, 180, 270 + int priority; // larger num == more important + Eina_Bool enabled : 1; // should this monitor be enabled? + Eina_Bool configured : 1; // has screen been configured by e? + } config; +}; + +struct _E_Config_Randr2 +{ + int version; + Eina_List *screens; + unsigned char restore; +}; + +struct _E_Config_Randr2_Screen +{ + const char *id; + const char *rel_to; + double rel_align; + double mode_refresh; + int mode_w; + int mode_h; + int rotation; + int priority; + unsigned char rel_mode; + unsigned char enabled; +}; + +extern EAPI E_Config_Randr2 *e_randr2_cfg; +extern EAPI E_Randr2 *e_randr2; + +extern EAPI int E_EVENT_RANDR_CHANGE; + +EINTERN Eina_Bool e_randr2_init(void); +EINTERN int e_randr2_shutdown(void); +EAPI Eina_Bool e_randr2_config_save(void); +EAPI void e_randr2_config_apply(void); +EAPI void e_randr2_screeninfo_update(void); + +#endif +#endif diff --git a/src/bin/e_xinerama.c b/src/bin/e_xinerama.c index d26a2ddde..e75704f84 100644 --- a/src/bin/e_xinerama.c +++ b/src/bin/e_xinerama.c @@ -132,6 +132,7 @@ _e_xinerama_update(void) INF("======================= screens:"); EINA_LIST_FOREACH(chosen_screens, l, scr) { + scr->screen = n; scr->escreen = n; INF("E INIT: XINERAMA CHOSEN: [%i][%i], %ix%i+%i+%i", scr->screen, scr->escreen, scr->w, scr->h, scr->x, scr->y); diff --git a/src/modules/Makefile_conf_randr.mk b/src/modules/Makefile_conf_randr.mk index 0a727c287..280a4021b 100644 --- a/src/modules/Makefile_conf_randr.mk +++ b/src/modules/Makefile_conf_randr.mk @@ -14,12 +14,8 @@ src_modules_conf_randr_module_la_CPPFLAGS = $(MOD_CPPFLAGS) -DNEED_X=1 src_modules_conf_randr_module_la_LDFLAGS = $(MOD_LDFLAGS) src_modules_conf_randr_module_la_SOURCES = src/modules/conf_randr/e_mod_main.c \ src/modules/conf_randr/e_mod_main.h \ - src/modules/conf_randr/e_int_config_randr.c \ - src/modules/conf_randr/e_int_config_randr.h \ - src/modules/conf_randr/e_smart_randr.c \ - src/modules/conf_randr/e_smart_randr.h \ - src/modules/conf_randr/e_smart_monitor.c \ - src/modules/conf_randr/e_smart_monitor.h + src/modules/conf_randr/e_int_config_randr2.c \ + src/modules/conf_randr/e_int_config_randr2.h PHONIES += conf_randr install-conf_randr conf_randr: $(conf_randrpkg_LTLIBRARIES) $(conf_randr_DATA) diff --git a/src/modules/conf_randr/e_int_config_randr2.c b/src/modules/conf_randr/e_int_config_randr2.c new file mode 100644 index 000000000..c51e93d91 --- /dev/null +++ b/src/modules/conf_randr/e_int_config_randr2.c @@ -0,0 +1,744 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_int_config_randr2.h" + +/* local structures */ +struct _E_Config_Dialog_Data +{ + E_Config_Dialog *cfd; + Eina_List *screen_items; + Eina_List *screen_items2; + Eina_List *screens; + Eina_List *freelist; + Evas_Object *name_obj; + Evas_Object *screen_obj; + Evas_Object *lid_obj; + Evas_Object *backlight_obj; + Evas_Object *size_obj; + Evas_Object *modes_obj; + Evas_Object *rotations_obj; + Evas_Object *enabled_obj; + Evas_Object *priority_obj; + Evas_Object *rel_mode_obj; + Evas_Object *rel_to_obj; + Evas_Object *rel_align_obj; + int restore; + int screen; +}; + +typedef struct +{ + E_Config_Dialog_Data *cfdata; + E_Randr2_Mode mode; +} Mode_CBData; + +typedef struct +{ + E_Config_Dialog_Data *cfdata; + int rot; +} Rot_CBData; + +/* local function prototypes */ +static void *_create_data(E_Config_Dialog *cfd); +static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static int _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static int _basic_check(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); + +/* public functions */ +E_Config_Dialog * +e_int_config_randr2(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v; + + if (e_config_dialog_find("E", "screen/screen_setup")) return NULL; + if (!(v = E_NEW(E_Config_Dialog_View, 1))) return NULL; + + /* set dialog view functions & properties */ + v->create_cfdata = _create_data; + v->free_cfdata = _free_data; + v->basic.create_widgets = _basic_create; + v->basic.apply_cfdata = _basic_apply; + v->basic.check_changed = _basic_check; + v->override_auto_apply = EINA_TRUE; + + /* create new dialog */ + cfd = e_config_dialog_new(NULL, _("Screen Setup"), + "E", "screen/screen_setup", + "preferences-system-screen-resolution", + 0, v, NULL); + return cfd; +} + +/* local functions */ +static void * +_create_data(E_Config_Dialog *cfd EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata; + + if (!(cfdata = E_NEW(E_Config_Dialog_Data, 1))) return NULL; + cfdata->restore = e_randr2_cfg->restore; + return cfdata; +} + +static void +_free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata) +{ + void *dt; + E_Config_Randr2_Screen *cs; + + EINA_LIST_FREE(cfdata->screens, cs) + { + eina_stringshare_del(cs->id); + eina_stringshare_del(cs->rel_to); + free(cs); + } + eina_list_free(cfdata->screen_items); + eina_list_free(cfdata->screen_items2); + EINA_LIST_FREE(cfdata->freelist, dt) free(dt); + E_FREE(cfdata); +} + +static void +_cb_restore_changed(void *data EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + cfdata->restore = elm_check_state_get(obj); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static E_Config_Randr2_Screen * +_config_screen_find(E_Config_Dialog_Data *cfdata) +{ + return eina_list_nth(cfdata->screens, cfdata->screen); +} + +static E_Config_Randr2_Screen * +_config_screen_n_find(E_Config_Dialog_Data *cfdata, int n) +{ + return eina_list_nth(cfdata->screens, n); +} + +static E_Randr2_Screen * +_screen_config_find(E_Config_Randr2_Screen *cs) +{ + Eina_List *l; + E_Randr2_Screen *s; + + if (!cs->id) return NULL; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (!s->id) continue; + if (!strcmp(cs->id, s->id)) return s; + } + return NULL; +} + +static E_Randr2_Screen * +_screen_config_id_find(const char *id) +{ + Eina_List *l; + E_Randr2_Screen *s; + + if (!id) return NULL; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + if (!s->id) continue; + if (!strcmp(s->id, id)) return s; + } + return NULL; +} + +static E_Config_Randr2_Screen * +_screen_config_randr_id_find(const char *id) +{ + Eina_List *l; + E_Config_Randr2_Screen *cs; + + if (!id) return NULL; + EINA_LIST_FOREACH(e_randr2_cfg->screens, l, cs) + { + if (!cs->id) continue; + if (!strcmp(cs->id, id)) return cs; + } + return NULL; +} + +static void +_cb_mode_set(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + Mode_CBData *dat = data; + E_Config_Dialog_Data *cfdata = dat->cfdata; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->mode_w = dat->mode.w; + cs->mode_h = dat->mode.h; + cs->mode_refresh = dat->mode.refresh; + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rot_set(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + Rot_CBData *dat = data; + E_Config_Dialog_Data *cfdata = dat->cfdata; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rotation = dat->rot; + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_basic_screen_info_fill(E_Config_Dialog_Data *cfdata, E_Config_Randr2_Screen *cs, E_Randr2_Screen *s) +{ + char buf[100]; + Eina_List *l; + E_Randr2_Mode *m; + Elm_Object_Item *it, *it_sel; + void *dt; + + if (!s) return; + // fill all the screen status info + elm_object_text_set(cfdata->name_obj, s->info.name); + elm_object_text_set(cfdata->screen_obj, s->info.screen); + elm_check_state_set(cfdata->lid_obj, s->info.is_lid); + elm_check_state_set(cfdata->backlight_obj, s->info.backlight); + snprintf(buf, sizeof(buf), "%imm x %imm", s->info.size.w, s->info.size.h); + elm_object_text_set(cfdata->size_obj, buf); + // XXX: connector + + EINA_LIST_FREE(cfdata->freelist, dt) free(dt); + + elm_list_clear(cfdata->modes_obj); + it_sel = NULL; + EINA_LIST_FOREACH(s->info.modes, l, m) + { + Mode_CBData *mode_cbdata = calloc(1, sizeof(Mode_CBData)); + + if (mode_cbdata) + { + mode_cbdata->cfdata = cfdata; + mode_cbdata->mode = *m; + snprintf(buf, sizeof(buf), "%ix%i @ %1.2fHz", m->w, m->h, m->refresh); + it = elm_list_item_append(cfdata->modes_obj, buf, NULL, NULL, _cb_mode_set, mode_cbdata); + cfdata->freelist = eina_list_append(cfdata->freelist, mode_cbdata); + printf("mode add %p %p %p\n", mode_cbdata, cfdata->modes_obj, it); + if ((cs->mode_w == m->w) && (cs->mode_h == m->h) && + (cs->mode_refresh == m->refresh)) + it_sel = it; + } + } + if (it_sel) elm_list_item_selected_set(it_sel, EINA_TRUE); + elm_list_go(cfdata->modes_obj); + + elm_list_clear(cfdata->rotations_obj); + it_sel = NULL; + if (s->info.can_rot_0) + { + Rot_CBData *rot_cbdata = calloc(1, sizeof(Rot_CBData)); + if (rot_cbdata) + { + rot_cbdata->cfdata = cfdata; + rot_cbdata->rot = 0; + it = elm_list_item_append(cfdata->rotations_obj, "0", NULL, NULL, _cb_rot_set, rot_cbdata); + cfdata->freelist = eina_list_append(cfdata->freelist, rot_cbdata); + if (cs->rotation == 0) it_sel = it; + } + } + if (s->info.can_rot_90) + { + Rot_CBData *rot_cbdata = calloc(1, sizeof(Rot_CBData)); + if (rot_cbdata) + { + rot_cbdata->cfdata = cfdata; + rot_cbdata->rot = 90; + it = elm_list_item_append(cfdata->rotations_obj, "90", NULL, NULL, _cb_rot_set, rot_cbdata); + cfdata->freelist = eina_list_append(cfdata->freelist, rot_cbdata); + if (cs->rotation == 90) it_sel = it; + } + } + if (s->info.can_rot_180) + { + Rot_CBData *rot_cbdata = calloc(1, sizeof(Rot_CBData)); + if (rot_cbdata) + { + rot_cbdata->cfdata = cfdata; + rot_cbdata->rot = 180; + it = elm_list_item_append(cfdata->rotations_obj, "180", NULL, NULL, _cb_rot_set, rot_cbdata); + cfdata->freelist = eina_list_append(cfdata->freelist, rot_cbdata); + if (cs->rotation == 180) it_sel = it; + } + } + if (s->info.can_rot_270) + { + Rot_CBData *rot_cbdata = calloc(1, sizeof(Rot_CBData)); + if (rot_cbdata) + { + rot_cbdata->cfdata = cfdata; + rot_cbdata->rot = 270; + it = elm_list_item_append(cfdata->rotations_obj, "270", NULL, NULL, _cb_rot_set, rot_cbdata); + cfdata->freelist = eina_list_append(cfdata->freelist, rot_cbdata); + if (cs->rotation == 270) it_sel = it; + } + } + if (it_sel) elm_list_item_selected_set(it_sel, EINA_TRUE); + elm_list_go(cfdata->rotations_obj); + + elm_check_state_set(cfdata->enabled_obj, cs->enabled); + + elm_slider_value_set(cfdata->priority_obj, cs->priority); + + if (cs->rel_mode == E_RANDR2_RELATIVE_NONE) + elm_object_text_set(cfdata->rel_mode_obj, "None"); + else if (cs->rel_mode == E_RANDR2_RELATIVE_CLONE) + elm_object_text_set(cfdata->rel_mode_obj, "Clone"); + else if (cs->rel_mode == E_RANDR2_RELATIVE_TO_LEFT) + elm_object_text_set(cfdata->rel_mode_obj, "Left of"); + else if (cs->rel_mode == E_RANDR2_RELATIVE_TO_RIGHT) + elm_object_text_set(cfdata->rel_mode_obj, "Right of"); + else if (cs->rel_mode == E_RANDR2_RELATIVE_TO_ABOVE) + elm_object_text_set(cfdata->rel_mode_obj, "Above"); + else if (cs->rel_mode == E_RANDR2_RELATIVE_TO_BELOW) + elm_object_text_set(cfdata->rel_mode_obj, "Below"); + else + elm_object_text_set(cfdata->rel_mode_obj, "???"); + + elm_slider_value_set(cfdata->rel_align_obj, cs->rel_align); + + if (!cs->rel_to) + elm_object_text_set(cfdata->rel_to_obj, ""); + else + { + char *str = strdup(cs->rel_to); + if (str) + { + char *p = strchr(str, '/'); + if (p) + { + *p = 0; + elm_object_text_set(cfdata->rel_to_obj, str); + } + free(str); + } + } +} + +static void +_cb_screen_select(void *data, Evas_Object *obj, void *event) +{ + E_Config_Dialog_Data *cfdata = data; + Elm_Object_Item *it; + Eina_List *l; + int i = 0; + + EINA_LIST_FOREACH(cfdata->screen_items, l, it) + { + if (it == event) + { + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + cfdata->screen = i; + if (cs) + { + E_Randr2_Screen *s = _screen_config_find(cs); + if (s) + { + elm_object_text_set(obj, s->info.name); + _basic_screen_info_fill(cfdata, cs, s); + } + } + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); + return; + } + i++; + } +} + +static void +_cb_rel_to_set(void *data, Evas_Object *obj, void *event) +{ + E_Config_Dialog_Data *cfdata = data; + Elm_Object_Item *it; + Eina_List *l; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + int i = 0; + + EINA_LIST_FOREACH(cfdata->screen_items2, l, it) + { + if (it == event) + { + E_Config_Randr2_Screen *cs2 = _config_screen_n_find(cfdata, i); + printf("find cs = %p\n", cs2); + printf("cs id = %s\n", cs2->id); + if (cs2 == cs) return; + if (cs2) + { + E_Randr2_Screen *s = _screen_config_id_find(cs2->id); + if (s) + { + printf("find s = %p\n", s); + printf("s id = %s\n", s->id); + elm_object_text_set(obj, s->info.name); + eina_stringshare_del(cs->rel_to); + cs->rel_to = eina_stringshare_add(s->id); + } + } + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); + return; + } + i++; + } +} + +static void +_cb_rel_align_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_align = elm_slider_value_get(obj); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rel_mode_none(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_mode = E_RANDR2_RELATIVE_NONE; + elm_object_text_set(obj, "None"); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rel_mode_clone(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_mode = E_RANDR2_RELATIVE_CLONE; + elm_object_text_set(obj, "Clone"); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rel_mode_left_of(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_mode = E_RANDR2_RELATIVE_TO_LEFT; + elm_object_text_set(obj, "Left of"); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rel_mode_right_of(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_mode = E_RANDR2_RELATIVE_TO_RIGHT; + elm_object_text_set(obj, "Right of"); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rel_mode_above(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_mode = E_RANDR2_RELATIVE_TO_ABOVE; + elm_object_text_set(obj, "Above"); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_rel_mode_below(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->rel_mode = E_RANDR2_RELATIVE_TO_BELOW; + elm_object_text_set(obj, "Below"); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_priority_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->priority = elm_slider_value_get(obj); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_enabled_changed(void *data, Evas_Object *obj, void *event EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + E_Config_Randr2_Screen *cs = _config_screen_find(cfdata); + if (!cs) return; + cs->enabled = elm_check_state_get(obj); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static Evas_Object * +_basic_create(E_Config_Dialog *cfd, Evas *evas EINA_UNUSED, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *win = cfd->dia->win; + Evas_Object *o, *bx, *tb; + Eina_List *l; + E_Randr2_Screen *s, *first = NULL; + E_Config_Randr2_Screen *first_cfg = NULL; + int i; + + e_dialog_resizable_set(cfd->dia, 1); + + o = elm_box_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(o); + bx = o; + + o = elm_table_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, o); + evas_object_show(o); + tb = o; + + o = elm_hoversel_add(win); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Outputs"); + cfdata->screens = NULL; + cfdata->screen_items = NULL; + i = 0; + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + Elm_Object_Item *it = NULL; + + if (s->info.connected) + { + E_Config_Randr2_Screen *cs; + + cs = calloc(1, sizeof(E_Config_Randr2_Screen)); + if (cs) + { + if (s->id) + cs->id = eina_stringshare_add(s->id); + if (s->config.relative.to) + cs->rel_to = eina_stringshare_add(s->config.relative.to); + cs->rel_align = s->config.relative.align; + cs->mode_refresh = s->config.mode.refresh; + cs->mode_w = s->config.mode.w; + cs->mode_h = s->config.mode.h; + cs->rotation = s->config.rotation; + cs->priority = s->config.priority; + cs->rel_mode = s->config.relative.mode; + cs->enabled = s->config.enabled; + cfdata->screens = eina_list_append(cfdata->screens, cs); + it = elm_hoversel_item_add(o, s->info.name, + NULL, ELM_ICON_NONE, + _cb_screen_select, cfdata); + if (!first) + { + first = s; + first_cfg = cs; + cfdata->screen = i; + elm_object_text_set(o, s->info.name); + } + cfdata->screen_items = eina_list_append(cfdata->screen_items, it); + i++; + } + } + } + elm_table_pack(tb, o, 0, 0, 1, 1); + evas_object_show(o); + + o = elm_entry_add(win); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_single_line_set(o, EINA_TRUE); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_table_pack(tb, o, 0, 1, 1, 1); + evas_object_show(o); + cfdata->name_obj = o; + + o = elm_entry_add(win); + elm_entry_scrollable_set(o, EINA_TRUE); + elm_entry_single_line_set(o, EINA_TRUE); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_table_pack(tb, o, 0, 2, 1, 1); + evas_object_show(o); + cfdata->screen_obj = o; + + o = elm_check_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Laptop lid"); + elm_table_pack(tb, o, 0, 3, 1, 1); + evas_object_show(o); + cfdata->lid_obj = o; + + o = elm_check_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Backlight"); + elm_table_pack(tb, o, 0, 4, 1, 1); + evas_object_show(o); + cfdata->backlight_obj = o; + + o = elm_label_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_table_pack(tb, o, 0, 5, 1, 1); + evas_object_show(o); + cfdata->size_obj = o; + + o = elm_list_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(tb, o, 1, 0, 1, 10); + evas_object_show(o); + cfdata->modes_obj = o; + + o = elm_list_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(tb, o, 2, 0, 1, 4); + evas_object_show(o); + cfdata->rotations_obj = o; + + o = elm_check_add(win); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "On"); + elm_table_pack(tb, o, 2, 4, 1, 1); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", _cb_enabled_changed, cfdata); + cfdata->enabled_obj = o; + + o = elm_slider_add(win); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Priority"); + elm_slider_unit_format_set(o, "%3.0f"); + elm_slider_span_size_set(o, 100); + elm_slider_min_max_set(o, 0, 100); + elm_table_pack(tb, o, 2, 5, 1, 1); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", _cb_priority_changed, cfdata); + cfdata->priority_obj = o; + + o = elm_hoversel_add(win); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Relative"); + elm_hoversel_item_add(o, "None", NULL, ELM_ICON_NONE, _cb_rel_mode_none, cfdata); + elm_hoversel_item_add(o, "Clone", NULL, ELM_ICON_NONE, _cb_rel_mode_clone, cfdata); + elm_hoversel_item_add(o, "Left of", NULL, ELM_ICON_NONE, _cb_rel_mode_left_of, cfdata); + elm_hoversel_item_add(o, "Right of", NULL, ELM_ICON_NONE, _cb_rel_mode_right_of, cfdata); + elm_hoversel_item_add(o, "Above", NULL, ELM_ICON_NONE, _cb_rel_mode_above, cfdata); + elm_hoversel_item_add(o, "Below", NULL, ELM_ICON_NONE, _cb_rel_mode_below, cfdata); + elm_table_pack(tb, o, 2, 6, 1, 1); + evas_object_show(o); + cfdata->rel_mode_obj = o; + + o = elm_hoversel_add(win); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "To"); + EINA_LIST_FOREACH(e_randr2->screens, l, s) + { + Elm_Object_Item *it = NULL; + + if (s->info.connected) + { + it = elm_hoversel_item_add(o, s->info.name, + NULL, ELM_ICON_NONE, + _cb_rel_to_set, cfdata); + cfdata->screen_items2 = eina_list_append(cfdata->screen_items2, it); + } + } + elm_table_pack(tb, o, 2, 7, 1, 1); + evas_object_show(o); + cfdata->rel_to_obj = o; + + o = elm_slider_add(win); + evas_object_size_hint_weight_set(o, 0.0, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5); + elm_object_text_set(o, "Align"); + elm_slider_unit_format_set(o, "%1.1f"); + elm_slider_span_size_set(o, 100); + elm_slider_min_max_set(o, 0.0, 1.0); + elm_table_pack(tb, o, 2, 8, 1, 1); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", _cb_rel_align_changed, cfdata); + cfdata->rel_align_obj = o; + + _basic_screen_info_fill(cfdata, first_cfg, first); + + o = elm_check_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(o, "Restore setup on start"); + elm_check_state_set(o, e_randr2_cfg->restore); + elm_box_pack_end(bx, o); + evas_object_show(o); + evas_object_smart_callback_add(o, "changed", _cb_restore_changed, cfdata); + + evas_smart_objects_calculate(evas_object_evas_get(win)); + + e_util_win_auto_resize_fill(win); + elm_win_center(win, 1, 1); + cfdata->cfd = cfd; + return bx; +} + +static int +_basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata) +{ + Eina_List *l; + E_Config_Randr2_Screen *cs, *cs2; + + e_randr2_cfg->restore = cfdata->restore; + EINA_LIST_FOREACH(cfdata->screens, l, cs2) + { + if (!cs2->id) continue; + cs = _screen_config_randr_id_find(cs2->id); + if (!cs) + { + cs = calloc(1, sizeof(E_Config_Randr2_Screen)); + cs->id = eina_stringshare_add(cs2->id); + e_randr2_cfg->screens = eina_list_append(e_randr2_cfg->screens, cs); + } + if (cs->rel_to) eina_stringshare_del(cs->rel_to); + cs->rel_to = NULL; + if (cs2->rel_to) cs->rel_to = eina_stringshare_add(cs2->rel_to); + cs->rel_align = cs2->rel_align; + cs->mode_refresh = cs2->mode_refresh; + cs->mode_w = cs2->mode_w; + cs->mode_h = cs2->mode_h; + cs->mode_refresh = cs2->mode_refresh; + cs->rotation = cs2->rotation; + cs->priority = cs2->priority; + cs->rel_mode = cs2->rel_mode; + cs->enabled = cs2->enabled; + } + e_randr2_config_save(); + e_randr2_config_apply(); + return 1; +} + +static int +_basic_check(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata EINA_UNUSED) +{ + return 1; +} diff --git a/src/modules/conf_randr/e_int_config_randr2.h b/src/modules/conf_randr/e_int_config_randr2.h new file mode 100644 index 000000000..60f2aa2b1 --- /dev/null +++ b/src/modules/conf_randr/e_int_config_randr2.h @@ -0,0 +1,9 @@ +#ifdef E_TYPEDEFS +#else +# ifndef E_INT_CONFIG_RANDR2_H +# define E_INT_CONFIG_RANDR2_H + +E_Config_Dialog *e_int_config_randr2(Evas_Object *parent, const char *params); + +# endif +#endif diff --git a/src/modules/conf_randr/e_mod_main.c b/src/modules/conf_randr/e_mod_main.c index 9f0c32c09..d8cb733ac 100644 --- a/src/modules/conf_randr/e_mod_main.c +++ b/src/modules/conf_randr/e_mod_main.c @@ -1,8 +1,8 @@ #include "e.h" #include "e_mod_main.h" -#include "e_int_config_randr.h" +#include "e_int_config_randr2.h" -EAPI E_Module_Api e_modapi = +EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Settings - Screen Setup" }; @@ -13,43 +13,31 @@ e_modapi_init(E_Module *m) /* create Screen configuration category * * NB: If the category already exists, this function just returns */ - e_configure_registry_category_add("screen", 30, _("Screen"), + e_configure_registry_category_add("screen", 30, _("Screen"), NULL, "preferences-desktop-display"); /* add the randr dialog to the screen category and provide * the configure category with the function to call */ - e_configure_registry_item_add("screen/screen_setup", 20, _("Screen Setup"), - NULL, - "preferences-system-screen-resolution", - e_int_config_randr); - - - /* return the module */ + e_configure_registry_item_add("screen/screen_setup", 20, _("Screen Setup"), + NULL, "preferences-system-screen-resolution", + e_int_config_randr2); return m; } -EAPI int +EAPI int e_modapi_shutdown(E_Module *m __UNUSED__) { E_Config_Dialog *cfd; - /* destroy existing dialogs */ while ((cfd = e_config_dialog_get("E", "screen/screen_setup"))) e_object_del(E_OBJECT(cfd)); - /* remove randr dialog from the configuration category */ e_configure_registry_item_del("screen/screen_setup"); - - /* remove the screen configuration category - * - * NB: If there are other items in 'screen' then this function is a no-op */ e_configure_registry_category_del("screen"); - - /* return 1 for shutdown success */ return 1; } -EAPI int +EAPI int e_modapi_save(E_Module *m __UNUSED__) { return 1; diff --git a/src/modules/conf_randr/e_mod_main.h b/src/modules/conf_randr/e_mod_main.h index 45c7afaa0..9ff8663ee 100644 --- a/src/modules/conf_randr/e_mod_main.h +++ b/src/modules/conf_randr/e_mod_main.h @@ -1,6 +1,7 @@ #ifndef E_MOD_MAIN_H # define E_MOD_MAIN_H +#if 0 //# define LOGFNS 1 # ifdef LOGFNS @@ -29,3 +30,4 @@ EAPI int e_modapi_save(E_Module *m); */ #endif +#endif