Note with this patch, the previous patch is unnecessary: the configuration can be sent to all agents (gdm & user) the creation/deletion races will be ignored.<br><div class="gmail_extra"><br><br><div class="gmail_quote">
On Thu, Nov 22, 2012 at 4:08 PM, Marc-André Lureau <span dir="ltr"><<a href="mailto:marcandre.lureau@gmail.com" target="_blank">marcandre.lureau@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The agent creates a unique mode vdagent-N per output, that is deleted<br>
when the custom resolution is changed. In order to be deleted, it<br>
can't be the current active crtc config.<br>
<br>
Now, the vdagent just sets the mode to NULL, but that causes a change<br>
of resolution probably due to gnome-settings-daemon (in RHEL6, it<br>
switches to max resultion 2560x1600 before switching back to custom<br>
resolution).<br>
<br>
We can avoid deleting current mode by creating a different mode,<br>
switching to it, and then deleting the previous mode. Also, we can<br>
ignore some Create/Delete races with other XRandR clients that may<br>
modify the mode simultaneously. This shouldn't be fatal, as long as<br>
the rest of the resolution switching can take place.<br>
---<br>
 src/vdagent-x11-randr.c | 53 +++++++++++++++++++++++++++----------------------<br>
 1 file changed, 29 insertions(+), 24 deletions(-)<br>
<br>
diff --git a/src/vdagent-x11-randr.c b/src/vdagent-x11-randr.c<br>
index 2ffd264..2c1819a 100644<br>
--- a/src/vdagent-x11-randr.c<br>
+++ b/src/vdagent-x11-randr.c<br>
@@ -47,13 +47,16 @@ static void arm_error_handler(struct vdagent_x11 *x11)<br>
     old_error_handler = XSetErrorHandler(error_handler);<br>
 }<br>
<br>
-static void check_error_handler(struct vdagent_x11 *x11)<br>
+static int check_error_handler(struct vdagent_x11 *x11)<br>
 {<br>
+    int error;<br>
+<br>
     XSync(x11->display, False);<br>
     XSetErrorHandler(old_error_handler);<br>
-    if (caught_error) {<br>
-        x11->set_crtc_config_not_functional = 1;<br>
-    }<br>
+    error = caught_error;<br>
+    caught_error = 0;<br>
+<br>
+    return error;<br>
 }<br>
<br>
 static XRRModeInfo *mode_from_id(struct vdagent_x11 *x11, int id)<br>
@@ -196,7 +199,7 @@ find_mode_by_size (struct vdagent_x11 *x11, int width, int height)<br>
     return ret;<br>
 }<br>
