diff --git a/src/bin/e_config.c b/src/bin/e_config.c index 3592bf886..e62d3c1bf 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -6,23 +6,9 @@ #define DEF_MENUCLICK 0.25 #endif -typedef enum _Eet_Union -{ - EET_SCREEN_INFO_11 = (int)((1 << 16) | 1), - EET_SCREEN_INFO_12 = (int)((1 << 16) | 2), - EET_SCREEN_INFO_13 = (int)((1 << 16) | 3), - EET_UNKNOWN -} Eet_Union; - -struct { - Eet_Union u; - const char *name; -} eet_mapping[] = { - { EET_SCREEN_INFO_11, "E_Config_Screen_11" }, - { EET_SCREEN_INFO_12, "E_Config_Screen_12" }, - { EET_SCREEN_INFO_12, "E_Config_Screen_13" }, - { EET_UNKNOWN, NULL } -}; +#define RANDR_SERIALIZED_SETUP_11 ((int)((1 << 16) | 1)) +#define RANDR_SERIALIZED_SETUP_12 ((int)((1 << 16) | 2)) +#define RANDR_SERIALIZED_SETUP_13 ((int)((1 << 16) | 3)) EAPI E_Config *e_config = NULL; @@ -34,8 +20,6 @@ static void _e_config_free(E_Config *cfg); static Eina_Bool _e_config_cb_timer(void *data); static int _e_config_eet_close_handle(Eet_File *ef, char *file); static void _e_config_acpi_bindings_add(void); -static const char * _eet_union_type_get(const void *data, Eina_Bool *unknow); -static Eina_Bool _eet_union_type_set(const char *type, void *data, Eina_Bool unknow); /* local subsystem globals */ static int _e_config_save_block = 0; @@ -65,15 +49,16 @@ static E_Config_DD *_e_config_shelf_desk_edd = NULL; static E_Config_DD *_e_config_mime_icon_edd = NULL; static E_Config_DD *_e_config_syscon_action_edd = NULL; static E_Config_DD *_e_config_env_var_edd = NULL; -static E_Config_DD *_e_config_screen_size_edd = NULL; -static E_Config_DD *_e_config_screen_size_mm_edd = NULL; -static E_Config_DD *_e_config_eina_rectangle_edd = NULL; -static E_Config_DD *_e_config_screen_info_edd = NULL; -static E_Config_DD *_e_config_screen_restore_info_11_edd = NULL; -static E_Config_DD *_e_config_screen_restore_info_12_edd = NULL; -static E_Config_DD *_e_config_screen_output_edid_hash_edd = NULL; -static E_Config_DD *_e_config_screen_output_restore_info_edd = NULL; -static E_Config_DD *_e_config_screen_crtc_restore_info_edd = NULL; +static E_Config_DD *_e_config_randr_size_edd = NULL; +static E_Config_DD *_e_config_randr_size_mm_edd = NULL; +static E_Config_DD *_e_config_randr_edid_hash_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_setup_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_setup_11_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_setup_12_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_output_policy_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_output_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_mode_info_edd = NULL; +static E_Config_DD *_e_config_randr_serialized_crtc_edd = NULL; EAPI int E_EVENT_CONFIG_ICON_THEME = 0; @@ -526,107 +511,109 @@ e_config_init(void) E_CONFIG_VAL(D, T, val, STR); E_CONFIG_VAL(D, T, unset, UCHAR); - _e_config_screen_size_edd = E_CONFIG_DD_NEW("Ecore_X_Randr_Screen_Size", Ecore_X_Randr_Screen_Size); + _e_config_randr_size_edd = E_CONFIG_DD_NEW("Ecore_X_Randr_Screen_Size", Ecore_X_Randr_Screen_Size); #undef T #undef D #define T Ecore_X_Randr_Screen_Size -#define D _e_config_screen_size_edd +#define D _e_config_randr_size_edd E_CONFIG_VAL(D, T, width, INT); E_CONFIG_VAL(D, T, height, INT); E_CONFIG_VAL(D, T, width, INT); E_CONFIG_VAL(D, T, height, INT); - _e_config_screen_size_mm_edd = E_CONFIG_DD_NEW("Ecore_X_Randr_Screen_Size_MM", Ecore_X_Randr_Screen_Size_MM); + _e_config_randr_size_mm_edd = E_CONFIG_DD_NEW("Ecore_X_Randr_Screen_Size_MM", Ecore_X_Randr_Screen_Size_MM); #undef T #undef D #define T Ecore_X_Randr_Screen_Size_MM -#define D _e_config_screen_size_mm_edd +#define D _e_config_randr_size_mm_edd E_CONFIG_VAL(D, T, width, INT); E_CONFIG_VAL(D, T, height, INT); E_CONFIG_VAL(D, T, width_mm, INT); E_CONFIG_VAL(D, T, height_mm, INT); - _e_config_screen_restore_info_11_edd = E_CONFIG_DD_NEW("E_Randr_Screen_Restore_Info_11", E_Randr_Screen_Restore_Info_11); + _e_config_randr_edid_hash_edd = E_CONFIG_DD_NEW("E_Randr_Edid_Hash", E_Randr_Edid_Hash); #undef T #undef D -#define T E_Randr_Screen_Restore_Info_11 -#define D _e_config_screen_restore_info_11_edd - E_CONFIG_SUB(D, T, size, _e_config_screen_size_edd); +#define T E_Randr_Edid_Hash +#define D _e_config_randr_edid_hash_edd + E_CONFIG_VAL(D, T, hash, INT); + + _e_config_randr_serialized_setup_11_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Setup_11", E_Randr_Serialized_Setup_11); +#undef T +#undef D +#define T E_Randr_Serialized_Setup_11 +#define D _e_config_randr_serialized_setup_11_edd + E_CONFIG_SUB(D, T, size, _e_config_randr_size_edd); E_CONFIG_VAL(D, T, orientation, INT); E_CONFIG_VAL(D, T, refresh_rate, SHORT); - _e_config_eina_rectangle_edd = E_CONFIG_DD_NEW("Eina_Rectangle", Eina_Rectangle); + _e_config_randr_serialized_output_policy_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Output_Policy", E_Randr_Serialized_Output_Policy); #undef T #undef D -#define T Eina_Rectangle -#define D _e_config_eina_rectangle_edd - E_CONFIG_VAL(D, T, x, INT); - E_CONFIG_VAL(D, T, y, INT); - E_CONFIG_VAL(D, T, w, INT); - E_CONFIG_VAL(D, T, h, INT); +#define T E_Randr_Serialized_Output_Policy +#define D _e_config_randr_serialized_output_policy_edd + E_CONFIG_VAL(D, T, name, STR); + E_CONFIG_VAL(D, T, name_length, INT); + E_CONFIG_VAL(D, T, policy, INT); - _e_config_screen_output_edid_hash_edd = E_CONFIG_DD_NEW("E_Randr_Output_Edid_Hash", E_Randr_Output_Edid_Hash); + _e_config_randr_serialized_output_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Output", E_Randr_Serialized_Output); #undef T #undef D -#define T E_Randr_Output_Edid_Hash -#define D _e_config_screen_output_edid_hash_edd - E_CONFIG_VAL(D, T, hash, INT); - - // FIXME: need to totally re-do this randr config stuff - remove the - // union stuff. do this differently to not use unions really. not - // intended for how it is used here really. - _e_config_screen_output_restore_info_edd = E_CONFIG_DD_NEW("E_Randr_Output_Restore_Info", E_Randr_Output_Restore_Info); -#undef T -#undef D -#define T E_Randr_Output_Restore_Info -#define D _e_config_screen_output_restore_info_edd - E_CONFIG_SUB(D, T, edid_hash, _e_config_screen_output_edid_hash_edd); +#define T E_Randr_Serialized_Output +#define D _e_config_randr_serialized_output_edd + E_CONFIG_VAL(D, T, name, STR); + E_CONFIG_VAL(D, T, name_length, INT); + E_CONFIG_SUB(D, T, edid_hash, _e_config_randr_edid_hash_edd); E_CONFIG_VAL(D, T, backlight_level, DOUBLE); - _e_config_screen_crtc_restore_info_edd = E_CONFIG_DD_NEW("E_Randr_Crtc_Restore_Info", E_Randr_Crtc_Restore_Info); + _e_config_randr_serialized_mode_info_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Mode_Info", Ecore_X_Randr_Mode_Info); #undef T #undef D -#define T E_Randr_Crtc_Restore_Info -#define D _e_config_screen_crtc_restore_info_edd - E_CONFIG_SUB(D, T, geometry, _e_config_eina_rectangle_edd); - E_CONFIG_LIST(D, T, outputs, _e_config_screen_output_restore_info_edd); +#define T Ecore_X_Randr_Mode_Info +#define D _e_config_randr_serialized_mode_info_edd + E_CONFIG_VAL(D, T, width, INT); + E_CONFIG_VAL(D, T, height, INT); + E_CONFIG_VAL(D, T, dotClock, LL); + E_CONFIG_VAL(D, T, hSyncStart, INT); + E_CONFIG_VAL(D, T, hSyncEnd, INT); + E_CONFIG_VAL(D, T, hTotal, INT); + E_CONFIG_VAL(D, T, hSkew, INT); + E_CONFIG_VAL(D, T, vSyncStart, INT); + E_CONFIG_VAL(D, T, vSyncEnd, INT); + E_CONFIG_VAL(D, T, vTotal, INT); + E_CONFIG_VAL(D, T, name, STR); + E_CONFIG_VAL(D, T, nameLength, INT); + E_CONFIG_VAL(D, T, modeFlags, LL); + + _e_config_randr_serialized_crtc_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Crtc", E_Randr_Serialized_Crtc); +#undef T +#undef D +#define T E_Randr_Serialized_Crtc +#define D _e_config_randr_serialized_crtc_edd + E_CONFIG_LIST(D, T, serialized_outputs, _e_config_randr_serialized_output_edd); + E_CONFIG_SUB(D, T, mode_info, _e_config_randr_serialized_mode_info_edd); + E_CONFIG_VAL(D, T, pos.x, INT); + E_CONFIG_VAL(D, T, pos.y, INT); + EET_DATA_DESCRIPTOR_ADD_LIST_STRING(D, T, "Crtc_Possible_Outputs_Names", possible_outputs_names); E_CONFIG_VAL(D, T, orientation, INT); - _e_config_screen_restore_info_12_edd = E_CONFIG_DD_NEW("E_Randr_Screen_Restore_Info_12", E_Randr_Screen_Restore_Info_12); + _e_config_randr_serialized_setup_12_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Setup_12", E_Randr_Serialized_Setup_12); #undef T #undef D -#define T E_Randr_Screen_Restore_Info_12 -#define D _e_config_screen_restore_info_12_edd - E_CONFIG_LIST(D, T, crtcs, _e_config_screen_crtc_restore_info_edd); - E_CONFIG_LIST(D, T, outputs_edid_hashes, _e_config_screen_output_edid_hash_edd); - E_CONFIG_VAL(D, T, noutputs, INT); - E_CONFIG_VAL(D, T, output_policy, INT); - E_CONFIG_VAL(D, T, alignment, INT); +#define T E_Randr_Serialized_Setup_12 +#define D _e_config_randr_serialized_setup_12_edd + E_CONFIG_VAL(D, T, timestamp, DOUBLE); + E_CONFIG_LIST(D, T, serialized_crtcs, _e_config_randr_serialized_crtc_edd); + E_CONFIG_LIST(D, T, serialized_edid_hashes, _e_config_randr_edid_hash_edd); + _e_config_randr_serialized_setup_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Setup", E_Randr_Serialized_Setup); #undef T #undef D -#define T E_Randr_Screen_Restore_Info -#define D _e_config_screen_info_edd - Eet_Data_Descriptor_Class eddc; - Eet_Data_Descriptor *unified, *edd_11_info, *edd_12_info; - EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, T); - D = eet_data_descriptor_stream_new(&eddc); - eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; - eddc.func.type_get = _eet_union_type_get; - eddc.func.type_set = _eet_union_type_set; - //virtual types to work around EET's inability to differentiate when it - //comes to pointers (a->b) vs. values (a.b) in union mappings - edd_11_info = E_CONFIG_DD_NEW("E_Randr_Screen_Restore_Info_11_Struct", E_Randr_Screen_Restore_Info_11); - E_CONFIG_SUB(edd_11_info, E_Randr_Screen_Restore_Info_Union, restore_info_11, _e_config_screen_restore_info_11_edd); - edd_12_info = E_CONFIG_DD_NEW("E_Randr_Screen_Restore_Info_12_Struct", E_Randr_Screen_Restore_Info_12); - E_CONFIG_LIST(edd_12_info, E_Randr_Screen_Restore_Info_Union, restore_info_12, _e_config_screen_restore_info_12_edd); - unified = eet_data_descriptor_stream_new(&eddc); - EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "E_Config_Screen_11", edd_11_info); - EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "E_Config_Screen_12", edd_12_info); - EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "E_Config_Screen_13", edd_12_info); -// DISABLE! crashie crashie long time -// EET_DATA_DESCRIPTOR_ADD_UNION(D, T, "E_Randr_Screen_Restore_Info_Union", rrvd_restore_info, randr_version, unified); - E_CONFIG_VAL(D, T, randr_version, INT); +#define T E_Randr_Serialized_Setup +#define D _e_config_randr_serialized_setup_edd + E_CONFIG_SUB(D, T, serialized_setup_11, _e_config_randr_serialized_setup_11_edd); + E_CONFIG_LIST(D, T, serialized_setups_12, _e_config_randr_serialized_setup_12_edd); + E_CONFIG_LIST(D, T, serialized_outputs_policies, _e_config_randr_serialized_output_policy_edd); _e_config_edd = E_CONFIG_DD_NEW("E_Config", E_Config); #undef T @@ -787,7 +774,8 @@ e_config_init(void) E_CONFIG_VAL(D, T, desklock_ask_presentation, UCHAR); E_CONFIG_VAL(D, T, desklock_ask_presentation_timeout, DOUBLE); - E_CONFIG_LIST(D, T, screen_info, _e_config_screen_info_edd); + //randr specifics + E_CONFIG_SUB(D, T, randr_serialized_setup, _e_config_randr_serialized_setup_edd); E_CONFIG_VAL(D, T, screensaver_enable, INT); E_CONFIG_VAL(D, T, screensaver_timeout, INT); @@ -959,7 +947,7 @@ e_config_shutdown(void) E_CONFIG_DD_FREE(_e_config_mime_icon_edd); E_CONFIG_DD_FREE(_e_config_syscon_action_edd); E_CONFIG_DD_FREE(_e_config_env_var_edd); - E_CONFIG_DD_FREE(_e_config_screen_info_edd); + E_CONFIG_DD_FREE(_e_config_randr_serialized_setup_edd); return 1; } @@ -1915,10 +1903,13 @@ _e_config_free(E_Config *ecf) E_Color_Class *cc; E_Path_Dir *epd; E_Remember *rem; - E_Randr_Screen_Restore_Info *screen_info; - E_Randr_Crtc_Restore_Info *crtc_info; - E_Randr_Output_Info *output_info; - E_Randr_Screen_Restore_Info_12 *restore_info_12; + E_Randr_Serialized_Setup *serialized_setup; + E_Randr_Serialized_Setup_12 *serialized_setup_12; + E_Randr_Serialized_Crtc *serialized_crtc; + E_Randr_Serialized_Output_Policy *serialized_output_policy; + E_Randr_Serialized_Output *serialized_output; + E_Randr_Edid_Hash *edid_hash; + char *output_name; E_Config_Env_Var *evr; @@ -2069,37 +2060,50 @@ _e_config_free(E_Config *ecf) if (sca->icon) eina_stringshare_del(sca->icon); E_FREE(sca); } - if (ecf->screen_info) + if(ecf->randr_serialized_setup) { - EINA_LIST_FREE(ecf->screen_info, screen_info) - { - switch (screen_info->randr_version) - { - case EET_SCREEN_INFO_11: - free(screen_info->rrvd_restore_info.restore_info_11); - break; - case EET_SCREEN_INFO_12: - case EET_SCREEN_INFO_13: - EINA_LIST_FREE(screen_info->rrvd_restore_info.restore_info_12, restore_info_12) - { - EINA_LIST_FREE(restore_info_12->crtcs, crtc_info) - { - EINA_LIST_FREE(crtc_info->outputs, output_info) - { - free(output_info->name); - free(output_info->edid); - free (output_info); - } - free (crtc_info); - } - free(restore_info_12); - } - eina_list_free(screen_info->rrvd_restore_info.restore_info_12); - break; - } - free(screen_info); - } + if(ecf->randr_serialized_setup->serialized_setup_11) + free(serialized_setup->serialized_setup_11); + else if(ecf->randr_serialized_setup->serialized_setups_12) + { + EINA_LIST_FREE(ecf->randr_serialized_setup->serialized_setups_12, serialized_setup_12) + { + EINA_LIST_FREE(serialized_setup_12->serialized_crtcs, serialized_crtc) + { + if (!serialized_crtc) continue; + EINA_LIST_FREE(serialized_crtc->serialized_outputs, serialized_output) + { + if (serialized_output) + { + if (serialized_output->name) free(serialized_output); + free(serialized_output); + } + } + EINA_LIST_FREE(serialized_crtc->possible_outputs_names, output_name) + { + if (output_name) free(output_name); + } + if (serialized_crtc->mode_info.name) + free(serialized_crtc->mode_info.name); + free(serialized_crtc); + } + EINA_LIST_FREE(serialized_setup_12->serialized_edid_hashes, edid_hash) + { + if (edid_hash) free(edid_hash); + } + free(serialized_setup_12); + } + } + EINA_LIST_FREE(ecf->randr_serialized_setup->serialized_outputs_policies, serialized_output_policy) + { + if (!serialized_output) continue; + if (serialized_output_policy->name) + free(serialized_output_policy->name); + free(serialized_output_policy); + } + free(ecf->randr_serialized_setup); } + EINA_LIST_FREE(ecf->env_vars, evr) { if (evr->var) eina_stringshare_del(evr->var); @@ -2116,14 +2120,14 @@ _e_config_free(E_Config *ecf) E_FREE(ecf); } -static Eina_Bool + static Eina_Bool _e_config_cb_timer(void *data) { e_util_dialog_show(_("Settings Upgraded"), "%s", (char *)data); return 0; } -static int + static int _e_config_eet_close_handle(Eet_File *ef, char *file) { Eet_Error err; @@ -2133,16 +2137,16 @@ _e_config_eet_close_handle(Eet_File *ef, char *file) switch (err) { case EET_ERROR_NONE: - /* all good - no error */ - break; + /* all good - no error */ + break; case EET_ERROR_BAD_OBJECT: - erstr = _("The EET file handle is bad."); - break; + erstr = _("The EET file handle is bad."); + break; case EET_ERROR_EMPTY: - erstr = _("The file data is empty."); - break; + erstr = _("The file data is empty."); + break; case EET_ERROR_NOT_WRITABLE: - erstr = _("The file is not writable. Perhaps the disk is read-only
or you lost permissions to your files."); + erstr = _("The file is not writable. Perhaps the disk is read-only
or you lost permissions to your files."); break; case EET_ERROR_OUT_OF_MEMORY: erstr = _("Memory ran out while preparing the write.
Please free up memory."); @@ -2280,36 +2284,3 @@ _e_config_acpi_bindings_add(void) bind->params = eina_stringshare_add("now"); e_config->acpi_bindings = eina_list_append(e_config->acpi_bindings, bind); } - -static const char * -_eet_union_type_get(const void *data, Eina_Bool *unknow) -{ - const Eet_Union *u = data; - int i; - - if (unknow) *unknow = EINA_FALSE; - for (i = 0; eet_mapping[i].name; ++i) - if (*u == eet_mapping[i].u) - return eet_mapping[i].name; - - if (unknow) *unknow = EINA_TRUE; - return NULL; -} - -static Eina_Bool -_eet_union_type_set(const char *type, void *data, Eina_Bool unknow) -{ - Eet_Union *u = data; - int i; - - if (unknow) return EINA_FALSE; - - for (i = 0; eet_mapping[i].name; ++i) - if (strcmp(eet_mapping[i].name, type) == 0) - { - *u = eet_mapping[i].u; - return EINA_TRUE; - } - - return EINA_FALSE; -} diff --git a/src/bin/e_config.h b/src/bin/e_config.h index 123843b2f..e793cb733 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -33,7 +33,7 @@ typedef struct _E_Event_Config_Icon_Theme E_Event_Config_Icon_Theme; /* increment this whenever a new set of config values are added but the users * config doesn't need to be wiped - simply new values need to be put in */ -#define E_CONFIG_FILE_GENERATION 0x0145 +#define E_CONFIG_FILE_GENERATION 0x0146 #define E_CONFIG_FILE_VERSION ((E_CONFIG_FILE_EPOCH << 16) | E_CONFIG_FILE_GENERATION) #define E_EVAS_ENGINE_DEFAULT 0 @@ -250,7 +250,7 @@ struct _E_Config int mouse_accel_denominator; // GUI int mouse_accel_threshold; // GUI - Eina_List *screen_info; // GUI + E_Randr_Serialized_Setup *randr_serialized_setup; // GUI int border_raise_on_mouse_action; // GUI int border_raise_on_focus; // GUI diff --git a/src/bin/e_gadcon.c b/src/bin/e_gadcon.c index 289715120..e300a428e 100644 --- a/src/bin/e_gadcon.c +++ b/src/bin/e_gadcon.c @@ -1466,10 +1466,10 @@ e_gadcon_client_util_menu_items_append(E_Gadcon_Client *gcc, E_Menu *menu_gadget { mi = e_menu_item_new(menu_main); if (gcc->client_class->func.label) - snprintf(buf, sizeof(buf), "Gadget %s", + snprintf(buf, sizeof(buf), "%s", gcc->client_class->func.label((E_Gadcon_Client_Class *)gcc->client_class)); else - snprintf(buf, sizeof(buf), "Gadget %s", gcc->name); + snprintf(buf, sizeof(buf), "%s", gcc->name); e_menu_item_label_set(mi, _(buf)); e_menu_item_realize_callback_set(mi, _e_gadcon_client_cb_menu_pre, gcc); diff --git a/src/bin/e_randr.c b/src/bin/e_randr.c index bb64ecf14..4b8cc7660 100644 --- a/src/bin/e_randr.c +++ b/src/bin/e_randr.c @@ -11,6 +11,13 @@ #define Ecore_X_Randr_Unset -1 /* + * Save mechanism: + * Single monitor: + * - Save monitor using the resolution + * + * Multiple monitors: + * - Use the EDID information to make sure we restore the right monitor. + * * TODO: * -fix output policies above and left */ @@ -57,6 +64,11 @@ static E_Randr_Crtc_Info *_e_randr_crtc_info_new(int nrequested); static void _e_randr_crtc_info_free(E_Randr_Crtc_Info *crtc_info); static Eina_Bool _e_randr_screen_outputs_init(void); static Eina_Bool _e_randr_screen_crtcs_init(void); + +static Eina_Bool _e_randr_try_restore_11(E_Randr_Screen_Info_11 *si_11); +static Eina_Bool _e_randr_try_restore_12(E_Randr_Screen_Info_12 *si_12); +EAPI void e_randr_store_configuration(E_Randr_Screen_Info *screen_info); +EAPI Eina_Bool e_randr_try_restore_configuration(E_Randr_Screen_Info *screen_info); static Eina_Bool _e_randr_output_modes_add(E_Randr_Output_Info *output_info); static void _e_randr_notify_crtc_mode_change(E_Randr_Crtc_Info *crtc_info); static void _e_randr_notify_output_change(E_Randr_Output_Info *output_info); @@ -66,12 +78,8 @@ static E_Randr_Output_Info *_e_randr_output_info_get(Ecore_X_Randr_Output output static void _e_randr_output_info_set(E_Randr_Output_Info *output_info); static void _e_randr_crtc_info_set(E_Randr_Crtc_Info *crtc_info); static const E_Randr_Crtc_Info *_e_randr_policy_crtc_get(E_Randr_Crtc_Info* but, E_Randr_Crtc_Info *hint, Ecore_X_Randr_Output_Policy policy); -//static Eina_Bool _e_randr_outputs_connected(Eina_List *outputs_info); static Ecore_X_Randr_Output *_e_randr_outputs_to_array(Eina_List *outputs_info); -//static int _e_randr_config_find_suiting_config_11(E_Randr_Screen_Restore_Info_11** restore_info); -static E_Randr_Screen_Restore_Info_12 * _e_randr_config_find_suiting_config_12(void); -//static Eina_Bool _e_randr_config_enable_11(int size_index, Ecore_X_Randr_Refresh_Rate refresh_rate, Ecore_X_Randr_Orientation orientation); -//static Eina_Bool _e_randr_config_enable_12(const E_Randr_Screen_Restore_Info_12 *restore_info); +static E_Randr_Serialized_Setup_12 * _e_randr_config_find_suiting_config_12(void); static Eina_Bool _e_randr_try_enable_output(E_Randr_Output_Info *output_info, Eina_Bool force); static void _e_randr_crtcs_possible_output_update(E_Randr_Output_Info *output_info); static void _e_randr_crtc_outputs_refs_update(E_Randr_Crtc_Info *crtc_info); @@ -90,7 +98,7 @@ static void _e_randr_output_info_hw_info_set(E_Randr_Output_Info *output_info); static void _e_randr_output_hw_info_free(E_Randr_Output_Info *output_info); static Eina_Bool _e_randr_outputs_are_clones(E_Randr_Output_Info *output_info, Eina_List *outputs); -E_Randr_Screen_Info *e_randr_screen_info = NULL; +EAPI E_Randr_Screen_Info *e_randr_screen_info = NULL; static Eina_List *_e_randr_event_handlers = NULL; EINTERN Eina_Bool @@ -270,7 +278,6 @@ _e_randr_screen_info_12_new(void) .crtcs = NULL, .outputs = NULL, .primary_output = NULL, - .output_policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE, .alignment = ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE }; @@ -459,7 +466,8 @@ _e_randr_output_info_new(int nrequested) .connector_type = Ecore_X_Randr_Unset, .connection_status = ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED, .subpixel_order= Ecore_X_Randr_Unset, - .compatible_outputs = NULL + .compatible_outputs = NULL, + .policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE }; if (!(ret = malloc(sizeof(E_Randr_Output_Info) * nrequested))) return NULL; @@ -760,7 +768,7 @@ _e_randr_event_cb(void *data __UNUSED__, int type, void *ev) else if (type == ECORE_X_EVENT_RANDR_OUTPUT_CHANGE) { Ecore_X_Event_Randr_Output_Change *event = ev; - const E_Randr_Screen_Restore_Info_12 *restore_info; + const E_Randr_Serialized_Setup_12 *restore_info; E_Randr_Output_Info* output_info = NULL; /* available information: struct _Ecore_X_Event_Randr_Output_Change @@ -807,11 +815,13 @@ _e_randr_event_cb(void *data __UNUSED__, int type, void *ev) _e_randr_output_info_hw_info_set(output_info); //make the crtcs aware of their possibly new output _e_randr_crtcs_possible_output_update(output_info); + /* if ((restore_info = _e_randr_config_find_suiting_config_12())) //maybe we have a suiting configuration //_e_randr_config_enable_12(restore_info); ; else + */ enabled = _e_randr_try_enable_output(output_info, EINA_FALSE); //maybe give a success message? } _e_randr_notify_output_change(output_info); @@ -841,11 +851,13 @@ _e_randr_event_cb(void *data __UNUSED__, int type, void *ev) _e_randr_screen_primary_output_assign(output_info); //let's try to get a proper config for the new setup and crop the //screen afterwards. + /* if ((restore_info = _e_randr_config_find_suiting_config_12())) { //in case we didn't have, init it anyway... //_e_randr_config_enable_12(restore_info); } + */ } _e_randr_notify_output_change(output_info); _e_randr_output_hw_info_free(output_info); @@ -865,6 +877,7 @@ _e_randr_event_cb(void *data __UNUSED__, int type, void *ev) }; */ } + e_randr_try_restore_configuration(e_randr_screen_info); on_exit: return ECORE_CALLBACK_RENEW; } @@ -999,146 +1012,602 @@ _e_randr_policy_crtc_get(E_Randr_Crtc_Info *but, E_Randr_Crtc_Info *hint __UNUSE return ret; } -/* -static Eina_Bool -_e_randr_outputs_connected(Eina_List *outputs_info) +// Setup store functions + Eina_Bool +_e_randr_copy_mode_info(Ecore_X_Randr_Mode_Info *dest, Ecore_X_Randr_Mode_Info *src) { - Eina_List *iter; - E_Randr_Output_Info *output_info; - EINA_LIST_FOREACH(outputs_info, iter, output_info) - if (output_info->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) return EINA_TRUE; - return EINA_FALSE; -} + if (!dest || !src) return EINA_FALSE; -static Eina_Bool -_e_randr_config_enable_11(int size_index, Ecore_X_Randr_Refresh_Rate refresh_rate, Ecore_X_Randr_Orientation orientation) -{ - E_Randr_Screen_Info_11 *current_info_11; - - if (E_RANDR_NO_11 || (size_index < 0) || (refresh_rate < 0) || - (orientation < 0)) return EINA_FALSE; - - if (!ecore_x_randr_screen_primary_output_size_set(e_randr_screen_info->root, size_index) - || !ecore_x_randr_screen_primary_output_orientation_set(e_randr_screen_info->root, orientation) - || !ecore_x_randr_screen_primary_output_refresh_rate_set(e_randr_screen_info->root, size_index, refresh_rate)) return EINA_FALSE; - - //TODO: move this to the screen event later. - current_info_11 = e_randr_screen_info->rrvd_info.randr_info_11; - - current_info_11->csize_index = size_index; - current_info_11->corientation = orientation; - current_info_11->current_rate = refresh_rate; + dest->width = src->width; + dest->height = src->height; + dest->dotClock = src->dotClock; + dest->hSyncStart = src->hSyncStart; + dest->hSyncEnd = src->hSyncEnd; + dest->hTotal = src->hTotal; + dest->hSkew = src->hSkew; + dest->vSyncStart = src->vSyncStart; + dest->vSyncEnd = src->vSyncEnd; + dest->vTotal = src->vTotal; + if (src->nameLength > 0) + { + if (!(dest->name = malloc(src->nameLength + 1))) return EINA_FALSE; + if (!strncpy(dest->name, src->name, src->nameLength)) goto _e_randr_copy_mode_info_fail_free_name; + } + dest->nameLength = src->nameLength; + dest->modeFlags = src->modeFlags; return EINA_TRUE; -} -static Eina_Bool -_e_randr_config_enable_12(const E_Randr_Screen_Restore_Info_12 *restore_info __UNUSED__) -{ - if (E_RANDR_NO_12 || !restore_info) return EINA_FALSE; - E_Randr_Screen_Info_12 *current_info_12; - E_Randr_Screen_Restore_Info_12 *restore_info_12 = NULL; - E_Randr_Crtc_Restore_Info *crtc_restore_info = NULL; - E_Randr_Crtc_Info *crtc_info; - E_Randr_Output_Info *output_info; - Eina_List *crtc_restore_iter; - - current_info_12 = (e_randr_screen_info->rrvd_info).randr_info_12; - EINA_LIST_FOREACH(restore_info_12->crtcs, crtc_restore_iter, crtc_restore_info) - { - ; - } - current_info_12->alignment = restore_info_12->alignment; - current_info_12->output_policy = restore_info_12->output_policy; - return EINA_TRUE; +_e_randr_copy_mode_info_fail_free_name: + free(dest->name); return EINA_FALSE; } -static int -_e_randr_config_find_suiting_config_11(E_Randr_Screen_Restore_Info_11 **restore_info) + void +_e_randr_free_serialized_mode_info(Ecore_X_Randr_Mode_Info *mode_info) { - E_RANDR_NO_11_RET(Ecore_X_Randr_None); - Eina_List *cfg_screen_restore_info_iter; - E_Randr_Screen_Restore_Info *screen_restore_info; - - E_Randr_Screen_Restore_Info_11 *restore_info_11; - Ecore_X_Randr_Screen_Size_MM *sizes; - Ecore_X_Randr_Refresh_Rate *rates = NULL; - int i = 0, j = 0, nsizes = 0, nrates = 0; - - EINA_LIST_FOREACH(e_config->screen_info, cfg_screen_restore_info_iter, screen_restore_info) - { - // 'screen_restore_info' should _never_ be NULL, since this functions shouldn't be called due to randr init failing. - if (!screen_restore_info) continue; - if (screen_restore_info->randr_version != ECORE_X_RANDR_1_1) continue; - restore_info_11 = screen_restore_info->rrvd_restore_info.restore_info_11; - if((sizes = ecore_x_randr_screen_primary_output_sizes_get(e_randr_screen_info->root, &nsizes))) - { - for (i = 0; i < nsizes; i++) - { - if ((restore_info_11->size.width == sizes[i].width) - && (restore_info_11->size.height == sizes[i].height)) - { - if ((rates = ecore_x_randr_screen_primary_output_refresh_rates_get(e_randr_screen_info->root, i, &nrates))) - { - for (j = 0; j < nrates; j++) - if (rates[j] == restore_info_11->refresh_rate) - { - if (restore_info) *restore_info = restore_info_11; - free(rates); - free(sizes); - return i; - } - free(rates); - } - } - } - if (sizes) free(sizes); - } - } - return Ecore_X_Randr_Unset; + if (mode_info->name) free(mode_info->name); } -*/ -/** - * @Brief find configuration with the most hardware currently available - */ -static E_Randr_Screen_Restore_Info_12 * -_e_randr_config_find_suiting_config_12(void) + Eina_List +*_e_randr_create_outputs_policies_list(Eina_List *outputs) { - //TODO: write geometry based loading - /* - Eina_List *cfg_screen_restore_info_iter; - E_Randr_Screen_Restore_Info *screen_restore_info; + Eina_List *iter, *list = NULL; + E_Randr_Output_Info *oi; + E_Randr_Serialized_Output_Policy *sop; + char *name; - E_Randr_Screen_Info_12 *current_info_12; - E_Randr_Screen_Restore_Info_12 *restore_info_12, *most_matches = NULL; - E_Randr_Output_Info *output_info; - E_Randr_Crtc_Restore_Info *crtc_restore_info; - Ecore_X_Randr_Output *outputs_xids; - Ecore_X_Randr_Crtc *crtcs_xids; - Eina_List *restore_info_12_iter, *output_iter, *restore_crtcs_iter; + EINA_LIST_FOREACH(outputs, iter, oi) + { + if (!oi->name || (oi->name_length <= 0)) continue; + if (!(sop = E_NEW(E_Randr_Serialized_Output_Policy, 1)) + || !(sop->name = malloc(oi->name_length + 1)) + || !(strncpy(sop->name, oi->name, oi->name_length))) + goto _e_randr_create_outputs_policies_list_fail_free_list; + sop->name_length = oi->name_length; + sop->policy = oi->policy; + if (!(list = eina_list_append(list, sop))) + goto _e_randr_create_outputs_policies_list_fail_free_list; + } - if (e_randr_screen_info && e_config && e_config->screen_info) - { - - EINA_LIST_FOREACH(e_config->screen_info, cfg_screen_restore_info_iter, screen_restore_info) - { - if (screen_restore_info->randr_version < ECORE_X_RANDR_1_2) continue; - - //HINT: use eina_list_clone and a sort callback to find proper - //crtcs and outputs - - //current_info_12 = e_randr_screen_info->rrvd_info.randr_info_12; - } - - } - */ + return list; +_e_randr_create_outputs_policies_list_fail_free_list: + EINA_LIST_FREE(list, sop) + { + if (sop->name) free(sop->name); + free(sop); + } return NULL; } -static Ecore_X_Randr_Output * +void +_e_randr_free_serialized_output_policy(E_Randr_Serialized_Output_Policy *sop) +{ + if (!sop) return; + if (sop->name) free(sop->name); + free(sop); +} + + Eina_List +*_e_randr_update_serialized_outputs_policies(E_Randr_Screen_Info_12 *si_12, Eina_List *sops) +{ + E_Randr_Serialized_Output_Policy *sop; + + EINA_LIST_FREE(sops, sop) + { + _e_randr_free_serialized_output_policy(sop); + } + + return _e_randr_create_outputs_policies_list(si_12->outputs); +} + + Eina_List +*_e_randr_create_possible_outputs_names_list(Eina_List *outputs) +{ + Eina_List *iter, *list = NULL; + E_Randr_Output_Info *oi; + char *name; + + if (!outputs) return NULL; + + EINA_LIST_FOREACH(outputs, iter, oi) + { + if (!oi->name || (oi->name_length <= 0)) continue; + if (!(name = malloc(oi->name_length)) + || !strncpy(name, oi->name, oi->name_length) + || !(list = eina_list_append(list, name))) goto _e_randr_create_possible_outputs_names_list_fail_free_list; + } + return list; + +_e_randr_create_possible_outputs_names_list_fail_free_list: + EINA_LIST_FREE(list, name) + { + if(name) free(name); + } + return NULL; +} + + E_Randr_Edid_Hash +*_e_randr_create_edid_hash(E_Randr_Output_Info *output_info) +{ + E_Randr_Edid_Hash *edid_hash; + + if (!output_info || (output_info->edid_hash.hash == 0) || !(edid_hash = malloc(sizeof(E_Randr_Edid_Hash)))) return NULL; + + edid_hash->hash = output_info->edid_hash.hash; + + return edid_hash; +} + + E_Randr_Serialized_Output +*_e_randr_create_serialized_output(E_Randr_Output_Info *output_info) +{ + E_Randr_Serialized_Output *so; + char *name; + + if (!output_info || !output_info->name || (output_info->name_length <= 0) || !(so = malloc(sizeof(E_Randr_Serialized_Output)))) return NULL; + + if (!(name = malloc(output_info->name_length)) + || !strncpy(so->name, output_info->name, output_info->name_length)) + goto _e_randr_create_serialized_outputs_fail_free_so; + so->name_length = output_info->name_length; + so->edid_hash.hash = output_info->edid_hash.hash; + so->backlight_level = output_info->backlight_level; + + return so; + +_e_randr_create_serialized_outputs_fail_free_so: + free(so); + return NULL; +} + + void +_e_randr_free_serialized_output(E_Randr_Serialized_Output *so) +{ + if (so->name) free(so->name); + free(so); +} + + E_Randr_Serialized_Crtc +*_e_randr_create_serialized_crtc(E_Randr_Crtc_Info *crtc_info) +{ + E_Randr_Serialized_Crtc *sc; + E_Randr_Serialized_Output *so; + E_Randr_Output_Info *output_info; + Eina_List *iter; + char *output_name; + size_t len; + + if (!(sc = E_NEW(E_Randr_Serialized_Crtc, 1))) return NULL; + if(!_e_randr_copy_mode_info(&sc->mode_info, crtc_info->current_mode)) goto _e_randr_create_serialized_crtc_free_sc; + if(!(sc->possible_outputs_names = _e_randr_create_possible_outputs_names_list(crtc_info->possible_outputs))) goto _e_randr_create_serialized_crtc_free_mode_sc; + //Create list of serialized outputs + EINA_LIST_FOREACH(crtc_info->outputs, iter, output_info) + { + if(!(so = _e_randr_create_serialized_output(output_info)) + || !(sc->serialized_outputs = eina_list_append(sc->serialized_outputs, so))) goto _e_randr_create_serialized_crtc_free_outputs_list_sc; + } + sc->pos.x = crtc_info->geometry.x; + sc->pos.y = crtc_info->geometry.y; + sc->orientation = crtc_info->current_orientation; + + return sc; + +_e_randr_create_serialized_crtc_free_outputs_list_sc: + EINA_LIST_FREE(sc->possible_outputs_names, output_name) + { + if (output_name) free(output_name); + } + EINA_LIST_FREE(sc->serialized_outputs, so) + { + if (so) _e_randr_free_serialized_output(so); + } +_e_randr_create_serialized_crtc_free_mode_sc: + _e_randr_free_serialized_mode_info(&sc->mode_info); +_e_randr_create_serialized_crtc_free_sc: + E_FREE(sc); + + return NULL; +} + + void +_e_randr_free_serialized_crtc(E_Randr_Serialized_Crtc *sc) +{ + E_Randr_Serialized_Output *so; + char *name; + + EINA_LIST_FREE(sc->serialized_outputs, so) + _e_randr_free_serialized_output(so); + _e_randr_free_serialized_mode_info(&sc->mode_info); + EINA_LIST_FREE(sc->possible_outputs_names, name) + free(name); + free(sc); +} + + E_Randr_Serialized_Setup_11 +*_e_randr_create_serialized_setup_11(E_Randr_Screen_Info_11 *screen_info_11) +{ + E_Randr_Serialized_Setup_11 *ss; + Ecore_X_Randr_Screen_Size_MM* size; + + if (!(ss = malloc(sizeof(*ss)))) return NULL; + if(!(size = (Ecore_X_Randr_Screen_Size_MM*)eina_list_data_get(eina_list_nth(screen_info_11->sizes, screen_info_11->csize_index)))) goto _e_randr_create_serialized_setup_11_failed_free_ss; + ss->size.width = size->width; + ss->size.height = size->height; + ss->refresh_rate = screen_info_11->current_rate; + ss->orientation = screen_info_11->corientation; + + return ss; + +_e_randr_create_serialized_setup_11_failed_free_ss: + free(ss); +} + + E_Randr_Serialized_Setup_11 +*_e_randr_update_serialized_setup_11(E_Randr_Serialized_Setup_11 *ss_11, E_Randr_Screen_Info_11 *si_11) +{ + Ecore_X_Randr_Screen_Size_MM* size; + + if (ss_11) + { + if(!(size = (Ecore_X_Randr_Screen_Size_MM*)eina_list_data_get(eina_list_nth(si_11->sizes, si_11->csize_index)))) return NULL; + if (!memcpy(&ss_11->size, size, sizeof(Ecore_X_Randr_Screen_Size_MM))) + goto _e_randr_update_serialized_setup_11_failed_free_ss; + ss_11->refresh_rate = si_11->current_rate; + ss_11->orientation = si_11->corientation; + } + else + ss_11 = _e_randr_create_serialized_setup_11(si_11); + + return ss_11; + +_e_randr_update_serialized_setup_11_failed_free_ss: + free(ss_11); + return NULL; +} + + E_Randr_Serialized_Setup_12 +*_e_randr_create_serialized_setup_12(E_Randr_Screen_Info_12 *screen_info_12) +{ + E_Randr_Serialized_Setup_12 *ss; + Eina_List *iter; + E_Randr_Crtc_Info *ci; + E_Randr_Output_Info *oi; + E_Randr_Serialized_Crtc *sc; + E_Randr_Edid_Hash *edid_hash; + + if (!(ss = E_NEW(E_Randr_Serialized_Setup_12, 1))) return NULL; + + ss->timestamp = ecore_time_get(); + + //Add CRTCs and their configuration + EINA_LIST_FOREACH(screen_info_12->crtcs, iter, ci) + { + //ignore disabled crtcs for now + if (!ci->current_mode) continue; + + if (!(sc = _e_randr_create_serialized_crtc(ci)) + || !(ss->serialized_crtcs = eina_list_append(ss->serialized_crtcs, sc))) + goto _e_randr_create_serialized_setup_12_failed_free_list_ss; + } + + /* + * Add EDID hashes of connected and enabled + * outputs for easier comparison during + * setup restoration + */ + EINA_LIST_FOREACH(screen_info_12->outputs, iter, oi) + { + if ((oi->connection_status != ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) || !oi->crtc || !oi->crtc->current_mode) + continue; + if (!(edid_hash = _e_randr_create_edid_hash(oi)) || !(ss->serialized_edid_hashes = eina_list_append(ss->serialized_edid_hashes, edid_hash))) + goto _e_randr_create_serialized_setup_12_failed_free_output_list_crtc_list_ss; + } + + return ss; + +_e_randr_create_serialized_setup_12_failed_free_output_list_crtc_list_ss: + EINA_LIST_FREE(ss->serialized_edid_hashes, edid_hash) + { + if (edid_hash) free(edid_hash); + } +_e_randr_create_serialized_setup_12_failed_free_list_ss: + EINA_LIST_FREE(ss->serialized_crtcs, sc) + { + _e_randr_free_serialized_crtc(sc); + } +_e_randr_create_serialized_setup_12_failed_free_ss: + free(ss); +} + +E_Randr_Serialized_Setup_12 +*_e_randr_find_matching_serialized_setup(Eina_List *setups_12, E_Randr_Screen_Info_12 *si_12) +{ + E_Randr_Serialized_Setup_12 *ss_12; + Eina_List *setups_iter, *r_iter, *s_iter; + Eina_Bool found = EINA_FALSE; + E_Randr_Edid_Hash *edid_hash; + E_Randr_Output_Info *oi; + + if (!setups_12 || !si_12) return NULL; + + EINA_LIST_FOREACH(setups_12, setups_iter, ss_12) + { + EINA_LIST_FOREACH(si_12->outputs, r_iter, oi) + { + //skip disconnected/-abled monitors + if ((oi->connection_status != ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) || !oi->crtc || !oi->crtc->current_mode) + continue; + found = EINA_FALSE; + EINA_LIST_FOREACH(ss_12->serialized_edid_hashes, s_iter, edid_hash) + { + if (oi->edid_hash.hash == edid_hash->hash) + { + found = EINA_TRUE; + break; + } + } + if (!found) + break; + } + if (found) + break; + } + if (found) + return ss_12; + + return NULL; +} + + void +_e_randr_free_serialized_setup_12(E_Randr_Serialized_Setup_12 *ss_12) +{ + E_Randr_Serialized_Crtc *sc; + E_Randr_Edid_Hash *edid_hash; + + if (!ss_12) return; + + EINA_LIST_FREE(ss_12->serialized_crtcs, sc) + { + if (!sc) continue; + _e_randr_free_serialized_crtc(sc); + } + EINA_LIST_FREE(ss_12->serialized_edid_hashes, edid_hash) + if (edid_hash) free(edid_hash); + + free(ss_12); +} + + Eina_List +*_e_randr_update_serialized_setup_12(Eina_List *setups_12, E_Randr_Screen_Info_12 *si_12) +{ + E_Randr_Serialized_Setup_12 *ss_12; + E_Randr_Serialized_Output *so; + E_Randr_Output_Info *oi; + E_Randr_Edid_Hash *edid_hash; + + if (setups_12) + { + /* + * try to find the setup with the same monitors + * connected in order to replace it + */ + if((ss_12 = _e_randr_find_matching_serialized_setup(setups_12, si_12))) + _e_randr_free_serialized_setup_12(ss_12); + } + ss_12 = _e_randr_create_serialized_setup_12(si_12); + setups_12 = eina_list_append(setups_12, ss_12); + + return setups_12; +} + + E_Randr_Serialized_Setup +*_e_randr_create_serialized_setup(E_Randr_Screen_Info *screen_info) +{ + E_Randr_Serialized_Setup *ss; + E_Randr_Serialized_Setup_12 *ss_12; + + if (!(ss = E_NEW(E_Randr_Serialized_Setup, 1))) return NULL; + if ((screen_info->randr_version == ECORE_X_RANDR_1_1) && !(ss->serialized_setup_11 = _e_randr_create_serialized_setup_11(screen_info->rrvd_info.randr_info_11))) goto _e_randr_create_serialized_setup_failed_free_ss; + if ((screen_info->randr_version >= ECORE_X_RANDR_1_2)) + { + if (!(ss_12 = _e_randr_create_serialized_setup_12(screen_info->rrvd_info.randr_info_12)) + || !(ss->serialized_setups_12 = eina_list_append(ss->serialized_setups_12, ss_12))) + goto _e_randr_create_serialized_setup_failed_free_ss; + } + + return ss; + +_e_randr_create_serialized_setup_failed_free_ss: + free(ss); +} + + EAPI void +e_randr_store_configuration(E_Randr_Screen_Info *screen_info) +{ + if (E_RANDR_NO_11) return; + + if (!e_config->randr_serialized_setup) + { + e_config->randr_serialized_setup = _e_randr_create_serialized_setup(screen_info); + e_config_save_queue(); + return; + } + + if (screen_info->randr_version == ECORE_X_RANDR_1_1) + { + e_config->randr_serialized_setup->serialized_setup_11 = _e_randr_update_serialized_setup_11(e_config->randr_serialized_setup->serialized_setup_11, screen_info->rrvd_info.randr_info_11); + } + else if (screen_info->randr_version >= ECORE_X_RANDR_1_2) + { + e_config->randr_serialized_setup->serialized_setups_12 = _e_randr_update_serialized_setup_12(e_config->randr_serialized_setup->serialized_setups_12, screen_info->rrvd_info.randr_info_12); + + //Also, update output policies + e_config->randr_serialized_setup->serialized_outputs_policies = _e_randr_update_serialized_outputs_policies(screen_info->rrvd_info.randr_info_12, e_config->randr_serialized_setup->serialized_outputs_policies); + } + e_config_save_queue(); +} + +//setup restore functions + EAPI Eina_Bool +e_randr_try_restore_configuration(E_Randr_Screen_Info *si) +{ + if (!e_config || !e_config->randr_serialized_setup) return EINA_FALSE; + + if (si->randr_version == ECORE_X_RANDR_1_1) + return _e_randr_try_restore_11(si->rrvd_info.randr_info_11); + else if (si->randr_version >= ECORE_X_RANDR_1_2) + return _e_randr_try_restore_12(si->rrvd_info.randr_info_12); + + return EINA_FALSE; +} + + Eina_Bool +_e_randr_try_restore_11(E_Randr_Screen_Info_11 *si_11) +{ + E_Manager *man; + Eina_List *iter; + Ecore_X_Randr_Screen_Size_MM *stored_size, *size; + int i = 0; + + if (!e_config->randr_serialized_setup->serialized_setup_11) return EINA_FALSE; + stored_size = &e_config->randr_serialized_setup->serialized_setup_11->size; + EINA_LIST_FOREACH(si_11->sizes, iter, size) + { + if ((stored_size->width == size->width) + && (stored_size->height == size->height) + && (stored_size->width_mm == size->width_mm) + && (stored_size->height_mm == size->height_mm)) + { + man = e_manager_current_get(); + return ecore_x_randr_screen_primary_output_size_set(man->root, i); + } + i++; + } + + return EINA_FALSE; +} + + E_Randr_Crtc_Info +*_e_randr_find_matching_crtc(Eina_List *crtcs, E_Randr_Serialized_Crtc *sc) +{ + Eina_List *iter, *s_name_iter, *p_output_iter; + E_Randr_Crtc_Info *ci; + E_Randr_Output_Info *oi; + char *s_output_name; + Eina_Bool name_found; + + EINA_LIST_FOREACH(crtcs, iter, ci) + { + if (eina_list_count(ci->possible_outputs) != eina_list_count(sc->possible_outputs_names)) + continue; + EINA_LIST_FOREACH(sc->possible_outputs_names, s_name_iter, s_output_name) + { + name_found = EINA_FALSE; + EINA_LIST_FOREACH(ci->possible_outputs, p_output_iter, oi) + { + if (!strncmp(s_output_name, oi->name, oi->name_length)) + { + name_found = EINA_TRUE; + break; + } + } + if (!name_found) + break; + } + if (name_found) + break; + } + if (name_found) + return ci; + else + return NULL; +} + + Eina_List +*_e_randr_find_matching_outputs(Eina_List *sois, Eina_List *ois) +{ + Eina_List *r_output_iter, *s_output_iter, *list = NULL; + E_Randr_Output_Info *oi; + E_Randr_Serialized_Output *so; + + EINA_LIST_FOREACH(sois, s_output_iter, so) + { + EINA_LIST_FOREACH(ois, r_output_iter, oi) + { + if (so->edid_hash.hash == oi->edid_hash.hash) + { + list = eina_list_append(list, oi); + break; + } + } + } + if (list && (eina_list_count(sois) != eina_list_count(list))) + { + eina_list_free(list); + list = NULL; + } + + return list; +} + + Ecore_X_Randr_Mode_Info +*_e_randr_find_matching_mode_info(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode) +{ + Eina_List *iter; + Ecore_X_Randr_Mode_Info *mi = NULL; + + EINA_LIST_FOREACH(modes, iter, mi) + { + if ((mode->width == mi->width) + && (mode->height == mi->height) + && (mode->dotClock == mi->dotClock) + && (mode->hSyncStart == mi->hSyncStart) + && (mode->hSyncEnd == mi->hSyncEnd) + && (mode->hTotal == mi->hTotal) + && (mode->hSkew == mi->hSkew) + && (mode->vSyncStart == mi->vSyncStart) + && (mode->vSyncEnd == mi->vSyncEnd) + && (mode->vTotal == mi->vTotal) + && (mode->nameLength == mi->nameLength) + && !strncpy(mode->name, mi->name, mode->nameLength) + && (mode->modeFlags == mi->modeFlags)) + return mi; + } + return NULL; +} + + Eina_Bool +_e_randr_try_restore_12(E_Randr_Screen_Info_12 *si_12) +{ + E_Randr_Serialized_Setup_12 *ss_12; + E_Randr_Serialized_Crtc *sc; + E_Randr_Crtc_Info *ci; + Ecore_X_Randr_Output *outputs_array; + Ecore_X_Randr_Mode_Info *mi; + Eina_List *iter, *outputs_list; + Eina_Bool ret = EINA_TRUE; + E_Manager *man; + + if(!(ss_12 = _e_randr_find_matching_serialized_setup(e_config->randr_serialized_setup->serialized_setups_12, si_12))) return EINA_FALSE; + + man = e_manager_current_get(); + + EINA_LIST_FOREACH(ss_12->serialized_crtcs, iter, sc) + { + ci = _e_randr_find_matching_crtc(si_12->crtcs, sc); + outputs_list = _e_randr_find_matching_outputs(si_12->outputs, sc->serialized_outputs); + outputs_array = _e_randr_outputs_to_array(outputs_list); + mi = _e_randr_find_matching_mode_info(si_12->modes, &sc->mode_info); + ret &= ecore_x_randr_crtc_mode_set(man->root, ci->xid, outputs_array, eina_list_count(outputs_list), mi->xid); + ret &= ecore_x_randr_crtc_pos_set(man->root, ci->xid, sc->pos.x, sc->pos.y); + } + return ret; +} + +//Utility functions + static Ecore_X_Randr_Output * _e_randr_outputs_to_array(Eina_List *outputs_info) { Ecore_X_Randr_Output *ret = NULL; @@ -1148,7 +1617,7 @@ _e_randr_outputs_to_array(Eina_List *outputs_info) if (!outputs_info || !(ret = malloc(sizeof(Ecore_X_Randr_Output) * eina_list_count(outputs_info)))) return NULL; EINA_LIST_FOREACH(outputs_info, output_iter, output_info) - /* output_info == NULL should _not_ be possible! */ + /* output_info == NULL should _not_ be possible! */ ret[i++] = output_info ? output_info->xid : Ecore_X_Randr_None; return ret; } @@ -1191,7 +1660,7 @@ _e_randr_try_enable_output(E_Randr_Output_Info *output_info, Eina_Bool force) if (!usable_crtc) return EINA_FALSE; //get the CRTC we will refer to, dependend on policy - switch (e_randr_screen_info->rrvd_info.randr_info_12->output_policy) + switch (output_info->policy) { case ECORE_X_RANDR_OUTPUT_POLICY_NONE: return EINA_TRUE; @@ -1386,15 +1855,19 @@ static Eina_Bool _e_randr_crtc_move_policy(E_Randr_Crtc_Info *new_crtc) { const E_Randr_Crtc_Info *crtc_rel; + E_Randr_Output_Info *last_output = NULL; int dx = Ecore_X_Randr_None, dy = Ecore_X_Randr_None; Eina_Bool ret = EINA_TRUE; + //use the policy of the new crtc's last output + last_output = (E_Randr_Output_Info*)eina_list_data_get(eina_list_last(new_crtc->outputs)); + if (!last_output) return EINA_FALSE; //get the crtc we will place our's relative to. If it's NULL, this is the //only output attached, work done. - if(!(crtc_rel = _e_randr_policy_crtc_get(new_crtc, NULL, e_randr_screen_info->rrvd_info.randr_info_12->output_policy))) return EINA_TRUE; + if(!(crtc_rel = _e_randr_policy_crtc_get(new_crtc, NULL, last_output->policy))) return EINA_TRUE; //following is policy dependend. - switch (e_randr_screen_info->rrvd_info.randr_info_12->output_policy) + switch (last_output->policy) { case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE: dy = (crtc_rel->geometry.y - new_crtc->geometry.h); @@ -1425,7 +1898,7 @@ _e_randr_crtc_move_policy(E_Randr_Crtc_Info *new_crtc) default: break; } - ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info->root, new_crtc->xid, crtc_rel->xid, e_randr_screen_info->rrvd_info.randr_info_12->output_policy, e_randr_screen_info->rrvd_info.randr_info_12->alignment); + ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info->root, new_crtc->xid, crtc_rel->xid, last_output->policy, e_randr_screen_info->rrvd_info.randr_info_12->alignment); return ret; } @@ -1686,6 +2159,8 @@ _e_randr_output_info_hw_info_set(E_Randr_Output_Info *output_info) _e_randr_output_modes_add(output_info); output_info->edid = ecore_x_randr_output_edid_get(e_randr_screen_info->root, output_info->xid, &output_info->edid_length); + if (output_info->edid_length > 0) + output_info->edid_hash.hash = eina_hash_superfast(output_info->edid, output_info->edid_length); //get the outputs we can use on the same CRTC alongside this one. if ((outputs = ecore_x_randr_output_clones_get(e_randr_screen_info->root, output_info->xid, &num))) { @@ -1711,6 +2186,10 @@ _e_randr_output_info_hw_info_set(E_Randr_Output_Info *output_info) } free(crtcs); } + else + { + fprintf(stderr, "E_RANDR: Output %x does not have a single possible CRTC.\n", output_info->xid); + } } /* diff --git a/src/bin/e_randr.h b/src/bin/e_randr.h index 448fc8901..7f04d0283 100644 --- a/src/bin/e_randr.h +++ b/src/bin/e_randr.h @@ -1,24 +1,26 @@ #ifdef E_TYPEDEFS typedef struct _E_Randr_Crtc_Info E_Randr_Crtc_Info; +typedef struct _E_Randr_Edid_Hash E_Randr_Edid_Hash; typedef struct _E_Randr_Output_Info E_Randr_Output_Info; typedef struct _E_Randr_Screen_Info_11 E_Randr_Screen_Info_11; typedef struct _E_Randr_Screen_Info_12 E_Randr_Screen_Info_12; typedef union _E_Randr_Screen_RRVD_Info E_Randr_Screen_RRVD_Info; typedef struct _E_Randr_Screen_Info E_Randr_Screen_Info; -typedef struct _E_Randr_Output_Edid_Hash E_Randr_Output_Edid_Hash; -typedef struct _E_Randr_Output_Restore_Info E_Randr_Output_Restore_Info; -typedef struct _E_Randr_Crtc_Restore_Info E_Randr_Crtc_Restore_Info; -typedef struct _E_Randr_Screen_Restore_Info_11 E_Randr_Screen_Restore_Info_11; -typedef struct _E_Randr_Screen_Restore_Info_12 E_Randr_Screen_Restore_Info_12; -typedef union _E_Randr_Screen_Restore_Info_Union E_Randr_Screen_Restore_Info_Union; -typedef struct _E_Randr_Screen_Restore_Info E_Randr_Screen_Restore_Info; +typedef struct _E_Randr_Serialized_Output_Policy E_Randr_Serialized_Output_Policy; +typedef struct _E_Randr_Serialized_Output E_Randr_Serialized_Output; +typedef struct _E_Randr_Serialized_Crtc E_Randr_Serialized_Crtc; +typedef struct _E_Randr_Serialized_Setup_11 E_Randr_Serialized_Setup_11; +typedef struct _E_Randr_Serialized_Setup_12 E_Randr_Serialized_Setup_12; +typedef struct _E_Randr_Serialized_Setup E_Randr_Serialized_Setup; + +EAPI void e_randr_store_configuration(E_Randr_Screen_Info *screen_info); #else #ifndef E_RANDR_H #define E_RANDR_H -struct _E_Randr_Crtc_Info +struct _E_Randr_Crtc_Info { Ecore_X_ID xid; Eina_Rectangle geometry; @@ -35,7 +37,12 @@ struct _E_Randr_Crtc_Info Ecore_X_Randr_Mode_Info *current_mode; }; -struct _E_Randr_Output_Info +struct _E_Randr_Edid_Hash +{ + int hash; +}; + +struct _E_Randr_Output_Info { Ecore_X_ID xid; char *name; @@ -47,6 +54,7 @@ struct _E_Randr_Output_Info int connector_number; Ecore_X_Randr_Connector_Type connector_type; Ecore_X_Randr_Connection_Status connection_status; + Ecore_X_Randr_Output_Policy policy; /* * Attached Monitor specific: */ @@ -57,6 +65,7 @@ struct _E_Randr_Output_Info Ecore_X_Randr_Screen_Size size_mm; unsigned char *edid; unsigned long edid_length; + E_Randr_Edid_Hash edid_hash; int max_backlight; double backlight_level; Ecore_X_Render_Subpixel_Order subpixel_order; @@ -75,7 +84,7 @@ struct _E_Randr_Screen_Info_11 Ecore_X_Randr_Refresh_Rate current_rate; }; -struct _E_Randr_Screen_Info_12 +struct _E_Randr_Screen_Info_12 { Ecore_X_Randr_Screen_Size min_size; Ecore_X_Randr_Screen_Size max_size; @@ -84,18 +93,17 @@ struct _E_Randr_Screen_Info_12 Eina_List *crtcs; Eina_List *outputs; E_Randr_Output_Info *primary_output; - Ecore_X_Randr_Output_Policy output_policy; Ecore_X_Randr_Relative_Alignment alignment; }; //RRVD == RandR(R) Version Depended -union _E_Randr_Screen_RRVD_Info +union _E_Randr_Screen_RRVD_Info { E_Randr_Screen_Info_11 *randr_info_11; E_Randr_Screen_Info_12 *randr_info_12; }; -struct _E_Randr_Screen_Info +struct _E_Randr_Screen_Info { Ecore_X_Window root; int randr_version; @@ -103,56 +111,67 @@ struct _E_Randr_Screen_Info }; //Following stuff is just for configuration purposes -struct _E_Randr_Output_Edid_Hash { - int hash; + +struct _E_Randr_Serialized_Output_Policy +{ + char *name; + int name_length; + Ecore_X_Randr_Output_Policy policy; }; -struct _E_Randr_Output_Restore_Info +struct _E_Randr_Serialized_Output { - E_Randr_Output_Edid_Hash edid_hash; + char *name; + int name_length; + E_Randr_Edid_Hash edid_hash; double backlight_level; }; -struct _E_Randr_Crtc_Restore_Info +struct _E_Randr_Serialized_Crtc { - Eina_Rectangle geometry; + //List of E_Randr_Serialized_Output objects that were used on the same output + Eina_List *serialized_outputs; + //the serialized mode_info misses its xid value + Ecore_X_Randr_Mode_Info mode_info; + Evas_Coord_Point pos; + //List of all possible outputs' names + //e.g. "LVDS", "CRT-0", "VGA" + Eina_List *possible_outputs_names; Ecore_X_Randr_Orientation orientation; - //list of the outputs; - Eina_List *outputs; }; -struct _E_Randr_Screen_Restore_Info_11 +struct _E_Randr_Serialized_Setup_12 { - Ecore_X_Randr_Screen_Size size; + double timestamp; + //List of E_Randr_Serialized_Crtc objects + Eina_List *serialized_crtcs; + /* + * List of E_Randr_Edid_Hash elements of monitors, + * that were enabled, when the setup was stored + */ + Eina_List *serialized_edid_hashes; +}; + +struct _E_Randr_Serialized_Setup_11 +{ + Ecore_X_Randr_Screen_Size_MM size; Ecore_X_Randr_Refresh_Rate refresh_rate; Ecore_X_Randr_Orientation orientation; }; -struct _E_Randr_Screen_Restore_Info_12 +struct _E_Randr_Serialized_Setup { - Eina_List *outputs_edid_hashes; - int noutputs; - Eina_List *crtcs; - Ecore_X_Randr_Output_Policy output_policy; - Ecore_X_Randr_Relative_Alignment alignment; -}; - -union _E_Randr_Screen_Restore_Info_Union -{ - E_Randr_Screen_Restore_Info_11 *restore_info_11; - Eina_List *restore_info_12; -}; - -struct _E_Randr_Screen_Restore_Info -{ - int randr_version; - E_Randr_Screen_Restore_Info_Union rrvd_restore_info; + E_Randr_Serialized_Setup_11 *serialized_setup_11; + //List of E_Randr_Serialized_Setup_12 objects + Eina_List *serialized_setups_12; + //List of E_Randr_Serialized_Output_Policy objects + Eina_List *serialized_outputs_policies; }; EINTERN Eina_Bool e_randr_init(void); EINTERN int e_randr_shutdown(void); -extern E_Randr_Screen_Info *e_randr_screen_info; +EAPI extern E_Randr_Screen_Info *e_randr_screen_info; #endif #endif