[Xfce4-commits] <xfce4-settings:bluesabre/display-settings> Move position handling into XfceRandr

Simon Steinbeiss noreply at xfce.org
Thu Oct 18 23:38:03 CEST 2012


Updating branch refs/heads/bluesabre/display-settings
         to 2c994717763c0c248f292ec03e99bba30c1d0a5b (commit)
       from 62ee88f41a811cb3f89759507ea7d092ca065ed0 (commit)

commit 2c994717763c0c248f292ec03e99bba30c1d0a5b
Author: Lionel Le Folgoc <lionel at lefolgoc.net>
Date:   Wed Oct 17 20:13:07 2012 +0200

    Move position handling into XfceRandr
    
    Now the UI only manage "relations" (left of, right of, etc.), and XfceRandr
    computes the real positions.
    Clean up (or move to private structs) now unused functions and structures.
    
    Signed-off-by: Simon Steinbeiss <simon.steinbeiss at elfenbeinturm.at>

 dialogs/display-settings/main.c       |  421 +++++++++++----------------------
 dialogs/display-settings/xfce-randr.c |  374 ++++++++++++++++++++++-------
 dialogs/display-settings/xfce-randr.h |  103 +++-----
 3 files changed, 459 insertions(+), 439 deletions(-)

diff --git a/dialogs/display-settings/main.c b/dialogs/display-settings/main.c
index 107b4d9..89559dd 100644
--- a/dialogs/display-settings/main.c
+++ b/dialogs/display-settings/main.c
@@ -70,6 +70,27 @@ typedef struct {
 
 
 
+typedef struct _XfceRelation XfceRelation;
+typedef struct _XfceRotation XfceRotation;
+
+
+
+struct _XfceRelation
+{
+    XfceOutputRelation  relation;
+    const gchar        *name;
+};
+
+
+
+struct _XfceRotation
+{
+    Rotation     rotation;
+    const gchar *name;
+};
+
+
+
 /* Xrandr relation name conversion */
 static const XfceRelation relation_names[] =
 {
@@ -127,13 +148,15 @@ static GOptionEntry option_entries[] =
 
 /* Global xfconf channel */
 static XfconfChannel *display_channel;
-static gboolean       bound_to_channel = FALSE;
 
 /* output currently selected in the treeview */
 static guint active_output;
 
 /* Pointer to the used randr structure */
-XfceRandr *xfce_randr = NULL;
+static XfceRandr *xfce_randr = NULL;
+
+/* event base for XRandR notifications */
+static gint randr_event_base;
 
 /* Used to identify the display */
 static GHashTable *display_popups;
@@ -303,118 +326,63 @@ display_setting_timed_confirmation (GtkBuilder *main_builder)
     return ((response_id == 2) ? TRUE : FALSE);
 }
 
+
+
 static void
 display_setting_positions_changed (GtkComboBox *combobox,
-                                     GtkBuilder  *builder)
+                                   GtkBuilder  *builder)
 {
-    gint value, current_x, current_y, selected_display, selected_x, selected_y;
-    GObject *display_combobox;
-    XfceRRMode   *current_mode, *selected_mode;
-    
-    display_combobox = gtk_builder_get_object(builder, "randr-active-displays");
+    GObject            *display_combobox;
+    XfceOutputRelation  previous_relation;
+    gint                value, selected_display, previous_related_to;
+
+    display_combobox = gtk_builder_get_object (builder, "randr-active-displays");
 
     if (!display_setting_combo_box_get_value (combobox, &value))
         return;
-        
-    if (!display_setting_combo_box_get_value (GTK_COMBO_BOX(display_combobox), &selected_display))
+
+    if (!display_setting_combo_box_get_value (GTK_COMBO_BOX (display_combobox),
+                                              &selected_display))
         return;
-        
+
     /* Skip if the display combobox hasn't made a selection yet */
     if (selected_display == -1) return;
-    
-    /* Store the currently active display's position and mode */
-    current_mode = xfce_randr_find_mode_by_id (xfce_randr, active_output,
-                                               xfce_randr->mode[active_output]);
-    current_x = xfce_randr->position[active_output].x;
-    current_y = xfce_randr->position[active_output].y;
-    
-    /* Store the selected display's position and mode */
-    selected_mode = xfce_randr_find_mode_by_id (xfce_randr, selected_display,
-                                                xfce_randr->mode[selected_display]);
-    selected_x = xfce_randr->position[selected_display].x;
-    selected_y = xfce_randr->position[selected_display].y;
-    
-    switch (value) {
-        case XFCE_RANDR_PLACEMENT_LEFT: // Extend Left
-            /* Move the selected display to the right of the currently active display. */
-            xfce_randr->position[selected_display].x = current_mode->width;
-            
-            /* Move the currently active display to where the selected was */
-            xfce_randr->position[active_output].x = selected_x;
-            xfce_randr->position[active_output].y = selected_y;
-
-            break;
-            
-        case XFCE_RANDR_PLACEMENT_RIGHT: // Extend Right
-			/* Move the selected display to where the currently active one is */
-            xfce_randr->position[selected_display].x = current_x;
-            xfce_randr->position[selected_display].y = current_y;
-            
-            /* Move the currently active display to the right of the selected display. */
-            xfce_randr->position[active_output].x = selected_mode->width;
-            
-            break;
-            
-        case XFCE_RANDR_PLACEMENT_UP: // Extend Above
-            /* Move the selected display above the currently active display. */
-            xfce_randr->position[selected_display].y = current_mode->height;
 
-            /* Move the currently active display to where the selected was */
-            xfce_randr->position[active_output].x = selected_x;
-            xfce_randr->position[active_output].y = selected_y;
+    /* back up */
+    previous_relation = xfce_randr->relation[active_output];
+    previous_related_to = xfce_randr->related_to[active_output];
 
-            break;
-            
-        case XFCE_RANDR_PLACEMENT_DOWN: // Extend Below
-        	/* Move the selected display to where the currently active one is */
-            xfce_randr->position[selected_display].x = current_x;
-            xfce_randr->position[selected_display].y = current_y;
-            
-            /* Move the currently active display below the selected display. */
-            xfce_randr->position[active_output].y = selected_mode->height;
-            
-            break;
-            
-        case XFCE_RANDR_PLACEMENT_MIRROR: // Mirror Display
-
-            xfce_randr->position[active_output].x = current_x;
-            xfce_randr->position[active_output].y = current_y;
-            break;
-            
-        default:
-            break;
-    }
-    
     /* Save changes to currently active display */
+    xfce_randr->relation[active_output] = value;
+    xfce_randr->related_to[active_output] = selected_display;
     xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                            active_output);
-    
+                            active_output, TRUE);
+
     /* Save changes to selected display */
     xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                            selected_display);
-                            
+                            selected_display, FALSE);
+
     /* Apply all changes */
     xfce_randr_apply (xfce_randr, "Default", display_channel);
-    
+
     /* Ask user confirmation */
     if (!display_setting_timed_confirmation (builder))
     {
         /* Restore the currently active display */
-        xfce_randr->position[active_output].x = current_x;
-        xfce_randr->position[active_output].y = current_y;
+        xfce_randr->relation[active_output] = previous_relation;
+        xfce_randr->related_to[active_output] = previous_related_to;
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                active_output);
-
+                                active_output, TRUE);
         /* Restore the selected display */
-        xfce_randr->position[selected_display].x = selected_x;
-        xfce_randr->position[selected_display].y = selected_y;
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                selected_display);
-        
+                                selected_display, FALSE);
+
         xfce_randr_apply (xfce_randr, "Default", display_channel);
     }
 }
 
+
+
 static void
 display_setting_positions_populate (GtkBuilder *builder)
 {
@@ -449,6 +417,10 @@ display_setting_positions_populate (GtkBuilder *builder)
         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
                             COLUMN_COMBO_NAME, _(relation_names[n].name),
                             COLUMN_COMBO_VALUE, relation_names[n].relation, -1);
+
+        /* Select the active relation */
+        if (relation_names[n].relation == xfce_randr->relation[active_output])
+            gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
     }
     
     /* Reconnect the signal */
@@ -475,15 +447,14 @@ display_setting_active_displays_populate (GtkBuilder *builder)
 {
     GtkTreeModel *model;
     GObject      *combobox;
-    gchar         *name;
     guint         n;
     GtkTreeIter   iter;
-    
+
     /* Get the active-displays combo box store and clear it */
     combobox = gtk_builder_get_object (builder, "randr-active-displays");
     model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));
     gtk_list_store_clear (GTK_LIST_STORE (model));
-    
+
     /* Only make the combobox interactive if there is more than one output */
     if (display_settings_get_n_active_outputs () > 1)
     {
@@ -491,7 +462,7 @@ display_setting_active_displays_populate (GtkBuilder *builder)
     }
     else
         gtk_widget_set_sensitive (GTK_WIDGET (combobox), FALSE);
-    
+
     /* Disconnect the "changed" signal to avoid triggering the confirmation
      * dialog */
     g_object_disconnect (combobox, "any_signal::changed",
@@ -499,113 +470,27 @@ display_setting_active_displays_populate (GtkBuilder *builder)
                          builder, NULL);
 
     /* Insert all active displays */
-    for (n = 0; n < display_settings_get_n_active_outputs (); n++)
+    for (n = 0; n < xfce_randr->noutput; ++n)
     {
-        if (n != active_output)
-        {
-        /* Get a friendly name for the output */
-        name = xfce_randr_friendly_name (xfce_randr,
-                                         xfce_randr->resources->outputs[n],
-                                         xfce_randr->output_info[n]->name);
+        if (xfce_randr->mode[n] == None || n == active_output)
+            continue;
+
         /* Insert display name */
         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                            COLUMN_COMBO_NAME, _(name),
+                            COLUMN_COMBO_NAME, xfce_randr->friendly_name[n],
                             COLUMN_COMBO_VALUE, n, -1);
-        g_free (name);
 
-        }
+        /* Select the active related output */
+        if (n == xfce_randr->related_to[active_output])
+            gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
     }
 
     /* Reconnect the signal */
     g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (display_setting_active_displays_changed), builder);
 }
 
-static void
-display_setting_guess_positioning (GtkBuilder *builder)
-{
-    GObject *position_combo, *display_combo;
-    gint current_x, current_y, cb_index;
-    XfceOutputRelation rel;
-    guint n;
-    
-    current_x = xfce_randr->position[active_output].x;
-    current_y = xfce_randr->position[active_output].y;
-    
-    position_combo = gtk_builder_get_object(builder, "randr-position");
-    display_combo = gtk_builder_get_object(builder, "randr-active-displays");
-    
-    g_object_disconnect (position_combo, "any_signal::changed",
-                         display_setting_positions_changed,
-                         builder, NULL);
-                         
-    g_object_disconnect (display_combo, "any_signal::changed",
-                         display_setting_active_displays_changed,
-                         builder, NULL);
-                         
-    cb_index = 0;
-    
-    for (n = 0; n < display_settings_get_n_active_outputs (); n++)
-    {
-        if (n != active_output)
-        {
-            /* Check for mirror */
-            if ( (xfce_randr->position[n].x == current_x) && 
-                 (xfce_randr->position[n].y == current_y) ) {
-                rel = XFCE_RANDR_PLACEMENT_MIRROR;
-                gtk_combo_box_set_active( GTK_COMBO_BOX(display_combo), cb_index );
-                break;       
-            }
-            
-            /* Check for Left Of */
-            if ( (xfce_randr->position[n].y == current_y) &&
-                 (xfce_randr->position[n].x > current_x) ) {
-                rel = XFCE_RANDR_PLACEMENT_LEFT;
-                gtk_combo_box_set_active( GTK_COMBO_BOX(display_combo), cb_index );
-                break;
-            }
-            
-            /* Check for Right Of */
-            if ( (xfce_randr->position[n].y == current_y) &&
-                 (xfce_randr->position[n].x < current_x) ) {
-                rel = XFCE_RANDR_PLACEMENT_RIGHT;
-                gtk_combo_box_set_active( GTK_COMBO_BOX(display_combo), cb_index );
-                break;
-            }
-            
-            /* Check for Above */
-            if ( (xfce_randr->position[n].x == current_x) &&
-                 (xfce_randr->position[n].y > current_y) ) {
-                rel = XFCE_RANDR_PLACEMENT_UP;
-                gtk_combo_box_set_active( GTK_COMBO_BOX(display_combo), cb_index );
-                break;
-            }
-            
-            /* Check for Below */
-            if ( (xfce_randr->position[n].x == current_x) &&
-                 (xfce_randr->position[n].y < current_y) ) {
-                rel = XFCE_RANDR_PLACEMENT_DOWN;
-                gtk_combo_box_set_active( GTK_COMBO_BOX(display_combo), cb_index );
-                break;
-            }
-            
-            cb_index++;
-        }
-    }
 
-    /* set the correct index for the position combobox */
-    for (n = 0; n < G_N_ELEMENTS (relation_names); n++)
-    {
-        if (rel == relation_names[n].relation)
-        {
-            gtk_combo_box_set_active (GTK_COMBO_BOX (position_combo), n);
-            break;
-        }
-    }
-
-    g_signal_connect (G_OBJECT (position_combo), "changed", G_CALLBACK (display_setting_positions_changed), builder);
-    g_signal_connect (G_OBJECT (display_combo), "changed", G_CALLBACK (display_setting_active_displays_changed), builder);
-}
 
 static void
 display_setting_reflections_changed (GtkComboBox *combobox,
@@ -627,7 +512,7 @@ display_setting_reflections_changed (GtkComboBox *combobox,
 
     /* Apply the changes */
     xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                            active_output);
+                            active_output, FALSE);
     xfce_randr_apply (xfce_randr, "Default", display_channel);
 
     /* Ask user confirmation */
@@ -635,7 +520,7 @@ display_setting_reflections_changed (GtkComboBox *combobox,
     {
         xfce_randr->rotation[active_output] = old_rotation;
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                active_output);
+                                active_output, FALSE);
         xfce_randr_apply (xfce_randr, "Default", display_channel);
     }
 }
@@ -720,7 +605,7 @@ display_setting_rotations_changed (GtkComboBox *combobox,
 
     /* Apply the changes */
     xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                            active_output);
+                            active_output, TRUE);
     xfce_randr_apply (xfce_randr, "Default", display_channel);
 
     /* Ask user confirmation */
@@ -728,7 +613,7 @@ display_setting_rotations_changed (GtkComboBox *combobox,
     {
         xfce_randr->rotation[active_output] = old_rotation;
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                active_output);
+                                active_output, TRUE);
         xfce_randr_apply (xfce_randr, "Default", display_channel);
     }
 }
@@ -810,7 +695,7 @@ display_setting_refresh_rates_changed (GtkComboBox *combobox,
 
     /* Apply the changes */
     xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                            active_output);
+                            active_output, FALSE);
     xfce_randr_apply (xfce_randr, "Default", display_channel);
 
     /* Ask user confirmation */
@@ -818,7 +703,7 @@ display_setting_refresh_rates_changed (GtkComboBox *combobox,
     {
         xfce_randr->mode[active_output] = old_mode;
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                active_output);
+                                active_output, FALSE);
         xfce_randr_apply (xfce_randr, "Default", display_channel);
     }
 }