<br>
-static void delete_mode(struct vdagent_x11 *x11, int output_index)<br>
+static void delete_mode(struct vdagent_x11 *x11, int output_index, const char* name)<br>
 {<br>
     int m;<br>
     XRRModeInfo *mode;<br>
@@ -204,7 +207,6 @@ static void delete_mode(struct vdagent_x11 *x11, int output_index)<br>
     XRRCrtcInfo *crtc_info;<br>
     RRCrtc crtc;<br>
     int current_mode = -1;<br>
-    char name[20];<br>
<br>
     output_info = x11->randr.outputs[output_index];<br>
     if (output_info->ncrtc != 1) {<br>
@@ -215,23 +217,22 @@ static void delete_mode(struct vdagent_x11 *x11, int output_index)<br>
     crtc_info = crtc_from_id(x11, output_info->crtcs[0]);<br>
     current_mode = crtc_info->mode;<br>
     crtc = output_info->crtc;<br>
-    snprintf(name, sizeof(name), "vdagent-%d", output_index);<br>
     for (m = 0 ; m < x11->randr.res->nmode; ++m) {<br>
         mode = &x11->randr.res->modes[m];<br>
         if (strcmp(mode->name, name) == 0)<br>
             break;<br>
     }<br>
     if (m < x11->randr.res->nmode) {<br>
-        if (crtc && mode->id == current_mode) {<br>
-            syslog(LOG_DEBUG,<br>
-                   "delete_mode of in use mode, setting crtc to NULL mode");<br>
-            XRRSetCrtcConfig(x11->display, x11->randr.res, crtc,<br>
-                             CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0);<br>
-        }<br>
+        arm_error_handler(x11);<br>
         XRRDeleteOutputMode (x11->display, x11->randr.res->outputs[output_index],<br>
                              mode->id);<br>
         XRRDestroyMode (x11->display, mode->id);<br>
+       // ignore race error, if mode is created by others<br>
+       check_error_handler(x11);<br>
     }<br>
+<br>
+    /* silly to update everytime for more then one monitor */<br>
+    update_randr_res(x11);<br>
 }<br>
<br>
 static void set_reduced_cvt_mode(XRRModeInfo *mode, int width, int height)<br>
@@ -315,24 +316,21 @@ static XRRModeInfo *create_new_mode(struct vdagent_x11 *x11, int output_index,<br>
     char modename[20];<br>
     XRRModeInfo mode;<br>
<br>
-    /* we may be using this mode from an old invocation - check first */<br>
-    snprintf(modename, sizeof(modename), "vdagent-%d", output_index);<br>
-    arm_error_handler(x11);<br>
-    delete_mode(x11, output_index);<br>
-    check_error_handler(x11);<br>
-    if (x11->set_crtc_config_not_functional) {<br>
-        return NULL;<br>
-    }<br>
+    snprintf(modename, sizeof(modename), "%dx%d-%d", width, height, output_index);<br>
     mode.hSkew = 0;<br>
     <a href="http://mode.name" target="_blank">mode.name</a> = modename;<br>
     mode.nameLength = strlen(<a href="http://mode.name" target="_blank">mode.name</a>);<br>
     set_reduced_cvt_mode(&mode, width, height);<br>
     mode.modeFlags = 0;<br>
     <a href="http://mode.id" target="_blank">mode.id</a> = 0;<br>
-<br>
+    arm_error_handler(x11);<br>
     XRRCreateMode (x11->display, x11->root_window, &mode);<br>
+    // ignore race error, if mode is created by others<br>
+    check_error_handler(x11);<br>
+<br>
     /* silly to update everytime for more then one monitor */<br>
     update_randr_res(x11);<br>
+<br>
     return find_mode_by_name(x11, modename);<br>
 }<br>
<br>
@@ -343,6 +341,7 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, int output, int x, int y,<br>
     int xid;<br>
     Status s;<br>
     RROutput outputs[1];<br>
+    char modename[20];<br>
<br>
     if (!x11->randr.res || output >= x11->randr.res->noutput || output < 0) {<br>
         syslog(LOG_ERR, "%s: program error: missing RANDR or bad output",<br>
@@ -367,12 +366,17 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, int output, int x, int y,<br>
     s = XRRSetCrtcConfig(x11->display, x11->randr.res, x11->randr.res->crtcs[output],<br>
                          CurrentTime, x, y, mode->id, RR_Rotate_0, outputs,<br>
                          1);<br>
+<br>
     if (s != RRSetConfigSuccess) {<br>
         syslog(LOG_ERR, "failed to XRRSetCrtcConfig");<br>
-        delete_mode(x11, output);<br>
         x11->set_crtc_config_not_functional = 1;<br>
         return 0;<br>
     }<br>
+<br>
+    /* clean the previous name, if any */<br>
+    snprintf(modename, sizeof(modename), "%dx%d-%d", x11->width, x11->height, output);<br>
+    delete_mode(x11, output, modename);<br>
+<br>
     return 1;<br>
 }<br>
<br>
@@ -695,7 +699,8 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11,<br>
         XRRSetScreenSize(x11->display, x11->root_window, primary_w, primary_h,<br>
                          DisplayWidthMM(x11->display, x11->screen),<br>
                          DisplayHeightMM(x11->display, x11->screen));<br>
-        check_error_handler(x11);<br>
+<br>
+        x11->set_crtc_config_not_functional = check_error_handler(x11);<br>
     }<br>
<br>
 update:<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.11.7<br>
<br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Marc-André Lureau<br>
</div>