princeamd pushed a commit to branch enlightenment-0.17.
commit 7fa2c66d742f6bb0ce001b36d4387ec07560a05c
Author: Chris Michael <[email protected]>
Date: Sat May 18 16:25:54 2013 +0100
Backport: 9e605eb :: Fix randr plug-n-play for cedric because he asked
nicely ;)
- Add config timestamping to our randr config.
- remove property_notify handler as we never use it.
- Unify some code to remove duplication
- Add a lot of debugging output.
Yes, e_randr is going to be noisy for a little while until I can
verify that it works for others also.
- Too many other changes to list.
Suffice to say, this makes e_randr plug-n-play work (here anyway).
NB: Right now, this just clones. It Could be changed to extend new
monitors tho
NB: This works here, on my laptop at home. If you find it does not
work for you, please supply the output of E's startup/restart when you
plug AND unplug monitors.
Signed-off-by: Chris Michael <[email protected]>
Signed-off-by: Deon Thomas <[email protected]>
---
src/bin/e_randr.c | 773 +++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 614 insertions(+), 159 deletions(-)
diff --git a/src/bin/e_randr.c b/src/bin/e_randr.c
index 154275d..9096e4b 100644
--- a/src/bin/e_randr.c
+++ b/src/bin/e_randr.c
@@ -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("\tHave 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\tChecking 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\tFound Crtc in Config\n");
+ valid_crtcs = eina_list_append(valid_crtcs, crtc_cfg);
+ }
+
+ if (!crtc_found)
+ {
+ printf("\t\t\tCrtc Not Found in Config\n");
+ printf("\t\t\t\tCreating 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\tNew Crtc Geom: %d %d %d %d\n",
+ crtc_cfg->x, crtc_cfg->y, crtc_cfg->width,
+ crtc_cfg->height);
+ printf("\t\t\t\tNew 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\tLooping 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\tHave 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\tChecking 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\tFound 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\tNo 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\tApplying Crtc Settings: %d\n", crtc_cfg->xid);
+
+ if (!crtc_cfg->mode)
+ {
+ printf("\t\t\t\t\tCRTC 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\tNum 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\tCrtc 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("\tWidth Changed\n");
e_randr_cfg->screen.width = ev->size.width;
changed = EINA_TRUE;
}
if (e_randr_cfg->screen.height != ev->size.height)
{
+ printf("\tHeight Changed\n");
e_randr_cfg->screen.height = ev->size.height;
changed = EINA_TRUE;
}
+ if (e_randr_cfg->config_timestamp != ev->config_time)
+ {
+ printf("\tConfig 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("\tCrtc: %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("\tOutput: %d\n", ev->output);
+
+ if (ev->crtc)
+ printf("\t\tCrtc: %lu\n", (unsigned long)ev->crtc);
+ else
+ printf("\t\tNo Crtc\n");
+
+ printf("\t\tMode: %d\n", ev->mode);
+
+ if (ev->connection == 0)
+ printf("\t\tOutput Connected\n");
+ else if (ev->connection == 1)
+ printf("\t\tOutput Disconnected\n");
+
+ /* loop our crtcs and try to find this output */
+ printf("\tLooping 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\tLooping 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\tFound 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\tOutput 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\tOutput Moved to New Crtc\n");
+ }
+ }
+ else
+ {
+ printf("\t\t\t\tOutput 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("\tOutput Not Found In Config: %d\n", ev->output);
+ printf("\t\tCreate 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\tOutput 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("\tConnected: %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("\tNum 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("\tCrtc 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\tOutput 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;
}
--
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev