Blob Blame History Raw
diff -up gnome-desktop-2.24.0/libgnome-desktop/gnome-rr.c.clone-modes gnome-desktop-2.24.0/libgnome-desktop/gnome-rr.c
--- gnome-desktop-2.24.0/libgnome-desktop/gnome-rr.c.clone-modes	2008-09-24 14:09:09.000000000 -0400
+++ gnome-desktop-2.24.0/libgnome-desktop/gnome-rr.c	2008-09-24 14:09:09.000000000 -0400
@@ -50,6 +50,8 @@ struct ScreenInfo
     GnomeRRMode **	modes;
     
     GnomeRRScreen *	screen;
+
+    GnomeRRMode **	clone_modes;
 };
 
 struct GnomeRRScreen
@@ -222,11 +224,86 @@ screen_info_free (ScreenInfo *info)
 	    mode_free (*mode);
 	g_free (info->modes);
     }
+
+    if (info->clone_modes)
+    {
+	/* The modes themselves were freed above */
+	g_free (info->clone_modes);
+    }
     
     g_free (info);
 }
 
 static gboolean
+has_similar_mode (GnomeRROutput *output, GnomeRRMode *mode)
+{
+    int i;
+    GnomeRRMode **modes = gnome_rr_output_list_modes (output);
+    int width = gnome_rr_mode_get_width (mode);
+    int height = gnome_rr_mode_get_height (mode);
+
+    for (i = 0; modes[i] != NULL; ++i)
+    {
+	GnomeRRMode *m = modes[i];
+
+	if (gnome_rr_mode_get_width (m) == width	&&
+	    gnome_rr_mode_get_height (m) == height)
+	{
+	    return TRUE;
+	}
+    }
+
+    return FALSE;
+}
+
+static void
+gather_clone_modes (ScreenInfo *info)
+{
+    int i;
+    GPtrArray *result = g_ptr_array_new ();
+
+    for (i = 0; info->outputs[i] != NULL; ++i)
+    {
+	int j;
+	GnomeRROutput *output1, *output2;
+
+	output1 = info->outputs[i];
+	
+	if (!output1->connected)
+	    continue;
+	
+	for (j = 0; output1->modes[j] != NULL; ++j)
+	{
+	    GnomeRRMode *mode = output1->modes[j];
+	    gboolean valid;
+	    int k;
+
+	    valid = TRUE;
+	    for (k = 0; info->outputs[k] != NULL; ++k)
+	    {
+		output2 = info->outputs[k];
+		
+		if (!output2->connected)
+		    continue;
+		
+		if (!has_similar_mode (output2, mode))
+		{
+		    valid = FALSE;
+		    break;
+		}
+	    }
+
+	    if (valid)
+		g_ptr_array_add (result, mode);
+	}
+    }
+
+    g_ptr_array_add (result, NULL);
+    
+    info->clone_modes = (GnomeRRMode **)g_ptr_array_free (result, FALSE);
+}
+
+static gboolean
 fill_out_screen_info (Display *xdisplay,
 		      Window xroot,
 		      ScreenInfo *info)
@@ -322,6 +399,8 @@ fill_out_screen_info (Display *xdisplay,
 	    
 	    mode_initialize (mode, &(resources->modes[i]));
 	}
+
+	gather_clone_modes (info);
 	
 	return TRUE;
     }
@@ -526,6 +605,15 @@ gnome_rr_screen_list_modes (GnomeRRScree
     return screen->info->modes;
 }
 
