435 lines
11 KiB
Diff
435 lines
11 KiB
Diff
diff --git a/libgnome-desktop/gnome-rr-config.c b/libgnome-desktop/gnome-rr-config.c
|
|
index 4c21fa1..49e7a4b 100644
|
|
--- a/libgnome-desktop/gnome-rr-config.c
|
|
+++ b/libgnome-desktop/gnome-rr-config.c
|
|
@@ -745,6 +745,42 @@ output_match (GnomeOutputInfo *output1, GnomeOutputInfo *output2)
|
|
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)
|
|
{
|
|
@@ -761,6 +797,9 @@ find_output (GnomeRRConfig *config, const char *name)
|
|
return NULL;
|
|
}
|
|
|
|
+/* Match means "these configurations apply to the same hardware
|
|
+ * setups"
|
|
+ */
|
|
gboolean
|
|
gnome_rr_config_match (GnomeRRConfig *c1, GnomeRRConfig *c2)
|
|
{
|
|
@@ -779,6 +818,28 @@ gnome_rr_config_match (GnomeRRConfig *c1, GnomeRRConfig *c2)
|
|
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)
|
|
{
|
|
@@ -840,21 +901,6 @@ gnome_rr_config_applicable (GnomeRRConfig *configuration,
|
|
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 *
|
|
@@ -1036,13 +1082,68 @@ gnome_rr_config_save (GnomeRRConfig *configuration, GError **err)
|
|
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;
|
|
|
|
- outputs = make_outputs (conf);
|
|
+ outputs = make_outputs (config);
|
|
|
|
assignment = crtc_assignment_new (screen, outputs);
|
|
|
|
@@ -1065,42 +1166,51 @@ apply_configuration (GnomeRRConfig *conf, GnomeRRScreen *screen)
|
|
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 --git a/libgnome-desktop/gnome-rr.c b/libgnome-desktop/gnome-rr.c
|
|
index 826e64c..d07499e 100644
|
|
--- a/libgnome-desktop/gnome-rr.c
|
|
+++ b/libgnome-desktop/gnome-rr.c
|
|
@@ -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 (GnomeRRScreen *screen)
|
|
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 --git a/libgnome-desktop/libgnomeui/gnome-rr-config.h b/libgnome-desktop/libgnomeui/gnome-rr-config.h
|
|
index 6a8302d..8834b1f 100644
|
|
--- a/libgnome-desktop/libgnomeui/gnome-rr-config.h
|
|
+++ b/libgnome-desktop/libgnomeui/gnome-rr-config.h
|
|
@@ -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 --git a/libgnome-desktop/libgnomeui/gnome-rr.h b/libgnome-desktop/libgnomeui/gnome-rr.h
|
|
index 01b4f45..c7907fc 100644
|
|
--- a/libgnome-desktop/libgnomeui/gnome-rr.h
|
|
+++ b/libgnome-desktop/libgnomeui/gnome-rr.h
|
|
@@ -56,6 +56,7 @@ void gnome_rr_screen_destroy (GnomeRRScreen *scree
|
|
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,
|