forked from enlightenment/enlightenment
parent
55b8337d6e
commit
b27aec4ad5
|
@ -276,6 +276,13 @@ e_popup.c \
|
||||||
e_powersave.c \
|
e_powersave.c \
|
||||||
e_prefix.c \
|
e_prefix.c \
|
||||||
e_randr.c \
|
e_randr.c \
|
||||||
|
e_randr_serialization.c \
|
||||||
|
e_randr_11.c \
|
||||||
|
e_randr_11_serialization.c \
|
||||||
|
e_randr_12.c \
|
||||||
|
e_randr_12_output.c \
|
||||||
|
e_randr_12_crtc.c \
|
||||||
|
e_randr_12_serialization.c \
|
||||||
e_remember.c \
|
e_remember.c \
|
||||||
e_resist.c \
|
e_resist.c \
|
||||||
e_scale.c \
|
e_scale.c \
|
||||||
|
|
|
@ -57,7 +57,7 @@ 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_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_policy_edd = NULL;
|
||||||
static E_Config_DD *_e_config_randr_serialized_output_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_mode_info_edd = NULL;
|
||||||
static E_Config_DD *_e_config_randr_serialized_crtc_edd = NULL;
|
static E_Config_DD *_e_config_randr_serialized_crtc_edd = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
@ -555,7 +555,6 @@ e_config_init(void)
|
||||||
#define T E_Randr_Serialized_Output_Policy
|
#define T E_Randr_Serialized_Output_Policy
|
||||||
#define D _e_config_randr_serialized_output_policy_edd
|
#define D _e_config_randr_serialized_output_policy_edd
|
||||||
E_CONFIG_VAL(D, T, name, STR);
|
E_CONFIG_VAL(D, T, name, STR);
|
||||||
E_CONFIG_VAL(D, T, name_length, INT);
|
|
||||||
E_CONFIG_VAL(D, T, policy, INT);
|
E_CONFIG_VAL(D, T, policy, INT);
|
||||||
|
|
||||||
_e_config_randr_serialized_output_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Output", E_Randr_Serialized_Output);
|
_e_config_randr_serialized_output_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Output", E_Randr_Serialized_Output);
|
||||||
|
@ -564,15 +563,14 @@ e_config_init(void)
|
||||||
#define T E_Randr_Serialized_Output
|
#define T E_Randr_Serialized_Output
|
||||||
#define D _e_config_randr_serialized_output_edd
|
#define D _e_config_randr_serialized_output_edd
|
||||||
E_CONFIG_VAL(D, T, name, STR);
|
E_CONFIG_VAL(D, T, name, STR);
|
||||||
E_CONFIG_VAL(D, T, name_length, INT);
|
|
||||||
E_CONFIG_VAL(D, T, edid_hash.hash, INT);
|
|
||||||
E_CONFIG_VAL(D, T, backlight_level, DOUBLE);
|
E_CONFIG_VAL(D, T, backlight_level, DOUBLE);
|
||||||
|
|
||||||
_e_config_randr_serialized_mode_info_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Mode_Info", Ecore_X_Randr_Mode_Info);
|
_e_config_randr_mode_info_edd = E_CONFIG_DD_NEW("Ecore_X_Randr_Mode_Info", Ecore_X_Randr_Mode_Info);
|
||||||
#undef T
|
#undef T
|
||||||
#undef D
|
#undef D
|
||||||
#define T Ecore_X_Randr_Mode_Info
|
#define T Ecore_X_Randr_Mode_Info
|
||||||
#define D _e_config_randr_serialized_mode_info_edd
|
#define D _e_config_randr_mode_info_edd
|
||||||
|
E_CONFIG_VAL(D, T, xid, INT);
|
||||||
E_CONFIG_VAL(D, T, width, INT);
|
E_CONFIG_VAL(D, T, width, INT);
|
||||||
E_CONFIG_VAL(D, T, height, INT);
|
E_CONFIG_VAL(D, T, height, INT);
|
||||||
E_CONFIG_VAL(D, T, dotClock, LL);
|
E_CONFIG_VAL(D, T, dotClock, LL);
|
||||||
|
@ -592,11 +590,10 @@ e_config_init(void)
|
||||||
#undef D
|
#undef D
|
||||||
#define T E_Randr_Serialized_Crtc
|
#define T E_Randr_Serialized_Crtc
|
||||||
#define D _e_config_randr_serialized_crtc_edd
|
#define D _e_config_randr_serialized_crtc_edd
|
||||||
E_CONFIG_LIST(D, T, serialized_outputs, _e_config_randr_serialized_output_edd);
|
E_CONFIG_LIST(D, T, outputs, _e_config_randr_serialized_output_edd);
|
||||||
E_CONFIG_SUB(D, T, mode_info, _e_config_randr_serialized_mode_info_edd);
|
E_CONFIG_SUB(D, T, mode_info, _e_config_randr_mode_info_edd);
|
||||||
E_CONFIG_VAL(D, T, pos.x, INT);
|
E_CONFIG_VAL(D, T, pos.x, INT);
|
||||||
E_CONFIG_VAL(D, T, pos.y, 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_VAL(D, T, orientation, INT);
|
||||||
|
|
||||||
_e_config_randr_serialized_setup_12_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Setup_12", E_Randr_Serialized_Setup_12);
|
_e_config_randr_serialized_setup_12_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Setup_12", E_Randr_Serialized_Setup_12);
|
||||||
|
@ -605,8 +602,8 @@ e_config_init(void)
|
||||||
#define T E_Randr_Serialized_Setup_12
|
#define T E_Randr_Serialized_Setup_12
|
||||||
#define D _e_config_randr_serialized_setup_12_edd
|
#define D _e_config_randr_serialized_setup_12_edd
|
||||||
E_CONFIG_VAL(D, T, timestamp, DOUBLE);
|
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, crtcs, _e_config_randr_serialized_crtc_edd);
|
||||||
E_CONFIG_LIST(D, T, serialized_edid_hashes, _e_config_randr_edid_hash_edd);
|
E_CONFIG_LIST(D, T, 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);
|
_e_config_randr_serialized_setup_edd = E_CONFIG_DD_NEW("E_Randr_Serialized_Setup", E_Randr_Serialized_Setup);
|
||||||
#undef T
|
#undef T
|
||||||
|
@ -615,7 +612,7 @@ e_config_init(void)
|
||||||
#define D _e_config_randr_serialized_setup_edd
|
#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_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_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_LIST(D, T, outputs_policies, _e_config_randr_serialized_output_policy_edd);
|
||||||
|
|
||||||
_e_config_edd = E_CONFIG_DD_NEW("E_Config", E_Config);
|
_e_config_edd = E_CONFIG_DD_NEW("E_Config", E_Config);
|
||||||
#undef T
|
#undef T
|
||||||
|
@ -936,7 +933,7 @@ e_config_shutdown(void)
|
||||||
E_CONFIG_DD_FREE(_e_config_mime_icon_edd);
|
E_CONFIG_DD_FREE(_e_config_mime_icon_edd);
|
||||||
E_CONFIG_DD_FREE(_e_config_syscon_action_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_env_var_edd);
|
||||||
E_CONFIG_DD_FREE(_e_config_randr_serialized_setup_edd);
|
//E_CONFIG_DD_FREE(_e_config_randr_serialized_setup_edd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1881,15 +1878,8 @@ _e_config_free(E_Config *ecf)
|
||||||
E_Color_Class *cc;
|
E_Color_Class *cc;
|
||||||
E_Path_Dir *epd;
|
E_Path_Dir *epd;
|
||||||
E_Remember *rem;
|
E_Remember *rem;
|
||||||
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;
|
E_Config_Env_Var *evr;
|
||||||
|
|
||||||
|
|
||||||
if (!ecf) return;
|
if (!ecf) return;
|
||||||
|
|
||||||
EINA_LIST_FREE(ecf->modules, em)
|
EINA_LIST_FREE(ecf->modules, em)
|
||||||
|
@ -2039,44 +2029,8 @@ _e_config_free(E_Config *ecf)
|
||||||
}
|
}
|
||||||
if(ecf->randr_serialized_setup)
|
if(ecf->randr_serialized_setup)
|
||||||
{
|
{
|
||||||
free (ecf->randr_serialized_setup->serialized_setup_11);
|
e_randr_serialized_setup_free(ecf->randr_serialized_setup);
|
||||||
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) continue;
|
|
||||||
free(serialized_output->name);
|
|
||||||
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_policy) continue;
|
|
||||||
free(serialized_output_policy->name);
|
|
||||||
free(serialized_output_policy);
|
|
||||||
}
|
|
||||||
free(ecf->randr_serialized_setup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EINA_LIST_FREE(ecf->env_vars, evr)
|
EINA_LIST_FREE(ecf->env_vars, evr)
|
||||||
{
|
{
|
||||||
if (evr->var) eina_stringshare_del(evr->var);
|
if (evr->var) eina_stringshare_del(evr->var);
|
||||||
|
|
2423
src/bin/e_randr.c
2423
src/bin/e_randr.c
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
typedef struct _E_Randr_Crtc_Info E_Randr_Crtc_Info;
|
typedef struct _E_Randr_Crtc_Info E_Randr_Crtc_Info;
|
||||||
typedef struct _E_Randr_Edid_Hash E_Randr_Edid_Hash;
|
typedef struct _E_Randr_Edid_Hash E_Randr_Edid_Hash;
|
||||||
|
typedef struct _E_Randr_Monitor_Info E_Randr_Monitor_Info;
|
||||||
typedef struct _E_Randr_Output_Info E_Randr_Output_Info;
|
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_11 E_Randr_Screen_Info_11;
|
||||||
typedef struct _E_Randr_Screen_Info_12 E_Randr_Screen_Info_12;
|
typedef struct _E_Randr_Screen_Info_12 E_Randr_Screen_Info_12;
|
||||||
|
@ -27,8 +28,7 @@ typedef enum _E_Randr_Configuration_Store_Modifier
|
||||||
| E_RANDR_CONFIGURATION_STORE_ORIENTATIONS)
|
| E_RANDR_CONFIGURATION_STORE_ORIENTATIONS)
|
||||||
} E_Randr_Configuration_Store_Modifier;
|
} E_Randr_Configuration_Store_Modifier;
|
||||||
|
|
||||||
EAPI void e_randr_store_configuration(E_Randr_Screen_Info *screen_info, E_Randr_Configuration_Store_Modifier modifier);
|
EAPI void e_randr_store_configuration(E_Randr_Configuration_Store_Modifier modifier);
|
||||||
EAPI Eina_Bool e_randr_try_restore_configuration(E_Randr_Screen_Info *screen_info);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifndef E_RANDR_H
|
#ifndef E_RANDR_H
|
||||||
|
@ -56,6 +56,18 @@ struct _E_Randr_Edid_Hash
|
||||||
int hash;
|
int hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _E_Randr_Monitor_Info
|
||||||
|
{
|
||||||
|
Eina_List *modes;
|
||||||
|
Eina_List *preferred_modes;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
struct _E_Randr_Output_Info
|
struct _E_Randr_Output_Info
|
||||||
{
|
{
|
||||||
Ecore_X_ID xid;
|
Ecore_X_ID xid;
|
||||||
|
@ -69,21 +81,13 @@ struct _E_Randr_Output_Info
|
||||||
Ecore_X_Randr_Connector_Type connector_type;
|
Ecore_X_Randr_Connector_Type connector_type;
|
||||||
Ecore_X_Randr_Connection_Status connection_status;
|
Ecore_X_Randr_Connection_Status connection_status;
|
||||||
Ecore_X_Randr_Output_Policy policy;
|
Ecore_X_Randr_Output_Policy policy;
|
||||||
|
Eina_List *possible_crtcs;
|
||||||
|
Eina_List *compatibility_list;
|
||||||
|
Ecore_X_Render_Subpixel_Order subpixel_order;
|
||||||
/*
|
/*
|
||||||
* Attached Monitor specific:
|
* Attached Monitor specific:
|
||||||
*/
|
*/
|
||||||
Eina_List *modes;
|
E_Randr_Monitor_Info *monitor;
|
||||||
Eina_List *preferred_modes;
|
|
||||||
Eina_List *clones;
|
|
||||||
Eina_List *possible_crtcs;
|
|
||||||
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;
|
|
||||||
Eina_List *compatible_outputs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _E_Randr_Screen_Info_11
|
struct _E_Randr_Screen_Info_11
|
||||||
|
@ -129,41 +133,35 @@ struct _E_Randr_Screen_Info
|
||||||
struct _E_Randr_Serialized_Output_Policy
|
struct _E_Randr_Serialized_Output_Policy
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
int name_length;
|
|
||||||
Ecore_X_Randr_Output_Policy policy;
|
Ecore_X_Randr_Output_Policy policy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _E_Randr_Serialized_Output
|
struct _E_Randr_Serialized_Output
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
int name_length;
|
|
||||||
E_Randr_Edid_Hash edid_hash;
|
|
||||||
double backlight_level;
|
double backlight_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _E_Randr_Serialized_Crtc
|
struct _E_Randr_Serialized_Crtc
|
||||||
{
|
{
|
||||||
|
int index;
|
||||||
//List of E_Randr_Serialized_Output objects that were used on the same output
|
//List of E_Randr_Serialized_Output objects that were used on the same output
|
||||||
Eina_List *serialized_outputs;
|
Eina_List *outputs;
|
||||||
//the serialized mode_info misses its xid value
|
|
||||||
Ecore_X_Randr_Mode_Info mode_info;
|
|
||||||
Evas_Coord_Point pos;
|
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;
|
Ecore_X_Randr_Orientation orientation;
|
||||||
|
//the serialized mode_info
|
||||||
|
Ecore_X_Randr_Mode_Info mode_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _E_Randr_Serialized_Setup_12
|
struct _E_Randr_Serialized_Setup_12
|
||||||
{
|
{
|
||||||
double timestamp;
|
double timestamp;
|
||||||
//List of E_Randr_Serialized_Crtc objects
|
//List of E_Randr_Serialized_Crtc objects
|
||||||
Eina_List *serialized_crtcs;
|
Eina_List *crtcs;
|
||||||
/*
|
/*
|
||||||
* List of E_Randr_Edid_Hash elements of monitors,
|
* List of E_Randr_Edid_Hash elements of all connected monitors
|
||||||
* that were enabled, when the setup was stored
|
|
||||||
*/
|
*/
|
||||||
Eina_List *serialized_edid_hashes;
|
Eina_List *edid_hashes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _E_Randr_Serialized_Setup_11
|
struct _E_Randr_Serialized_Setup_11
|
||||||
|
@ -179,14 +177,18 @@ struct _E_Randr_Serialized_Setup
|
||||||
//List of E_Randr_Serialized_Setup_12 objects
|
//List of E_Randr_Serialized_Setup_12 objects
|
||||||
Eina_List *serialized_setups_12;
|
Eina_List *serialized_setups_12;
|
||||||
//List of E_Randr_Serialized_Output_Policy objects
|
//List of E_Randr_Serialized_Output_Policy objects
|
||||||
Eina_List *serialized_outputs_policies;
|
Eina_List *outputs_policies;
|
||||||
};
|
};
|
||||||
|
|
||||||
EINTERN Eina_Bool e_randr_init(void);
|
EINTERN Eina_Bool e_randr_init(void);
|
||||||
EAPI Eina_Bool e_randr_screen_info_refresh(void);
|
EAPI void e_randr_screen_info_refresh(void);
|
||||||
EINTERN int e_randr_shutdown(void);
|
EINTERN int e_randr_shutdown(void);
|
||||||
|
EINTERN void e_randr_serialized_setup_free(E_Randr_Serialized_Setup *ss);
|
||||||
|
EINTERN void e_randr_11_serialized_setup_free(E_Randr_Serialized_Setup_11 *ss_11);
|
||||||
|
EINTERN void e_randr_12_serialized_setup_free(E_Randr_Serialized_Setup_12 *ss_12);
|
||||||
|
EINTERN void e_randr_12_serialized_output_policy_free(E_Randr_Serialized_Output_Policy *policy);
|
||||||
|
|
||||||
EAPI extern E_Randr_Screen_Info *e_randr_screen_info;
|
EAPI extern E_Randr_Screen_Info e_randr_screen_info;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
#include "e_randr.h"
|
||||||
|
|
||||||
|
//New helper functions
|
||||||
|
/**
|
||||||
|
* @brief allocate and initialize a new E_Randr_Screen_Info_11 element
|
||||||
|
* @return E_Randr_Screen_Info_11 elements or in case it could
|
||||||
|
* not be created and properly initialized, NULL
|
||||||
|
*/
|
||||||
|
E_Randr_Screen_Info_11 *
|
||||||
|
_11_screen_info_new(void)
|
||||||
|
{
|
||||||
|
E_Randr_Screen_Info_11 *randr_info_11 = NULL;
|
||||||
|
Ecore_X_Randr_Screen_Size_MM *sizes = NULL;
|
||||||
|
Ecore_X_Randr_Refresh_Rate *rates = NULL;
|
||||||
|
Eina_List *rates_list;
|
||||||
|
int i, j, nsizes, nrates;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_11_NO, NULL);
|
||||||
|
|
||||||
|
randr_info_11 = malloc(sizeof(E_Randr_Screen_Info_11));
|
||||||
|
|
||||||
|
randr_info_11->sizes = NULL;
|
||||||
|
randr_info_11->csize_index = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_11->corientation = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_11->orientations = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_11->rates = NULL;
|
||||||
|
randr_info_11->current_rate = Ecore_X_Randr_Unset;
|
||||||
|
|
||||||
|
if (!(sizes = ecore_x_randr_screen_primary_output_sizes_get(e_randr_screen_info.root, &nsizes)))
|
||||||
|
goto _info_11_new_fail;
|
||||||
|
for (i = 0; i < nsizes; i++)
|
||||||
|
if (!(randr_info_11->sizes = eina_list_append(randr_info_11->sizes, &sizes[i])))
|
||||||
|
goto _info_11_new_fail_sizes;
|
||||||
|
ecore_x_randr_screen_primary_output_current_size_get(e_randr_screen_info.root, NULL, NULL, NULL, NULL, &(randr_info_11->csize_index));
|
||||||
|
randr_info_11->corientation = ecore_x_randr_screen_primary_output_orientation_get(e_randr_screen_info.root);
|
||||||
|
randr_info_11->orientations = ecore_x_randr_screen_primary_output_orientations_get(e_randr_screen_info.root);
|
||||||
|
for (i = 0; i < nsizes; i++)
|
||||||
|
{
|
||||||
|
rates_list = NULL;
|
||||||
|
if (!(rates = ecore_x_randr_screen_primary_output_refresh_rates_get(e_randr_screen_info.root, i, &nrates)))
|
||||||
|
return EINA_FALSE;
|
||||||
|
for (j = 0; j < nrates; j++)
|
||||||
|
if (!(rates_list = eina_list_append(rates_list, &rates[j])))
|
||||||
|
goto _info_11_new_fail_rates_list;
|
||||||
|
if (!(randr_info_11->rates = eina_list_append(randr_info_11->rates, rates_list)))
|
||||||
|
goto _info_11_new_fail_rates;
|
||||||
|
}
|
||||||
|
randr_info_11->current_rate = ecore_x_randr_screen_primary_output_current_refresh_rate_get(e_randr_screen_info.root);
|
||||||
|
|
||||||
|
return randr_info_11;
|
||||||
|
|
||||||
|
_info_11_new_fail_rates_list:
|
||||||
|
eina_list_free(rates_list);
|
||||||
|
_info_11_new_fail_rates:
|
||||||
|
free(rates);
|
||||||
|
_info_11_new_fail_sizes:
|
||||||
|
free(sizes);
|
||||||
|
_info_11_new_fail:
|
||||||
|
free(randr_info_11);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Free helper functions
|
||||||
|
/**
|
||||||
|
* @param screen_info the screen info to be freed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_11_screen_info_free(E_Randr_Screen_Info_11 *screen_info)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(screen_info);
|
||||||
|
|
||||||
|
if (screen_info->sizes)
|
||||||
|
{
|
||||||
|
free(eina_list_nth(screen_info->sizes, 0));
|
||||||
|
eina_list_free(screen_info->sizes);
|
||||||
|
screen_info->sizes = NULL;
|
||||||
|
}
|
||||||
|
if (screen_info->rates)
|
||||||
|
{
|
||||||
|
/* this may be leaking, but at least it will be valid */
|
||||||
|
eina_list_free(eina_list_nth(screen_info->rates, 0));
|
||||||
|
eina_list_free(screen_info->rates);
|
||||||
|
screen_info->rates = NULL;
|
||||||
|
}
|
||||||
|
free(screen_info);
|
||||||
|
screen_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
*
|
||||||
|
* Init. and Shutdown code
|
||||||
|
*
|
||||||
|
*****************************************************************
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_11_screen_info_refresh(void)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_11_NO);
|
||||||
|
|
||||||
|
_11_screen_info_free(e_randr_screen_info.rrvd_info.randr_info_11);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_11 = _11_screen_info_new();
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
#include "e_randr.h"
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Storage/Restorage of setups
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
//New helper functions
|
||||||
|
|
||||||
|
E_Randr_Serialized_Setup_11 *
|
||||||
|
_serialized_setup_11_new(void)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Setup_11 *ss;
|
||||||
|
Ecore_X_Randr_Screen_Size_MM *size;
|
||||||
|
|
||||||
|
ss = malloc(sizeof(*ss));
|
||||||
|
|
||||||
|
if (!(size = (Ecore_X_Randr_Screen_Size_MM *)eina_list_data_get(eina_list_nth(e_randr_screen_info.rrvd_info.randr_info_11->sizes, e_randr_screen_info.rrvd_info.randr_info_11->csize_index)))) goto _serialized_setup_11_new_failed_free_ss;
|
||||||
|
ss->size.width = size->width;
|
||||||
|
ss->size.height = size->height;
|
||||||
|
ss->refresh_rate = e_randr_screen_info.rrvd_info.randr_info_11->current_rate;
|
||||||
|
ss->orientation = e_randr_screen_info.rrvd_info.randr_info_11->corientation;
|
||||||
|
|
||||||
|
return ss;
|
||||||
|
|
||||||
|
_serialized_setup_11_new_failed_free_ss:
|
||||||
|
free(ss);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update/value set helper functions
|
||||||
|
E_Randr_Serialized_Setup_11 *
|
||||||
|
_serialized_setup_11_update(E_Randr_Serialized_Setup_11 *ss_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(e_randr_screen_info.rrvd_info.randr_info_11->sizes, e_randr_screen_info.rrvd_info.randr_info_11->csize_index)))) return NULL;
|
||||||
|
if (!memcpy(&ss_11->size, size, sizeof(Ecore_X_Randr_Screen_Size_MM)))
|
||||||
|
goto _update_serialized_setup_11_failed_free_ss;
|
||||||
|
ss_11->refresh_rate = e_randr_screen_info.rrvd_info.randr_info_11->current_rate;
|
||||||
|
ss_11->orientation = e_randr_screen_info.rrvd_info.randr_info_11->corientation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ss_11 = _serialized_setup_11_new();
|
||||||
|
|
||||||
|
return ss_11;
|
||||||
|
|
||||||
|
_update_serialized_setup_11_failed_free_ss:
|
||||||
|
free(ss_11);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Free helper functions
|
||||||
|
void
|
||||||
|
_e_randr_serialized_setup_11_free(E_Randr_Serialized_Setup_11 *ss11)
|
||||||
|
{
|
||||||
|
free(ss11);
|
||||||
|
}
|
||||||
|
|
||||||
|
EINTERN void
|
||||||
|
e_randr_11_serialized_setup_free(E_Randr_Serialized_Setup_11 *ss_11)
|
||||||
|
{
|
||||||
|
_e_randr_serialized_setup_11_free(ss_11);
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
_11_try_restore_configuration(void)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Screen_Size_MM *stored_size, *size;
|
||||||
|
Eina_List *iter;
|
||||||
|
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(e_randr_screen_info.rrvd_info.randr_info_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))
|
||||||
|
{
|
||||||
|
return ecore_x_randr_screen_primary_output_size_set(e_randr_screen_info.root, i);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_11_store_configuration(E_Randr_Configuration_Store_Modifier modifier)
|
||||||
|
{
|
||||||
|
if (e_config->randr_serialized_setup->serialized_setup_11)
|
||||||
|
e_config->randr_serialized_setup->serialized_setup_11 = _serialized_setup_11_update(e_config->randr_serialized_setup->serialized_setup_11);
|
||||||
|
else
|
||||||
|
e_config->randr_serialized_setup->serialized_setup_11 = _serialized_setup_11_new();
|
||||||
|
}
|
|
@ -0,0 +1,717 @@
|
||||||
|
#include "e.h"
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
|
||||||
|
#define POLLINTERVAL 128
|
||||||
|
|
||||||
|
// Set functions for the global e_randr_screen_info struct
|
||||||
|
static void _screen_primary_output_assign(E_Randr_Output_Info *removed);
|
||||||
|
|
||||||
|
// Init helper functions
|
||||||
|
static void _outputs_init(void);
|
||||||
|
static void _crtcs_init(void);
|
||||||
|
static Eina_Bool _structs_init(void);
|
||||||
|
|
||||||
|
// Retrieval helper functions
|
||||||
|
static Ecore_X_Randr_Mode_Info *_mode_geo_identical_find(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode);
|
||||||
|
|
||||||
|
// Event helper functions
|
||||||
|
static Eina_Bool _x_poll_cb(void *data __UNUSED__);
|
||||||
|
static Eina_Bool _crtc_change_event_cb(void *data, int type, void *e);
|
||||||
|
static Eina_Bool _output_change_event_cb(void *data, int type, void *e);
|
||||||
|
static Eina_Bool _output_property_change_event_cb(void *data, int type, void *e);
|
||||||
|
static Eina_Bool _try_enable_output(E_Randr_Output_Info *output_info, Eina_Bool force);
|
||||||
|
|
||||||
|
static Ecore_Poller *poller = NULL;
|
||||||
|
static Eina_List *_event_handlers = NULL;
|
||||||
|
const static char *_CONNECTION_STATES_STRINGS[] = {"CONNECTED", "DISCONNECTED", "UNKNOWN"};
|
||||||
|
const static char *_POLICIES_STRINGS[] = {"ABOVE", "RIGHT", "BELOW", "LEFT", "CLONE", "NONE"};
|
||||||
|
|
||||||
|
//"New" helper functions
|
||||||
|
/**
|
||||||
|
* @return array of E_Randr_Screen_Info_12 elements, or in case not all could
|
||||||
|
* be created or parameter 'nrequested'==0, NULL
|
||||||
|
*/
|
||||||
|
static E_Randr_Screen_Info_12 *
|
||||||
|
_screen_info_12_new(void)
|
||||||
|
{
|
||||||
|
E_Randr_Screen_Info_12 *randr_info_12 = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2), NULL);
|
||||||
|
|
||||||
|
randr_info_12 = E_NEW(E_Randr_Screen_Info_12, 1);
|
||||||
|
|
||||||
|
randr_info_12->min_size.width = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_12->min_size.height = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_12->max_size.width = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_12->max_size.height = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_12->current_size.width = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_12->current_size.height = Ecore_X_Randr_Unset;
|
||||||
|
randr_info_12->crtcs = NULL;
|
||||||
|
randr_info_12->outputs = NULL;
|
||||||
|
randr_info_12->modes = NULL;
|
||||||
|
randr_info_12->primary_output = NULL;
|
||||||
|
randr_info_12->alignment = ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE;
|
||||||
|
|
||||||
|
ecore_x_randr_screen_size_range_get(e_randr_screen_info.root,
|
||||||
|
&randr_info_12->min_size.width,
|
||||||
|
&randr_info_12->min_size.height,
|
||||||
|
&randr_info_12->max_size.width,
|
||||||
|
&randr_info_12->max_size.height);
|
||||||
|
ecore_x_randr_screen_current_size_get(e_randr_screen_info.root,
|
||||||
|
&randr_info_12->current_size.width,
|
||||||
|
&randr_info_12->current_size.height,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
return randr_info_12;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_structs_init(void)
|
||||||
|
{
|
||||||
|
//Output stuff
|
||||||
|
Ecore_X_Randr_Output *outputs;
|
||||||
|
E_Randr_Output_Info *output_info = NULL;
|
||||||
|
int noutputs = 0;
|
||||||
|
//CRTC stuff
|
||||||
|
Ecore_X_Randr_Crtc *crtcs = NULL;
|
||||||
|
E_Randr_Crtc_Info *crtc_info = NULL;
|
||||||
|
int ncrtcs = 0;
|
||||||
|
//Modes stuff
|
||||||
|
Ecore_X_Randr_Mode_Info **modes = NULL;
|
||||||
|
int nmodes = 0;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, EINA_FALSE);
|
||||||
|
|
||||||
|
outputs = ecore_x_randr_outputs_get(e_randr_screen_info.root, &noutputs);
|
||||||
|
if (noutputs == 0) return EINA_FALSE;
|
||||||
|
|
||||||
|
while (--noutputs >= 0)
|
||||||
|
{
|
||||||
|
output_info = _output_info_new(outputs[noutputs]);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->outputs = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->outputs, output_info);
|
||||||
|
}
|
||||||
|
free(outputs);
|
||||||
|
|
||||||
|
crtcs = ecore_x_randr_crtcs_get(e_randr_screen_info.root, &ncrtcs);
|
||||||
|
if (ncrtcs == 0) return EINA_FALSE;
|
||||||
|
|
||||||
|
while (--ncrtcs >= 0)
|
||||||
|
{
|
||||||
|
crtc_info = _crtc_info_new(crtcs[ncrtcs]);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->crtcs = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, crtc_info);
|
||||||
|
}
|
||||||
|
free(crtcs);
|
||||||
|
|
||||||
|
modes = ecore_x_randr_modes_info_get(e_randr_screen_info.root, &nmodes);
|
||||||
|
if (nmodes == 0) return EINA_FALSE;
|
||||||
|
|
||||||
|
while (--nmodes >= 0)
|
||||||
|
{
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->modes = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->modes, modes[nmodes]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_outputs_init();
|
||||||
|
_crtcs_init();
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set value / retrieval helper functions
|
||||||
|
|
||||||
|
static void
|
||||||
|
_crtcs_init(void)
|
||||||
|
{
|
||||||
|
E_Randr_Crtc_Info *crtc = NULL;
|
||||||
|
Eina_List *iter;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc)
|
||||||
|
_crtc_refs_set(crtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_outputs_init(void)
|
||||||
|
{
|
||||||
|
E_Randr_Output_Info *output = NULL;
|
||||||
|
Eina_List *iter;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output)
|
||||||
|
{
|
||||||
|
_output_refs_set(output);
|
||||||
|
if (output->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
|
||||||
|
output->monitor = _monitor_info_new(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_screen_primary_output_assign(E_Randr_Output_Info *removed)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Randr_Output_Info *primary_output = NULL, *output_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO_OUTPUTS);
|
||||||
|
|
||||||
|
if (e_randr_screen_info.rrvd_info.randr_info_12->primary_output && (removed != e_randr_screen_info.rrvd_info.randr_info_12->primary_output)) return;
|
||||||
|
if (!(primary_output = _12_screen_info_output_info_get(ecore_x_randr_primary_output_get(e_randr_screen_info.root))))
|
||||||
|
{
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
|
||||||
|
{
|
||||||
|
if (!output_info || (output_info->connection_status != ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) || !output_info->crtc || !output_info->crtc->current_mode) continue;
|
||||||
|
primary_output = output_info;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->primary_output = primary_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//"Free" helper functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param screen_info the screen info to be freed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_12_screen_info_free(E_Randr_Screen_Info_12 *screen_info)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info;
|
||||||
|
E_Randr_Crtc_Info *crtc_info;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(screen_info);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
|
||||||
|
|
||||||
|
if (screen_info->crtcs)
|
||||||
|
{
|
||||||
|
EINA_LIST_FREE (screen_info->crtcs, crtc_info)
|
||||||
|
_crtc_info_free(crtc_info);
|
||||||
|
free(eina_list_nth(screen_info->crtcs, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen_info->outputs)
|
||||||
|
{
|
||||||
|
EINA_LIST_FREE (screen_info->outputs, output_info)
|
||||||
|
_output_info_free(output_info);
|
||||||
|
free(eina_list_nth(screen_info->outputs, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen_info->modes)
|
||||||
|
{
|
||||||
|
EINA_LIST_FREE (screen_info->modes, mode_info)
|
||||||
|
ecore_x_randr_mode_info_free(mode_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (screen_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*********************************************
|
||||||
|
*
|
||||||
|
* Getter functions for e_randr_screen_info struct
|
||||||
|
*
|
||||||
|
* ********************************************
|
||||||
|
*/
|
||||||
|
Ecore_X_Randr_Mode_Info *
|
||||||
|
_12_screen_info_mode_info_get(const Ecore_X_Randr_Mode mode)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_MODE(mode), NULL);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->modes, iter, mode_info)
|
||||||
|
{
|
||||||
|
if (mode_info && (mode_info->xid == mode)) return mode_info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_Randr_Output_Info *
|
||||||
|
_12_screen_info_output_info_get(const Ecore_X_Randr_Output output)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_OUTPUTS, NULL);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
|
||||||
|
{
|
||||||
|
if (output_info && (output_info->xid == output)) return output_info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_Randr_Crtc_Info *
|
||||||
|
_12_screen_info_crtc_info_get(const Ecore_X_Randr_Crtc crtc)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Randr_Crtc_Info *crtc_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_CRTCS, NULL);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc_info)
|
||||||
|
{
|
||||||
|
if (crtc_info && (crtc_info->xid == crtc)) return crtc_info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
_12_screen_info_edid_is_available(const E_Randr_Edid_Hash *hash)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_OUTPUTS, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
|
||||||
|
{
|
||||||
|
if (!output_info || !output_info->monitor)
|
||||||
|
continue;
|
||||||
|
if (output_info->monitor->edid_hash.hash == hash->hash)
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* returns a mode within a given list of modes that is gemetrically identical.
|
||||||
|
* If none is found, NULL is returned.
|
||||||
|
*/
|
||||||
|
static Ecore_X_Randr_Mode_Info *
|
||||||
|
_mode_geo_identical_find(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(modes, iter, mode_info)
|
||||||
|
{
|
||||||
|
if ((mode_info->width == mode->width) && (mode_info->height == mode->height))
|
||||||
|
return mode_info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
*
|
||||||
|
* Init. and Shutdown code
|
||||||
|
*
|
||||||
|
*****************************************************************
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_12_screen_info_refresh(void)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2);
|
||||||
|
|
||||||
|
_12_screen_info_free(e_randr_screen_info.rrvd_info.randr_info_12);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12 = _screen_info_12_new();
|
||||||
|
_structs_init();
|
||||||
|
_screen_primary_output_assign(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
*
|
||||||
|
* Event code
|
||||||
|
*
|
||||||
|
******************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_x_poll_cb(void *data __UNUSED__)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_randr_screen_info.rrvd_info.randr_info_12, ECORE_CALLBACK_CANCEL);
|
||||||
|
|
||||||
|
ecore_x_randr_screen_primary_output_orientations_get(e_randr_screen_info.root);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_12_event_listeners_add(void)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
|
||||||
|
|
||||||
|
ecore_x_randr_events_select(e_randr_screen_info.root, EINA_TRUE);
|
||||||
|
_event_handlers = eina_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, _crtc_change_event_cb, NULL));
|
||||||
|
_event_handlers = eina_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, _output_change_event_cb, NULL));
|
||||||
|
_event_handlers = eina_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, _output_property_change_event_cb, NULL));
|
||||||
|
// WORKAROUND problem of X not sending events
|
||||||
|
poller = ecore_poller_add(ECORE_POLLER_CORE, POLLINTERVAL, _x_poll_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Usually events are triggered in the following order.
|
||||||
|
* (Dis)connect Display Scenario:
|
||||||
|
* 1.) ECORE_X_EVENT_OUTPUT_CHANGE //Triggered, when a display is connected to an
|
||||||
|
* output
|
||||||
|
* 2.) ECORE_X_EVENT_CRTC_CHANGE //Triggered when the CRTC mode is changed (eg.
|
||||||
|
* enabled by e.g. e_randr or xrandr)
|
||||||
|
* 3.) ECORE_X_EVENT_OUTPUT_CHANGE //Triggered for each output changed by the
|
||||||
|
* preceeding enabling.
|
||||||
|
*
|
||||||
|
* When the mode of a CRTC is changed only events 2 and 3 are triggered
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static Eina_Bool
|
||||||
|
_output_change_event_cb(void *data __UNUSED__, int type, void *ev)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Randr_Output_Change *oce = (Ecore_X_Event_Randr_Output_Change*)ev;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
E_Randr_Crtc_Info *crtc_info = NULL;
|
||||||
|
Eina_Bool policy_success = EINA_FALSE;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, ECORE_CALLBACK_CANCEL);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((type != ECORE_X_EVENT_RANDR_OUTPUT_CHANGE), ECORE_CALLBACK_RENEW);
|
||||||
|
|
||||||
|
/* event information:
|
||||||
|
Ecore_X_Window win;
|
||||||
|
Ecore_X_Randr_Output output;
|
||||||
|
Ecore_X_Randr_Crtc crtc;
|
||||||
|
Ecore_X_Randr_Mode mode;
|
||||||
|
Ecore_X_Randr_Orientation orientation;
|
||||||
|
Ecore_X_Randr_Connection_Status connection;
|
||||||
|
Ecore_X_Render_Subpixel_Order subpixel_order;
|
||||||
|
*/
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL((output_info = _12_screen_info_output_info_get(oce->output)), ECORE_CALLBACK_RENEW);
|
||||||
|
|
||||||
|
fprintf(stderr, "E_RANDR: Output event: \n"
|
||||||
|
"\t\t: relative to win: %d\n"
|
||||||
|
"\t\t: output (xid): %d\n"
|
||||||
|
"\t\t: used by crtc (xid): %d\n"
|
||||||
|
"\t\t: mode: %d\n"
|
||||||
|
"\t\t: orientation: %d\n"
|
||||||
|
"\t\t: connection state: %s\n"
|
||||||
|
"\t\t: subpixel_order: %d\n",
|
||||||
|
oce->win,
|
||||||
|
oce->output,
|
||||||
|
oce->crtc,
|
||||||
|
oce->mode,
|
||||||
|
oce->orientation,
|
||||||
|
_CONNECTION_STATES_STRINGS[oce->connection],
|
||||||
|
oce->subpixel_order);
|
||||||
|
|
||||||
|
crtc_info = _12_screen_info_crtc_info_get(oce->crtc);
|
||||||
|
//WORKAROUND
|
||||||
|
//Reason: Missing events, when an output is moved from one CRTC to
|
||||||
|
// another
|
||||||
|
if (output_info->crtc && (crtc_info != output_info->crtc))
|
||||||
|
output_info->crtc->outputs = eina_list_remove(output_info->crtc->outputs, output_info);
|
||||||
|
//END WORKAROUND
|
||||||
|
output_info->crtc = crtc_info;
|
||||||
|
|
||||||
|
//Update mode references in case a mode was added manually
|
||||||
|
if (output_info->monitor)
|
||||||
|
{
|
||||||
|
eina_list_free(output_info->monitor->modes);
|
||||||
|
output_info->monitor->modes = NULL;
|
||||||
|
eina_list_free(output_info->monitor->preferred_modes);
|
||||||
|
output_info->monitor->preferred_modes = NULL;
|
||||||
|
_monitor_modes_refs_set(output_info->monitor, output_info->xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_info->connection_status = oce->connection;
|
||||||
|
output_info->subpixel_order = oce->subpixel_order;
|
||||||
|
|
||||||
|
if (output_info->connection_status != oce->connection)
|
||||||
|
{
|
||||||
|
_monitor_info_free(output_info->monitor);
|
||||||
|
output_info->monitor = NULL;
|
||||||
|
|
||||||
|
if (oce->connection == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
|
||||||
|
{
|
||||||
|
//New device connected!
|
||||||
|
output_info->monitor = _monitor_info_new(output_info);
|
||||||
|
fprintf(stderr, "E_RANDR: Output %d was newly connected.\n", output_info->xid);
|
||||||
|
|
||||||
|
//only try to enable the monitor if there is no serialized setup
|
||||||
|
if(!_12_try_restore_configuration())
|
||||||
|
{
|
||||||
|
policy_success = _try_enable_output(output_info, EINA_FALSE); //maybe give a success message?
|
||||||
|
fprintf(stderr, "E_RANDR: Policy \"%s\" was enforced %ssuccesfully.\n", _POLICIES_STRINGS[output_info->policy - 1], (policy_success ? "" : "un"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//connection_state is 'unknown' or 'disconnected': treat as disconnected!
|
||||||
|
if (output_info->crtc)
|
||||||
|
{
|
||||||
|
output_info->crtc->outputs = eina_list_remove(output_info->crtc->outputs, output_info);
|
||||||
|
//in case this output was the last one connected on a CRTC,
|
||||||
|
//disable it again
|
||||||
|
if (eina_list_count(output_info->crtc->outputs) == 0)
|
||||||
|
{
|
||||||
|
//in case it was the only output running on this CRTC, disable
|
||||||
|
//it.
|
||||||
|
ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, output_info->crtc->xid, NULL, Ecore_X_Randr_None, Ecore_X_Randr_None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//retry to find a suiting serialized setup for the remaining
|
||||||
|
//connected monitors
|
||||||
|
_12_try_restore_configuration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_crtc_change_event_cb(void *data __UNUSED__, int type, void *ev)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Randr_Crtc_Change *cce = (Ecore_X_Event_Randr_Crtc_Change*)ev;
|
||||||
|
E_Randr_Crtc_Info *crtc_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, ECORE_CALLBACK_CANCEL);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((type != ECORE_X_EVENT_RANDR_CRTC_CHANGE), ECORE_CALLBACK_RENEW);
|
||||||
|
|
||||||
|
/* event information:
|
||||||
|
Ecore_X_Window win;
|
||||||
|
Ecore_X_Randr_Crtc crtc;
|
||||||
|
Ecore_X_Randr_Mode mode;
|
||||||
|
Ecore_X_Randr_Orientation orientation;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
*/
|
||||||
|
fprintf(stderr, "E_RANDR: CRTC event: \n"
|
||||||
|
"\t\t: relative to win: %d\n"
|
||||||
|
"\t\t: crtc (xid): %d\n"
|
||||||
|
"\t\t: mode (xid): %d\n"
|
||||||
|
"\t\t: orientation: %d\n"
|
||||||
|
"\t\t: x: %d\n"
|
||||||
|
"\t\t: y: %d\n"
|
||||||
|
"\t\t: width: %d\n"
|
||||||
|
"\t\t: height: %d\n",
|
||||||
|
cce->win,
|
||||||
|
cce->crtc,
|
||||||
|
cce->mode,
|
||||||
|
cce->orientation,
|
||||||
|
cce->geo.x,
|
||||||
|
cce->geo.y,
|
||||||
|
cce->geo.w,
|
||||||
|
cce->geo.h);
|
||||||
|
|
||||||
|
|
||||||
|
crtc_info = _12_screen_info_crtc_info_get(cce->crtc);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(crtc_info, ECORE_CALLBACK_RENEW);
|
||||||
|
|
||||||
|
crtc_info->current_mode = _12_screen_info_mode_info_get(cce->mode);
|
||||||
|
crtc_info->current_orientation = cce->orientation;
|
||||||
|
crtc_info->geometry.x = cce->geo.x;
|
||||||
|
crtc_info->geometry.y = cce->geo.y;
|
||||||
|
crtc_info->geometry.w = cce->geo.w;
|
||||||
|
crtc_info->geometry.h = cce->geo.h;
|
||||||
|
|
||||||
|
//update screensize if necessary
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->current_size.width = MAX((cce->geo.x + cce->geo.w), e_randr_screen_info.rrvd_info.randr_info_12->current_size.width);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->current_size.height = MAX((cce->geo.y + cce->geo.h), e_randr_screen_info.rrvd_info.randr_info_12->current_size.height);
|
||||||
|
|
||||||
|
//update output data
|
||||||
|
eina_list_free(crtc_info->outputs);
|
||||||
|
crtc_info->outputs = NULL;
|
||||||
|
eina_list_free(crtc_info->outputs_common_modes);
|
||||||
|
crtc_info->outputs_common_modes = NULL;
|
||||||
|
|
||||||
|
//if still enabled, update references to outputs
|
||||||
|
if (crtc_info->current_mode)
|
||||||
|
{
|
||||||
|
_crtc_outputs_refs_set(crtc_info);
|
||||||
|
crtc_info->outputs_common_modes = _outputs_common_modes_get(crtc_info->outputs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//crop the screen
|
||||||
|
ecore_x_randr_screen_reset(e_randr_screen_info.root);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_output_property_change_event_cb(void *data __UNUSED__, int type, void *ev)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Randr_Output_Property_Notify *opce = (Ecore_X_Event_Randr_Output_Property_Notify*)ev;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, ECORE_CALLBACK_CANCEL);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((type != ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY), ECORE_CALLBACK_RENEW);
|
||||||
|
|
||||||
|
/* event information:
|
||||||
|
Ecore_X_Window win;
|
||||||
|
Ecore_X_Randr_Output output;
|
||||||
|
Ecore_X_Atom property;
|
||||||
|
Ecore_X_Time time;
|
||||||
|
Ecore_X_Randr_Property_Change state;
|
||||||
|
*/
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL((output_info = _12_screen_info_output_info_get(opce->output)), ECORE_CALLBACK_RENEW);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to enable this output on an unoccupied CRTC. 'Force' in this context
|
||||||
|
* means, that if there are only occupied CRTCs, we disable another output to
|
||||||
|
* enable this one. If not forced we will - if we don't find an unoccupied CRTC
|
||||||
|
* - try to share the output of a CRTC with other outputs already using it
|
||||||
|
* (clone).
|
||||||
|
*/
|
||||||
|
static Eina_Bool
|
||||||
|
_try_enable_output(E_Randr_Output_Info *output_info, Eina_Bool force)
|
||||||
|
{
|
||||||
|
Eina_List *iter, *outputs_list = NULL, *common_modes = NULL;
|
||||||
|
E_Randr_Crtc_Info *crtc_info, *usable_crtc = NULL;
|
||||||
|
E_Randr_Output_Info *primary_output;
|
||||||
|
Ecore_X_Randr_Output *outputs;
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info;
|
||||||
|
Eina_Bool ret = EINA_FALSE;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(output_info, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((output_info->crtc && output_info->crtc->current_mode), EINA_FALSE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to find a usable crtc for this output. Either unused or forced.
|
||||||
|
*/
|
||||||
|
EINA_LIST_FOREACH(output_info->possible_crtcs, iter, crtc_info)
|
||||||
|
{
|
||||||
|
if (!crtc_info->current_mode || !crtc_info->outputs || force)
|
||||||
|
{
|
||||||
|
usable_crtc = crtc_info;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* apparently we don't have a CRTC to make use of the device
|
||||||
|
*/
|
||||||
|
if (!usable_crtc)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
//get the CRTC we will refer to, dependend on policy
|
||||||
|
switch (output_info->policy)
|
||||||
|
{
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
|
||||||
|
/*
|
||||||
|
* Order of approaches to enable a clone (of the primary output):
|
||||||
|
*
|
||||||
|
* 0. Get Primary output from Server
|
||||||
|
* 1. Try to add new Output to primary output's CRTC, using the mode used
|
||||||
|
* by the primary output
|
||||||
|
* 2. Try to enable clone in the same
|
||||||
|
* 2a. exact mode or a
|
||||||
|
* 2b. geometrically identical mode
|
||||||
|
* 3. Find a most high resolution mode in common to enable on primary output's CRTC and the new
|
||||||
|
* output's CRTC
|
||||||
|
* 4. fail.
|
||||||
|
*/
|
||||||
|
//Assign new output, if necessary
|
||||||
|
_screen_primary_output_assign(output_info);
|
||||||
|
if ((primary_output = e_randr_screen_info.rrvd_info.randr_info_12->primary_output))
|
||||||
|
{
|
||||||
|
if (primary_output->crtc && primary_output->crtc->current_mode && eina_list_data_find(output_info->monitor->modes, primary_output->crtc->current_mode))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* mode currently used by primary output's CRTC is also supported by the new output
|
||||||
|
*/
|
||||||
|
if (eina_list_data_find(primary_output->crtc->possible_outputs, output_info) && eina_list_data_find(output_info->monitor->modes, primary_output->crtc->current_mode))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 1. Try to add new Output to primary output's CRTC, using the mode used
|
||||||
|
* by the primary output
|
||||||
|
* TODO: check with compatibility list in RandRR >= 1.3
|
||||||
|
* if available
|
||||||
|
*
|
||||||
|
* The new output is also usable by the primary output's
|
||||||
|
* CRTC. Try to enable this output together with the already
|
||||||
|
* enabled outputs on the CRTC in already used mode.
|
||||||
|
*/
|
||||||
|
outputs_list = primary_output->crtc->outputs;
|
||||||
|
outputs_list = eina_list_append(outputs_list, output_info);
|
||||||
|
outputs = _outputs_to_array(outputs_list);
|
||||||
|
primary_output->crtc->outputs = NULL;
|
||||||
|
ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, primary_output->crtc->xid, outputs, eina_list_count(outputs_list), primary_output->crtc->current_mode->xid);
|
||||||
|
free(outputs);
|
||||||
|
eina_list_free(outputs_list);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 2. Try to enable clone in the same
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2a. exact mode.
|
||||||
|
*/
|
||||||
|
ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, primary_output->crtc->current_mode->xid);
|
||||||
|
return ret && ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info.rrvd_info.randr_info_12->alignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 2b. geometrically identical mode
|
||||||
|
*/
|
||||||
|
if (primary_output->crtc && (mode_info = _mode_geo_identical_find(output_info->monitor->modes, primary_output->crtc->current_mode)))
|
||||||
|
{
|
||||||
|
ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid);
|
||||||
|
return ret && ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info.rrvd_info.randr_info_12->alignment);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 3. Find the highest resolution mode common to enable on primary output's CRTC and the new one.
|
||||||
|
*/
|
||||||
|
if (((outputs_list = eina_list_append(outputs_list, primary_output)) && (outputs_list = eina_list_append(outputs_list, output_info))))
|
||||||
|
{
|
||||||
|
if (primary_output->crtc)
|
||||||
|
{
|
||||||
|
common_modes = _outputs_common_modes_get(outputs_list, primary_output->crtc->current_mode);
|
||||||
|
if ((mode_info = eina_list_nth(common_modes, 0)))
|
||||||
|
{
|
||||||
|
eina_list_free(common_modes);
|
||||||
|
fprintf(stderr, "Will try to set mode: %dx%d for primary and clone.\n", mode_info->width, mode_info->height);
|
||||||
|
ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, primary_output->crtc->xid, ((Ecore_X_Randr_Output *)Ecore_X_Randr_Unset), Ecore_X_Randr_Unset, mode_info->xid);
|
||||||
|
ret = (ret && ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid));
|
||||||
|
ret = (ret && ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info.rrvd_info.randr_info_12->alignment));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina_list_free(outputs_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "E_RANDR: Failed to clone, because of missing or disabled primary output!\n");
|
||||||
|
/*
|
||||||
|
* 4. FAIL
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//enable and position according to used policies
|
||||||
|
if (!(mode_info = ((Ecore_X_Randr_Mode_Info *)eina_list_data_get(output_info->monitor->preferred_modes))))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "E_RANDR: Could not enable output(%d), as it has no preferred modes (and there for none at all)!\n", output_info->xid);
|
||||||
|
ret = EINA_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid)))
|
||||||
|
{
|
||||||
|
ret &= _crtc_move_policy(usable_crtc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
ecore_x_randr_screen_reset(e_randr_screen_info.root);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_12_event_listeners_remove(void)
|
||||||
|
{
|
||||||
|
Ecore_Event_Handler *_event_handler = NULL;
|
||||||
|
|
||||||
|
EINA_LIST_FREE (_event_handlers, _event_handler)
|
||||||
|
ecore_event_handler_del(_event_handler);
|
||||||
|
ecore_poller_del(poller);
|
||||||
|
poller = NULL;
|
||||||
|
}
|
|
@ -0,0 +1,333 @@
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
#include "e_randr.h"
|
||||||
|
|
||||||
|
// E_Randr_Crtc_Info helper functions
|
||||||
|
static Eina_Bool _crtc_mode_intersects_crtcs(E_Randr_Crtc_Info *crtc_info, Ecore_X_Randr_Mode_Info *mode);
|
||||||
|
static Eina_Bool _crtc_outputs_mode_max_set(E_Randr_Crtc_Info *crtc_info);
|
||||||
|
|
||||||
|
void
|
||||||
|
_crtc_outputs_refs_set(E_Randr_Crtc_Info *crtc_info)
|
||||||
|
{
|
||||||
|
E_Randr_Output_Info *output_info = NULL;
|
||||||
|
Ecore_X_Randr_Output *outputs = NULL;
|
||||||
|
int noutputs;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(crtc_info);
|
||||||
|
|
||||||
|
outputs = ecore_x_randr_crtc_outputs_get(e_randr_screen_info.root, crtc_info->xid, &noutputs);
|
||||||
|
|
||||||
|
while (--noutputs >= 0)
|
||||||
|
{
|
||||||
|
output_info = _12_screen_info_output_info_get(outputs[noutputs]);
|
||||||
|
if (!output_info)
|
||||||
|
fprintf(stderr, "E_RANDR: Could not find output struct for output %d.\n", outputs[noutputs]);
|
||||||
|
crtc_info->outputs = eina_list_append(crtc_info->outputs, output_info);
|
||||||
|
}
|
||||||
|
crtc_info->outputs_common_modes = _outputs_common_modes_get(crtc_info->outputs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_crtc_refs_set(E_Randr_Crtc_Info *crtc_info)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Mode mode = Ecore_X_Randr_None;
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info = NULL;
|
||||||
|
Ecore_X_Randr_Output *poutputs = NULL;
|
||||||
|
E_Randr_Output_Info *output_info = NULL;
|
||||||
|
int npoutputs;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(crtc_info);
|
||||||
|
|
||||||
|
mode = ecore_x_randr_crtc_mode_get(e_randr_screen_info.root, crtc_info->xid);
|
||||||
|
if (!(mode_info = _12_screen_info_mode_info_get(mode)))
|
||||||
|
{
|
||||||
|
//Mode unknown to the global structure, so add it
|
||||||
|
mode_info = ecore_x_randr_mode_info_get(e_randr_screen_info.root, mode);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->modes = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->modes, mode_info);
|
||||||
|
}
|
||||||
|
crtc_info->current_mode = mode_info;
|
||||||
|
|
||||||
|
poutputs = ecore_x_randr_crtc_possible_outputs_get(e_randr_screen_info.root, crtc_info->xid, &npoutputs);
|
||||||
|
|
||||||
|
while (--npoutputs >= 0)
|
||||||
|
{
|
||||||
|
output_info = _12_screen_info_output_info_get(poutputs[npoutputs]);
|
||||||
|
if (!output_info)
|
||||||
|
fprintf(stderr, "E_RANDR: Could not find output struct for output %d.\n", poutputs[npoutputs]);
|
||||||
|
crtc_info->possible_outputs = eina_list_append(crtc_info->possible_outputs, output_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
_crtc_outputs_refs_set(crtc_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate and init with values.
|
||||||
|
* @param crtc the crtc the display is queried for. If Ecore_X_Randr_None is
|
||||||
|
* given, a struct with only the xid will be set
|
||||||
|
* @return E_Randr_Crtc_Info element
|
||||||
|
*/
|
||||||
|
E_Randr_Crtc_Info *
|
||||||
|
_crtc_info_new(Ecore_X_Randr_Crtc crtc)
|
||||||
|
{
|
||||||
|
E_Randr_Crtc_Info *crtc_info = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, NULL);
|
||||||
|
|
||||||
|
crtc_info = E_NEW(E_Randr_Crtc_Info, 1);
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((crtc == Ecore_X_Randr_None), crtc_info);
|
||||||
|
|
||||||
|
crtc_info->xid = crtc;
|
||||||
|
crtc_info->panning.x = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->panning.y = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->panning.w = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->panning.h = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->tracking.x = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->tracking.y = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->tracking.w = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->tracking.h = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->border.x = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->border.y = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->border.w = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->border.h = Ecore_X_Randr_Unset;
|
||||||
|
|
||||||
|
crtc_info->gamma_ramps = NULL;
|
||||||
|
crtc_info->gamma_ramp_size = Ecore_X_Randr_Unset;
|
||||||
|
crtc_info->outputs = NULL;
|
||||||
|
crtc_info->possible_outputs = NULL;
|
||||||
|
crtc_info->outputs_common_modes = NULL;
|
||||||
|
crtc_info->current_mode = NULL;
|
||||||
|
|
||||||
|
ecore_x_randr_crtc_geometry_get(e_randr_screen_info.root, crtc_info->xid, &crtc_info->geometry.x, &crtc_info->geometry.y, &crtc_info->geometry.w, &crtc_info->geometry.h);
|
||||||
|
crtc_info->current_orientation = ecore_x_randr_crtc_orientation_get(e_randr_screen_info.root, crtc_info->xid);
|
||||||
|
crtc_info->orientations = ecore_x_randr_crtc_orientations_get(e_randr_screen_info.root, crtc_info->xid);
|
||||||
|
|
||||||
|
return crtc_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param crtc_info the crtc info to be freed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_crtc_info_free(E_Randr_Crtc_Info *crtc_info)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(crtc_info);
|
||||||
|
|
||||||
|
if (crtc_info->gamma_ramps) free(crtc_info->gamma_ramps);
|
||||||
|
if (crtc_info->outputs)
|
||||||
|
{
|
||||||
|
eina_list_free(crtc_info->outputs);
|
||||||
|
crtc_info->outputs = NULL;
|
||||||
|
}
|
||||||
|
if (crtc_info->possible_outputs)
|
||||||
|
{
|
||||||
|
eina_list_free(crtc_info->possible_outputs);
|
||||||
|
crtc_info->possible_outputs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns EINA_TRUE if given CRTC would intersect with other CRTCs if set to
|
||||||
|
* given mode
|
||||||
|
*/
|
||||||
|
static Eina_Bool
|
||||||
|
_crtc_mode_intersects_crtcs(E_Randr_Crtc_Info *crtc_info, Ecore_X_Randr_Mode_Info *mode)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Randr_Crtc_Info *tmp;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, tmp)
|
||||||
|
{
|
||||||
|
if ((tmp == crtc_info) ||
|
||||||
|
((tmp->geometry.w <= 0) || (tmp->geometry.h <= 0)))
|
||||||
|
continue;
|
||||||
|
if (E_INTERSECTS(crtc_info->geometry.x, crtc_info->geometry.y,
|
||||||
|
mode->width, mode->height, tmp->geometry.x,
|
||||||
|
tmp->geometry.y, tmp->geometry.w, tmp->geometry.h)
|
||||||
|
&& ((crtc_info->geometry.x != tmp->geometry.x) &&
|
||||||
|
(crtc_info->geometry.y != tmp->geometry.y)))
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reconfigures a CRTC enabling the highest resolution amongst its outputs,
|
||||||
|
* without touching any other CRTC currently activated
|
||||||
|
*/
|
||||||
|
static Eina_Bool
|
||||||
|
_crtc_outputs_mode_max_set(E_Randr_Crtc_Info *crtc_info)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info;
|
||||||
|
Eina_List *iter;
|
||||||
|
Eina_Bool ret = EINA_TRUE;
|
||||||
|
Ecore_X_Randr_Output *outputs;
|
||||||
|
|
||||||
|
if (!crtc_info || !crtc_info->outputs || !crtc_info->outputs_common_modes) return EINA_FALSE;
|
||||||
|
|
||||||
|
EINA_LIST_REVERSE_FOREACH(crtc_info->outputs_common_modes, iter, mode_info)
|
||||||
|
{
|
||||||
|
if (!_crtc_mode_intersects_crtcs(crtc_info, mode_info))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!mode_info)
|
||||||
|
{
|
||||||
|
//eina_list_free(crtc_info->outputs_common_modes);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
if ((outputs = _outputs_to_array(crtc_info->outputs)))
|
||||||
|
{
|
||||||
|
ret = ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, crtc_info->xid, outputs, eina_list_count(crtc_info->outputs), mode_info->xid);
|
||||||
|
free(outputs);
|
||||||
|
}
|
||||||
|
//eina_list_free(crtc_info->outputs_common_modes);
|
||||||
|
//crtc_info->outputs_common_modes = NULL;
|
||||||
|
|
||||||
|
ecore_x_randr_screen_reset(e_randr_screen_info.root);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reconfigure screen setup according to policy. This is only required if all
|
||||||
|
* CRTCs' positions might be affected by the another screens' movement. This includes 'virtual' moves,
|
||||||
|
* which means that e.g. when a crtc should be placed at a position < 0, all
|
||||||
|
* other crtcs are accordingly moved instead, so the result is the same.
|
||||||
|
*/
|
||||||
|
const Eina_Bool
|
||||||
|
_crtc_move_policy(E_Randr_Crtc_Info *new_crtc)
|
||||||
|
{
|
||||||
|
const E_Randr_Crtc_Info *crtc_rel;
|
||||||
|
E_Randr_Output_Info *first_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 first output
|
||||||
|
first_output = (E_Randr_Output_Info *)eina_list_data_get(new_crtc->outputs);
|
||||||
|
if (!first_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 = _crtc_according_to_policy_get(new_crtc, first_output->policy)))
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
//following is policy dependend.
|
||||||
|
switch (first_output->policy)
|
||||||
|
{
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
|
||||||
|
dy = (crtc_rel->geometry.y - new_crtc->geometry.h);
|
||||||
|
if (dy < 0)
|
||||||
|
{
|
||||||
|
//virtual move (move other CRTCs as nessesary)
|
||||||
|
dy = -dy;
|
||||||
|
ret = ecore_x_randr_move_all_crtcs_but(e_randr_screen_info.root,
|
||||||
|
&new_crtc->xid,
|
||||||
|
1,
|
||||||
|
dx,
|
||||||
|
dy);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
|
||||||
|
dx = (crtc_rel->geometry.x - new_crtc->geometry.w);
|
||||||
|
if (dx < 0)
|
||||||
|
{
|
||||||
|
//virtual move (move other CRTCs as nessesary)
|
||||||
|
dx = -dx;
|
||||||
|
ret = ecore_x_randr_move_all_crtcs_but(e_randr_screen_info.root,
|
||||||
|
&new_crtc->xid,
|
||||||
|
1,
|
||||||
|
dx,
|
||||||
|
dy);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, new_crtc->xid, crtc_rel->xid, first_output->policy, e_randr_screen_info.rrvd_info.randr_info_12->alignment);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this retrieves a CRTC depending on a policy.
|
||||||
|
* Note that this is enlightenment specific! Enlightenment doesn't 'allow' zones
|
||||||
|
* to overlap. Thus we always use the output with the most extreme position
|
||||||
|
* instead of trying to fill gaps like tetris. Though this could be done by
|
||||||
|
* simply implementing another policy.
|
||||||
|
*
|
||||||
|
* Simply put: get the
|
||||||
|
* -right
|
||||||
|
* -left
|
||||||
|
* -top
|
||||||
|
* -bottom
|
||||||
|
* most CRTC and return it.
|
||||||
|
*/
|
||||||
|
const E_Randr_Crtc_Info *
|
||||||
|
_crtc_according_to_policy_get(E_Randr_Crtc_Info *but, Ecore_X_Randr_Output_Policy policy)
|
||||||
|
{
|
||||||
|
Eina_List *iter, *possible_crtcs = NULL;
|
||||||
|
E_Randr_Crtc_Info *crtc_info, *ret = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_CRTCS, NULL);
|
||||||
|
|
||||||
|
//get any crtc that besides 'but' to start with
|
||||||
|
possible_crtcs = eina_list_clone(e_randr_screen_info.rrvd_info.randr_info_12->crtcs);
|
||||||
|
possible_crtcs = eina_list_remove(possible_crtcs, but);
|
||||||
|
|
||||||
|
if ((eina_list_count(possible_crtcs) == 0) && (policy != ECORE_X_RANDR_OUTPUT_POLICY_CLONE))
|
||||||
|
{
|
||||||
|
eina_list_free(possible_crtcs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get an initial value for ret
|
||||||
|
ret = (E_Randr_Crtc_Info*)eina_list_data_get(eina_list_last(possible_crtcs));
|
||||||
|
|
||||||
|
switch (policy)
|
||||||
|
{
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc_info)
|
||||||
|
{
|
||||||
|
if (crtc_info->geometry.y < ret->geometry.y)
|
||||||
|
ret = crtc_info;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc_info)
|
||||||
|
{
|
||||||
|
if ((crtc_info->geometry.x + crtc_info->geometry.w) >
|
||||||
|
(ret->geometry.x + ret->geometry.w))
|
||||||
|
ret = crtc_info;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc_info)
|
||||||
|
{
|
||||||
|
if ((crtc_info->geometry.y + crtc_info->geometry.h) >
|
||||||
|
(ret->geometry.y + ret->geometry.h))
|
||||||
|
ret = crtc_info;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc_info)
|
||||||
|
{
|
||||||
|
if (crtc_info->geometry.x < ret->geometry.x)
|
||||||
|
ret = crtc_info;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
|
||||||
|
ret = (e_randr_screen_info.rrvd_info.randr_info_12->primary_output) ? e_randr_screen_info.rrvd_info.randr_info_12->primary_output->crtc : NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_list_free(possible_crtcs);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,233 @@
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
#include "e_randr.h"
|
||||||
|
|
||||||
|
E_Randr_Monitor_Info *_monitor_info_new(E_Randr_Output_Info *output_info);
|
||||||
|
static int _modes_size_sort_cb(const void *d1, const void *d2);
|
||||||
|
|
||||||
|
void
|
||||||
|
_monitor_modes_refs_set(E_Randr_Monitor_Info *mi, Ecore_X_Randr_Output o)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Mode *modes = NULL;
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info = NULL;
|
||||||
|
int nmodes, npreferred;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(mi);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(o == Ecore_X_Randr_None);
|
||||||
|
|
||||||
|
// Add (preferred) modes
|
||||||
|
modes = ecore_x_randr_output_modes_get(e_randr_screen_info.root, o, &nmodes, &npreferred);
|
||||||
|
while (--nmodes >= 0)
|
||||||
|
{
|
||||||
|
if (!(mode_info = _12_screen_info_mode_info_get(modes[nmodes])))
|
||||||
|
{
|
||||||
|
//Mode unknown to the global structure, so add it
|
||||||
|
mode_info = ecore_x_randr_mode_info_get(e_randr_screen_info.root, modes[nmodes]);
|
||||||
|
e_randr_screen_info.rrvd_info.randr_info_12->modes = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->modes, mode_info);
|
||||||
|
}
|
||||||
|
mi->modes = eina_list_append(mi->modes, mode_info);
|
||||||
|
if (nmodes >= npreferred)
|
||||||
|
mi->preferred_modes = eina_list_append(mi->preferred_modes, mode_info);
|
||||||
|
}
|
||||||
|
free(modes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates a new E_Randr_Monitor_Info struct and initializes it with
|
||||||
|
* default values.
|
||||||
|
* @return E_Randr_Monitor_Info element, or if it could not be
|
||||||
|
* created, NULL
|
||||||
|
*/
|
||||||
|
E_Randr_Monitor_Info *
|
||||||
|
_monitor_info_new(E_Randr_Output_Info *oi)
|
||||||
|
{
|
||||||
|
E_Randr_Monitor_Info *mi = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(oi, NULL);
|
||||||
|
|
||||||
|
mi = E_NEW(E_Randr_Monitor_Info, 1);
|
||||||
|
|
||||||
|
// Set some default values
|
||||||
|
mi->modes = NULL;
|
||||||
|
mi->preferred_modes = NULL;
|
||||||
|
mi->size_mm.width = Ecore_X_Randr_Unset;
|
||||||
|
mi->size_mm.height = Ecore_X_Randr_Unset;
|
||||||
|
mi->edid = NULL;
|
||||||
|
mi->edid_length = 0;
|
||||||
|
mi->edid_hash.hash = 0;
|
||||||
|
mi->max_backlight = Ecore_X_Randr_Unset;
|
||||||
|
mi->backlight_level = 0.0;
|
||||||
|
|
||||||
|
_monitor_modes_refs_set(mi, oi->xid);
|
||||||
|
|
||||||
|
ecore_x_randr_output_size_mm_get(e_randr_screen_info.root, oi->xid, &mi->size_mm.width, &mi->size_mm.height);
|
||||||
|
mi->edid = ecore_x_randr_output_edid_get(e_randr_screen_info.root, oi->xid, &mi->edid_length);
|
||||||
|
if (mi->edid_length > 0)
|
||||||
|
mi->edid_hash.hash = eina_hash_superfast((char *)mi->edid, mi->edid_length);
|
||||||
|
|
||||||
|
return mi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Frees E_Randr_Monitor_Info structure
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_monitor_info_free(E_Randr_Monitor_Info *monitor_info)
|
||||||
|
{
|
||||||
|
if (!monitor_info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eina_list_free(monitor_info->modes);
|
||||||
|
eina_list_free(monitor_info->preferred_modes);
|
||||||
|
free(monitor_info->edid);
|
||||||
|
free(monitor_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief allocates a struct and fills it with default values.
|
||||||
|
* @param output the output the display is queried for. If Ecore_X_Randr_None is
|
||||||
|
* given, a struct with only the xid will be set
|
||||||
|
* @return E_Randr_Output_Info element
|
||||||
|
*/
|
||||||
|
E_Randr_Output_Info *
|
||||||
|
_output_info_new(Ecore_X_Randr_Output output)
|
||||||
|
{
|
||||||
|
E_Randr_Output_Info *output_info = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, NULL);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((output == Ecore_X_Randr_None), NULL);
|
||||||
|
|
||||||
|
output_info = malloc(sizeof(E_Randr_Output_Info));
|
||||||
|
|
||||||
|
output_info->xid = output;
|
||||||
|
|
||||||
|
//Use default values
|
||||||
|
output_info->crtc = NULL;
|
||||||
|
output_info->wired_clones = NULL;
|
||||||
|
output_info->possible_crtcs = NULL;
|
||||||
|
output_info->signalformats = Ecore_X_Randr_Unset;
|
||||||
|
output_info->signalformat = Ecore_X_Randr_Unset;
|
||||||
|
output_info->connector_number = 0;
|
||||||
|
output_info->connector_type = Ecore_X_Randr_Unset;
|
||||||
|
output_info->policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE;
|
||||||
|
output_info->compatibility_list = NULL;
|
||||||
|
output_info->subpixel_order = Ecore_X_Randr_Unset;
|
||||||
|
|
||||||
|
output_info->name = ecore_x_randr_output_name_get(e_randr_screen_info.root, output_info->xid, &output_info->name_length);
|
||||||
|
output_info->connection_status = ecore_x_randr_output_connection_status_get(e_randr_screen_info.root, output_info->xid);
|
||||||
|
|
||||||
|
return output_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_output_info_free(E_Randr_Output_Info *output_info)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(output_info);
|
||||||
|
|
||||||
|
eina_list_free(output_info->wired_clones);
|
||||||
|
eina_list_free(output_info->possible_crtcs);
|
||||||
|
eina_list_free(output_info->compatibility_list);
|
||||||
|
free(output_info->name);
|
||||||
|
_monitor_info_free(output_info->monitor);
|
||||||
|
output_info->monitor = NULL;
|
||||||
|
free(output_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_output_refs_set(E_Randr_Output_Info *output_info)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Crtc crtc, *crtcs = NULL;
|
||||||
|
E_Randr_Crtc_Info *crtc_info;
|
||||||
|
int ncrtcs = 0;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(output_info);
|
||||||
|
|
||||||
|
eina_list_free(output_info->possible_crtcs);
|
||||||
|
|
||||||
|
//Add possible crtcs
|
||||||
|
crtcs = ecore_x_randr_output_possible_crtcs_get(e_randr_screen_info.root, output_info->xid, &ncrtcs);
|
||||||
|
while (--ncrtcs >= 0)
|
||||||
|
{
|
||||||
|
if (!(crtc_info = _12_screen_info_crtc_info_get(crtcs[ncrtcs])))
|
||||||
|
continue;
|
||||||
|
output_info->possible_crtcs = eina_list_append(output_info->possible_crtcs, crtc_info);
|
||||||
|
}
|
||||||
|
free(crtcs);
|
||||||
|
|
||||||
|
crtc = ecore_x_randr_output_crtc_get(e_randr_screen_info.root, output_info->xid);
|
||||||
|
output_info->crtc = _12_screen_info_crtc_info_get(crtc);
|
||||||
|
|
||||||
|
if (output_info->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
|
||||||
|
output_info->monitor = _monitor_info_new(output_info);
|
||||||
|
else
|
||||||
|
output_info->monitor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ecore_X_Randr_Output *
|
||||||
|
_outputs_to_array(Eina_List *outputs_info)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Output *ret = NULL;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
Eina_List *output_iter;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
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! */
|
||||||
|
ret[i++] = output_info ? output_info->xid : Ecore_X_Randr_None;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns a list of modes common ammongst the given outputs,
|
||||||
|
* optionally limited by max_size_mode. If none are found, NULL is returned.
|
||||||
|
*/
|
||||||
|
Eina_List
|
||||||
|
*_outputs_common_modes_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode)
|
||||||
|
{
|
||||||
|
Eina_List *common_modes = NULL, *mode_iter, *output_iter;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
Ecore_X_Randr_Mode_Info *mode_info;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(outputs, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_randr_screen_info.rrvd_info.randr_info_12->modes, NULL);
|
||||||
|
|
||||||
|
//create a list of all common modes
|
||||||
|
common_modes = eina_list_clone(e_randr_screen_info.rrvd_info.randr_info_12->modes);
|
||||||
|
common_modes = eina_list_sort(common_modes, 0, _modes_size_sort_cb);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(common_modes, mode_iter, mode_info)
|
||||||
|
{
|
||||||
|
EINA_LIST_FOREACH(outputs, output_iter, output_info)
|
||||||
|
{
|
||||||
|
if (!eina_list_data_find(output_info->monitor->modes, mode_info))
|
||||||
|
common_modes = eina_list_remove(common_modes, mode_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_size_mode)
|
||||||
|
{
|
||||||
|
//remove all modes that are larger than max_size_mode
|
||||||
|
EINA_LIST_FOREACH(common_modes, mode_iter, mode_info)
|
||||||
|
{
|
||||||
|
if (_modes_size_sort_cb((void *)max_size_mode, (void *)mode_info) < 0)
|
||||||
|
common_modes = eina_list_remove(common_modes, mode_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//sort modes desc. by their sizes
|
||||||
|
common_modes = eina_list_reverse(common_modes);
|
||||||
|
|
||||||
|
return common_modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_modes_size_sort_cb(const void *d1, const void *d2)
|
||||||
|
{
|
||||||
|
Ecore_X_Randr_Mode_Info *mode1 = ((Ecore_X_Randr_Mode_Info *)d1), *mode2 = ((Ecore_X_Randr_Mode_Info *)d2);
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(d1, 1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(d2, -1);
|
||||||
|
|
||||||
|
return (mode1->width * mode1->height) - (mode2->width * mode2->height);
|
||||||
|
}
|
|
@ -0,0 +1,594 @@
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
#include "e_randr.h"
|
||||||
|
|
||||||
|
#define MODE_STR_LENGTH_MAX 100
|
||||||
|
|
||||||
|
const static char *_POLICIES_STRINGS[] = {"ABOVE", "RIGHT", "BELOW", "LEFT", "CLONE", "NONE"};
|
||||||
|
|
||||||
|
static E_Randr_Serialized_Crtc *_serialized_crtc_new(E_Randr_Crtc_Info *crtc_info);
|
||||||
|
static inline int _sort_by_number_of_edids(const void *d1, const void *d2);
|
||||||
|
static inline Eina_List *_find_matching_outputs(Eina_List *sois);
|
||||||
|
static inline E_Randr_Crtc_Info *_find_matching_crtc(E_Randr_Serialized_Crtc *sc);
|
||||||
|
static inline Ecore_X_Randr_Mode_Info *_find_matching_mode_info(Ecore_X_Randr_Mode_Info *mode);
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Storage/Restorage of setups
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Layout:
|
||||||
|
*
|
||||||
|
* Serialized_Setup_12 {
|
||||||
|
* - timestamp
|
||||||
|
* - List<Serialized_CRTC>
|
||||||
|
* - List<EDID>
|
||||||
|
* }
|
||||||
|
* Serialized_Crtc {
|
||||||
|
* - index
|
||||||
|
* - List<Serialized_Output>
|
||||||
|
* - pos
|
||||||
|
* - orientation
|
||||||
|
* - mode
|
||||||
|
* }
|
||||||
|
* Serialized_Output {
|
||||||
|
* - name
|
||||||
|
* - name_length
|
||||||
|
* - serialized_edid
|
||||||
|
* - backlight_level
|
||||||
|
* }
|
||||||
|
* Serialized_EDID {
|
||||||
|
* - edid_hash
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//"Free" helper functions
|
||||||
|
|
||||||
|
void
|
||||||
|
_serialized_output_free(E_Randr_Serialized_Output *so)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(so);
|
||||||
|
|
||||||
|
free(so);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_serialized_output_policy_free(E_Randr_Serialized_Output_Policy *sop)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(sop);
|
||||||
|
|
||||||
|
free(sop->name);
|
||||||
|
free(sop);
|
||||||
|
}
|
||||||
|
|
||||||
|
EINTERN void
|
||||||
|
e_randr_12_serialized_output_policy_free(E_Randr_Serialized_Output_Policy *policy)
|
||||||
|
{
|
||||||
|
_serialized_output_policy_free(policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_serialized_mode_info_free(Ecore_X_Randr_Mode_Info *mode_info)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(mode_info);
|
||||||
|
|
||||||
|
free(mode_info->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_serialized_crtc_free(E_Randr_Serialized_Crtc *sc)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Output *so;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(sc);
|
||||||
|
|
||||||
|
EINA_LIST_FREE (sc->outputs, so)
|
||||||
|
_serialized_output_free(so);
|
||||||
|
_serialized_mode_info_free(&sc->mode_info);
|
||||||
|
free(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//"New" helper functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Seeks given data in the list and returns the index
|
||||||
|
* of the first element equaling @data
|
||||||
|
* @param list The list to be examined
|
||||||
|
* @param data The data to be found
|
||||||
|
* @return if found, the index of the list node. Else -1.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
_eina_list_data_index_get(const Eina_List *list, const void *data)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
void *ndata;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
EINA_LIST_REVERSE_FOREACH(list, iter, ndata)
|
||||||
|
{
|
||||||
|
if (ndata == data)
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_mode_info_clone(Ecore_X_Randr_Mode_Info *dst, const Ecore_X_Randr_Mode_Info *src)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(dst);
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
{
|
||||||
|
dst->xid = Ecore_X_Randr_None;
|
||||||
|
dst->name = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->xid = src->xid;
|
||||||
|
dst->width = src->width;
|
||||||
|
dst->height = src->height;
|
||||||
|
dst->dotClock = src->dotClock;
|
||||||
|
dst->hSyncStart = src->hSyncStart;
|
||||||
|
dst->hSyncEnd = src->hSyncEnd;
|
||||||
|
dst->hTotal = src->hTotal;
|
||||||
|
dst->hSkew = src->hSkew;
|
||||||
|
dst->vSyncStart = src->vSyncStart;
|
||||||
|
dst->vSyncEnd = src->vSyncEnd;
|
||||||
|
dst->vTotal = src->vTotal;
|
||||||
|
if (src->nameLength > 0)
|
||||||
|
{
|
||||||
|
dst->name = malloc(src->nameLength + 1);
|
||||||
|
strncpy(dst->name, src->name, src->nameLength);
|
||||||
|
}
|
||||||
|
dst->nameLength = src->nameLength;
|
||||||
|
dst->modeFlags = src->modeFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_Randr_Edid_Hash
|
||||||
|
*_monitor_edid_hash_clone(E_Randr_Monitor_Info *mi)
|
||||||
|
{
|
||||||
|
E_Randr_Edid_Hash *edid_hash;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(mi, NULL);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((mi->edid_hash.hash == 0), NULL);
|
||||||
|
edid_hash = malloc(sizeof(E_Randr_Edid_Hash));
|
||||||
|
|
||||||
|
edid_hash->hash = mi->edid_hash.hash;
|
||||||
|
|
||||||
|
return edid_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_List *
|
||||||
|
_outputs_policies_list_new(Eina_List *outputs)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Output_Policy *sop;
|
||||||
|
Eina_List *iter, *list = NULL;
|
||||||
|
E_Randr_Output_Info *oi;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(outputs, NULL);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(outputs, iter, oi)
|
||||||
|
{
|
||||||
|
if (!oi->name) continue;
|
||||||
|
|
||||||
|
sop = E_NEW(E_Randr_Serialized_Output_Policy, 1);
|
||||||
|
sop->name = malloc(oi->name_length + 1);
|
||||||
|
strncpy(sop->name, oi->name, oi->name_length);
|
||||||
|
sop->policy = oi->policy;
|
||||||
|
list = eina_list_append(list, sop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_Randr_Serialized_Output *
|
||||||
|
_serialized_output_new(E_Randr_Output_Info *output_info)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Output *so;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(output_info, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(output_info->name, NULL);
|
||||||
|
|
||||||
|
so = E_NEW(E_Randr_Serialized_Output, 1);
|
||||||
|
|
||||||
|
so->name = malloc(output_info->name_length + 1);
|
||||||
|
strncpy(so->name, output_info->name, output_info->name_length);
|
||||||
|
if (output_info->monitor)
|
||||||
|
{
|
||||||
|
so->backlight_level = output_info->monitor->backlight_level;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
so->backlight_level = Ecore_X_Randr_Unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_Randr_Serialized_Crtc *
|
||||||
|
_serialized_crtc_new(E_Randr_Crtc_Info *crtc_info)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Crtc *sc = NULL;
|
||||||
|
E_Randr_Serialized_Output *so = NULL;
|
||||||
|
E_Randr_Output_Info *output_info = NULL;
|
||||||
|
Eina_List *iter;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(crtc_info, NULL);
|
||||||
|
|
||||||
|
sc = E_NEW(E_Randr_Serialized_Crtc, 1);
|
||||||
|
|
||||||
|
//Get relative index of CRTC
|
||||||
|
sc->index = _eina_list_data_index_get(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, crtc_info);
|
||||||
|
//Create list of serialized outputs
|
||||||
|
EINA_LIST_FOREACH(crtc_info->outputs, iter, output_info)
|
||||||
|
{
|
||||||
|
if (!(so = _serialized_output_new(output_info)))
|
||||||
|
continue;
|
||||||
|
sc->outputs = eina_list_append(sc->outputs, so);
|
||||||
|
fprintf(stderr, "E_RANDR:\t Serialized output %s.\n", so->name);
|
||||||
|
}
|
||||||
|
sc->pos.x = crtc_info->geometry.x;
|
||||||
|
sc->pos.y = crtc_info->geometry.y;
|
||||||
|
sc->orientation = crtc_info->current_orientation;
|
||||||
|
//Clone mode
|
||||||
|
_mode_info_clone(&sc->mode_info, crtc_info->current_mode);
|
||||||
|
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_Randr_Serialized_Setup_12 *
|
||||||
|
_12_serialized_setup_new(void)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Setup_12 *ss = NULL;
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Randr_Crtc_Info *ci;
|
||||||
|
E_Randr_Output_Info *oi;
|
||||||
|
E_Randr_Serialized_Crtc *sc;
|
||||||
|
E_Randr_Edid_Hash *edid_hash;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_randr_screen_info.rrvd_info.randr_info_12->outputs, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, NULL);
|
||||||
|
|
||||||
|
ss = E_NEW(E_Randr_Serialized_Setup_12, 1);
|
||||||
|
|
||||||
|
ss->timestamp = ecore_time_get();
|
||||||
|
|
||||||
|
//Add CRTCs and their configuration
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, ci)
|
||||||
|
{
|
||||||
|
sc = _serialized_crtc_new(ci);
|
||||||
|
if (!sc)
|
||||||
|
continue;
|
||||||
|
ss->crtcs = eina_list_append(ss->crtcs, sc);
|
||||||
|
fprintf(stderr, "E_RANDR: Serialized CRTC %d (index %d) in mode %s.\n", ci->xid, sc->index, sc->mode_info.name ? sc->mode_info.name : "(disabled)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add EDID hashes of connected outputs
|
||||||
|
* for easier comparison during
|
||||||
|
* setup restoration
|
||||||
|
*/
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, oi)
|
||||||
|
{
|
||||||
|
if (oi->connection_status != ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
|
||||||
|
continue;
|
||||||
|
edid_hash = _monitor_edid_hash_clone(oi->monitor);
|
||||||
|
ss->edid_hashes = eina_list_append(ss->edid_hashes, edid_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update (also retrieval) helper functions
|
||||||
|
|
||||||
|
E_Randr_Serialized_Setup_12 *
|
||||||
|
_matching_serialized_setup_get(Eina_List *setups_12)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Setup_12 *ss_12;
|
||||||
|
Eina_List *setups_iter, *edid_iter;
|
||||||
|
E_Randr_Edid_Hash *edid_hash;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, NULL);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(setups_12, NULL);
|
||||||
|
|
||||||
|
//Sort list of setups by the number of monitors involved
|
||||||
|
setups_12 = eina_list_sort(setups_12, 0, _sort_by_number_of_edids);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(setups_12, setups_iter, ss_12)
|
||||||
|
{
|
||||||
|
//1. Make sure: #outputs >= #serialized EDIDs
|
||||||
|
if (eina_list_count(e_randr_screen_info.rrvd_info.randr_info_12->outputs) < eina_list_count(ss_12->edid_hashes))
|
||||||
|
continue;
|
||||||
|
//2. Compare #CRTCs
|
||||||
|
if (eina_list_count(e_randr_screen_info.rrvd_info.randr_info_12->crtcs) != eina_list_count(ss_12->crtcs))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//3. Find all serialized EDIDs
|
||||||
|
EINA_LIST_FOREACH(ss_12->edid_hashes, edid_iter, edid_hash)
|
||||||
|
{
|
||||||
|
if (!_12_screen_info_edid_is_available(edid_hash))
|
||||||
|
goto _setup_12_skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
//4. All EDIDs found? Great, let's go!
|
||||||
|
return ss_12;
|
||||||
|
_setup_12_skip:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// None found!
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_List *
|
||||||
|
_outputs_policies_update(Eina_List *sops)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Output_Policy *sop;
|
||||||
|
|
||||||
|
EINA_LIST_FREE (sops, sop)
|
||||||
|
{
|
||||||
|
_serialized_output_policy_free(sop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _outputs_policies_list_new(e_randr_screen_info.rrvd_info.randr_info_12->outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_List *
|
||||||
|
_12_serialized_setup_update(Eina_List *setups_12)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Setup_12 *ss_12;
|
||||||
|
|
||||||
|
if (setups_12)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* try to find the setup with the same monitors
|
||||||
|
* connected in order to replace it
|
||||||
|
*/
|
||||||
|
if ((ss_12 = _matching_serialized_setup_get(setups_12)))
|
||||||
|
{
|
||||||
|
_12_serialized_setup_free(ss_12);
|
||||||
|
setups_12 = eina_list_remove(setups_12, ss_12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss_12 = _12_serialized_setup_new();
|
||||||
|
setups_12 = eina_list_append(setups_12, ss_12);
|
||||||
|
|
||||||
|
return setups_12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_12_policies_restore(void)
|
||||||
|
{
|
||||||
|
E_Randr_Output_Info *output;
|
||||||
|
E_Randr_Serialized_Output_Policy *sop;
|
||||||
|
Eina_List *iter, *iter2;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(e_config->randr_serialized_setup);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(e_config->randr_serialized_setup->outputs_policies);
|
||||||
|
|
||||||
|
// Restore policies
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output)
|
||||||
|
{
|
||||||
|
EINA_LIST_FOREACH(e_config->randr_serialized_setup->outputs_policies, iter2, sop)
|
||||||
|
{
|
||||||
|
if (!strncmp(sop->name, output->name, output->name_length))
|
||||||
|
{
|
||||||
|
output->policy = sop->policy;
|
||||||
|
fprintf(stderr, "E_RANDR: Policy \"%s\" for output \"%s\" restored.\n", _POLICIES_STRINGS[sop->policy - 1], output->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
_12_try_restore_configuration(void)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Setup_12 *ss_12;
|
||||||
|
E_Randr_Serialized_Crtc *sc;
|
||||||
|
E_Randr_Crtc_Info *ci;
|
||||||
|
Ecore_X_Randr_Output *outputs_array;
|
||||||
|
E_Randr_Output_Info *output_info;
|
||||||
|
Ecore_X_Randr_Mode_Info *mi;
|
||||||
|
Ecore_X_Randr_Mode mode;
|
||||||
|
Eina_List *iter, *outputs_list, *outputs_iter;
|
||||||
|
Eina_Bool ret = EINA_TRUE;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_config, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_config->randr_serialized_setup, EINA_FALSE);
|
||||||
|
|
||||||
|
if (!(ss_12 = _matching_serialized_setup_get(e_config->randr_serialized_setup->serialized_setups_12)))
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
fprintf(stderr, "E_RANDR: Found matching serialized setup.\n");
|
||||||
|
EINA_LIST_FOREACH(ss_12->crtcs, iter, sc)
|
||||||
|
{
|
||||||
|
ci = _find_matching_crtc(sc);
|
||||||
|
outputs_list = _find_matching_outputs(sc->outputs);
|
||||||
|
outputs_array = _outputs_to_array(outputs_list);
|
||||||
|
fprintf(stderr, "E_RANDR: \tSerialized mode ");
|
||||||
|
if (sc->mode_info.xid == Ecore_X_Randr_None)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "was disabled.\n");
|
||||||
|
mode = Ecore_X_Randr_None;
|
||||||
|
}
|
||||||
|
else if ((mi = _find_matching_mode_info(&sc->mode_info)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "is now known under the name %s.\n", mi->name);
|
||||||
|
mode = mi->xid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The serialized mode is no longer available
|
||||||
|
mi->name = malloc(MODE_STR_LENGTH_MAX);
|
||||||
|
//IMPROVABLE: Use random string, like mktemp for files
|
||||||
|
snprintf(mi->name, (MODE_STR_LENGTH_MAX - 1), "%ux%u,%lu,%lu", sc->mode_info.width, sc->mode_info.height, sc->mode_info.dotClock, sc->mode_info.modeFlags);
|
||||||
|
mi = &sc->mode_info;
|
||||||
|
mode = ecore_x_randr_mode_info_add(e_randr_screen_info.root, mi);
|
||||||
|
if (mode == Ecore_X_Randr_None)
|
||||||
|
{
|
||||||
|
eina_list_free(outputs_list);
|
||||||
|
free(outputs_array);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EINA_LIST_FOREACH(outputs_list, outputs_iter, output_info)
|
||||||
|
ecore_x_randr_output_mode_add(output_info->xid, mode);
|
||||||
|
fprintf(stderr, "was now added to the server manually using the name %s.\n", mi->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
fprintf(stderr, "E_RANDR: \tRestoring CRTC %d (index %d) in mode %s.\n", ci->xid, sc->index, (mode == Ecore_X_Randr_None) ? "(disabled)" : mi->name);
|
||||||
|
fprintf(stderr, "E_RANDR: \t\tUsed outputs:");
|
||||||
|
EINA_LIST_FOREACH(outputs_list, outputs_iter, output_info)
|
||||||
|
fprintf(stderr, " %s", output_info->name);
|
||||||
|
fprintf(stderr, ".\n");
|
||||||
|
// DEBUG END
|
||||||
|
|
||||||
|
ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, ci->xid, outputs_array, eina_list_count(outputs_list), mode);
|
||||||
|
eina_list_free(outputs_list);
|
||||||
|
free(outputs_array);
|
||||||
|
ret &= ecore_x_randr_crtc_pos_set(e_randr_screen_info.root, ci->xid, sc->pos.x, sc->pos.y);
|
||||||
|
ret &= ecore_x_randr_crtc_orientation_set(e_randr_screen_info.root, ci->xid, sc->orientation);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_12_serialized_setup_free(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->crtcs, sc)
|
||||||
|
{
|
||||||
|
_serialized_crtc_free(sc);
|
||||||
|
}
|
||||||
|
EINA_LIST_FREE (ss_12->edid_hashes, edid_hash)
|
||||||
|
free(edid_hash);
|
||||||
|
|
||||||
|
free(ss_12);
|
||||||
|
}
|
||||||
|
|
||||||
|
EINTERN void
|
||||||
|
e_randr_12_serialized_setup_free(E_Randr_Serialized_Setup_12 *ss_12)
|
||||||
|
{
|
||||||
|
_12_serialized_setup_free(ss_12);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_12_store_configuration(E_Randr_Configuration_Store_Modifier modifier)
|
||||||
|
{
|
||||||
|
if (modifier & (E_RANDR_CONFIGURATION_STORE_RESOLUTIONS | E_RANDR_CONFIGURATION_STORE_ARRANGEMENT | E_RANDR_CONFIGURATION_STORE_ORIENTATIONS))
|
||||||
|
{
|
||||||
|
e_config->randr_serialized_setup->serialized_setups_12 = _12_serialized_setup_update(e_config->randr_serialized_setup->serialized_setups_12);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifier & E_RANDR_CONFIGURATION_STORE_POLICIES)
|
||||||
|
{
|
||||||
|
//update output policies
|
||||||
|
e_config->randr_serialized_setup->outputs_policies = _outputs_policies_update(e_config->randr_serialized_setup->outputs_policies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Retrievel functions for the current e_randr_screen_info context
|
||||||
|
|
||||||
|
// Find entities for restoration in current e_randr_screen_info context
|
||||||
|
static E_Randr_Crtc_Info *
|
||||||
|
_find_matching_crtc(E_Randr_Serialized_Crtc *sc)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(sc, NULL);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, NULL);
|
||||||
|
|
||||||
|
return eina_list_nth(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, sc->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates list of E_Randr_Output_Info* elements for list of
|
||||||
|
* E_Randr_Serialized_Output* objects.
|
||||||
|
* @param sois list of E_Randr_Serialized_Output* elements
|
||||||
|
* @return List of E_Randr_Output* elements or NULL, if not all outputs could be
|
||||||
|
* found or monitors are connected to different outputs
|
||||||
|
*/
|
||||||
|
static Eina_List *
|
||||||
|
_find_matching_outputs(Eina_List *sois)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "E_RANDR: \tLooking for serialized output \"%s\"\n", so->name);
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, r_output_iter, oi)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "E_RANDR: \t\tComparing to output \"%s\"\n", oi->name);
|
||||||
|
if (!strncmp(so->name, oi->name, oi->name_length))
|
||||||
|
{
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Ecore_X_Randr_Mode_Info *
|
||||||
|
_find_matching_mode_info(Ecore_X_Randr_Mode_Info *mode)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
Ecore_X_Randr_Mode_Info *mi = NULL;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->modes, iter, mi)
|
||||||
|
{
|
||||||
|
if (!strncmp(mode->name, mi->name, mode->nameLength))
|
||||||
|
return mi;
|
||||||
|
}
|
||||||
|
EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->modes, iter, mi)
|
||||||
|
{
|
||||||
|
#define EQL(arg) (mi->arg == mode->arg)
|
||||||
|
if (EQL(width) &&
|
||||||
|
EQL(height) &&
|
||||||
|
EQL(dotClock) &&
|
||||||
|
EQL(hSyncStart) &&
|
||||||
|
EQL(hSyncEnd) &&
|
||||||
|
EQL(hTotal) &&
|
||||||
|
EQL(hSkew) &&
|
||||||
|
EQL(vSyncStart) &&
|
||||||
|
EQL(vSyncEnd) &&
|
||||||
|
EQL(vTotal) &&
|
||||||
|
EQL(modeFlags))
|
||||||
|
return mi;
|
||||||
|
#undef EQL
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sort_by_number_of_edids(const void *d1, const void *d2)
|
||||||
|
{
|
||||||
|
const E_Randr_Serialized_Setup_12 *ss1 = (const E_Randr_Serialized_Setup_12*)d1;
|
||||||
|
const E_Randr_Serialized_Setup_12 *ss2 = (const E_Randr_Serialized_Setup_12*)d1;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ss1, 1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ss2, -1);
|
||||||
|
|
||||||
|
if (eina_list_count(ss2->edid_hashes) > eina_list_count(ss1->edid_hashes))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#ifdef E_TYPEDEFS
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifndef E_RANDR_PRIVATE_H
|
||||||
|
#define E_RANDR_PRIVATE_H
|
||||||
|
|
||||||
|
#include "e.h"
|
||||||
|
|
||||||
|
#define ECORE_X_RANDR_1_1 ((1 << 16) | 1)
|
||||||
|
#define ECORE_X_RANDR_1_2 ((1 << 16) | 2)
|
||||||
|
#define ECORE_X_RANDR_1_3 ((1 << 16) | 3)
|
||||||
|
|
||||||
|
#define Ecore_X_Randr_Unset -1
|
||||||
|
#define Ecore_X_Randr_None 0
|
||||||
|
|
||||||
|
#define E_RANDR_11_NO ((e_randr_screen_info.randr_version < ECORE_X_RANDR_1_1) || !e_randr_screen_info.rrvd_info.randr_info_11)
|
||||||
|
#define E_RANDR_12_NO ((e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2) || !e_randr_screen_info.rrvd_info.randr_info_12)
|
||||||
|
#define E_RANDR_12_NO_CRTCS (E_RANDR_12_NO || !e_randr_screen_info.rrvd_info.randr_info_12->crtcs)
|
||||||
|
#define E_RANDR_12_NO_CRTC(crtc) (E_RANDR_12_NO || !e_randr_screen_info.rrvd_info.randr_info_12->crtcs || (crtc == Ecore_X_Randr_None))
|
||||||
|
#define E_RANDR_12_NO_OUTPUTS (E_RANDR_12_NO || !e_randr_screen_info.rrvd_info.randr_info_12->outputs)
|
||||||
|
#define E_RANDR_12_NO_OUTPUT(output) (E_RANDR_12_NO || !e_randr_screen_info.rrvd_info.randr_info_12->outputs || (output == Ecore_X_Randr_None))
|
||||||
|
#define E_RANDR_12_NO_MODES (E_RANDR_12_NO || !e_randr_screen_info.rrvd_info.randr_info_12->modes)
|
||||||
|
#define E_RANDR_12_NO_MODE(mode) (E_RANDR_12_NO || !e_randr_screen_info.rrvd_info.randr_info_12->modes || (mode == Ecore_X_Randr_None))
|
||||||
|
|
||||||
|
// RandRR == 1.1
|
||||||
|
E_Randr_Screen_Info_11 *_11_screen_info_new(void);
|
||||||
|
void _11_screen_info_free(E_Randr_Screen_Info_11 *screen_info_11);
|
||||||
|
void _11_screen_info_refresh(void);
|
||||||
|
Eina_Bool _11_try_restore_configuration(void);
|
||||||
|
void _11_store_configuration(E_Randr_Configuration_Store_Modifier modifier);
|
||||||
|
|
||||||
|
// RandRR >= 1.2
|
||||||
|
E_Randr_Screen_Info_12 *_12_screen_info_new(void);
|
||||||
|
void _12_screen_info_free(E_Randr_Screen_Info_12 *screen_info_12);
|
||||||
|
void _12_screen_info_refresh(void);
|
||||||
|
void _12_policies_restore(void);
|
||||||
|
void _12_event_listeners_add(void);
|
||||||
|
void _12_event_listeners_remove(void);
|
||||||
|
// Retrieval functions
|
||||||
|
Ecore_X_Randr_Mode_Info *_12_screen_info_mode_info_get(const Ecore_X_Randr_Mode mode);
|
||||||
|
E_Randr_Crtc_Info *_12_screen_info_crtc_info_get(const Ecore_X_Randr_Crtc crtc);
|
||||||
|
E_Randr_Output_Info *_12_screen_info_output_info_get(const Ecore_X_Randr_Output output);
|
||||||
|
Eina_Bool _12_screen_info_edid_is_available(const E_Randr_Edid_Hash *hash);
|
||||||
|
// (Re)store data
|
||||||
|
E_Randr_Serialized_Setup_12 *_12_serialized_setup_new(void);
|
||||||
|
void _12_serialized_setup_free(E_Randr_Serialized_Setup_12 *ss_12);
|
||||||
|
Eina_Bool _12_try_restore_configuration(void);
|
||||||
|
void _12_store_configuration(E_Randr_Configuration_Store_Modifier modifier);
|
||||||
|
|
||||||
|
// >= 1.2 Substructures helper functions
|
||||||
|
E_Randr_Monitor_Info *_monitor_info_new(E_Randr_Output_Info *output_info);
|
||||||
|
void _monitor_info_free(E_Randr_Monitor_Info *monitor_info);
|
||||||
|
void _monitor_modes_refs_set(E_Randr_Monitor_Info *mi, Ecore_X_Randr_Output output);
|
||||||
|
E_Randr_Output_Info *_output_info_new(Ecore_X_Randr_Output output);
|
||||||
|
void _output_info_free(E_Randr_Output_Info *output_info);
|
||||||
|
void _output_refs_set(E_Randr_Output_Info *output_info);
|
||||||
|
Ecore_X_Randr_Output *_outputs_to_array(Eina_List *outputs_info);
|
||||||
|
Eina_List *_outputs_common_modes_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode);
|
||||||
|
|
||||||
|
E_Randr_Crtc_Info * _crtc_info_new(Ecore_X_Randr_Crtc crtc);
|
||||||
|
void _crtc_info_free(E_Randr_Crtc_Info *crtc_info);
|
||||||
|
void _crtc_refs_set(E_Randr_Crtc_Info *crtc_info);
|
||||||
|
void _crtc_outputs_refs_set(E_Randr_Crtc_Info *crtc_info);
|
||||||
|
const Eina_Bool _crtc_move_policy(E_Randr_Crtc_Info *new_crtc);
|
||||||
|
const E_Randr_Crtc_Info *_crtc_according_to_policy_get(E_Randr_Crtc_Info *but, Ecore_X_Randr_Output_Policy policy);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include "e_randr_private.h"
|
||||||
|
#include "e_randr.h"
|
||||||
|
|
||||||
|
#define ECORE_X_RANDR_1_1 ((1 << 16) | 1)
|
||||||
|
#define ECORE_X_RANDR_1_2 ((1 << 16) | 2)
|
||||||
|
#define ECORE_X_RANDR_1_3 ((1 << 16) | 3)
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Storage/Restorage of setups
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
E_Randr_Serialized_Setup *
|
||||||
|
_new_serialized_setup(void)
|
||||||
|
{
|
||||||
|
return E_NEW(E_Randr_Serialized_Setup, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
e_randr_store_configuration(E_Randr_Configuration_Store_Modifier modifier)
|
||||||
|
{
|
||||||
|
if (!e_config->randr_serialized_setup)
|
||||||
|
e_config->randr_serialized_setup = _new_serialized_setup();
|
||||||
|
|
||||||
|
fprintf(stderr, "E_RANDR: Configuration shall be stored using the following modifier: %d.\n", modifier);
|
||||||
|
|
||||||
|
if (e_randr_screen_info.randr_version == ECORE_X_RANDR_1_1)
|
||||||
|
{
|
||||||
|
_11_store_configuration(modifier);
|
||||||
|
}
|
||||||
|
else if (e_randr_screen_info.randr_version >= ECORE_X_RANDR_1_2)
|
||||||
|
{
|
||||||
|
_12_store_configuration(modifier);
|
||||||
|
}
|
||||||
|
e_config_save_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
_try_restore_configuration(void)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_config, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e_config->randr_serialized_setup, EINA_FALSE);
|
||||||
|
|
||||||
|
if (e_randr_screen_info.randr_version == ECORE_X_RANDR_1_1)
|
||||||
|
return _11_try_restore_configuration();
|
||||||
|
else if (e_randr_screen_info.randr_version >= ECORE_X_RANDR_1_2)
|
||||||
|
return _12_try_restore_configuration();
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EINTERN void e_randr_serialized_setup_free(E_Randr_Serialized_Setup *ss)
|
||||||
|
{
|
||||||
|
E_Randr_Serialized_Setup_12 *serialized_setup_12 = NULL;
|
||||||
|
E_Randr_Serialized_Output_Policy *serialized_output_policy = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(ss);
|
||||||
|
|
||||||
|
e_randr_11_serialized_setup_free(ss->serialized_setup_11);
|
||||||
|
if (ss->serialized_setups_12)
|
||||||
|
{
|
||||||
|
EINA_LIST_FREE(ss->serialized_setups_12, serialized_setup_12)
|
||||||
|
{
|
||||||
|
e_randr_12_serialized_setup_free(serialized_setup_12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EINA_LIST_FREE(ss->outputs_policies, serialized_output_policy)
|
||||||
|
{
|
||||||
|
e_randr_12_serialized_output_policy_free(serialized_output_policy);
|
||||||
|
}
|
||||||
|
free(ss);
|
||||||
|
}
|
Loading…
Reference in New Issue