@ -6,11 +6,15 @@ static void _e_randr_config_new(void);
static void _e_randr_config_free ( void ) ;
static Eina_Bool _e_randr_config_cb_timer ( void * data ) ;
static void _e_randr_config_restore ( void ) ;
static Eina_Bool _e_randr_config_crtc_update ( E_Randr_Crtc_Config * cfg ) ;
static Eina_Bool _e_randr_config_output_update ( E_Randr_Output_Config * cfg ) ;
static E_Randr_Crtc_Config * _e_randr_config_output_crtc_find ( E_Randr_Output_Config * cfg ) ;
static Ecore_X_Randr_Mode _e_randr_config_output_preferred_mode_get ( E_Randr_Output_Config * cfg ) ;
static E_Randr_Output_Config * _e_randr_config_output_new ( unsigned int id ) ;
static Eina_Bool _e_randr_event_cb_screen_change ( void * data EINA_UNUSED , int type EINA_UNUSED , void * event ) ;
static Eina_Bool _e_randr_event_cb_crtc_change ( void * data EINA_UNUSED , int type EINA_UNUSED , void * event ) ;
static Eina_Bool _e_randr_event_cb_output_change ( void * data EINA_UNUSED , int type EINA_UNUSED , void * event ) ;
static Eina_Bool _e_randr_event_cb_property_change ( void * data EINA_UNUSED , int type EINA_UNUSED , void * event EINA_UNUSED ) ;
/* local variables */
static Eina_List * _randr_event_handlers = NULL ;
@ -55,9 +59,6 @@ e_randr_init(void)
E_LIST_HANDLER_APPEND ( _randr_event_handlers ,
ECORE_X_EVENT_RANDR_OUTPUT_CHANGE ,
_e_randr_event_cb_output_change , NULL ) ;
E_LIST_HANDLER_APPEND ( _randr_event_handlers ,
ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY ,
_e_randr_event_cb_property_change , NULL ) ;
}
return EINA_TRUE ;
@ -154,6 +155,7 @@ _e_randr_config_load(void)
E_CONFIG_LIST ( D , T , crtcs , _e_randr_crtc_edd ) ;
E_CONFIG_VAL ( D , T , restore , UCHAR ) ;
E_CONFIG_VAL ( D , T , poll_interval , INT ) ;
E_CONFIG_VAL ( D , T , config_timestamp , ULL ) ;
/* try to load the randr config */
if ( ( e_randr_cfg = e_config_domain_load ( " e_randr " , _e_randr_edd ) ) )
@ -199,12 +201,6 @@ _e_randr_config_load(void)
/* e_randr_config_new could return without actually creating a new config */
if ( ! e_randr_cfg ) return EINA_FALSE ;
/* handle upgrading any old config */
/* if (e_randr_cfg->version < E_RANDR_CONFIG_FILE_VERSION) */
/* { */
/* } */
if ( ( do_restore ) & & ( e_randr_cfg - > restore ) )
_e_randr_config_restore ( ) ;
@ -216,7 +212,6 @@ _e_randr_config_new(void)
{
Ecore_X_Window root = 0 ;
Ecore_X_Randr_Crtc * crtcs = NULL ;
Ecore_X_Randr_Output primary = 0 ;
int ncrtcs = 0 , i = 0 ;
/* create new randr cfg */
@ -235,9 +230,6 @@ _e_randr_config_new(void)
/* grab the root window once */
root = ecore_x_window_root_first_get ( ) ;
/* get which output is primary */
primary = ecore_x_randr_primary_output_get ( root ) ;
/* record the current screen size in our config */
ecore_x_randr_screen_current_size_get ( root , & e_randr_cfg - > screen . width ,
& e_randr_cfg - > screen . height ,
@ -261,18 +253,8 @@ _e_randr_config_new(void)
crtc_cfg - > xid = crtcs [ i ] ;
crtc_cfg - > exists = EINA_TRUE ;
/* record the geometry of this crtc in our config */
ecore_x_randr_crtc_geometry_get ( root , crtcs [ i ] ,
& crtc_cfg - > x , & crtc_cfg - > y ,
& crtc_cfg - > width ,
& crtc_cfg - > height ) ;
/* record the orientation of this crtc in our config */
crtc_cfg - > orient =
ecore_x_randr_crtc_orientation_get ( root , crtcs [ i ] ) ;
/* record the mode id of this crtc in our config */
crtc_cfg - > mode = ecore_x_randr_crtc_mode_get ( root , crtcs [ i ] ) ;
/* fill in crtc_cfg values from X */
_e_randr_config_crtc_update ( crtc_cfg ) ;
/* try to get any outputs on this crtc */
if ( ( outputs =
@ -283,46 +265,13 @@ _e_randr_config_new(void)
for ( j = 0 ; j < noutputs ; j + + )
{
E_Randr_Output_Config * output_cfg = NULL ;
Ecore_X_Randr_Connection_Status status = 1 ;
int clone_count = 0 ;
/* try to create new output config */
if ( ! ( output_cfg = E_NEW ( E_Randr_Output_Config , 1 ) ) )
if ( ! ( output_cfg = _e_randr_config_output_new ( outputs [ j ] ) ) )
continue ;
/* assign output xid */
output_cfg - > xid = outputs [ j ] ;
/* assign crtc for this output */
output_cfg - > crtc = crtcs [ i ] ;
/* set this output policy */
output_cfg - > policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE ;
/* get if this output is the primary */
output_cfg - > primary = EINA_FALSE ;
if ( outputs [ j ] = = primary )
output_cfg - > primary = EINA_TRUE ;
/* record the edid for this output */
output_cfg - > edid =
ecore_x_randr_output_edid_get ( root , outputs [ j ] ,
& output_cfg - > edid_count ) ;
/* get the clones for this output */
output_cfg - > clones =
ecore_x_randr_output_clones_get ( root , outputs [ j ] ,
& clone_count ) ;
output_cfg - > clone_count = ( long ) clone_count ;
status =
ecore_x_randr_output_connection_status_get ( root , outputs [ j ] ) ;
output_cfg - > connected = EINA_FALSE ;
if ( status = = ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED )
output_cfg - > connected = EINA_TRUE ;
output_cfg - > exists = EINA_TRUE ;
/* add this output to the list for this crtc */
@ -341,6 +290,9 @@ _e_randr_config_new(void)
free ( crtcs ) ;
}
/* update recorded config timestamp */
e_randr_cfg - > config_timestamp = ecore_x_randr_config_timestamp_get ( root ) ;
/* set limits */
E_CONFIG_LIMIT ( e_randr_cfg - > poll_interval , 1 , 1024 ) ;
@ -390,37 +342,34 @@ _e_randr_config_restore(void)
Ecore_X_Window root = 0 ;
Ecore_X_Randr_Crtc * crtcs ;
int ncrtcs = 0 ;
Eina_Bool need_reset = EINA_FALSE ;
/* try to restore settings
*
* NB : When we restore , check the resolutions ( current vs saved )
* and if there is no change then we do not need to call
* screen_reset as this triggers a full comp refresh . We can
* accomplish this simply by checking the mode */
printf ( " E_RANDR Restore \n " ) ;
/* grab the root window */
root = ecore_x_window_root_first_get ( ) ;
/* try to get the list of crtcs */
/* set the screen size */
/* NB: Disabled for now as our saved screen size may not be valid
* if any of our saved outputs are missing in X */
/* ecore_x_randr_screen_current_size_set(root, e_randr_cfg->screen.width, */
/* e_randr_cfg->screen.height, -1, -1); */
/* try to get the list of existing crtcs from X */
if ( ( crtcs = ecore_x_randr_crtcs_get ( root , & ncrtcs ) ) )
{
int i = 0 ;
Eina_List * valid_crtcs = NULL ;
Eina_List * l ;
E_Randr_Crtc_Config * crtc_cfg ;
printf ( " \t Have Crtcs \n " ) ;
/* for each crtc that X has, check our config and see if we have it */
for ( i = 0 ; i < ncrtcs ; i + + )
{
Eina_List * l ;
E_Randr_Crtc_Config * crtc_cfg ;
Ecore_X_Randr_Mode mode ;
Ecore_X_Randr_Output * outputs ;
int noutputs = 0 ;
/* get the mode */
mode = ecore_x_randr_crtc_mode_get ( root , crtcs [ i ] ) ;
Eina_Bool crtc_found = EINA_FALSE ;
/* get the outputs */
outputs =
ecore_x_randr_crtc_outputs_get ( root , crtcs [ i ] , & noutputs ) ;
printf ( " \t \t Checking For Crtc: %d in Our Config \n " , crtcs [ i ] ) ;
/* loop our config and find this crtc */
EINA_LIST_FOREACH ( e_randr_cfg - > crtcs , l , crtc_cfg )
@ -428,33 +377,167 @@ _e_randr_config_restore(void)
/* try to find this crtc */
if ( crtc_cfg - > xid ! = crtcs [ i ] ) continue ;
/* apply the stored settings */
if ( ! crtc_cfg - > mode )
ecore_x_randr_crtc_settings_set ( root , crtc_cfg - > xid ,
NULL , 0 , 0 , 0 , 0 ,
ECORE_X_RANDR_ORIENTATION_ROT_0 ) ;
else
ecore_x_randr_crtc_settings_set ( root , crtc_cfg - > xid ,
outputs , noutputs ,
crtc_cfg - > x , crtc_cfg - > y ,
crtc_cfg - > mode ,
crtc_cfg - > orient ) ;
crtc_found = EINA_TRUE ;
printf ( " \t \t \t Found Crtc in Config \n " ) ;
valid_crtcs = eina_list_append ( valid_crtcs , crtc_cfg ) ;
}
if ( ! crtc_found )
{
printf ( " \t \t \t Crtc Not Found in Config \n " ) ;
printf ( " \t \t \t \t Creating New \n " ) ;
/* create new crtc config */
if ( ( crtc_cfg = E_NEW ( E_Randr_Crtc_Config , 1 ) ) )
{
/* assign id */
crtc_cfg - > xid = crtcs [ i ] ;
crtc_cfg - > exists = EINA_TRUE ;
if ( crtc_cfg - > mode ! = mode )
need_reset = EINA_TRUE ;
/* fill in crtc_cfg values from X */
_e_randr_config_crtc_update ( crtc_cfg ) ;
break ;
}
printf ( " \t \t \t \t New Crtc Geom: %d %d %d %d \n " ,
crtc_cfg - > x , crtc_cfg - > y , crtc_cfg - > width ,
crtc_cfg - > height ) ;
printf ( " \t \t \t \t New Crtc Mode: %d \n " , crtc_cfg - > mode ) ;
/* append to randr cfg */
e_randr_cfg - > crtcs =
eina_list_append ( e_randr_cfg - > crtcs , crtc_cfg ) ;
/* free any allocated memory from ecore_x_randr */
free ( outputs ) ;
e_randr_config_save ( ) ;
/* append to our short list */
valid_crtcs = eina_list_append ( valid_crtcs , crtc_cfg ) ;
}
}
}
/* free any allocated memory from ecore_x_randr */
free ( crtcs ) ;
printf ( " \t \t Looping Valid Crtcs \n " ) ;
/* for each X crtc that we have config for, check outputs */
EINA_LIST_FOREACH ( valid_crtcs , l , crtc_cfg )
{
Ecore_X_Randr_Output * outputs ;
int noutputs ;
Eina_List * valid_outputs = NULL ;
/* we have this crtc. try to get list of outputs from X */
if ( ( outputs =
ecore_x_randr_crtc_outputs_get ( root , crtc_cfg - > xid , & noutputs ) ) )
{
int j = 0 ;
printf ( " \t \t \t Have X Outputs For Crtc: %d \n " , crtc_cfg - > xid ) ;
/* loop the X outputs and find a matching config */
for ( j = 0 ; j < noutputs ; j + + )
{
Eina_List * ll ;
E_Randr_Output_Config * output_cfg ;
/* Eina_Bool output_found = EINA_FALSE; */
printf ( " \t \t \t \t Checking for Output: %d in Our Config \n " , outputs [ j ] ) ;
/* loop our outputs for this crtc */
EINA_LIST_FOREACH ( crtc_cfg - > outputs , ll , output_cfg )
{
/* try to find this output */
if ( output_cfg - > xid ! = outputs [ j ] ) continue ;
/* we have this output */
/* output_found = EINA_TRUE; */
printf ( " \t \t \t \t Found Output In Config: %d \n " , outputs [ j ] ) ;
/* add this output config to the list of
* ones that we are going to restore for
* this crtc */
valid_outputs =
eina_list_append ( valid_outputs , output_cfg ) ;
break ;
}
/* if (!output_found) */
/* { */
/* printf("\t\t\tOutput Not Found, Creating New\n"); */
/* if ((output_cfg = */
/* _e_randr_output_config_new(outputs[j]))) */
/* { */
/* valid_outputs = */
/* eina_list_append(valid_outputs, output_cfg); */
/* } */
/* } */
}
free ( outputs ) ;
}
else
{
printf ( " \t \t \t No Outputs For Crtc: %d \n " , crtc_cfg - > xid ) ;
/* crtc has no outputs assigned */
/* Need to check possibles */
}
/* apply settings for this crtc */
printf ( " \t \t \t \t Applying Crtc Settings: %d \n " , crtc_cfg - > xid ) ;
if ( ! crtc_cfg - > mode )
{
printf ( " \t \t \t \t \t CRTC HAS NO MODE !!! \n " ) ;
ecore_x_randr_crtc_settings_set ( root , crtc_cfg - > xid ,
NULL , 0 , 0 , 0 , 0 ,
ECORE_X_RANDR_ORIENTATION_ROT_0 ) ;
}
else
{
int ocount , c = 0 ;
ocount = eina_list_count ( valid_outputs ) ;
printf ( " \t \t \t \t \t Num Outputs: %d \n " , ocount ) ;
if ( ocount > 0 )
{
Ecore_X_Randr_Output * couts ;
Eina_List * o ;
E_Randr_Output_Config * out ;
couts = malloc ( ocount * sizeof ( Ecore_X_Randr_Output ) ) ;
EINA_LIST_FOREACH ( valid_outputs , o , out )
{
couts [ c ] = out - > xid ;
c + + ;
}
printf ( " \t \t \t \t \t Crtc Settings: %d %d %d %d \n " , crtc_cfg - > xid ,
crtc_cfg - > x , crtc_cfg - > y , crtc_cfg - > mode ) ;
/* Evas_Coord mw, mh; */
/* get the size of the mode */
/* ecore_x_randr_mode_size_get(root, crtc_cfg->mode, &mw, &mh); */
/* printf("\t\t\t\t\t\tMode Size: %d %d\n", mw, mh); */
ecore_x_randr_crtc_settings_set ( root , crtc_cfg - > xid ,
couts , ocount ,
crtc_cfg - > x ,
crtc_cfg - > y ,
crtc_cfg - > mode ,
crtc_cfg - > orient ) ;
free ( couts ) ;
}
}
eina_list_free ( valid_outputs ) ;
}
eina_list_free ( valid_crtcs ) ;
}
if ( need_reset ) ecore_x_randr_screen_reset ( root ) ;
// e_randr_config_save();
// if (need_reset) ecore_x_randr_screen_reset(root);
}
static Eina_Bool
@ -465,20 +548,34 @@ _e_randr_event_cb_screen_change(void *data EINA_UNUSED, int type EINA_UNUSED, vo
ev = event ;
printf ( " E_RANDR Event: Screen Change \n " ) ;
printf ( " E_RANDR Event: Screen Change: %d %d \n " ,
ev - > size . width , ev - > size . height ) ;
/* check if this event's root window is Our root window */
if ( ev - > root ! = e_manager_current_get ( ) - > root )
return ECORE_CALLBACK_RENEW ;
if ( e_randr_cfg - > screen . width ! = ev - > size . width )
{
printf ( " \t Width Changed \n " ) ;
e_randr_cfg - > screen . width = ev - > size . width ;
changed = EINA_TRUE ;
}
if ( e_randr_cfg - > screen . height ! = ev - > size . height )
{
printf ( " \t Height Changed \n " ) ;
e_randr_cfg - > screen . height = ev - > size . height ;
changed = EINA_TRUE ;
}
if ( e_randr_cfg - > config_timestamp ! = ev - > config_time )
{
printf ( " \t Config Timestamp Changed \n " ) ;
e_randr_cfg - > config_timestamp = ev - > config_time ;
changed = EINA_TRUE ;
}
if ( changed ) e_randr_config_save ( ) ;
return ECORE_CALLBACK_RENEW ;
@ -490,39 +587,50 @@ _e_randr_event_cb_crtc_change(void *data EINA_UNUSED, int type EINA_UNUSED, void
Ecore_X_Event_Randr_Crtc_Change * ev ;
Eina_List * l = NULL ;
E_Randr_Crtc_Config * crtc_cfg ;
Eina_Bool changed = EINA_FALSE ;
Eina_Bool crtc_new = EINA_FALSE ;
Eina_Bool crtc_found = EINA_FALSE ;
Eina_Bool crtc_changed = EINA_FALSE ;
ev = event ;
if ( ev - > crtc = = 0 ) return ECORE_CALLBACK_RENEW ;
printf ( " E_RANDR Event: Crtc Change: %d \n " , ev - > crtc ) ;
/* loop our crtc configs and try to find this one */
EINA_LIST_FOREACH ( e_randr_cfg - > crtcs , l , crtc_cfg )
{
if ( crtc_cfg - > xid = = ev - > crtc )
/* skip if not this crtc */
if ( crtc_cfg - > xid ! = ev - > crtc ) continue ;
crtc_found = EINA_TRUE ;
break ;
}
if ( ! crtc_found )
{
/* if this crtc is not found in our config, create it */
if ( ( crtc_cfg = E_NEW ( E_Randr_Crtc_Config , 1 ) ) )
{
if ( ( crtc_cfg - > x ! = ev - > geo . x ) | |
( crtc_cfg - > y ! = ev - > geo . y ) | |
( crtc_cfg - > width ! = ev - > geo . w ) | |
( crtc_cfg - > height ! = ev - > geo . h ) | |
( crtc_cfg - > orient ! = ev - > orientation ) | |
( crtc_cfg - > mode ! = ev - > mode ) )
{
crtc_cfg - > x = ev - > geo . x ;
crtc_cfg - > y = ev - > geo . y ;
crtc_cfg - > width = ev - > geo . w ;
crtc_cfg - > height = ev - > geo . h ;
crtc_cfg - > orient = ev - > orientation ;
crtc_cfg - > mode = ev - > mode ;
changed = EINA_TRUE ;
}
/* assign id */
crtc_cfg - > xid = ev - > crtc ;
crtc_cfg - > exists = EINA_TRUE ;
break ;
crtc_new = EINA_TRUE ;
/* append to randr cfg */
e_randr_cfg - > crtcs =
eina_list_append ( e_randr_cfg - > crtcs , crtc_cfg ) ;
}
}
if ( changed ) e_randr_config_save ( ) ;
/* check (and update if needed) our crtc config
* NB : This will fill in any new ones also */
crtc_changed = _e_randr_config_crtc_update ( crtc_cfg ) ;
/* save the config if anything changed or we added a new one */
if ( ( crtc_changed ) | | ( crtc_new ) )
{
printf ( " E_RANDR Event: Crtc Change \n " ) ;
printf ( " \t Crtc: %d Changed or New. Saving Config \n " , ev - > crtc ) ;
e_randr_config_save ( ) ;
}
return ECORE_CALLBACK_RENEW ;
}
@ -533,71 +641,418 @@ _e_randr_event_cb_output_change(void *data EINA_UNUSED, int type EINA_UNUSED, vo
Ecore_X_Event_Randr_Output_Change * ev ;
Eina_List * l = NULL ;
E_Randr_Crtc_Config * crtc_cfg ;
Eina_Bool changed = EINA_FALSE ;
E_Randr_Output_Config * output_cfg ;
Eina_Bool output_new = EINA_FALSE ;
Eina_Bool output_found = EINA_FALSE ;
Eina_Bool output_changed = EINA_FALSE ;
Eina_Bool output_removed = EINA_FALSE ;
ev = event ;
/* TODO: NB: Hmmm, this is problematic :( The spec says we should get an
* event here when an output is disconnected ( hotplug ) if
* the hardware ( video card ) is capable of detecting this HOWEVER , in my
* tests , my nvidia card does not detect this .
*
* To work around this , we have added a poller to check X randr config
* against what we have saved in e_randr_cfg */
printf ( " E_RANDR Event: Output Change: %d \n " , ev - > output ) ;
/* check if this event's root window is Our root window */
if ( ev - > win ! = e_manager_current_get ( ) - > root )
return ECORE_CALLBACK_RENEW ;
printf ( " E_RANDR Event: Output Change \n " ) ;
printf ( " \t Output: %d \n " , ev - > output ) ;
if ( ev - > crtc )
printf ( " \t \t Crtc: %lu \n " , ( unsigned long ) ev - > crtc ) ;
else
printf ( " \t \t No Crtc \n " ) ;
printf ( " \t \t Mode: %d \n " , ev - > mode ) ;
if ( ev - > connection = = 0 )
printf ( " \t \t Output Connected \n " ) ;
else if ( ev - > connection = = 1 )
printf ( " \t \t Output Disconnected \n " ) ;
/* loop our crtcs and try to find this output */
printf ( " \t Looping Our Crtc Configs \n " ) ;
EINA_LIST_FOREACH ( e_randr_cfg - > crtcs , l , crtc_cfg )
{
Eina_List * o ;
E_Randr_Output_Config * output_cfg ;
if ( ev - > crtc ! = crtc_cfg - > xid ) continue ;
Eina_List * ll ;
if ( ( crtc_cfg - > mode ! = ev - > mode ) | |
( crtc_cfg - > orient ! = ev - > orientation ) )
/* loop the outputs in our crtc cfg and try to find this one */
printf ( " \t \t Looping Our Output Configs on this Crtc: %d \n " , crtc_cfg - > xid ) ;
EINA_LIST_FOREACH ( crtc_cfg - > outputs , ll , output_cfg )
{
crtc_cfg - > mode = ev - > mode ;
crtc_cfg - > orient = ev - > orientation ;
changed = EINA_TRUE ;
/* try to find this output */
if ( output_cfg - > xid ! = ev - > output ) continue ;
/* FIXME: NB: Hmmm, we may need to also compare edids here (not just X id) */
printf ( " \t \t \t Found Output %d on Crtc: %d \n " , output_cfg - > xid , output_cfg - > crtc ) ;
output_found = EINA_TRUE ;
/* is this output still on the same crtc ? */
if ( output_cfg - > crtc ! = ev - > crtc )
{
printf ( " \t \t \t \t Output Moved Crtc or Removed \n " ) ;
/* if event crtc is 0, then this output is not assigned to any crtc,
* so we need to remove it from any existing crtc_cfg Outputs .
*
* NB : In a typical scenario , we would remove and free this output cfg ,
* HOWEVER we will NOT do that here . Reasoning is that if someone
* replugs this output , we can restore any saved config .
*
* NB : Do not call _e_randr_config_output_update in this case as that will
* overwrite any of our saved config
*
* So for now , just disable it in config by setting exists = = FALSE */
if ( ! ev - > crtc )
{
/* free this output_cfg */
/* if (output_cfg->clones) free(output_cfg->clones); */
/* if (output_cfg->edid) free(output_cfg->edid); */
/* E_FREE(output_cfg); */
/* remove from this crtc */
/* crtc_cfg->outputs = eina_list_remove_list(crtc_cfg->outputs, ll); */
/* just mark it as not existing */
output_cfg - > exists = EINA_FALSE ;
/* set flag */
output_removed = EINA_TRUE ;
}
else
{
/* output moved to new crtc */
printf ( " \t \t \t Output Moved to New Crtc \n " ) ;
}
}
else
{
printf ( " \t \t \t \t Output On Same Crtc \n " ) ;
/* check (and update if needed) our output config */
output_changed = _e_randr_config_output_update ( output_cfg ) ;
}
if ( output_found ) break ;
}
EINA_LIST_FOREACH ( crtc_cfg - > outputs , o , output_cfg )
if ( output_found ) break ;
}
/* if the output was not found above, and it is plugged in,
* then we need to create a new one */
if ( ( ! output_found ) & & ( ev - > connection = = 0 ) )
{
printf ( " \t Output Not Found In Config: %d \n " , ev - > output ) ;
printf ( " \t \t Create New Output Config \n " ) ;
if ( ( output_cfg = _e_randr_config_output_new ( ev - > output ) ) )
{
if ( output_cfg - > xid = = ev - > output )
output_new = EINA_TRUE ;
/* since this is a new output cfg, the above
* output_update function ( inside new ) will set ' exists ' to false
* because no crtc has been assigned yet .
*
* We need to find a valid crtc for this output and set the
* ' crtc ' and ' exists ' properties */
if ( ( crtc_cfg = _e_randr_config_output_crtc_find ( output_cfg ) ) )
{
Eina_Bool connected = EINA_FALSE ;
Ecore_X_Randr_Mode mode ;
connected = ( ( ev - > connection ) ? EINA_FALSE : EINA_TRUE ) ;
/* we found a valid crtc for this output */
output_cfg - > crtc = crtc_cfg - > xid ;
output_cfg - > exists = ( output_cfg - > crtc ! = 0 ) ;
if ( ( output_cfg - > crtc ! = ev - > crtc ) | |
( output_cfg - > connected ! = connected ) )
printf ( " \t \t \t Output Crtc Is: %d \n " , output_cfg - > crtc ) ;
/* get the preferred mode for this output */
if ( ( mode = _e_randr_config_output_preferred_mode_get ( output_cfg ) ) )
{
printf ( " Output Changed: %d \n " , ev - > output ) ;
printf ( " \t Connected: %d \n " , connected ) ;
Evas_Coord mw = 0 , mh = 0 ;
output_cfg - > crtc = ev - > crtc ;
output_cfg - > connected = connected ;
output_cfg - > exists = connected ;
/* get the size of this mode */
ecore_x_randr_mode_size_get ( ev - > win , mode , & mw , & mh ) ;
changed = EINA_TRUE ;
/* update crtc config with this mode info */
crtc_cfg - > mode = mode ;
crtc_cfg - > width = mw ;
crtc_cfg - > height = mh ;
}
break ;
/* append this output_cfg to the crtc_cfg list of outputs */
crtc_cfg - > outputs =
eina_list_append ( crtc_cfg - > outputs , output_cfg ) ;
printf ( " APPLY NEW OUTPUT: %d \n " , output_cfg - > xid ) ;
/* tell X about this new output */
int ocount , c = 0 ;
ocount = eina_list_count ( crtc_cfg - > outputs ) ;
printf ( " \t Num Outputs: %d \n " , ocount ) ;
if ( ocount > 0 )
{
Ecore_X_Randr_Output * couts ;
Eina_List * o ;
E_Randr_Output_Config * out ;
couts = malloc ( ocount * sizeof ( Ecore_X_Randr_Output ) ) ;
EINA_LIST_FOREACH ( crtc_cfg - > outputs , o , out )
{
couts [ c ] = out - > xid ;
c + + ;
}
printf ( " \t Crtc Settings: %d %d %d %d \n " , crtc_cfg - > xid ,
crtc_cfg - > x , crtc_cfg - > y , crtc_cfg - > mode ) ;
/* Evas_Coord mw, mh; */
/* get the size of the mode */
/* ecore_x_randr_mode_size_get(root, crtc_cfg->mode, &mw, &mh); */
/* printf("\t\t\t\t\t\tMode Size: %d %d\n", mw, mh); */
ecore_x_randr_crtc_settings_set ( ev - > win , crtc_cfg - > xid ,
couts , ocount ,
crtc_cfg - > x ,
crtc_cfg - > y ,
crtc_cfg - > mode ,
crtc_cfg - > orient ) ;
free ( couts ) ;
}
}
}
}
if ( changed ) e_randr_config_save ( ) ;
/* save the config if anything changed or we added a new one */
if ( ( output_changed ) | | ( output_new ) | | ( output_removed ) )
{
printf ( " \t \t \t \t Output Changed, Added, or Removed. Saving Config \n " ) ;
e_randr_config_save ( ) ;
}
/* if we added or removed any outputs, we need to reset */
if ( ( output_new ) | | ( output_removed ) )
{
/* we need to inform X about the changes */
/* easier just to call the restore function with the updated config */
/* _e_randr_config_restore(); */
ecore_x_randr_screen_reset ( ev - > win ) ;
}
return ECORE_CALLBACK_RENEW ;
}
/* This function compares our crtc config against what X has and updates our
* view of this crtc . It returns EINA_TRUE is anything changed
*
* NB : This Does Not Handle Outputs on the Crtc . */
static Eina_Bool
_e_randr_event_cb_property_change ( void * data EINA_UNUSED , int type EINA_UNUSED , void * event EINA_UNUSED )
_e_randr_config_crtc_update ( E_Randr_Crtc_Config * cfg )
{
/* Ecore_X_Event_Randr_Output_Property_Notify *ev; */
Ecore_X_Window root = 0 ;
Eina_Bool ret = EINA_FALSE ;
/* ev = event; */
printf ( " E_RANDR Event: Property Change \n " ) ;
return ECORE_CALLBACK_RENEW ;
/* grab the root window */
root = ecore_x_window_root_first_get ( ) ;
# if ((ECORE_VERSION_MAJOR >= 1) && (ECORE_VERSION_MINOR >= 8))
Ecore_X_Randr_Crtc_Info * cinfo ;
/* get crtc info from X */
if ( ( cinfo = ecore_x_randr_crtc_info_get ( root , cfg - > xid ) ) )
{
/* check for changes */
if ( ( cfg - > x ! = cinfo - > x ) | | ( cfg - > y ! = cinfo - > y ) | |
( cfg - > width ! = ( int ) cinfo - > width ) | | ( cfg - > height ! = ( int ) cinfo - > height ) | |
( cfg - > mode ! = cinfo - > mode ) | | ( cfg - > orient ! = cinfo - > rotation ) )
{
cfg - > x = cinfo - > x ;
cfg - > y = cinfo - > y ;
cfg - > width = cinfo - > width ;
cfg - > height = cinfo - > height ;
cfg - > mode = cinfo - > mode ;
cfg - > orient = cinfo - > rotation ;
ret = EINA_TRUE ;
}
ecore_x_randr_crtc_info_free ( cinfo ) ;
}
# else
Evas_Coord x , y , w , h ;
unsigned int orient , mode ;
/* get geometry of this crtc */
ecore_x_randr_crtc_geometry_get ( root , ev - > crtc , & x , & y , & w , & h ) ;
if ( ( cfg - > x ! = x ) | | ( cfg - > y ! = y ) | |
( cfg - > width ! = w ) | | ( cfg - > height ! = h ) )
{
cfg - > x = x ;
cfg - > y = y ;
cfg - > width = w ;
cfg - > height = h ;
ret = EINA_TRUE ;
}
/* get orientation */
orient = ecore_x_randr_crtc_orientation_get ( root , cfg - > xid ) ;
if ( cfg - > orient ! = orient )
{
cfg - > orient = orient ;
ret = EINA_TRUE ;
}
/* get mode */
mode = ecore_x_randr_crtc_mode_get ( root , cfg - > xid ) ;
if ( cfg - > mode ! = mode )
{
cfg - > mode = mode ;
ret = EINA_TRUE ;
}
# endif
return ret ;
}
static Eina_Bool
_e_randr_config_output_update ( E_Randr_Output_Config * cfg )
{
Ecore_X_Window root = 0 ;
Eina_Bool ret = EINA_FALSE ;
Ecore_X_Randr_Output primary = 0 ;
Ecore_X_Randr_Crtc crtc ;
Ecore_X_Randr_Connection_Status status ;
/* int clone_count = 0; */
/* grab the root window */
root = ecore_x_window_root_first_get ( ) ;
/* get which output is primary */
primary = ecore_x_randr_primary_output_get ( root ) ;
/* set this output policy */
cfg - > policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE ;
/* get if this output is the primary */
if ( cfg - > primary ! = ( ( cfg - > xid = = primary ) ) )
{
cfg - > primary = ( ( cfg - > xid = = primary ) ) ;
ret = EINA_TRUE ;
}
/* get the crtc for this output */
crtc = ecore_x_randr_output_crtc_get ( root , cfg - > xid ) ;
if ( cfg - > crtc ! = crtc )
{
cfg - > crtc = crtc ;
ret = EINA_TRUE ;
}
/* does it exist in X ?? */
if ( cfg - > exists ! = ( crtc ! = 0 ) )
{
cfg - > exists = ( crtc ! = 0 ) ;
ret = EINA_TRUE ;
}
/* record the edid for this output */
/* cfg->edid = ecore_x_randr_output_edid_get(root, cfg->xid, &cfg->edid_count); */
/* get the clones for this output */
/* cfg->clones = */
/* ecore_x_randr_output_clones_get(root, cfg->xid, &clone_count); */
/* cfg->clone_count = (unsigned long)clone_count; */
status = ecore_x_randr_output_connection_status_get ( root , cfg - > xid ) ;
if ( cfg - > connected ! = ( status = = ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED ) )
{
cfg - > connected = ( status = = ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED ) ;
ret = EINA_TRUE ;
}
return ret ;
}
static E_Randr_Crtc_Config *
_e_randr_config_output_crtc_find ( E_Randr_Output_Config * cfg )
{
Ecore_X_Window root = 0 ;
E_Randr_Crtc_Config * crtc_cfg = NULL ;
Ecore_X_Randr_Crtc * possible ;
int num = 0 , i = 0 ;
Eina_List * l ;
Eina_Bool crtc_found = EINA_FALSE ;
/* grab the root window */
root = ecore_x_window_root_first_get ( ) ;
/* get a list of possible crtcs for this output */
possible = ecore_x_randr_output_possible_crtcs_get ( root , cfg - > xid , & num ) ;
if ( ( ! possible ) | | ( num = = 0 ) ) return NULL ;
/* loop the possible crtcs */
for ( i = 0 ; i < num ; i + + )
{
/* loop our crtc configs and try to find this one */
EINA_LIST_FOREACH ( e_randr_cfg - > crtcs , l , crtc_cfg )
{
/* skip if not the one we are looking for */
if ( crtc_cfg - > xid ! = possible [ i ] ) continue ;
/* check if this crtc already has outputs assigned.
* skip if it does because we are trying to find a free crtc */
if ( eina_list_count ( crtc_cfg - > outputs ) > 0 ) continue ;
crtc_found = EINA_TRUE ;
break ;
}
if ( crtc_found ) break ;
}
free ( possible ) ;
if ( crtc_found ) return crtc_cfg ;
return NULL ;
}
static Ecore_X_Randr_Mode
_e_randr_config_output_preferred_mode_get ( E_Randr_Output_Config * cfg )
{
Ecore_X_Window root = 0 ;
Ecore_X_Randr_Mode * modes ;
Ecore_X_Randr_Mode mode ;
int n = 0 , p = 0 ;
/* grab the root window */
root = ecore_x_window_root_first_get ( ) ;
/* get the list of modes for this output */
modes = ecore_x_randr_output_modes_get ( root , cfg - > xid , & n , & p ) ;
if ( ( ! modes ) | | ( n = = 0 ) ) return 0 ;
mode = modes [ p ] ;
free ( modes ) ;
return mode ;
}
static E_Randr_Output_Config *
_e_randr_config_output_new ( unsigned int id )
{
E_Randr_Output_Config * cfg = NULL ;
if ( ( cfg = E_NEW ( E_Randr_Output_Config , 1 ) ) )
{
/* assign output xid */
cfg - > xid = id ;
/* check (and update if needed) our output config */
_e_randr_config_output_update ( cfg ) ;
}
return cfg ;
}