From 70753a79037ee627f86036f2460ce6b9787440f4 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Wed, 26 Nov 2014 19:17:02 +0900 Subject: [PATCH] e - randr - stop saving config using XID - this is utterly WRONG so e was storing randr config using XIDs to match outputs etc. this is all kinds of wrong. XIDs are NOT STATIC. they change from xserver to xserver and from run to run. they MAY be the same. they may not. so this was just broken. use output name + edid as a big "string" (name.edid) as a way ofr identifying config for a specific combination of output plus monitor and to find/identify the corrent output+monitor to apply it to (of course missing edid gets replaced with ??? and missing output name is ??? too - i have never seen a missing output name so you get this at least). so this FIXES "restore" of screen mode on login for starters. this does nothing to "fix" the screen setup dialog in any way. there are separate issues there. this also breaks e_randr config compat so i bumped epoch so your old config is rejected. i don't see a sensible way of porting the config forward. --- src/bin/e_randr.c | 169 ++++++++++++++--------- src/bin/e_randr.h | 10 +- src/modules/conf_randr/e_smart_monitor.c | 8 +- src/modules/conf_randr/e_smart_randr.c | 4 +- 4 files changed, 119 insertions(+), 72 deletions(-) diff --git a/src/bin/e_randr.c b/src/bin/e_randr.c index b668f9d6e..3b88ab99b 100644 --- a/src/bin/e_randr.c +++ b/src/bin/e_randr.c @@ -15,8 +15,8 @@ static Eina_Bool _e_randr_config_cb_timer(void *data); static void _e_randr_load(void); static void _e_randr_apply(void); static void _e_randr_output_mode_update(E_Randr_Output *cfg); -static E_Config_Randr_Output *_e_randr_config_output_new(Ecore_X_Window root, unsigned int id); -static E_Config_Randr_Output *_e_randr_config_output_find(Ecore_X_Randr_Output output); +static E_Config_Randr_Output *_e_randr_config_output_new(void); +static E_Config_Randr_Output *_e_randr_config_output_find(E_Randr_Output *output); static E_Randr_Crtc *_e_randr_crtc_find(Ecore_X_Randr_Crtc xid); static E_Randr_Output *_e_randr_output_find(Ecore_X_Randr_Output xid); static E_Randr_Crtc *_e_randr_output_crtc_find(E_Randr_Output *output); @@ -34,7 +34,7 @@ static void _e_randr_crtc_from_outputs_set(E_Randr_Crtc *crtc); static Eina_Bool _e_randr_lid_update(void); static Eina_Bool _e_randr_output_mode_valid(Ecore_X_Randr_Mode mode, Ecore_X_Randr_Mode *modes, int nmodes); static void _e_randr_output_active_set(E_Randr_Output *output, Eina_Bool connected); -static int _e_randr_config_output_cmp(const void *a, const void *b); +//static int _e_randr_config_output_cmp(const void *a, const void *b); static char *_e_randr_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output output); /* local variables */ @@ -189,8 +189,8 @@ _e_randr_config_load(void) #undef D #define T E_Config_Randr_Output #define D _e_randr_output_edd - E_CONFIG_VAL(D, T, xid, UINT); - E_CONFIG_VAL(D, T, crtc, UINT); + E_CONFIG_VAL(D, T, name, STR); + E_CONFIG_VAL(D, T, edid, STR); E_CONFIG_VAL(D, T, orient, UINT); E_CONFIG_VAL(D, T, geo.x, INT); E_CONFIG_VAL(D, T, geo.y, INT); @@ -272,7 +272,9 @@ _e_randr_config_load(void) e_randr_config_save(); if ((do_restore) && (e_randr_cfg->restore)) - _e_randr_apply(); + { + _e_randr_apply(); + } return EINA_TRUE; } @@ -339,6 +341,7 @@ _e_randr_free(void) EINA_LIST_FREE(e_randr->outputs, output) { free(output->name); + free(output->edid); free(output); } @@ -353,6 +356,36 @@ _e_randr_config_cb_timer(void *data) return EINA_FALSE; } +static char * +_e_randr_output_edid_string_get(Ecore_X_Window root, Ecore_X_Randr_Output output) +{ + unsigned char *edid = NULL; + unsigned long edid_len = 0; + char *edid_str = NULL; + + edid = ecore_x_randr_output_edid_get(root, output, &edid_len); + if (edid) + { + int k, kk; + + edid_str = malloc((edid_len * 2) + 1); + if (edid_str) + { + const char *hexch = "0123456789abcdef"; + + for (kk = 0, k = 0; k < edid_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; +} + /* function to map X's settings with E's settings */ static void _e_randr_load(void) @@ -407,30 +440,30 @@ _e_randr_load(void) for (j = 0; j < noutputs; j++) { - E_Config_Randr_Output *output_cfg = NULL; E_Randr_Output *output = NULL; Eina_Bool unknown = EINA_FALSE; - output_cfg = _e_randr_config_output_find(outputs[j]); - if (!output_cfg) - { - output_cfg = _e_randr_config_output_new(root, outputs[j]); - unknown = EINA_TRUE; - } - if (!output_cfg) continue; - output = E_NEW(E_Randr_Output, 1); if (!output) continue; + e_randr->outputs = eina_list_append(e_randr->outputs, output); - output->cfg = output_cfg; - - output->name = _e_randr_output_name_get(root, output->cfg->xid); + output->xid = outputs[j]; + output->name = _e_randr_output_name_get(root, output->xid); output->is_lid = _e_randr_is_lid(output); - - output->status = ecore_x_randr_output_connection_status_get(root, output->cfg->xid); + output->edid = _e_randr_output_edid_string_get(root, outputs[j]); + output->status = ecore_x_randr_output_connection_status_get(root, output->xid); + output->cfg = _e_randr_config_output_find(output); + if (!output->cfg) + { + output->cfg = _e_randr_config_output_new(); + if (output->name) output->cfg->name = strdup(output->name); + if (output->edid) output->cfg->edid = strdup(output->edid); + unknown = EINA_TRUE; + } /* find a crtc if we want this output connected */ - if (output->cfg->connect && (output->status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)) + if (output->cfg->connect && + (output->status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)) { E_Randr_Crtc *crtc; @@ -457,7 +490,8 @@ _e_randr_load(void) free(outputs); } /* sort list by output id */ - e_randr_cfg->outputs = eina_list_sort(e_randr_cfg->outputs, -1, _e_randr_config_output_cmp); +// e_randr_cfg->outputs = eina_list_sort(e_randr_cfg->outputs, -1, +// _e_randr_config_output_cmp); /* update lid status */ _e_randr_lid_update(); @@ -495,6 +529,7 @@ _e_randr_apply(void) /* get the min and max screen size */ ecore_x_randr_screen_size_range_get(root, &minw, &minh, &maxw, &maxh); + fprintf(stderr, "RRR: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh); /* loop our lists of crtcs */ EINA_LIST_FOREACH(e_randr->crtcs, l, crtc) @@ -508,6 +543,7 @@ _e_randr_apply(void) int count = 0; Ecore_X_Randr_Output *coutputs; + fprintf(stderr, "RRR: crtc: %x %i %i %ix%i rot: %i mode: %i\n", crtc->xid, crtc->geo.x, crtc->geo.y, crtc->geo.w, crtc->geo.h, crtc->orient, crtc->mode); /* disable crtc if no outputs */ if (!crtc->outputs) { @@ -534,6 +570,7 @@ _e_randr_apply(void) /* if the crtc does not fit, disable it */ if (((x + w) > maxw) || ((y + h) > maxh) || (mode == 0)) { + fprintf(stderr, "RRR: crtc dose not fit - off\n"); ecore_x_randr_crtc_settings_set(root, crtc->xid, NULL, 0, 0, 0, 0, ECORE_X_RANDR_ORIENTATION_ROT_0); continue; @@ -543,12 +580,13 @@ _e_randr_apply(void) coutputs = calloc(eina_list_count(crtc->outputs), sizeof(Ecore_X_Randr_Output)); if (!coutputs) { + fprintf(stderr, "RRR: cannod alloc coutputs\n"); /* TODO: ERROR! */ continue; } EINA_LIST_FOREACH(crtc->outputs, ll, output) { - coutputs[count] = output->cfg->xid; + coutputs[count] = output->xid; count++; } @@ -558,6 +596,7 @@ _e_randr_apply(void) if (x < nx) nx = x; if (y < ny) ny = y; + fprintf(stderr, "RRR: set mode %x | %i %i %ix%i | %x | %i\n", crtc->xid, crtc->geo.x, crtc->geo.y, crtc->geo.w, crtc->geo.h, crtc->mode, crtc->orient); /* apply our stored crtc settings */ ecore_x_randr_crtc_settings_set(root, crtc->xid, coutputs, count, crtc->geo.x, crtc->geo.y, @@ -667,24 +706,25 @@ _e_randr_event_cb_output_change(void *data EINA_UNUSED, int type EINA_UNUSED, vo output = _e_randr_output_find(ev->output); if (!output) { - E_Config_Randr_Output *output_cfg = NULL; Ecore_X_Window root; root = ecore_x_window_root_first_get(); output = E_NEW(E_Randr_Output, 1); if (!output) goto error; - output_cfg = _e_randr_config_output_find(ev->output); - if (!output_cfg) - output_cfg = _e_randr_config_output_new(root, ev->output); - if (!output_cfg) goto error; - e_randr->outputs = eina_list_append(e_randr->outputs, output); - output->cfg = output_cfg; - - output->name = _e_randr_output_name_get(root, output->cfg->xid); + output->xid = ev->output; + output->name = _e_randr_output_name_get(root, output->xid); output->is_lid = _e_randr_is_lid(output); + output->edid = _e_randr_output_edid_string_get(root, ev->output); changed = EINA_TRUE; + output->cfg = _e_randr_config_output_find(output); + if (!output->cfg) + { + output->cfg = _e_randr_config_output_new(); + if (output->name) output->cfg->name = strdup(output->name); + if (output->edid) output->cfg->edid = strdup(output->edid); + } } output->status = ev->connection; @@ -698,15 +738,15 @@ _e_randr_event_cb_output_change(void *data EINA_UNUSED, int type EINA_UNUSED, vo E_Randr_Crtc *crtc = NULL; Eina_Bool unknown = EINA_FALSE; - if (output->cfg->crtc == 0) unknown = EINA_TRUE; + if ((!output->crtc) || (output->crtc->xid == 0)) unknown = EINA_TRUE; /* connected */ - if ((ev->crtc != 0) && (output->cfg->crtc != ev->crtc)) + if ((ev->crtc != 0) && ((!unknown) && (output->crtc->xid != ev->crtc))) { /* remove from old crtc */ _e_randr_output_active_set(output, EINA_FALSE); /* set new crtc on output */ - output->cfg->crtc = ev->crtc; + output->crtc = _e_randr_crtc_find(ev->crtc); } if ((!output->active) && (output->cfg->connect)) { @@ -805,7 +845,7 @@ _e_randr_output_mode_update(E_Randr_Output *output) if (nmode_infos == 0) goto error; /* get the list of modes for this output */ - modes = ecore_x_randr_output_modes_get(root, output->cfg->xid, &nmodes, &pref); + modes = ecore_x_randr_output_modes_get(root, output->xid, &nmodes, &pref); if (nmodes == 0) goto error; @@ -830,11 +870,11 @@ _e_randr_output_mode_update(E_Randr_Output *output) } /* see if we can use the mode of the crtc */ - if (!output->mode) + if ((!output->mode) && (output->crtc)) { E_Randr_Crtc *crtc; - crtc = _e_randr_crtc_find(output->cfg->crtc); + crtc = _e_randr_crtc_find(ecore_x_randr_output_crtc_get(root, output->xid)); if (crtc && crtc->mode) { if (_e_randr_output_mode_valid(crtc->mode, modes, nmodes)) @@ -887,18 +927,12 @@ error: } static E_Config_Randr_Output * -_e_randr_config_output_new(Ecore_X_Window root, unsigned int id) +_e_randr_config_output_new(void) { E_Config_Randr_Output *cfg = NULL; if ((cfg = E_NEW(E_Config_Randr_Output, 1))) { - /* assign output xid */ - cfg->xid = id; - - /* get the crtc for this output */ - cfg->crtc = ecore_x_randr_output_crtc_get(root, cfg->xid); - /* all new outputs should connect automatically */ /* TODO: config option */ cfg->connect = EINA_TRUE; @@ -912,15 +946,21 @@ _e_randr_config_output_new(Ecore_X_Window root, unsigned int id) } static E_Config_Randr_Output * -_e_randr_config_output_find(Ecore_X_Randr_Output output) +_e_randr_config_output_find(E_Randr_Output *output) { Eina_List *l; E_Config_Randr_Output *output_cfg; + char b1[4096], b2[4096]; + snprintf(b1, sizeof(b1), "%s.%s", + output->name ? output->name : "???", + output->edid ? output->edid : "???"); EINA_LIST_FOREACH(e_randr_cfg->outputs, l, output_cfg) { - if (output_cfg->xid == output) - return output_cfg; + snprintf(b2, sizeof(b2), "%s.%s", + output_cfg->name ? output_cfg->name : "???", + output_cfg->edid ? output_cfg->edid : "???"); + if (!strcmp(b1, b2)) return output_cfg; } return NULL; @@ -949,7 +989,7 @@ _e_randr_output_find(Ecore_X_Randr_Output xid) EINA_LIST_FOREACH(e_randr->outputs, l, output) { - if (output->cfg->xid == xid) + if (output->xid == xid) return output; } @@ -970,7 +1010,7 @@ _e_randr_output_crtc_find(E_Randr_Output *output) root = ecore_x_window_root_first_get(); /* check if last is available */ - if ((crtc = _e_randr_crtc_find(output->cfg->crtc))) + if ((crtc = _e_randr_crtc_find(ecore_x_randr_output_crtc_get(root, output->xid)))) { if (!crtc->outputs) goto done; @@ -978,7 +1018,7 @@ _e_randr_output_crtc_find(E_Randr_Output *output) crtc = NULL; /* get a list of possible crtcs for this output */ - possible = ecore_x_randr_output_possible_crtcs_get(root, output->cfg->xid, &num); + possible = ecore_x_randr_output_possible_crtcs_get(root, output->xid, &num); if (num == 0) goto error; /* loop the possible crtcs */ @@ -993,7 +1033,7 @@ _e_randr_output_crtc_find(E_Randr_Output *output) crtc = NULL; /* get the list of modes for this output */ - modes = ecore_x_randr_output_modes_get(root, output->cfg->xid, &nmodes, &pref); + modes = ecore_x_randr_output_modes_get(root, output->xid, &nmodes, &pref); if (nmodes == 0) goto error; @@ -1013,16 +1053,15 @@ done: free(possible); free(modes); - if (crtc) - output->cfg->crtc = crtc->xid; - return crtc; + output->crtc = crtc; + return output->crtc; error: free(possible); free(modes); - output->cfg->crtc = 0; - return NULL; + output->crtc = NULL; + return output->crtc; } static void @@ -1087,7 +1126,7 @@ _e_randr_config_primary_update(void) if (output->is_lid) { if (output->active) - e_randr_cfg->primary = output->cfg->xid; + e_randr_cfg->primary = output->xid; break; } } @@ -1099,7 +1138,7 @@ _e_randr_config_primary_update(void) { if (output->active) { - e_randr_cfg->primary = output->cfg->xid; + e_randr_cfg->primary = output->xid; break; } } @@ -1128,6 +1167,8 @@ _e_randr_is_lid(E_Randr_Output *cfg) else if (strstr(cfg->name, "lvds")) ret = 1; else if (strstr(cfg->name, "Lvds")) ret = 1; else if (strstr(cfg->name, "LCD")) ret = 1; + else if (strstr(cfg->name, "DP")) ret = 1; + else if (strstr(cfg->name, "dp")) ret = 1; return ret; } @@ -1139,6 +1180,7 @@ _e_randr_crtc_from_outputs_set(E_Randr_Crtc *crtc) EINA_LIST_FOREACH(crtc->outputs, l, output) { + fprintf(stderr, "RRR: output: '%s' lid: %i active: %i status: %i\n", output->name, output->is_lid, output->active, output->status); /* TODO: Match all connected outputs, not only the first */ crtc->mode = output->mode; crtc->orient = output->cfg->orient; @@ -1196,11 +1238,13 @@ static void _e_randr_output_active_set(E_Randr_Output *output, Eina_Bool active) { E_Randr_Crtc *crtc; + Ecore_X_Window root = 0; if (output->active == active) return; output->active = active; - crtc = _e_randr_crtc_find(output->cfg->crtc); + root = ecore_x_window_root_first_get(); + crtc = _e_randr_crtc_find(ecore_x_randr_output_crtc_get(root, output->xid)); if (crtc) { if (active) @@ -1218,8 +1262,9 @@ _e_randr_output_active_set(E_Randr_Output *output, Eina_Bool active) e_randr->active--; } } + else output->crtc = NULL; } - +/* static int _e_randr_config_output_cmp(const void *a, const void *b) { @@ -1230,7 +1275,7 @@ _e_randr_config_output_cmp(const void *a, const void *b) if (cfg1->xid > cfg2->xid) return 1; return 0; } - +*/ static char * _e_randr_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output output) { diff --git a/src/bin/e_randr.h b/src/bin/e_randr.h index 2be789c9c..654a7e482 100644 --- a/src/bin/e_randr.h +++ b/src/bin/e_randr.h @@ -16,15 +16,15 @@ typedef struct _E_Randr E_Randr; #define E_RANDR_VERSION_1_3 ((1 << 16) | 3) #define E_RANDR_VERSION_1_4 ((1 << 16) | 4) -#define E_RANDR_CONFIG_FILE_EPOCH 4 -#define E_RANDR_CONFIG_FILE_GENERATION 4 +#define E_RANDR_CONFIG_FILE_EPOCH 5 +#define E_RANDR_CONFIG_FILE_GENERATION 1 #define E_RANDR_CONFIG_FILE_VERSION \ ((E_RANDR_CONFIG_FILE_EPOCH * 1000000) + E_RANDR_CONFIG_FILE_GENERATION) struct _E_Config_Randr_Output { - unsigned int xid; // ecore_x_randr output id (xid) - unsigned int crtc; // ecore_x_randr crtc id (xid) + const char *name; + const char *edid; unsigned int orient; // value of the ecore_x_randr_orientation Eina_Rectangle geo; // geometry @@ -45,8 +45,10 @@ struct _E_Config_Randr struct _E_Randr_Output { + unsigned int xid; // ecore_x_randr output id (xid) unsigned int mode; // ecore_x_randr mode id (xid) char *name; // name of output + char *edid; // edid as a hex string Eina_Bool is_lid; // is this a laptop panel Eina_Bool active; // if this output is active Ecore_X_Randr_Connection_Status status; diff --git a/src/modules/conf_randr/e_smart_monitor.c b/src/modules/conf_randr/e_smart_monitor.c index 8d151867f..d5145070b 100644 --- a/src/modules/conf_randr/e_smart_monitor.c +++ b/src/modules/conf_randr/e_smart_monitor.c @@ -225,7 +225,7 @@ e_smart_monitor_output_set(Evas_Object *obj, E_Randr_Output *output) sd->max.mode_height = mode->height; /* set if it's primary */ - sd->primary = (output->cfg->xid == e_randr_cfg->primary); + sd->primary = (output->xid == e_randr_cfg->primary); if (sd->primary) edje_object_signal_emit(sd->o_frame, "e,state,primary,on", "e"); else @@ -426,7 +426,7 @@ e_smart_monitor_changes_apply(Evas_Object *obj) /* try to get the objects smart data */ if (!(sd = evas_object_smart_data_get(obj))) return; - sd->primary = (sd->output->cfg->xid == e_randr_cfg->primary); + sd->primary = (sd->output->xid == e_randr_cfg->primary); if (sd->primary) edje_object_signal_emit(sd->o_frame, "e,state,primary,on", "e"); @@ -468,7 +468,7 @@ e_smart_monitor_output_get(Evas_Object *obj) /* try to get the objects smart data */ if (!(sd = evas_object_smart_data_get(obj))) return 0; - return sd->output->cfg->xid; + return sd->output->xid; } void @@ -821,7 +821,7 @@ _e_smart_monitor_modes_fill(E_Smart_Data *sd) root = ecore_x_window_root_first_get(); /* try to get the modes for this output from ecore_x_randr */ - modes = ecore_x_randr_output_modes_get(root, sd->output->cfg->xid, &num, NULL); + modes = ecore_x_randr_output_modes_get(root, sd->output->xid, &num, NULL); if (!modes) return; /* loop the returned modes */ diff --git a/src/modules/conf_randr/e_smart_randr.c b/src/modules/conf_randr/e_smart_randr.c index 0a02a9b23..560fb755b 100644 --- a/src/modules/conf_randr/e_smart_randr.c +++ b/src/modules/conf_randr/e_smart_randr.c @@ -107,7 +107,7 @@ e_smart_randr_virtual_size_calc(Evas_Object *obj) /* try to get the list of modes for this output */ modes = - ecore_x_randr_output_modes_get(root, output->cfg->xid, + ecore_x_randr_output_modes_get(root, output->xid, &nmode, NULL); if (!modes) continue; @@ -191,7 +191,7 @@ e_smart_randr_monitors_create(Evas_Object *obj) if ((cw == 0) && (ch == 0)) { /* get the size of the preferred mode for this output */ - _e_smart_randr_monitor_preferred_mode_size_get(output->cfg->xid, + _e_smart_randr_monitor_preferred_mode_size_get(output->xid, &cw, &ch); /* safety */