diff --git a/src/bin/e_comp_x_randr.c b/src/bin/e_comp_x_randr.c index 3e793c717..d0745b866 100644 --- a/src/bin/e_comp_x_randr.c +++ b/src/bin/e_comp_x_randr.c @@ -752,6 +752,7 @@ e_comp_x_randr_create(void) } } free(modes); + e_randr2_screen_modes_sort(s); } cs = NULL; priority = 0; diff --git a/src/bin/e_randr2.c b/src/bin/e_randr2.c index 1dae6a0f3..f1ee1ceca 100644 --- a/src/bin/e_randr2.c +++ b/src/bin/e_randr2.c @@ -1,6 +1,6 @@ #include "e.h" -#define E_RANDR_CONFIG_VERSION 1 +#define E_RANDR_CONFIG_VERSION 2 ///////////////////////////////////////////////////////////////////////// static Eina_Bool _screen_closed(E_Randr2_Screen *s); @@ -13,7 +13,7 @@ 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 Eina_Bool _config_update(E_Randr2 *r, E_Config_Randr2 *cfg, Eina_Bool ); static void _config_apply(E_Randr2 *r, E_Config_Randr2 *cfg); static int _config_screen_match_count(E_Randr2 *r, E_Config_Randr2 *cfg); static char *_screens_fingerprint(E_Randr2 *r); @@ -44,6 +44,8 @@ E_API int E_EVENT_RANDR_CHANGE = 0; EINTERN Eina_Bool e_randr2_init(void) { + int count; + if (!E_EVENT_RANDR_CHANGE) E_EVENT_RANDR_CHANGE = ecore_event_type_new(); if ((!e_comp->screen) || (!e_comp->screen->available) || (!e_comp->screen->available())) return EINA_FALSE; // create data descriptors for config storage @@ -76,6 +78,7 @@ e_randr2_init(void) E_CONFIG_VAL(D, T, restore, UCHAR); E_CONFIG_VAL(D, T, ignore_hotplug_events, UCHAR); E_CONFIG_VAL(D, T, ignore_acpi_events, UCHAR); + E_CONFIG_VAL(D, T, default_policy, UINT); // set up events from the driver if (e_comp->screen->init) @@ -88,14 +91,20 @@ e_randr2_init(void) 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)) + + count = _config_screen_match_count(e_randr2, e_randr2_cfg); + if (e_randr2_cfg->restore && count) { + if (count != (int)eina_list_count(e_randr2->screens)) + { + if (_config_update(e_randr2, e_randr2_cfg, 1)) + e_randr2_config_save(); + } _do_apply(); } else { - _config_update(e_randr2, e_randr2_cfg); + _config_update(e_randr2, e_randr2_cfg, 0); e_randr2_config_save(); } ecore_event_add(E_EVENT_RANDR_CHANGE, NULL, NULL, NULL); @@ -314,6 +323,13 @@ _info_free(E_Randr2 *r) free(r); } +static void +_config_upgrade(E_Config_Randr2 *cfg) +{ + if (cfg->version < 2) + cfg->default_policy = E_RANDR2_POLICY_EXTEND; +} + static E_Config_Randr2 * _config_load(void) { @@ -324,15 +340,9 @@ _config_load(void) if (cfg) { if (cfg->version < E_RANDR_CONFIG_VERSION) - { - _config_free(cfg); - cfg = NULL; - } - else - { - printf("RRR: loaded existing config\n"); - return cfg; - } + _config_upgrade(cfg); + printf("RRR: loaded existing config\n"); + return cfg; } // need new config @@ -342,6 +352,7 @@ _config_load(void) cfg->restore = 1; cfg->ignore_hotplug_events = 0; cfg->ignore_acpi_events = 0; + cfg->default_policy = E_RANDR2_POLICY_EXTEND; printf("RRR: fresh config\n"); return cfg; } @@ -371,12 +382,20 @@ _config_save(E_Randr2 *r, E_Config_Randr2 *cfg) return e_config_domain_save("e_randr2", _e_randr2_cfg_edd, cfg); } -static void -_config_update(E_Randr2 *r, E_Config_Randr2 *cfg) +static Eina_Bool +_config_ask_dialog() +{ + e_configure_registry_call("screen/screen_setup", NULL, NULL); + return EINA_FALSE; +} + +static Eina_Bool +_config_update(E_Randr2 *r, E_Config_Randr2 *cfg, Eina_Bool update_only) { Eina_List *l; E_Randr2_Screen *s; E_Config_Randr2_Screen *cs; + Eina_Bool ret = EINA_FALSE; printf("--------------------------------------------------\n"); EINA_LIST_FOREACH(r->screens, l, s) @@ -384,6 +403,7 @@ _config_update(E_Randr2 *r, E_Config_Randr2 *cfg) printf("RRR: out id=%s: connected=%i\n", s->id, s->info.connected); if ((!s->id) || (!s->info.connected) || (_screen_closed(s))) continue; cs = e_randr2_config_screen_find(s, cfg); + if (cs && update_only) continue; if (!cs) { cs = calloc(1, sizeof(E_Config_Randr2_Screen)); @@ -395,16 +415,60 @@ _config_update(E_Randr2 *r, E_Config_Randr2 *cfg) } if (cs) { - 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; + if (update_only) + { + switch (cfg->default_policy) + { + case E_RANDR2_POLICY_EXTEND: + if (s->config.relative.mode < E_RANDR2_RELATIVE_TO_LEFT) + cs->rel_mode = E_RANDR2_RELATIVE_TO_RIGHT; + else + cs->rel_mode = s->config.relative.mode; + break; + case E_RANDR2_POLICY_CLONE: + cs->rel_mode = E_RANDR2_RELATIVE_CLONE; + break; + case E_RANDR2_POLICY_ASK: + ecore_timer_loop_add(2, _config_ask_dialog, NULL); + case E_RANDR2_POLICY_NONE: + cs->rel_mode = E_RANDR2_RELATIVE_NONE; + break; + } + } + else + cs->rel_mode = s->config.relative.mode; + if (update_only && + ((cfg->default_policy == E_RANDR2_POLICY_CLONE) || + (cfg->default_policy == E_RANDR2_POLICY_EXTEND))) + { + E_Randr2_Mode *m = eina_list_data_get(s->info.modes); + + cs->enabled = !!m; + cs->mode_refresh = m->refresh; + cs->mode_w = m->w; + cs->mode_h = m->h; + if (s->config.relative.to) + cs->rel_to = eina_stringshare_add(s->config.relative.to); + else + { + /* find right-most screen */ + E_Zone *zone = eina_list_last_data_get(e_comp->zones); + eina_stringshare_replace(&cs->rel_to, zone->randr2_id); + } + cs->rel_align = 0; + } + else + { + cs->enabled = s->config.enabled; + cs->mode_refresh = s->config.mode.refresh; + cs->mode_w = s->config.mode.w; + cs->mode_h = s->config.mode.h; + if (s->config.relative.to) + cs->rel_to = eina_stringshare_add(s->config.relative.to); + cs->rel_align = s->config.relative.align; + } cs->rotation = s->config.rotation; cs->priority = s->config.priority; - cs->rel_mode = s->config.relative.mode; - cs->enabled = s->config.enabled; if (cs->profile) { printf("RRR: store config profile '%s'\n", cs->profile); @@ -418,9 +482,11 @@ _config_update(E_Randr2 *r, E_Config_Randr2 *cfg) } printf("RRR: store scale mul %1.5f\n", cs->scale_multiplier); s->config.scale_multiplier = cs->scale_multiplier; + ret = EINA_TRUE; } } printf("--------------------------------------------------\n"); + return ret; } static void @@ -591,19 +657,28 @@ _screens_differ(E_Randr2 *r1, E_Randr2 *r2) static Eina_Bool _cb_screen_change_delay(void *data EINA_UNUSED) { + Eina_Bool change = EINA_FALSE; _screen_delay_timer = NULL; printf("RRR: ... %i %i\n", event_screen, event_ignore); // 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 = e_comp->screen->create(); if (rtemp) { if (_screens_differ(e_randr2, rtemp)) change = EINA_TRUE; + if (e_randr2_cfg->default_policy != E_RANDR2_POLICY_NONE) + { + if (_config_update(rtemp, e_randr2_cfg, 1)) + { + e_randr2_config_save(); + if (e_randr2_cfg->default_policy != E_RANDR2_POLICY_ASK) + change = EINA_TRUE; + } + } _info_free(rtemp); } printf("RRR: change = %i\n", change); @@ -1268,3 +1343,22 @@ e_randr2_screen_dpi_get(E_Randr2_Screen *s) dpi2 = (25.4 * (double)(s->config.mode.h)) / (double)(s->info.size.h); return (dpi1 + dpi2) / 2.0; } + +static int +_modelist_sort(const void *a, const void *b) +{ + const E_Randr2_Mode *ma = a, *mb = b; + + /* largest resolutions first */ + if ((ma->w * ma->h) > (mb->w * mb->h)) return -1; + /* highest refresh first */ + if (ma->refresh > mb->refresh) return -1; + return 1; +} + +EAPI void +e_randr2_screen_modes_sort(E_Randr2_Screen *s) +{ + EINA_SAFETY_ON_NULL_RETURN(s); + s->info.modes = eina_list_sort(s->info.modes, 0, _modelist_sort); +} diff --git a/src/bin/e_randr2.h b/src/bin/e_randr2.h index e964bb7eb..02614f2b3 100644 --- a/src/bin/e_randr2.h +++ b/src/bin/e_randr2.h @@ -11,6 +11,14 @@ typedef struct _E_Config_Randr2_Screen E_Config_Randr2_Screen; #ifndef E_RANDR2_H #define E_RAND2R_H +typedef enum +{ + E_RANDR2_POLICY_NONE, + E_RANDR2_POLICY_EXTEND, + E_RANDR2_POLICY_CLONE, + E_RANDR2_POLICY_ASK, +} E_Randr2_Policy; + typedef enum _E_Randr2_Relative { E_RANDR2_RELATIVE_UNKNOWN, @@ -92,6 +100,7 @@ struct _E_Config_Randr2 unsigned char restore; unsigned char ignore_hotplug_events; unsigned char ignore_acpi_events; + E_Randr2_Policy default_policy; }; struct _E_Config_Randr2_Screen @@ -128,6 +137,6 @@ E_API E_Config_Randr2_Screen *e_randr2_config_screen_find(E_Randr2_Screen *s, E_ E_API void e_randr2_screens_setup(int rw, int rh); E_API E_Randr2_Screen *e_randr2_screen_id_find(const char *id); E_API double e_randr2_screen_dpi_get(E_Randr2_Screen *s); - +E_API void e_randr2_screen_modes_sort(E_Randr2_Screen *s); #endif #endif diff --git a/src/modules/conf_randr/e_int_config_randr2.c b/src/modules/conf_randr/e_int_config_randr2.c index 42c98ccac..f724ecd4f 100644 --- a/src/modules/conf_randr/e_int_config_randr2.c +++ b/src/modules/conf_randr/e_int_config_randr2.c @@ -27,10 +27,12 @@ struct _E_Config_Dialog_Data Evas_Object *profile_list_obj; Evas_Object *scale_custom_obj; Evas_Object *scale_value_obj; + Evas_Object *policy_obj; int restore; int hotplug; int acpi; int screen; + E_Randr2_Policy policy; }; typedef struct @@ -101,6 +103,7 @@ _create_data(E_Config_Dialog *cfd EINA_UNUSED) cfdata->restore = e_randr2_cfg->restore; cfdata->hotplug = !e_randr2_cfg->ignore_hotplug_events; cfdata->acpi = !e_randr2_cfg->ignore_acpi_events; + cfdata->policy = e_randr2_cfg->default_policy; return cfdata; } @@ -742,6 +745,66 @@ _cb_enabled_changed(void *data, Evas_Object *obj, void *event EINA_UNUSED) e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); } +static void +_policy_text_update(E_Config_Dialog_Data *cfdata) +{ + char pbuf[128]; + const char *policy[] = + { + _("Ignore"), + _("Extend"), + _("Clone"), + _("Ask") + }; + + snprintf(pbuf, sizeof(pbuf), _("Hotplug Policy (%s)"), policy[cfdata->policy]); + elm_object_text_set(cfdata->policy_obj, pbuf); +} + +static void +_cb_policy_ignore(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + + if (cfdata->policy == E_RANDR2_POLICY_NONE) return; + cfdata->policy = E_RANDR2_POLICY_NONE; + _policy_text_update(cfdata); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_policy_ask(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + + if (cfdata->policy == E_RANDR2_POLICY_ASK) return; + cfdata->policy = E_RANDR2_POLICY_ASK; + _policy_text_update(cfdata); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_policy_extend(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + + if (cfdata->policy == E_RANDR2_POLICY_EXTEND) return; + cfdata->policy = E_RANDR2_POLICY_EXTEND; + _policy_text_update(cfdata); + e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE); +} + +static void +_cb_policy_clone(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + E_Config_Dialog_Data *cfdata = data; + + if (cfdata->policy == E_RANDR2_POLICY_CLONE) return; + cfdata->policy = E_RANDR2_POLICY_CLONE; + _policy_text_update(cfdata); + 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) { @@ -1045,6 +1108,17 @@ _basic_create(E_Config_Dialog *cfd, Evas *evas EINA_UNUSED, E_Config_Dialog_Data evas_object_show(o); evas_object_smart_callback_add(o, "changed", _cb_acpi_changed, cfdata); + cfdata->policy_obj = 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); + _policy_text_update(cfdata); + elm_hoversel_item_add(o, _("Clone"), NULL, ELM_ICON_NONE, _cb_policy_clone, cfdata); + elm_hoversel_item_add(o, _("Extend"), NULL, ELM_ICON_NONE, _cb_policy_extend, cfdata); + elm_hoversel_item_add(o, _("Ask"), NULL, ELM_ICON_NONE, _cb_policy_ask, cfdata); + elm_hoversel_item_add(o, _("Ignore"), NULL, ELM_ICON_NONE, _cb_policy_ignore, cfdata); + elm_box_pack_end(bx2, o); + evas_object_show(o); + evas_smart_objects_calculate(evas_object_evas_get(win)); e_util_win_auto_resize_fill(win); @@ -1062,6 +1136,7 @@ _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata) e_randr2_cfg->restore = cfdata->restore; e_randr2_cfg->ignore_hotplug_events = !cfdata->hotplug; e_randr2_cfg->ignore_acpi_events = !cfdata->acpi; + e_randr2_cfg->default_policy = cfdata->policy; printf("APPLY....................\n"); EINA_LIST_FOREACH(cfdata->screens, l, cs2)