@@ -828,13 +713,13 @@ display_setting_refresh_rates_changed (GtkComboBox *combobox,
 static void
 display_setting_refresh_rates_populate (GtkBuilder *builder)
 {
-    GtkTreeModel *model;
-    GObject      *combobox;
-    GtkTreeIter   iter;
-    gchar        *name = NULL;
-    gint          n;
-    GObject      *res_combobox;
-    XfceRRMode   *modes, *current_mode;
+    GtkTreeModel     *model;
+    GObject          *combobox;
+    GtkTreeIter       iter;
+    gchar            *name = NULL;
+    gint              nmode, n;
+    GObject          *res_combobox;
+    const XfceRRMode *modes, *current_mode;
 
     /* Get the combo box store and clear it */
     combobox = gtk_builder_get_object (builder, "randr-refresh-rate");
@@ -865,8 +750,8 @@ display_setting_refresh_rates_populate (GtkBuilder *builder)
         return;
 
     /* Walk all supported modes */
-    modes = xfce_randr->modes[active_output];
-    for (n = 0; n < xfce_randr->output_info[active_output]->nmode; ++n)
+    modes = xfce_randr_get_modes (xfce_randr, active_output, &nmode);
+    for (n = 0; n < nmode; ++n)
     {
         /* The mode resolution does not match the selected one */
         if (modes[n].width != current_mode->width
@@ -913,7 +798,7 @@ display_setting_resolutions_changed (GtkComboBox *combobox,
 
     /* Apply the changes */
     xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                            active_output);
+                            active_output, TRUE);
     xfce_randr_apply (xfce_randr, "Default", display_channel);
 
     /* Ask user confirmation */
@@ -921,7 +806,7 @@ display_setting_resolutions_changed (GtkComboBox *combobox,
     {
         xfce_randr->mode[active_output] = old_mode;
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                active_output);
+                                active_output, TRUE);
         xfce_randr_apply (xfce_randr, "Default", display_channel);
     }
 }
@@ -931,13 +816,13 @@ display_setting_resolutions_changed (GtkComboBox *combobox,
 static void
 display_setting_resolutions_populate (GtkBuilder *builder)
 {
-    GtkTreeModel  *model;
-    GObject       *combobox;
-    gint           n;
-    gchar         *name;
-    GtkTreeIter    iter;
-    XfceRRMode   *modes;
-    
+    GtkTreeModel     *model;
+    GObject          *combobox;
+    gint              nmode, n;
+    gchar            *name;
+    GtkTreeIter       iter;
+    const XfceRRMode *modes;
+
     /* Get the combo box store and clear it */
     combobox = gtk_builder_get_object (builder, "randr-resolution");
     model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox));
@@ -959,8 +844,8 @@ display_setting_resolutions_populate (GtkBuilder *builder)
                          builder, NULL);
 
     /* Walk all supported modes */