+GnomeRRMode **
+gnome_rr_screen_list_clone_modes   (GnomeRRScreen *screen)
+{
+    g_return_val_if_fail (screen != NULL, NULL);
+    g_return_val_if_fail (screen->info != NULL, NULL);
+
+    return screen->info->clone_modes;
+}
+
 GnomeRRCrtc **
 gnome_rr_screen_list_crtcs (GnomeRRScreen *screen)
 {
diff -up gnome-desktop-2.24.0/libgnome-desktop/gnome-rr-config.c.clone-modes gnome-desktop-2.24.0/libgnome-desktop/gnome-rr-config.c
--- gnome-desktop-2.24.0/libgnome-desktop/gnome-rr-config.c.clone-modes	2008-09-24 14:09:09.000000000 -0400
+++ gnome-desktop-2.24.0/libgnome-desktop/gnome-rr-config.c	2008-09-24 14:11:34.000000000 -0400
@@ -748,6 +748,42 @@ output_match (GnomeOutputInfo *output1, 
     return TRUE;
 }
 
+static gboolean
+output_equal (GnomeOutputInfo *output1, GnomeOutputInfo *output2)
+{
+    g_assert (output1 != NULL);
+    g_assert (output2 != NULL);
+
+    if (!output_match (output1, output2))
+	return FALSE;
+
+    if (output1->on != output2->on)
+	return FALSE;
+
+    if (output1->on)
+    {
+	if (output1->width != output2->width)
+	    return FALSE;
+	
+	if (output1->height != output2->height)
+	    return FALSE;
+	
+	if (output1->rate != output2->rate)
+	    return FALSE;
+	
+	if (output1->x != output2->x)
+	    return FALSE;
+	
+	if (output1->y != output2->y)
+	    return FALSE;
+	
+	if (output1->rotation != output2->rotation)
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
 static GnomeOutputInfo *
 find_output (GnomeRRConfig *config, const char *name)
 {
@@ -764,6 +800,9 @@ find_output (GnomeRRConfig *config, cons
     return NULL;
 }
 
+/* Match means "these configurations apply to the same hardware
+ * setups"
+ */
 gboolean
 gnome_rr_config_match (GnomeRRConfig *c1, GnomeRRConfig *c2)
 {
@@ -782,6 +821,28 @@ gnome_rr_config_match (GnomeRRConfig *c1
     return TRUE;
 }
 
+/* Equal means "the configurations will result in the same
+ * modes being set on the outputs"
+ */
+gboolean
+gnome_rr_config_equal (GnomeRRConfig  *c1,
+		       GnomeRRConfig  *c2)
+{
+    int i;
+
+    for (i = 0; c1->outputs[i] != NULL; ++i)
+    {
+	GnomeOutputInfo *output1 = c1->outputs[i];
+	GnomeOutputInfo *output2;
+
+	output2 = find_output (c2, output1->name);
+	if (!output2 || !output_equal (output1, output2))
+	    return FALSE;
+    }
+    
+    return TRUE;
+}
+
 static GnomeOutputInfo **
 make_outputs (GnomeRRConfig *config)
 {
@@ -843,21 +904,6 @@ gnome_rr_config_applicable (GnomeRRConfi
     return result;
 }
 
-static GnomeRRConfig *
-gnome_rr_config_find (GnomeRRConfig **haystack,
-		    GnomeRRConfig  *needle)
-{
-    int i;
-
-    for (i = 0; haystack[i] != NULL; ++i)
-    {
-	if (gnome_rr_config_match (haystack[i], needle))
-	    return haystack[i];
-    }
-
-    return NULL;
-}
-
 /* Database management */
 
 static gchar *
@@ -1039,14 +1085,69 @@ gnome_rr_config_save (GnomeRRConfig *con
     return result;
 }
 
-static gboolean
-apply_configuration (GnomeRRConfig *conf, GnomeRRScreen *screen)
+static GnomeRRConfig *
+gnome_rr_config_copy (GnomeRRConfig *config)
+{
+    GnomeRRConfig *copy = g_new0 (GnomeRRConfig, 1);
+    int i;
+    GPtrArray *array = g_ptr_array_new ();
+
+    copy->clone = config->clone;
+    
+    for (i = 0; config->outputs[i] != NULL; ++i)
+	g_ptr_array_add (array, output_copy (config->outputs[i]));
+
+    g_ptr_array_add (array, NULL);
+    copy->outputs = (GnomeOutputInfo **)g_ptr_array_free (array, FALSE);
+
+    return copy;
+}
+
+GnomeRRConfig *
+gnome_rr_config_new_stored (GnomeRRScreen *screen)
+{
+    GnomeRRConfig *current;
+    GnomeRRConfig **configs;
+    GnomeRRConfig *result;
+
+    if (!screen)
+	return NULL;
+    
+    current = gnome_rr_config_new_current (screen);
+    
+    configs = configurations_read (NULL); /* NULL_GError */
+
+    result = NULL;
+    if (configs)
+    {
+	int i;
+	
+	for (i = 0; configs[i] != NULL; ++i)
+	{
+	    if (gnome_rr_config_match (configs[i], current))
+	    {
+		result = gnome_rr_config_copy (configs[i]);
+		break;
+	    }
+	}
+
+	configurations_free (configs);
+    }
+
+    gnome_rr_config_free (current);
+    
+    return result;
+}
+
+gboolean
+gnome_rr_config_apply (GnomeRRConfig *config,
+		       GnomeRRScreen *screen)
 {
     CrtcAssignment *assignment;
     GnomeOutputInfo **outputs;
     gboolean result = FALSE;
 
-    outputs = make_outputs (conf);
+    outputs = make_outputs (config);
 
     assignment = crtc_assignment_new (screen, outputs);
 
@@ -1068,42 +1169,51 @@ apply_configuration (GnomeRRConfig *conf
 gboolean
 gnome_rr_config_apply_stored (GnomeRRScreen *screen)
 {
-    GnomeRRConfig **configs;
-    GnomeRRConfig *current;
-    GnomeRRConfig *found;
-    gboolean result = TRUE;
+    GnomeRRConfig *stored;
 
     if (!screen)
 	return FALSE;
 
-    configs = configurations_read (NULL); /* NULL-GError */
-
     gnome_rr_screen_refresh (screen);
-    
-    current = gnome_rr_config_new_current (screen);
 
-    if (configs)
+    stored = gnome_rr_config_new_stored (screen);
+
+    if (stored)
     {
-	if ((found = gnome_rr_config_find (configs, current)))
-	{
-	    apply_configuration (found, screen);
+	gnome_rr_config_apply (stored, screen);
 
-	    result = TRUE;
-	}
-	else
+	gnome_rr_config_free (stored);
+	
+	return TRUE;
+    }
+    else
+    {
+	return FALSE;
+    }
+}
+
+static gboolean
+has_similar_mode (GnomeRROutput *output, GnomeRRMode *mode)
+{
+    int i;
+    GnomeRRMode **modes = gnome_rr_output_list_modes (output);
+    int width = gnome_rr_mode_get_width (mode);
+    int height = gnome_rr_mode_get_height (mode);
+
+    for (i = 0; modes[i] != NULL; ++i)
+    {
+	GnomeRRMode *m = modes[i];
+
+	if (gnome_rr_mode_get_width (m) == width	&&
+	    gnome_rr_mode_get_height (m) == height)
 	{
-	    result = FALSE;
+	    return TRUE;
 	}
-	
-	configurations_free (configs);
     }
-	
-    gnome_rr_config_free (current);
 
-    return result;
+    return FALSE;
 }
 
-
 /*
  * CRTC assignment
  */
diff -up gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr-config.h.clone-modes gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr-config.h
--- gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr-config.h.clone-modes	2008-09-22 17:01:45.000000000 -0400
+++ gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr-config.h	2008-09-24 14:09:09.000000000 -0400
@@ -34,6 +34,13 @@
 typedef struct GnomeOutputInfo GnomeOutputInfo;
 typedef struct GnomeRRConfig GnomeRRConfig;
 
+/* FIXME:
+ *
+ * This structure is a Frankenstein monster where all of the fields
+ * are generated by the system, but some of them can be changed by
+ * the client.
+ */
+
 struct GnomeOutputInfo
 {
     char *		name;
@@ -66,14 +73,24 @@ struct GnomeRRConfig
 };
 
 GnomeRRConfig  *gnome_rr_config_new_current  (GnomeRRScreen  *screen);
+GnomeRRConfig  *gnome_rr_config_new_stored   (GnomeRRScreen  *screen);
 void            gnome_rr_config_free         (GnomeRRConfig  *configuration);
 gboolean        gnome_rr_config_match        (GnomeRRConfig  *config1,
 					      GnomeRRConfig  *config2);
+gboolean        gnome_rr_config_equal	     (GnomeRRConfig  *config1,
+					      GnomeRRConfig  *config2);
 gboolean        gnome_rr_config_save         (GnomeRRConfig  *configuration,
 					      GError        **err);
 void            gnome_rr_config_sanitize     (GnomeRRConfig  *configuration);
+gboolean	gnome_rr_config_apply        (GnomeRRConfig  *configuration,
+					      GnomeRRScreen  *screen);
 gboolean        gnome_rr_config_apply_stored (GnomeRRScreen  *screen);
 gboolean        gnome_rr_config_applicable   (GnomeRRConfig  *configuration,
 					      GnomeRRScreen  *screen);
 
+/* A utility function that isn't really in the spirit of this file, but I don't
+ * don't know a better place for it.
+ */
+GnomeRRMode **gnome_rr_create_clone_modes (GnomeRRScreen *screen);
+
 #endif
diff -up gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr.h.clone-modes gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr.h
--- gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr.h.clone-modes	2008-09-22 17:01:45.000000000 -0400
+++ gnome-desktop-2.24.0/libgnome-desktop/libgnomeui/gnome-rr.h	2008-09-24 14:09:09.000000000 -0400
@@ -56,6 +56,7 @@ void            gnome_rr_screen_destroy 
 GnomeRROutput **gnome_rr_screen_list_outputs       (GnomeRRScreen         *screen);
 GnomeRRCrtc **  gnome_rr_screen_list_crtcs         (GnomeRRScreen         *screen);
 GnomeRRMode **  gnome_rr_screen_list_modes         (GnomeRRScreen         *screen);
+GnomeRRMode **  gnome_rr_screen_list_clone_modes   (GnomeRRScreen	  *screen);
 void            gnome_rr_screen_set_size           (GnomeRRScreen         *screen,
 						    int                    width,
 						    int                    height,