-    modes = xfce_randr->modes[active_output];
-    for (n = 0; n < xfce_randr->output_info[active_output]->nmode; ++n)
+    modes = xfce_randr_get_modes (xfce_randr, active_output, &nmode);
+    for (n = 0; n < nmode; ++n)
     {
         /* Try to avoid duplicates */
         if (n == 0 || (n > 0 && (modes[n].width != modes[n - 1].width
@@ -1123,9 +1008,9 @@ display_setting_identity_display (gint display_id)
     
     GObject *display_name, *display_details;
     
-    gchar *name, *color_hex = "#FFFFFF", *name_label, *details_label;
+    gchar *color_hex = "#FFFFFF", *name_label, *details_label;
     
-    XfceRRMode   *current_mode;
+    const XfceRRMode   *current_mode;
     
     gint screen_pos_x, screen_pos_y;
     gint window_width, window_height, screen_width, screen_height;
@@ -1148,8 +1033,12 @@ display_setting_identity_display (gint display_id)
         {
             current_mode = xfce_randr_find_mode_by_id (xfce_randr, display_id,
                                                        xfce_randr->mode[display_id]);
-            screen_pos_x = xfce_randr->position[display_id].x;
-            screen_pos_y = xfce_randr->position[display_id].y;
+            if (!xfce_randr_get_positions (xfce_randr, display_id,
+                                           &screen_pos_x, &screen_pos_y))
+            {
+                screen_pos_x = 0;
+                screen_pos_y = 0;
+            }
             screen_width = current_mode->width;
             screen_height = current_mode->height;
         }
@@ -1161,12 +1050,8 @@ display_setting_identity_display (gint display_id)
             screen_height = gdk_screen_height();
         }
         
-        /* Get a friendly name for the output */
-        name = xfce_randr_friendly_name (xfce_randr,
-                                         xfce_randr->resources->outputs[display_id],
-                                         xfce_randr->output_info[display_id]->name);
-
-        name_label = g_markup_printf_escaped("<span foreground='%s'><big><b>%s %s</b></big></span>", color_hex, _("Display:"), name);
+        name_label = g_markup_printf_escaped("<span foreground='%s'><big><b>%s %s</b></big></span>",
+                                             color_hex, _("Display:"), xfce_randr->friendly_name[display_id]);
         gtk_label_set_markup (GTK_LABEL(display_name), name_label);
         g_free (name_label);
 
@@ -1235,12 +1120,11 @@ display_setting_mirror_displays_toggled (GtkToggleButton *togglebutton,
         /* Apply mirror settings to each monitor */
         for (n = 0; n < display_settings_get_n_active_outputs (); n++)
         {
-            xfce_randr->position[n].x = 0;
-            xfce_randr->position[n].y = 0;
-            
+            xfce_randr->relation[n] = XFCE_RANDR_PLACEMENT_MIRROR;
+            xfce_randr->related_to[n] = active_output;
+
             xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                    n);
-            
+                                    n, TRUE);
         }
         
         xfce_randr_apply (xfce_randr, "Default", display_channel);
@@ -1282,13 +1166,6 @@ display_setting_mirror_displays_populate (GtkBuilder *builder)
     else
         gtk_widget_set_sensitive (GTK_WIDGET (check), FALSE);
     
-    /* Unbind any existing property, and rebind it */
-    if (bound_to_channel)
-    {
-        xfconf_g_property_unbind_all (check);
-        bound_to_channel = FALSE;
-    }
-
     /* Disconnect the "toggled" signal to avoid writing the config again */
     g_object_disconnect (check, "any_signal::toggled",
                          display_setting_mirror_displays_toggled,
@@ -1303,7 +1180,6 @@ display_setting_mirror_displays_populate (GtkBuilder *builder)
 
     /* Write the correct RandR value to xfconf */
     
-    bound_to_channel = TRUE;
 }
 
 
@@ -1324,7 +1200,7 @@ display_setting_output_toggled (GtkToggleButton *togglebutton,
             xfce_randr_preferred_mode (xfce_randr, active_output);
         /* Apply the changes */
         xfce_randr_save_output (xfce_randr, "Default", display_channel,
-                                active_output);
+                                active_output, FALSE);
         xfce_randr_apply (xfce_randr, "Default", display_channel);
     }
     else
@@ -1334,6 +1210,8 @@ display_setting_output_toggled (GtkToggleButton *togglebutton,
         {
             xfce_randr->mode[active_output] = None;
             /* Apply the changes */
+            xfce_randr_save_output (xfce_randr, "Default", display_channel,
+                                    active_output, FALSE);
             xfce_randr_apply (xfce_randr, "Default", display_channel);
         }
         else
@@ -1353,7 +1231,6 @@ static void
 display_setting_output_status_populate (GtkBuilder *builder)
 {
     GObject *check;
-    gchar    property[512];
 
     if (!xfce_randr)
         return;
@@ -1362,12 +1239,6 @@ display_setting_output_status_populate (GtkBuilder *builder)
         return;
 
     check = gtk_builder_get_object (builder, "output-on");
-    /* Unbind any existing property, and rebind it */
-    if (bound_to_channel)
-    {
-        xfconf_g_property_unbind_all (check);
-        bound_to_channel = FALSE;
-    }
 
     /* Disconnect the "toggled" signal to avoid writing the config again */
     g_object_disconnect (check, "any_signal::toggled",
@@ -1378,12 +1249,6 @@ display_setting_output_status_populate (GtkBuilder *builder)
     /* Reconnect the signal */
     g_signal_connect (G_OBJECT (check), "toggled", G_CALLBACK (display_setting_output_toggled),
                       builder);
-
-    g_snprintf (property, sizeof (property), "/Default/%s/Active",
-                xfce_randr->output_info[active_output]->name);
-    xfconf_g_property_bind (display_channel, property, G_TYPE_BOOLEAN, check,
-                            "active");
-    bound_to_channel = TRUE;
 }
 
 
@@ -1413,7 +1278,6 @@ display_settings_treeview_selection_changed (GtkTreeSelection *selection,
         /* Update the combo boxes */
         display_setting_positions_populate (builder);
         display_setting_active_displays_populate (builder);
-        display_setting_guess_positioning (builder);
         display_setting_output_status_populate (builder);
         display_setting_mirror_displays_populate (builder);
         display_setting_resolutions_populate (builder);
@@ -1449,7 +1313,6 @@ display_settings_treeview_populate (GtkBuilder *builder)
     GtkListStore     *store;
     GObject          *treeview;
     GtkTreeIter       iter;
-    gchar            *name;
     GdkPixbuf        *display_icon, *lucent_display_icon;
     GtkTreeSelection *selection;
     gboolean          selected = FALSE;
@@ -1477,11 +1340,6 @@ display_settings_treeview_populate (GtkBuilder *builder)
     /* Walk all the connected outputs */
     for (m = 0; m < xfce_randr->noutput; ++m)
     {
-        /* Get a friendly name for the output */
-        name = xfce_randr_friendly_name (xfce_randr,
-                                         xfce_randr->resources->outputs[m],
-                                         xfce_randr->output_info[m]->name);
-
         if (xfce_randr->mode[m] == None && lucent_display_icon == NULL)
             lucent_display_icon =
                 exo_gdk_pixbuf_lucent (display_icon, 50);
@@ -1490,17 +1348,15 @@ display_settings_treeview_populate (GtkBuilder *builder)
         gtk_list_store_append (store, &iter);
         if (xfce_randr->mode[m] == None)
             gtk_list_store_set (store, &iter,
-                                COLUMN_OUTPUT_NAME, name,
+                                COLUMN_OUTPUT_NAME, xfce_randr->friendly_name[m],
                                 COLUMN_OUTPUT_ICON, lucent_display_icon,
                                 COLUMN_OUTPUT_ID, m, -1);
         else
             gtk_list_store_set (store, &iter,
-                                COLUMN_OUTPUT_NAME, name,
+                                COLUMN_OUTPUT_NAME, xfce_randr->friendly_name[m],
                                 COLUMN_OUTPUT_ICON, display_icon,
                                 COLUMN_OUTPUT_ID, m, -1);
 
-        g_free (name);
-
         /* Select active output */
         if (m == active_output)
         {
@@ -1662,8 +1518,8 @@ display_settings_minimal_only_display1_toggled (GtkToggleButton *button,
     xfce_randr->mode[1] = None;
     
     /* Apply the changes */
-    xfce_randr_save_output (xfce_randr, "Default", display_channel,0);
-    xfce_randr_save_output (xfce_randr, "Default", display_channel,1);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 0, FALSE);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 1, FALSE);
     xfce_randr_apply (xfce_randr, "Default", display_channel);
     
     gtk_widget_set_sensitive( GTK_WIDGET(buttons), TRUE );
@@ -1692,8 +1548,8 @@ display_settings_minimal_only_display2_toggled (GtkToggleButton *button,
     xfce_randr->mode[0] = None;
     
     /* Apply the changes */
-    xfce_randr_save_output (xfce_randr, "Default", display_channel,0);
-    xfce_randr_save_output (xfce_randr, "Default", display_channel,1);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 0, FALSE);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 1, FALSE);
     xfce_randr_apply (xfce_randr, "Default", display_channel);
     
     gtk_widget_set_sensitive( GTK_WIDGET(buttons), TRUE );
@@ -1705,7 +1561,6 @@ display_settings_minimal_mirror_displays_toggled (GtkToggleButton *button,
 {
     GObject *buttons;
     
-    gint selected_x, selected_y;
     guint n;
 
     if ( !gtk_toggle_button_get_active(button) ) 
@@ -1730,14 +1585,12 @@ display_settings_minimal_mirror_displays_toggled (GtkToggleButton *button,
     }
 
 	/* Save changes to primary display */
-    selected_x = xfce_randr->position[0].x;
-    selected_y = xfce_randr->position[0].y;
-    xfce_randr_save_output (xfce_randr, "Default", display_channel, 0);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 0, FALSE);
     
     /* Save changes to secondary display */
-    xfce_randr->position[1].x = selected_x;
-    xfce_randr->position[1].y = selected_y;
-    xfce_randr_save_output (xfce_randr, "Default", display_channel, 1);
+    xfce_randr->relation[1] = XFCE_RANDR_PLACEMENT_MIRROR;
+    xfce_randr->related_to[1] = 0;
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 1, TRUE);
                             
     /* Apply all changes */
     xfce_randr_apply (xfce_randr, "Default", display_channel);
@@ -1752,8 +1605,6 @@ display_settings_minimal_extend_right_toggled (GtkToggleButton *button,
     GObject *buttons;
 
     guint n;
-        
-    XfceRRMode   *current_mode;
     
     if ( !gtk_toggle_button_get_active(button) ) 
         return;
@@ -1776,22 +1627,20 @@ display_settings_minimal_extend_right_toggled (GtkToggleButton *button,
         }
     }
 
-    /* Retrieve mode of Display1 */
-    current_mode = xfce_randr_find_mode_by_id (xfce_randr, 0,
-                                               xfce_randr->mode[0]);
     
     /* (Re)set Display1 to 0x0 */
-    xfce_randr->position[0].x = 0;
-    xfce_randr->position[0].y = 0;
+    xfce_randr->relation[0] = 0;
+    xfce_randr->related_to[0] = 0;
     
     /* Move Display2 right of Display2 */
-    xfce_randr->position[1].x = current_mode->width;
+    xfce_randr->relation[1] = XFCE_RANDR_PLACEMENT_RIGHT;
+    xfce_randr->related_to[1] = 0;
 
     /* Move the secondary display to the right of the primary display. */
     
     /* Save changes to both displays */
-    xfce_randr_save_output (xfce_randr, "Default", display_channel, 0);
-    xfce_randr_save_output (xfce_randr, "Default", display_channel, 1);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 0, FALSE);
+    xfce_randr_save_output (xfce_randr, "Default", display_channel, 1, TRUE);
                             
     /* Apply all changes */
     xfce_randr_apply (xfce_randr, "Default", display_channel);
@@ -1813,7 +1662,7 @@ screen_on_event (GdkXEvent *xevent,
     if (!e)
         return GDK_FILTER_CONTINUE;
 
-    event_num = e->type - xfce_randr->event_base;
+    event_num = e->type - randr_event_base;
 
     if (event_num == RRScreenChangeNotify)
     {
@@ -1847,7 +1696,7 @@ display_settings_show_main_dialog (GdkDisplay  *display,
     {
         /* Build the dialog */
         dialog = display_settings_dialog_new (builder);
-        xfce_randr->event_base = event_base;
+        randr_event_base = event_base;
         /* Set up notifications */
         XRRSelectInput (gdk_x11_display_get_xdisplay (display),
                         GDK_WINDOW_XID (gdk_get_default_root_window ()),
@@ -1971,15 +1820,15 @@ display_settings_show_minimal_dialog (GdkDisplay  *display,
         else
         {
             /* Check for mirror */
-            if ( (xfce_randr->position[0].x == xfce_randr->position[1].x ) && 
-                 (xfce_randr->position[0].y == xfce_randr->position[1].y) ) {
+            if ( xfce_randr->relation[1] == XFCE_RANDR_PLACEMENT_MIRROR &&
+                 xfce_randr->related_to[1] == 0) {
                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mirror_displays),
                                              TRUE);
             }
             
             /* Check for Extend Right */
-            if ( (xfce_randr->position[0].y == xfce_randr->position[1].y) &&
-                 (xfce_randr->position[0].x < xfce_randr->position[1].x) ) {
+            if ( xfce_randr->relation[1] == XFCE_RANDR_PLACEMENT_RIGHT &&
+                 xfce_randr->related_to[1] == 0) {
                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(extend_right),
                                              TRUE);
             }
@@ -2140,8 +1989,6 @@ main (gint argc, gchar **argv)
         cleanup:
 
         /* Release the channel */
-        if (bound_to_channel)
-            xfconf_g_property_unbind_all (G_OBJECT (display_channel));
         g_object_unref (G_OBJECT (display_channel));
     }
 
diff --git a/dialogs/display-settings/xfce-randr.c b/dialogs/display-settings/xfce-randr.c
index a6de2ae..d2cd710 100644
--- a/dialogs/display-settings/xfce-randr.c
+++ b/dialogs/display-settings/xfce-randr.c
@@ -34,6 +34,41 @@
 #include "xfce-randr.h"
 #include "edid.h"
 
+
+
+typedef struct _XfceOutputPosition XfceOutputPosition;
+
+
+
+struct _XfceOutputPosition
+{
+    gint x;
+    gint y;
+};
+
+
+
+struct _XfceRandrPrivate
+{
+    /* xrandr 1.3 capable */
+    gint                 has_1_3;
+
+    GdkDisplay          *display;
+    XRRScreenResources  *resources;
+
+    /* cache for the output/mode info */
+    XRROutputInfo      **output_info;
+    XfceRRMode         **modes;
+    XfceOutputPosition  *position;
+};
+
+
+
+static gchar *xfce_randr_friendly_name (XfceRandr *randr,
+                                        guint      output);
+
+
+
 static void
 xfce_randr_list_clone_modes (XfceRandr *randr)
 {
@@ -44,7 +79,7 @@ xfce_randr_list_clone_modes (XfceRandr *randr)
     clone_modes = g_array_new (TRUE, FALSE, sizeof (RRMode));
 
     /* walk all available modes */
-    for (n = 0; n < randr->resources->nmode; ++n)
+    for (n = 0; n < randr->priv->resources->nmode; ++n)
     {
         candidate = TRUE;
         /* walk all connected outputs */
@@ -52,9 +87,9 @@ xfce_randr_list_clone_modes (XfceRandr *randr)
         {
             found = FALSE;
             /* walk supported modes from this output */
-            for (l = 0; l < randr->output_info[m]->nmode; ++l)
+            for (l = 0; l < randr->priv->output_info[m]->nmode; ++l)
             {
-                if (randr->resources->modes[n].id == randr->output_info[m]->modes[l])
+                if (randr->priv->resources->modes[n].id == randr->priv->output_info[m]->modes[l])
                 {
                     found = TRUE;
                     break;
@@ -67,7 +102,7 @@ xfce_randr_list_clone_modes (XfceRandr *randr)
 
         /* common to all outputs, can be used for clone mode */
         if (candidate)
-            clone_modes = g_array_append_val (clone_modes, randr->resources->modes[n].id);
+            clone_modes = g_array_append_val (clone_modes, randr->priv->resources->modes[n].id);
     }
 
     /* return a "normal" array (last value -> None) */
@@ -86,13 +121,13 @@ xfce_randr_get_safe_rotations (XfceRandr *randr,
     gint         n;
 
     g_return_val_if_fail (num_output < randr->noutput, RR_Rotate_0);
-    g_return_val_if_fail (randr->output_info[num_output]->ncrtc > 0, RR_Rotate_0);
+    g_return_val_if_fail (randr->priv->output_info[num_output]->ncrtc > 0, RR_Rotate_0);
 
     rot = XFCE_RANDR_ROTATIONS_MASK | XFCE_RANDR_REFLECTIONS_MASK;
-    for (n = 0; n < randr->output_info[num_output]->ncrtc; ++n)
+    for (n = 0; n < randr->priv->output_info[num_output]->ncrtc; ++n)
     {
-        crtc_info = XRRGetCrtcInfo (xdisplay, randr->resources,
-                                    randr->output_info[num_output]->crtcs[n]);
+        crtc_info = XRRGetCrtcInfo (xdisplay, randr->priv->resources,
+                                    randr->priv->output_info[num_output]->crtcs[n]);
         rot &= crtc_info->rotations;
         XRRFreeCrtcInfo (crtc_info);
     }
@@ -142,6 +177,107 @@ xfce_randr_list_supported_modes (XRRScreenResources *resources,
 
 
 static void
+xfce_randr_guess_relations (XfceRandr *randr)
+{
+    guint n, m;
+
+    /* walk the connected outputs */
+    for (n = 0; n < randr->noutput; ++n)
+    {
+        /* ignore relations for inactive outputs */
+        if (randr->mode[n] == None)
+            continue;
+
+        for (m = 0; m < randr->noutput; ++m)
+        {
+            /* additionally ignore itself */
+            if (randr->mode[m] == None || m == n)
+                continue;
+
+            /* horizontal scale */
+            if (randr->priv->position[n].x == randr->priv->position[m].x)
+            {
+                if (randr->priv->position[n].y == randr->priv->position[m].y)
+                    randr->relation[n] = XFCE_RANDR_PLACEMENT_MIRROR;
+                else if (randr->priv->position[n].y > randr->priv->position[m].y)
+                    randr->relation[n] = XFCE_RANDR_PLACEMENT_DOWN;
+                else
+                    randr->relation[n] = XFCE_RANDR_PLACEMENT_UP;
+
+                randr->related_to[n] = m;
+                break;
+            }
+
+            /* vertical scale */
+            if (randr->priv->position[n].y == randr->priv->position[m].y)
+            {
+                if (randr->priv->position[n].x == randr->priv->position[m].x)
+                    randr->relation[n] = XFCE_RANDR_PLACEMENT_MIRROR;
+                else if (randr->priv->position[n].x > randr->priv->position[m].x)
+                    randr->relation[n] = XFCE_RANDR_PLACEMENT_RIGHT;
+                else
+                    randr->relation[n] = XFCE_RANDR_PLACEMENT_LEFT;
+
+                randr->related_to[n] = m;
+                break;
+            }
+        }
+    }
+}
+
+
+
+static void
+xfce_randr_update_positions (XfceRandr *randr,
+                             guint      output)
+{
+    const XfceRRMode *cmode, *rmode;
+    guint             rel;
+    gint              x, y;
+
+    rel = randr->related_to[output];
+    /* ignore relations for inactive outputs */
+    if (randr->mode[output] == None || randr->mode[rel] == None)
+        return;
+
+    /* modes of the two related outputs */
+    cmode = xfce_randr_find_mode_by_id (randr, output, randr->mode[output]);
+    rmode = xfce_randr_find_mode_by_id (randr, rel, randr->mode[rel]);
+
+    /* coordinates of the related_to output */
+    x = randr->priv->position[rel].x;
+    y = randr->priv->position[rel].y;
+
+    switch (randr->relation[output])
+    {
+        case XFCE_RANDR_PLACEMENT_LEFT:
+            randr->priv->position[output].x = x;
+            randr->priv->position[output].y = y;
+            randr->priv->position[rel].x = x + xfce_randr_mode_width (cmode, randr->rotation[output]);
+            break;
+        case XFCE_RANDR_PLACEMENT_RIGHT:
+            randr->priv->position[output].x = x + xfce_randr_mode_width (rmode, randr->rotation[rel]);
+            randr->priv->position[output].y = y;
+            break;
+        case XFCE_RANDR_PLACEMENT_UP:
+            randr->priv->position[output].x = x;
+            randr->priv->position[output].y = y;
+            randr->priv->position[rel].y = y + xfce_randr_mode_height (cmode, randr->rotation[output]);
+            break;
+        case XFCE_RANDR_PLACEMENT_DOWN:
+            randr->priv->position[output].x = x;
+            randr->priv->position[output].y = y + xfce_randr_mode_height (rmode, randr->rotation[rel]);
+            break;
+        default:
+            randr->priv->position[output].x = x;
+            randr->priv->position[output].y = y;
+            break;
+    }
+}
+
+
+
+static void
 xfce_randr_populate (XfceRandr *randr,
                      Display   *xdisplay,
                      GdkWindow *root_window)
@@ -153,17 +289,18 @@ xfce_randr_populate (XfceRandr *randr,
     guint          m;
 
     g_return_if_fail (randr != NULL);
-    g_return_if_fail (randr->resources != NULL);
+    g_return_if_fail (randr->priv != NULL);
+    g_return_if_fail (randr->priv->resources != NULL);
 
     /* prepare the temporary cache */
     outputs = g_ptr_array_new ();
 
     /* walk the outputs */
-    for (n = 0; n < randr->resources->noutput; ++n)
+    for (n = 0; n < randr->priv->resources->noutput; ++n)
     {
         /* get the output info */
-        output_info = XRRGetOutputInfo (xdisplay, randr->resources,
-                                        randr->resources->outputs[n]);
+        output_info = XRRGetOutputInfo (xdisplay, randr->priv->resources,
+                                        randr->priv->resources->outputs[n]);
 
         /* forget about disconnected outputs */
         if (output_info->connection != RR_Connected)
@@ -178,39 +315,42 @@ xfce_randr_populate (XfceRandr *randr,
 
     /* migrate the temporary cache */
     randr->noutput = outputs->len;
-    randr->output_info = (XRROutputInfo **) g_ptr_array_free (outputs, FALSE);
+    randr->priv->output_info = (XRROutputInfo **) g_ptr_array_free (outputs, FALSE);
 
     /* allocate final space for the settings */
     randr->mode = g_new0 (RRMode, randr->noutput);
-    randr->modes = g_new0 (XfceRRMode *, randr->noutput);
+    randr->priv->modes = g_new0 (XfceRRMode *, randr->noutput);
+    randr->priv->position = g_new0 (XfceOutputPosition, randr->noutput);
     randr->rotation = g_new0 (Rotation, randr->noutput);
     randr->rotations = g_new0 (Rotation, randr->noutput);
-    randr->position = g_new0 (XfceOutputPosition, randr->noutput);
+    randr->relation = g_new0 (XfceOutputRelation, randr->noutput);
+    randr->related_to = g_new0 (guint, randr->noutput);
     randr->status = g_new0 (XfceOutputStatus, randr->noutput);
+    randr->friendly_name = g_new0 (gchar *, randr->noutput);
 
     /* walk the connected outputs */
     for (m = 0; m < randr->noutput; ++m)
     {
         /* fill in supported modes */
-        randr->modes[m] = xfce_randr_list_supported_modes (randr->resources, randr->output_info[m]);
+        randr->priv->modes[m] = xfce_randr_list_supported_modes (randr->priv->resources, randr->priv->output_info[m]);
 
 #ifdef HAS_RANDR_ONE_POINT_THREE
         /* find the primary screen if supported */
-        if (randr->has_1_3 && XRRGetOutputPrimary (xdisplay, GDK_WINDOW_XID (root_window)) == randr->resources->outputs[m])
+        if (randr->priv->has_1_3 && XRRGetOutputPrimary (xdisplay, GDK_WINDOW_XID (root_window)) == randr->priv->resources->outputs[m])
             randr->status[m] = XFCE_OUTPUT_STATUS_PRIMARY;
         else
 #endif
             randr->status[m] = XFCE_OUTPUT_STATUS_SECONDARY;
 
-        if (randr->output_info[m]->crtc != None)
+        if (randr->priv->output_info[m]->crtc != None)
         {
-            crtc_info = XRRGetCrtcInfo (xdisplay, randr->resources,
-                                        randr->output_info[m]->crtc);
+            crtc_info = XRRGetCrtcInfo (xdisplay, randr->priv->resources,
+                                        randr->priv->output_info[m]->crtc);
             randr->mode[m] = crtc_info->mode;
             randr->rotation[m] = crtc_info->rotation;
             randr->rotations[m] = crtc_info->rotations;
-            randr->position[m].x = crtc_info->x;
-            randr->position[m].y = crtc_info->y;
+            randr->priv->position[m].x = crtc_info->x;
+            randr->priv->position[m].y = crtc_info->y;
             XRRFreeCrtcInfo (crtc_info);
         }
         else
@@ -220,10 +360,16 @@ xfce_randr_populate (XfceRandr *randr,
             randr->rotation[m] = RR_Rotate_0;
             randr->rotations[m] = xfce_randr_get_safe_rotations (randr, xdisplay, m);
         }
+
+        /* fill in the name used by the UI */
+        randr->friendly_name[m] = xfce_randr_friendly_name (randr, m);
     }
 
     /* clone modes: same RRModes present for all outputs */
     xfce_randr_list_clone_modes (randr);
+
+    /* calculate relations from positions */
+    xfce_randr_guess_relations (randr);
 }
 
 
@@ -261,17 +407,18 @@ xfce_randr_new (GdkDisplay  *display,
 
     /* allocate the structure */
     randr = g_slice_new0 (XfceRandr);
+    randr->priv = g_slice_new0 (XfceRandrPrivate);
 
-    randr->has_1_3 = (major > 1 || (major == 1 && minor >= 3));
+    randr->priv->has_1_3 = (major > 1 || (major == 1 && minor >= 3));
 
     /* set display */
-    randr->display = display;
+    randr->priv->display = display;
 
     /* get the root window */
     root_window = gdk_get_default_root_window ();
 
     /* get the screen resource */
-    randr->resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XID (root_window));
+    randr->priv->resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XID (root_window));
 
     xfce_randr_populate (randr, xdisplay, root_window);
 
@@ -288,24 +435,29 @@ xfce_randr_cleanup (XfceRandr *randr)
     /* free the output/mode info cache */
     for (n = 0; n < randr->noutput; ++n)
     {
-        if (G_LIKELY (randr->output_info[n]))
-            XRRFreeOutputInfo (randr->output_info[n]);
-        if (G_LIKELY (randr->modes[n]))
-            g_free (randr->modes[n]);
+        if (G_LIKELY (randr->priv->output_info[n]))
+            XRRFreeOutputInfo (randr->priv->output_info[n]);
+        if (G_LIKELY (randr->priv->modes[n]))
+            g_free (randr->priv->modes[n]);
+        if (G_LIKELY (randr->friendly_name[n]))
+            g_free (randr->friendly_name[n]);
     }
 
     /* free the screen resources */
-    XRRFreeScreenResources (randr->resources);
+    XRRFreeScreenResources (randr->priv->resources);
 
     /* free the settings */
+    g_free (randr->friendly_name);
     g_free (randr->clone_modes);
     g_free (randr->mode);
-    g_free (randr->modes);
+    g_free (randr->priv->modes);
     g_free (randr->rotation);
     g_free (randr->rotations);
     g_free (randr->status);
-    g_free (randr->position);
-    g_free (randr->output_info);
+    g_free (randr->relation);
+    g_free (randr->related_to);
+    g_free (randr->priv->position);
+    g_free (randr->priv->output_info);
 }
 
 
@@ -316,6 +468,7 @@ xfce_randr_free (XfceRandr *randr)
     xfce_randr_cleanup (randr);
 
     /* free the structure */
+    g_slice_free (XfceRandrPrivate, randr->priv);
     g_slice_free (XfceRandr, randr);
 }
 
@@ -330,7 +483,7 @@ xfce_randr_reload (XfceRandr *randr)
     xfce_randr_cleanup (randr);
 
     /* get the x display */
-    xdisplay = gdk_x11_display_get_xdisplay (randr->display);
+    xdisplay = gdk_x11_display_get_xdisplay (randr->priv->display);
 
     /* get the root window */
     root_window = gdk_get_default_root_window ();
@@ -340,11 +493,11 @@ xfce_randr_reload (XfceRandr *randr)
     /* xfce_randr_reload() is only called after a xrandr notification, which
        means that X is aware of the new hardware already. So, if possible,
        do not reprobe the hardware again. */
-    if (randr->has_1_3)
-        randr->resources = XRRGetScreenResourcesCurrent (xdisplay, GDK_WINDOW_XID (root_window));
+    if (randr->priv->has_1_3)
+        randr->priv->resources = XRRGetScreenResourcesCurrent (xdisplay, GDK_WINDOW_XID (root_window));
     else
 #endif
-    randr->resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XID (root_window));
+    randr->priv->resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XID (root_window));
 
     /* repopulate */
     xfce_randr_populate (randr, xdisplay, root_window);
@@ -356,7 +509,8 @@ void
 xfce_randr_save_output (XfceRandr     *randr,
                         const gchar   *scheme,
                         XfconfChannel *channel,
-                        guint          output)
+                        guint          output,
+                        gint           rel_changed)
 {
     gchar             property[512];
     gchar            *str_value;
@@ -368,19 +522,16 @@ xfce_randr_save_output (XfceRandr     *randr,
     g_return_if_fail (output < randr->noutput);
 
     /* save the device name */
-    str_value = xfce_randr_friendly_name (randr, randr->resources->outputs[output],
-                                          randr->output_info[output]->name);
     g_snprintf (property, sizeof (property), "/%s/%s", scheme,
-                randr->output_info[output]->name);
-    xfconf_channel_set_string (channel, property, str_value);
-    g_free (str_value);
+                randr->priv->output_info[output]->name);
+    xfconf_channel_set_string (channel, property, randr->friendly_name[output]);
 
     /* find the resolution and refresh rate */
     mode = xfce_randr_find_mode_by_id (randr, output, randr->mode[output]);
 
     /* if no resolution was found, mark it as inactive and stop */
     g_snprintf (property, sizeof (property), "/%s/%s/Active", scheme,
-                randr->output_info[output]->name);
+                randr->priv->output_info[output]->name);
     xfconf_channel_set_bool (channel, property, mode != NULL);
 
     if (mode == NULL)
@@ -389,13 +540,13 @@ xfce_randr_save_output (XfceRandr     *randr,
     /* save the resolution */
     str_value = g_strdup_printf ("%dx%d", mode->width, mode->height);
     g_snprintf (property, sizeof (property), "/%s/%s/Resolution", scheme,
-                randr->output_info[output]->name);
+                randr->priv->output_info[output]->name);
     xfconf_channel_set_string (channel, property, str_value);
     g_free (str_value);
 
     /* save the refresh rate */
     g_snprintf (property, sizeof (property), "/%s/%s/RefreshRate", scheme,
-                randr->output_info[output]->name);
+                randr->priv->output_info[output]->name);
     xfconf_channel_set_double (channel, property, mode->rate);
 
     /* convert the rotation into degrees */
@@ -409,7 +560,7 @@ xfce_randr_save_output (XfceRandr     *randr,
 
     /* save the rotation in degrees */
     g_snprintf (property, sizeof (property), "/%s/%s/Rotation", scheme,
-                randr->output_info[output]->name);
+                randr->priv->output_info[output]->name);
     xfconf_channel_set_int (channel, property, degrees);
 
     /* convert the reflection into a string */
@@ -423,41 +574,28 @@ xfce_randr_save_output (XfceRandr     *randr,
 
     /* save the reflection string */
     g_snprintf (property, sizeof (property), "/%s/%s/Reflection", scheme,
-                randr->output_info[output]->name);
+                randr->priv->output_info[output]->name);
     xfconf_channel_set_string (channel, property, str_value);
 
 #ifdef HAS_RANDR_ONE_POINT_THREE
     /* is it the primary output? */
     g_snprintf (property, sizeof (property), "/%s/%s/Primary", scheme,
-                randr->output_info[output]->name);
+                randr->priv->output_info[output]->name);
     xfconf_channel_set_bool (channel, property,
                              randr->status[output] == XFCE_OUTPUT_STATUS_PRIMARY);
 #endif
 
+    /* update positions according to the current relations */
+    if (rel_changed)
+        xfce_randr_update_positions (randr, output);
+
     /* save the position */
     g_snprintf (property, sizeof (property), "/%s/%s/Position/X", scheme,
-                randr->output_info[output]->name);
-    xfconf_channel_set_int (channel, property, MAX (randr->position[output].x, 0));
+                randr->priv->output_info[output]->name);
+    xfconf_channel_set_int (channel, property, MAX (randr->priv->position[output].x, 0));
     g_snprintf (property, sizeof (property), "/%s/%s/Position/Y", scheme,
-                randr->output_info[output]->name);
-    xfconf_channel_set_int (channel, property, MAX (randr->position[output].y, 0));
-}
-
-
-
-void
-xfce_randr_save_all (XfceRandr     *randr,
-                     const gchar   *scheme,
-                     XfconfChannel *channel)
-{
-    guint        n;
-
-    g_return_if_fail (randr != NULL && scheme != NULL);
-    g_return_if_fail (XFCONF_IS_CHANNEL (channel));
-
-    /* save connected outputs */
-    for (n = 0; n < randr->noutput; ++n)
-        xfce_randr_save_output (randr, scheme, channel, n);
+                randr->priv->output_info[output]->name);
+    xfconf_channel_set_int (channel, property, MAX (randr->priv->position[output].y, 0));
 }
 
 
@@ -518,17 +656,15 @@ xfce_randr_read_edid_data (Display  *xdisplay,
 
 
 
-gchar *
-xfce_randr_friendly_name (XfceRandr   *randr,
-                          RROutput     output,
-                          const gchar *name)
+static gchar *
+xfce_randr_friendly_name (XfceRandr *randr,
+                          guint      output)
 {
     Display     *xdisplay;
     MonitorInfo *info = NULL;
     guint8      *edid_data;
     gchar       *friendly_name = NULL;
-
-    g_return_val_if_fail (randr != NULL && output != None && name != NULL, g_strdup ("<null>"));
+    const gchar *name = randr->priv->output_info[output]->name;
 
     /* special case, a laptop */
     if (g_str_has_prefix (name, "LVDS")
@@ -536,8 +672,8 @@ xfce_randr_friendly_name (XfceRandr   *randr,
         return g_strdup (_("Laptop"));
 
     /* otherwise, get the vendor & size */
-    xdisplay = gdk_x11_display_get_xdisplay (randr->display);
-    edid_data = xfce_randr_read_edid_data (xdisplay, output);
+    xdisplay = gdk_x11_display_get_xdisplay (randr->priv->display);
+    edid_data = xfce_randr_read_edid_data (xdisplay, randr->priv->resources->outputs[output]);
 
     if (edid_data)
         info = decode_edid (edid_data);
@@ -569,7 +705,7 @@ xfce_randr_friendly_name (XfceRandr   *randr,
 
 
 
-XfceRRMode *
+const XfceRRMode *
 xfce_randr_find_mode_by_id (XfceRandr *randr,
                             guint      output,
                             RRMode     id)
@@ -582,10 +718,10 @@ xfce_randr_find_mode_by_id (XfceRandr *randr,
     if (id == None)
         return NULL;
 
-    for (n = 0; n < randr->output_info[output]->nmode; ++n)
+    for (n = 0; n < randr->priv->output_info[output]->nmode; ++n)
     {
-        if (randr->modes[output][n].id == id)
-            return &randr->modes[output][n];
+        if (randr->priv->modes[output][n].id == id)
+            return &randr->priv->modes[output][n];
     }
 
     return NULL;
@@ -607,24 +743,84 @@ xfce_randr_preferred_mode (XfceRandr *randr,
 
     best_mode = None;
     best_dist = 0;
-    for (n = 0; n < randr->output_info[output]->nmode; ++n)
+    for (n = 0; n < randr->priv->output_info[output]->nmode; ++n)
     {
-        if (n < randr->output_info[output]->npreferred)
+        if (n < randr->priv->output_info[output]->npreferred)
             dist = 0;
-        else if (randr->output_info[output]->mm_height != 0)
+        else if (randr->priv->output_info[output]->mm_height != 0)
             dist = (1000 * gdk_screen_height () / gdk_screen_height_mm () -
-                1000 * randr->modes[output][n].height /
-                    randr->output_info[output]->mm_height);
+                1000 * randr->priv->modes[output][n].height /
+                    randr->priv->output_info[output]->mm_height);
         else
-            dist = gdk_screen_height () - randr->modes[output][n].height;
+            dist = gdk_screen_height () - randr->priv->modes[output][n].height;
 
         dist = ABS (dist);
 
         if (best_mode == None || dist < best_dist)
         {
-            best_mode = randr->modes[output][n].id;
+            best_mode = randr->priv->modes[output][n].id;
             best_dist = dist;
         }
     }
     return best_mode;
 }
+
+
+
+const XfceRRMode *
+xfce_randr_get_modes (XfceRandr *randr,
+                      guint      output,
+                      gint      *nmode)
+{
+    g_return_val_if_fail (randr != NULL && nmode != NULL, NULL);
+    g_return_val_if_fail (output < randr->noutput, NULL);
+
+    *nmode = randr->priv->output_info[output]->nmode;
+    return randr->priv->modes[output];
+}
+
+
+
+gboolean
+xfce_randr_get_positions (XfceRandr *randr,
+                          guint      output,
+                          gint      *x,
+                          gint      *y)
+{
+    g_return_val_if_fail (randr != NULL && x != NULL && y != NULL, FALSE);
+    g_return_val_if_fail (output < randr->noutput, FALSE);
+
+    xfce_randr_update_positions (randr, output);
+
+    *x = randr->priv->position[output].x;
+    *y = randr->priv->position[output].y;
+    return TRUE;
+}
+
+
+
+guint
+xfce_randr_mode_width (const XfceRRMode *mode,
+                       Rotation          rot)
+{
+    g_return_val_if_fail (mode != NULL, 0);
+
+    if ((rot & (RR_Rotate_90|RR_Rotate_270)) != 0)
+        return mode->height;
+    else
+        return mode->width;
+}
+
+
+
+guint
+xfce_randr_mode_height (const XfceRRMode *mode,
+                        Rotation          rot)
+{
+    g_return_val_if_fail (mode != NULL, 0);
+
+    if ((rot & (RR_Rotate_90|RR_Rotate_270)) != 0)
+        return mode->width;
+    else
+        return mode->height;
+}
diff --git a/dialogs/display-settings/xfce-randr.h b/dialogs/display-settings/xfce-randr.h
index e22bc8b..87eaa3d 100644
--- a/dialogs/display-settings/xfce-randr.h
+++ b/dialogs/display-settings/xfce-randr.h
@@ -35,10 +35,8 @@
 #endif
 
 typedef struct _XfceRandr          XfceRandr;
-typedef struct _XfceOutputPosition XfceOutputPosition;
+typedef struct _XfceRandrPrivate   XfceRandrPrivate;
 typedef struct _XfceRRMode         XfceRRMode;
-typedef struct _XfceRelation       XfceRelation;
-typedef struct _XfceRotation       XfceRotation;
 typedef enum   _XfceOutputStatus   XfceOutputStatus;
 typedef enum   _XfceOutputRelation XfceOutputRelation;
 
@@ -57,12 +55,6 @@ enum _XfceOutputRelation
     XFCE_RANDR_PLACEMENT_LEFT
 };
 
-struct _XfceOutputPosition
-{
-    gint x;
-    gint y;
-};
-
 struct _XfceRRMode
 {
     RRMode  id;
@@ -71,39 +63,11 @@ struct _XfceRRMode
     gdouble rate;
 };
 
-struct _XfceRelation
-{
-    XfceOutputRelation  relation;
-    const gchar        *name;
-};
-
-struct _XfceRotation
-{
-    Rotation     rotation;
-    const gchar *name;
-};
-
 struct _XfceRandr
 {
-    /* xrandr 1.3 capable */
-    gint                 has_1_3;
-
-    /* display for this randr config */
-    GdkDisplay          *display;
-
-    /* event base for notifications */
-    gint                 event_base;
-
-    /* screen resource for this display */
-    XRRScreenResources  *resources;
-
     /* number of connected outputs */
     guint                noutput;
 
-    /* cache for the output/mode info */
-    XRROutputInfo      **output_info;
-    XfceRRMode         **modes;
-
     /* modes common to all connected outputs */
     RRMode              *clone_modes;
 
@@ -111,45 +75,58 @@ struct _XfceRandr
     RRMode              *mode;
     Rotation            *rotation;
     Rotation            *rotations;
-    XfceOutputPosition  *position;
+    XfceOutputRelation  *relation;
+    guint               *related_to;
     XfceOutputStatus    *status;
+    gchar              **friendly_name;
+
+    /* implementation details */
+    XfceRandrPrivate    *priv;
 };
 
 
 
-XfceRandr  *xfce_randr_new             (GdkDisplay    *display,
-                                        GError       **error);
+XfceRandr        *xfce_randr_new             (GdkDisplay      *display,
+                                              GError         **error);
+
+void              xfce_randr_free            (XfceRandr        *randr);
+
+void              xfce_randr_reload          (XfceRandr        *randr);
 
-void        xfce_randr_free            (XfceRandr     *randr);
+void              xfce_randr_save_output     (XfceRandr        *randr,
+                                              const gchar      *scheme,
+                                              XfconfChannel    *channel,
+                                              guint             output,
+                                              gint              rel_changed);
 
-void        xfce_randr_reload          (XfceRandr     *randr);
+void              xfce_randr_apply           (XfceRandr        *randr,
+                                              const gchar      *scheme,
+                                              XfconfChannel    *channel);
 
-void        xfce_randr_save_output     (XfceRandr     *randr,
-                                        const gchar   *scheme,
-                                        XfconfChannel *channel,
-                                        guint          output);
+void              xfce_randr_load            (XfceRandr        *randr,
+                                              const gchar      *scheme,
+                                              XfconfChannel    *channel);
 
-void        xfce_randr_save_all        (XfceRandr     *randr,
-                                        const gchar   *scheme,
-                                        XfconfChannel *channel);
+const XfceRRMode *xfce_randr_find_mode_by_id (XfceRandr        *randr,
+                                              guint             output,
+                                              RRMode            id);
 
-void        xfce_randr_apply           (XfceRandr     *randr,
-                                        const gchar   *scheme,
-                                        XfconfChannel *channel);
+RRMode            xfce_randr_preferred_mode  (XfceRandr        *randr,
+                                              guint             output);
 
-void        xfce_randr_load            (XfceRandr     *randr,
-                                        const gchar   *scheme,
-                                        XfconfChannel *channel);
+const XfceRRMode *xfce_randr_get_modes       (XfceRandr        *randr,
+                                              guint             output,
+                                              gint             *nmode);
 
-gchar      *xfce_randr_friendly_name   (XfceRandr     *randr,
-                                        RROutput       output,
-                                        const gchar   *name);
+gboolean          xfce_randr_get_positions   (XfceRandr        *randr,
+                                              guint             output,
+                                              gint             *x,
+                                              gint             *y);
 
-XfceRRMode *xfce_randr_find_mode_by_id (XfceRandr     *randr,
-                                        guint          output,
-                                        RRMode         id);
+guint             xfce_randr_mode_width      (const XfceRRMode *mode,
+                                              Rotation          rot);
 
-RRMode      xfce_randr_preferred_mode  (XfceRandr     *randr,
-                                        guint          output);
+guint             xfce_randr_mode_height     (const XfceRRMode *mode,
+                                              Rotation          rot);
 
 #endif /* !__XFCE_RANDR_H__ */


More information about the Xfce4-commits mailing list