1134 lines
33 KiB
Diff
1134 lines
33 KiB
Diff
diff --git a/libgnome-desktop/ChangeLog b/libgnome-desktop/ChangeLog
|
|
index 747f8ae..3166b49 100644
|
|
--- a/libgnome-desktop/ChangeLog
|
|
+++ b/libgnome-desktop/ChangeLog
|
|
@@ -1,3 +1,43 @@
|
|
+2008-12-12 Vincent Untz <vuntz@gnome.org>
|
|
+
|
|
+ * gnome-rr-config.c: (crtc_assignment_new):
|
|
+ * gnome-rr.c: (gnome_rr_crtc_set_config): fix translator comments, to
|
|
+ really fix bug #563831.
|
|
+
|
|
+2008-12-10 Vincent Untz <vuntz@gnome.org>
|
|
+
|
|
+ * gnome-rr-config.c: (has_similar_mode): kill since it's unused and
|
|
+ creates a warning
|
|
+
|
|
+2008-12-10 Vincent Untz <vuntz@gnome.org>
|
|
+
|
|
+ * gnome-rr-config.c: (crtc_assignment_new):
|
|
+ * gnome-rr.c: (gnome_rr_crtc_set_config):
|
|
+ Fix build, thanks to Frederic Peters <fpeters@0d.be> for the quick
|
|
+ notice. Fix bug #563926 and bug #563927.
|
|
+
|
|
+2008-12-09 Federico Mena Quintero <federico@novell.com>
|
|
+
|
|
+ Fix http://bugzilla.gnome.org/show_bug.cgi?id=563831
|
|
+
|
|
+ * gnome-rr.c (gnome_rr_crtc_set_config): Make an error string more
|
|
+ friendly to translation.
|
|
+
|
|
+ * gnome-rr-config.c (crtc_assignment_new): Likewise.
|
|
+
|
|
+2008-10-16 Federico Mena Quintero <federico@novell.com>
|
|
+
|
|
+ Add error reporting to the GnomeRR API.
|
|
+
|
|
+ * libgnomeui/gnome-rr.h (GnomeRRError): New enum with error codes
|
|
+ for the GnomeRR API.
|
|
+
|
|
+ * gnome-rr.c (gnome_rr_error_quark): New public function.
|
|
+
|
|
+Wed Oct 8 21:05:22 2008 Søren Sandmann <sandmann@redhat.com>
|
|
+
|
|
+ * Various new RR API to support fn-F7 support
|
|
+
|
|
==================== 2.24.0 ====================
|
|
|
|
2008-09-22 Vincent Untz <vuntz@gnome.org>
|
|
diff --git a/libgnome-desktop/gnome-rr-config.c b/libgnome-desktop/gnome-rr-config.c
|
|
index 4c0800a..7880c7e 100644
|
|
--- a/libgnome-desktop/gnome-rr-config.c
|
|
+++ b/libgnome-desktop/gnome-rr-config.c
|
|
@@ -24,6 +24,8 @@
|
|
|
|
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
|
|
|
+#include <config.h>
|
|
+#include <glib/gi18n-lib.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <glib.h>
|
|
@@ -66,9 +68,11 @@ static gboolean parse_file_gmarkup (const gchar *file,
|
|
|
|
typedef struct CrtcAssignment CrtcAssignment;
|
|
|
|
-static gboolean crtc_assignment_apply (CrtcAssignment *assign);
|
|
+static gboolean crtc_assignment_apply (CrtcAssignment *assign,
|
|
+ GError **error);
|
|
static CrtcAssignment *crtc_assignment_new (GnomeRRScreen *screen,
|
|
- GnomeOutputInfo **outputs);
|
|
+ GnomeOutputInfo **outputs,
|
|
+ GError **error);
|
|
static void crtc_assignment_free (CrtcAssignment *assign);
|
|
static void output_free (GnomeOutputInfo *output);
|
|
static GnomeOutputInfo *output_copy (GnomeOutputInfo *output);
|
|
@@ -746,6 +750,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)
|
|
{
|
|
@@ -762,6 +802,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)
|
|
{
|
|
@@ -780,6 +823,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)
|
|
{
|
|
@@ -820,12 +885,19 @@ make_outputs (GnomeRRConfig *config)
|
|
|
|
gboolean
|
|
gnome_rr_config_applicable (GnomeRRConfig *configuration,
|
|
- GnomeRRScreen *screen)
|
|
+ GnomeRRScreen *screen,
|
|
+ GError **error)
|
|
{
|
|
- GnomeOutputInfo **outputs = make_outputs (configuration);
|
|
- CrtcAssignment *assign = crtc_assignment_new (screen, outputs);
|
|
+ GnomeOutputInfo **outputs;
|
|
+ CrtcAssignment *assign;
|
|
gboolean result;
|
|
|
|
+ g_return_val_if_fail (configuration != NULL, FALSE);
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
+
|
|
+ outputs = make_outputs (configuration);
|
|
+ assign = crtc_assignment_new (screen, outputs, error);
|
|
+
|
|
if (assign)
|
|
{
|
|
result = TRUE;
|
|
@@ -841,21 +913,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 *
|
|
@@ -992,14 +1049,19 @@ gnome_rr_config_sanitize (GnomeRRConfig *config)
|
|
|
|
|
|
gboolean
|
|
-gnome_rr_config_save (GnomeRRConfig *configuration, GError **err)
|
|
+gnome_rr_config_save (GnomeRRConfig *configuration, GError **error)
|
|
{
|
|
GnomeRRConfig **configurations;
|
|
- GString *output = g_string_new("");
|
|
+ GString *output;
|
|
int i;
|
|
gchar *filename;
|
|
gboolean result;
|
|
|
|
+ g_return_val_if_fail (configuration != NULL, FALSE);
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
+
|
|
+ output = g_string_new ("");
|
|
+
|
|
configurations = configurations_read (NULL); /* NULL-GError */
|
|
|
|
g_string_append_printf (output, "<monitors version=\"1\">\n");
|
|
@@ -1020,7 +1082,7 @@ gnome_rr_config_save (GnomeRRConfig *configuration, GError **err)
|
|
g_string_append_printf (output, "</monitors>\n");
|
|
|
|
filename = get_config_filename ();
|
|
- result = g_file_set_contents (filename, output->str, -1, err);
|
|
+ result = g_file_set_contents (filename, output->str, -1, error);
|
|
g_free (filename);
|
|
|
|
if (result)
|
|
@@ -1037,22 +1099,82 @@ 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, GError **error)
|
|
+{
|
|
+ GnomeRRConfig *current;
|
|
+ GnomeRRConfig **configs;
|
|
+ GnomeRRConfig *result;
|
|
+
|
|
+ g_return_val_if_fail (screen != NULL, NULL);
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
+
|
|
+ current = gnome_rr_config_new_current (screen);
|
|
+
|
|
+ configs = configurations_read (error);
|
|
+
|
|
+ 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;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (result == NULL)
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG,
|
|
+ _("none of the saved display configurations matched the active configuration"));
|
|
+
|
|
+ configurations_free (configs);
|
|
+ }
|
|
+
|
|
+ gnome_rr_config_free (current);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+gnome_rr_config_apply (GnomeRRConfig *config,
|
|
+ GnomeRRScreen *screen,
|
|
+ GError **error)
|
|
{
|
|
CrtcAssignment *assignment;
|
|
GnomeOutputInfo **outputs;
|
|
gboolean result = FALSE;
|
|
|
|
- outputs = make_outputs (conf);
|
|
+ outputs = make_outputs (config);
|
|
|
|
- assignment = crtc_assignment_new (screen, outputs);
|
|
+ assignment = crtc_assignment_new (screen, outputs, error);
|
|
|
|
outputs_free (outputs);
|
|
|
|
if (assignment)
|
|
{
|
|
- if (crtc_assignment_apply (assignment))
|
|
+ if (crtc_assignment_apply (assignment, error))
|
|
result = TRUE;
|
|
|
|
crtc_assignment_free (assignment);
|
|
@@ -1064,44 +1186,42 @@ apply_configuration (GnomeRRConfig *conf, GnomeRRScreen *screen)
|
|
}
|
|
|
|
gboolean
|
|
-gnome_rr_config_apply_stored (GnomeRRScreen *screen)
|
|
+gnome_rr_config_apply_stored (GnomeRRScreen *screen, GError **error)
|
|
{
|
|
- GnomeRRConfig **configs;
|
|
- GnomeRRConfig *current;
|
|
- GnomeRRConfig *found;
|
|
- gboolean result = TRUE;
|
|
+ GnomeRRConfig *stored;
|
|
+ GError *my_error;
|
|
|
|
- if (!screen)
|
|
- return FALSE;
|
|
+ g_return_val_if_fail (screen != NULL, FALSE);
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
- configs = configurations_read (NULL); /* NULL-GError */
|
|
+ my_error = NULL;
|
|
+ if (!gnome_rr_screen_refresh (screen, &my_error)) {
|
|
+ if (my_error) {
|
|
+ g_propagate_error (error, my_error);
|
|
+ return FALSE; /* This is a genuine error */
|
|
+ }
|
|
|
|
- gnome_rr_screen_refresh (screen);
|
|
-
|
|
- current = gnome_rr_config_new_current (screen);
|
|
+ /* This means the screen didn't change, so just proceed */
|
|
+ }
|
|
|
|
- if (configs)
|
|
+ stored = gnome_rr_config_new_stored (screen, error);
|
|
+
|
|
+ if (stored)
|
|
{
|
|
- if ((found = gnome_rr_config_find (configs, current)))
|
|
- {
|
|
- apply_configuration (found, screen);
|
|
+ gboolean result;
|
|
|
|
- result = TRUE;
|
|
- }
|
|
- else
|
|
- {
|
|
- result = FALSE;
|
|
- }
|
|
+ result = gnome_rr_config_apply (stored, screen, error);
|
|
+
|
|
+ gnome_rr_config_free (stored);
|
|
|
|
- configurations_free (configs);
|
|
+ return result;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ return FALSE;
|
|
}
|
|
-
|
|
- gnome_rr_config_free (current);
|
|
-
|
|
- return result;
|
|
}
|
|
|
|
-
|
|
/*
|
|
* CRTC assignment
|
|
*/
|
|
@@ -1214,6 +1334,11 @@ crtc_assignment_free (CrtcAssignment *assign)
|
|
g_free (assign);
|
|
}
|
|
|
|
+typedef struct {
|
|
+ gboolean has_error;
|
|
+ GError **error;
|
|
+} ConfigureCrtcState;
|
|
+
|
|
static void
|
|
configure_crtc (gpointer key,
|
|
gpointer value,
|
|
@@ -1221,13 +1346,19 @@ configure_crtc (gpointer key,
|
|
{
|
|
GnomeRRCrtc *crtc = key;
|
|
CrtcInfo *info = value;
|
|
-
|
|
- gnome_rr_crtc_set_config (crtc,
|
|
- info->x, info->y,
|
|
- info->mode,
|
|
- info->rotation,
|
|
- (GnomeRROutput **)info->outputs->pdata,
|
|
- info->outputs->len);
|
|
+ ConfigureCrtcState *state = data;
|
|
+
|
|
+ if (state->has_error)
|
|
+ return;
|
|
+
|
|
+ if (!gnome_rr_crtc_set_config (crtc,
|
|
+ info->x, info->y,
|
|
+ info->mode,
|
|
+ info->rotation,
|
|
+ (GnomeRROutput **)info->outputs->pdata,
|
|
+ info->outputs->len,
|
|
+ state->error))
|
|
+ state->has_error = TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
@@ -1368,7 +1499,7 @@ get_required_virtual_size (CrtcAssignment *assign, int *width, int *height)
|
|
}
|
|
|
|
static CrtcAssignment *
|
|
-crtc_assignment_new (GnomeRRScreen *screen, GnomeOutputInfo **outputs)
|
|
+crtc_assignment_new (GnomeRRScreen *screen, GnomeOutputInfo **outputs, GError **error)
|
|
{
|
|
CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1);
|
|
|
|
@@ -1388,6 +1519,15 @@ crtc_assignment_new (GnomeRRScreen *screen, GnomeOutputInfo **outputs)
|
|
if (width < min_width || width > max_width ||
|
|
height < min_height || height > max_height)
|
|
{
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
|
|
+ /* Translators: the "requested", "minimum", and
|
|
+ * "maximum" words here are not keywords; please
|
|
+ * translate them as usual. */
|
|
+ _("required virtual size does not fit available size: "
|
|
+ "requested=(%d, %d), minimum=(%d, %d), maximum=(%d, %d)"),
|
|
+ width, height,
|
|
+ min_width, min_height,
|
|
+ max_width, max_height);
|
|
goto fail;
|
|
}
|
|
|
|
@@ -1395,6 +1535,9 @@ crtc_assignment_new (GnomeRRScreen *screen, GnomeOutputInfo **outputs)
|
|
|
|
return assignment;
|
|
}
|
|
+ else
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
|
|
+ _("could not find a suitable configuration of screens"));
|
|
|
|
fail:
|
|
crtc_assignment_free (assignment);
|
|
@@ -1403,7 +1546,7 @@ fail:
|
|
}
|
|
|
|
static gboolean
|
|
-crtc_assignment_apply (CrtcAssignment *assign)
|
|
+crtc_assignment_apply (CrtcAssignment *assign, GError **error)
|
|
{
|
|
GnomeRRCrtc **all_crtcs = gnome_rr_screen_list_crtcs (assign->screen);
|
|
int width, height;
|
|
@@ -1425,6 +1568,8 @@ crtc_assignment_apply (CrtcAssignment *assign)
|
|
width = MIN (max_width, width);
|
|
height = MAX (min_height, height);
|
|
height = MIN (max_height, height);
|
|
+
|
|
+ /* FMQ: do we need to check the sizes instead of clamping them? */
|
|
|
|
/* Turn off all crtcs that are currently displaying outside the new screen,
|
|
* or are not used in the new setup
|
|
@@ -1452,7 +1597,7 @@ crtc_assignment_apply (CrtcAssignment *assign)
|
|
|
|
if (x + w > width || y + h > height || !g_hash_table_lookup (assign->info, crtc))
|
|
{
|
|
- if (!gnome_rr_crtc_set_config (crtc, 0, 0, NULL, GNOME_RR_ROTATION_0, NULL, 0))
|
|
+ if (!gnome_rr_crtc_set_config (crtc, 0, 0, NULL, GNOME_RR_ROTATION_0, NULL, 0, error))
|
|
{
|
|
success = FALSE;
|
|
break;
|
|
@@ -1473,9 +1618,16 @@ crtc_assignment_apply (CrtcAssignment *assign)
|
|
|
|
if (success)
|
|
{
|
|
+ ConfigureCrtcState state;
|
|
+
|
|
gnome_rr_screen_set_size (assign->screen, width, height, width_mm, height_mm);
|
|
+
|
|
+ state.has_error = FALSE;
|
|
+ state.error = error;
|
|
|
|
- g_hash_table_foreach (assign->info, configure_crtc, NULL);
|
|
+ g_hash_table_foreach (assign->info, configure_crtc, &state);
|
|
+
|
|
+ success = !state.has_error;
|
|
}
|
|
|
|
return success;
|
|
diff --git a/libgnome-desktop/gnome-rr.c b/libgnome-desktop/gnome-rr.c
|
|
index 6a37d32..109b89e 100644
|
|
--- a/libgnome-desktop/gnome-rr.c
|
|
+++ b/libgnome-desktop/gnome-rr.c
|
|
@@ -24,6 +24,8 @@
|
|
|
|
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
|
|
|
+#include <config.h>
|
|
+#include <glib/gi18n-lib.h>
|
|
#include "libgnomeui/gnome-rr.h"
|
|
#include <string.h>
|
|
#include <X11/Xlib.h>
|
|
@@ -50,6 +52,8 @@ struct ScreenInfo
|
|
GnomeRRMode ** modes;
|
|
|
|
GnomeRRScreen * screen;
|
|
+
|
|
+ GnomeRRMode ** clone_modes;
|
|
};
|
|
|
|
struct GnomeRRScreen
|
|
@@ -118,14 +122,16 @@ struct GnomeRRMode
|
|
static GnomeRRCrtc * crtc_new (ScreenInfo *info,
|
|
RRCrtc id);
|
|
static void crtc_free (GnomeRRCrtc *crtc);
|
|
-static void crtc_initialize (GnomeRRCrtc *crtc,
|
|
- XRRScreenResources *res);
|
|
+static gboolean crtc_initialize (GnomeRRCrtc *crtc,
|
|
+ XRRScreenResources *res,
|
|
+ GError **error);
|
|
|
|
/* GnomeRROutput */
|
|
static GnomeRROutput *output_new (ScreenInfo *info,
|
|
RROutput id);
|
|
-static void output_initialize (GnomeRROutput *output,
|
|
- XRRScreenResources *res);
|
|
+static gboolean output_initialize (GnomeRROutput *output,
|
|
+ XRRScreenResources *res,
|
|
+ GError **error);
|
|
static void output_free (GnomeRROutput *output);
|
|
|
|
/* GnomeRRMode */
|
|
@@ -136,6 +142,22 @@ static void mode_initialize (GnomeRRMode *mode,
|
|
static void mode_free (GnomeRRMode *mode);
|
|
|
|
|
|
+/* Errors */
|
|
+
|
|
+/**
|
|
+ * gnome_rr_error_quark:
|
|
+ *
|
|
+ * Returns the #GQuark that will be used for #GError values returned by the
|
|
+ * GnomeRR API.
|
|
+ *
|
|
+ * Return value: a #GQuark used to identify errors coming from the GnomeRR API.
|
|
+ */
|
|
+GQuark
|
|
+gnome_rr_error_quark (void)
|
|
+{
|
|
+ return g_quark_from_static_string ("gnome-rr-error-quark");
|
|
+}
|
|
+
|
|
/* Screen */
|
|
static GnomeRROutput *
|
|
gnome_rr_output_by_id (ScreenInfo *info, RROutput id)
|
|
@@ -222,14 +244,90 @@ 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)
|
|
+ ScreenInfo *info,
|
|
+ GError **error)
|
|
{
|
|
XRRScreenResources *resources;
|
|
|
|
@@ -244,14 +342,18 @@ fill_out_screen_info (Display *xdisplay,
|
|
&(info->max_width),
|
|
&(info->max_height))) {
|
|
/* XRR caught an error */
|
|
- return False;
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
|
|
+ _("could not get the range of screen sizes"));
|
|
+ return FALSE;
|
|
}
|
|
|
|
gdk_flush ();
|
|
if (gdk_error_trap_pop ())
|
|
{
|
|
/* Unhandled X Error was generated */
|
|
- return False;
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_UNKNOWN,
|
|
+ _("unhandled X error while getting the range of screen sizes"));
|
|
+ return FALSE;
|
|
}
|
|
|
|
#if 0
|
|
@@ -311,10 +413,16 @@ fill_out_screen_info (Display *xdisplay,
|
|
|
|
/* Initialize */
|
|
for (crtc = info->crtcs; *crtc; ++crtc)
|
|
- crtc_initialize (*crtc, resources);
|
|
+ {
|
|
+ if (!crtc_initialize (*crtc, resources, error))
|
|
+ return FALSE;
|
|
+ }
|
|
|
|
for (output = info->outputs; *output; ++output)
|
|
- output_initialize (*output, resources);
|
|
+ {
|
|
+ if (!output_initialize (*output, resources, error))
|
|
+ return FALSE;
|
|
+ }
|
|
|
|
for (i = 0; i < resources->nmode; ++i)
|
|
{
|
|
@@ -322,6 +430,8 @@ fill_out_screen_info (Display *xdisplay,
|
|
|
|
mode_initialize (mode, &(resources->modes[i]));
|
|
}
|
|
+
|
|
+ gather_clone_modes (info);
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -330,13 +440,14 @@ fill_out_screen_info (Display *xdisplay,
|
|
#if 0
|
|
g_print ("Couldn't get screen resources\n");
|
|
#endif
|
|
-
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
|
|
+ _("could not get the screen resources (CRTCs, outputs, modes)"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static ScreenInfo *
|
|
-screen_info_new (GnomeRRScreen *screen)
|
|
+screen_info_new (GnomeRRScreen *screen, GError **error)
|
|
{
|
|
ScreenInfo *info = g_new0 (ScreenInfo, 1);
|
|
|
|
@@ -347,36 +458,36 @@ screen_info_new (GnomeRRScreen *screen)
|
|
info->modes = NULL;
|
|
info->screen = screen;
|
|
|
|
- if (fill_out_screen_info (screen->xdisplay, screen->xroot, info))
|
|
+ if (fill_out_screen_info (screen->xdisplay, screen->xroot, info, error))
|
|
{
|
|
return info;
|
|
}
|
|
else
|
|
{
|
|
- g_free (info);
|
|
+ screen_info_free (info);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
-screen_update (GnomeRRScreen *screen, gboolean force_callback)
|
|
+screen_update (GnomeRRScreen *screen, gboolean force_callback, GError **error)
|
|
{
|
|
ScreenInfo *info;
|
|
gboolean changed = FALSE;
|
|
|
|
g_assert (screen != NULL);
|
|
-
|
|
- info = screen_info_new (screen);
|
|
- if (info)
|
|
- {
|
|
- if (info->resources->configTimestamp != screen->info->resources->configTimestamp)
|
|
+
|
|
+ info = screen_info_new (screen, error);
|
|
+ if (!info)
|
|
+ return FALSE;
|
|
+
|
|
+ if (info->resources->configTimestamp != screen->info->resources->configTimestamp)
|
|
changed = TRUE;
|
|
|
|
- screen_info_free (screen->info);
|
|
+ screen_info_free (screen->info);
|
|
|
|
- screen->info = info;
|
|
- }
|
|
-
|
|
+ screen->info = info;
|
|
+
|
|
if ((changed || force_callback) && screen->callback)
|
|
screen->callback (screen, screen->data);
|
|
|
|
@@ -404,7 +515,7 @@ screen_on_event (GdkXEvent *xevent,
|
|
/* FIXME: we may need to be more discriminating in
|
|
* what causes 'changed' events
|
|
*/
|
|
- screen_update (screen, TRUE);
|
|
+ screen_update (screen, TRUE, NULL); /* NULL-GError */
|
|
}
|
|
|
|
/* Pass the event on to GTK+ */
|
|
@@ -417,11 +528,14 @@ screen_on_event (GdkXEvent *xevent,
|
|
GnomeRRScreen *
|
|
gnome_rr_screen_new (GdkScreen *gdk_screen,
|
|
GnomeRRScreenChanged callback,
|
|
- gpointer data)
|
|
+ gpointer data,
|
|
+ GError **error)
|
|
{
|
|
Display *dpy = GDK_SCREEN_XDISPLAY (gdk_screen);
|
|
int event_base;
|
|
int ignore;
|
|
+
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
if (XRRQueryExtension (dpy, &event_base, &ignore))
|
|
{
|
|
@@ -438,7 +552,7 @@ gnome_rr_screen_new (GdkScreen *gdk_screen,
|
|
|
|
screen->randr_event_base = event_base;
|
|
|
|
- screen->info = screen_info_new (screen);
|
|
+ screen->info = screen_info_new (screen, error);
|
|
|
|
if (!screen->info) {
|
|
g_free (screen);
|
|
@@ -459,8 +573,13 @@ gnome_rr_screen_new (GdkScreen *gdk_screen,
|
|
gdk_window_add_filter (screen->gdk_root, screen_on_event, screen);
|
|
return screen;
|
|
}
|
|
-
|
|
- return NULL;
|
|
+ else
|
|
+ {
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
|
|
+ _("RANDR extension is not present"));
|
|
+
|
|
+ return NULL;
|
|
+ }
|
|
}
|
|
|
|
void
|
|
@@ -511,10 +630,25 @@ gnome_rr_screen_get_ranges (GnomeRRScreen *screen,
|
|
*max_height = screen->info->max_height;
|
|
}
|
|
|
|
+/**
|
|
+ * gnome_rr_screen_refresh
|
|
+ * @screen: a #GnomeRRScreen
|
|
+ * @error: location to store error, or %NULL
|
|
+ *
|
|
+ * Refreshes the screen configuration, and calls the screen's callback if it
|
|
+ * exists and if the screen's configuration changed.
|
|
+ *
|
|
+ * Return value: TRUE if the screen's configuration changed; otherwise, the
|
|
+ * function returns FALSE and a NULL error if the configuration didn't change,
|
|
+ * or FALSE and a non-NULL error if there was an error while refreshing the
|
|
+ * configuration.
|
|
+ */
|
|
gboolean
|
|
-gnome_rr_screen_refresh (GnomeRRScreen *screen)
|
|
+gnome_rr_screen_refresh (GnomeRRScreen *screen,
|
|
+ GError **error)
|
|
{
|
|
- return screen_update (screen, FALSE);
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
+ return screen_update (screen, FALSE, error);
|
|
}
|
|
|
|
GnomeRRMode **
|
|
@@ -526,6 +660,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)
|
|
{
|
|
@@ -647,8 +790,8 @@ read_edid_data (GnomeRROutput *output)
|
|
return NULL;
|
|
}
|
|
|
|
-static void
|
|
-output_initialize (GnomeRROutput *output, XRRScreenResources *res)
|
|
+static gboolean
|
|
+output_initialize (GnomeRROutput *output, XRRScreenResources *res, GError **error)
|
|
{
|
|
XRROutputInfo *info = XRRGetOutputInfo (
|
|
DISPLAY (output), res, output->id);
|
|
@@ -661,8 +804,11 @@ output_initialize (GnomeRROutput *output, XRRScreenResources *res)
|
|
|
|
if (!info || !output->info)
|
|
{
|
|
- /* FIXME */
|
|
- return;
|
|
+ /* FIXME: see the comment in crtc_initialize() */
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
|
|
+ _("could not get information about output %d"),
|
|
+ (int) output->id);
|
|
+ return FALSE;
|
|
}
|
|
|
|
output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */
|
|
@@ -714,6 +860,8 @@ output_initialize (GnomeRROutput *output, XRRScreenResources *res)
|
|
output->edid_data = read_edid_data (output);
|
|
|
|
XRRFreeOutputInfo (info);
|
|
+
|
|
+ return TRUE;
|
|
}
|
|
|
|
static void
|
|
@@ -927,22 +1075,38 @@ gnome_rr_crtc_set_config (GnomeRRCrtc *crtc,
|
|
GnomeRRMode *mode,
|
|
GnomeRRRotation rotation,
|
|
GnomeRROutput **outputs,
|
|
- int n_outputs)
|
|
+ int n_outputs,
|
|
+ GError **error)
|
|
{
|
|
ScreenInfo *info;
|
|
GArray *output_ids;
|
|
+ Status status;
|
|
gboolean result;
|
|
int i;
|
|
|
|
g_return_val_if_fail (crtc != NULL, FALSE);
|
|
g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
|
|
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
info = crtc->info;
|
|
|
|
if (mode)
|
|
{
|
|
- g_return_val_if_fail (x + mode->width <= info->max_width, FALSE);
|
|
- g_return_val_if_fail (y + mode->height <= info->max_height, FALSE);
|
|
+ if (x + mode->width > info->max_width
|
|
+ || y + mode->height > info->max_height)
|
|
+ {
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
|
|
+ /* Translators: the "position", "size", and "maximum"
|
|
+ * words here are not keywords; please translate them
|
|
+ * as usual. */
|
|
+ _("requested position/size for CRTC %d is outside the allowed limit: "
|
|
+ "position=(%d, %d), size=(%d, %d), maximum=(%d, %d)"),
|
|
+ (int) crtc->id,
|
|
+ x, y,
|
|
+ mode->width, mode->height,
|
|
+ info->max_width, info->max_height);
|
|
+ return FALSE;
|
|
+ }
|
|
}
|
|
|
|
output_ids = g_array_new (FALSE, FALSE, sizeof (RROutput));
|
|
@@ -953,15 +1117,24 @@ gnome_rr_crtc_set_config (GnomeRRCrtc *crtc,
|
|
g_array_append_val (output_ids, outputs[i]->id);
|
|
}
|
|
|
|
- result = XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id,
|
|
+ status = XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id,
|
|
CurrentTime,
|
|
x, y,
|
|
mode ? mode->id : None,
|
|
xrotation_from_rotation (rotation),
|
|
(RROutput *)output_ids->data,
|
|
- output_ids->len) == RRSetConfigSuccess;
|
|
+ output_ids->len);
|
|
|
|
g_array_free (output_ids, TRUE);
|
|
+
|
|
+ if (status == RRSetConfigSuccess)
|
|
+ result = TRUE;
|
|
+ else {
|
|
+ result = FALSE;
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
|
|
+ _("could not set the configuration for CRTC %d"),
|
|
+ (int) crtc->id);
|
|
+ }
|
|
|
|
return result;
|
|
}
|
|
@@ -1049,9 +1222,10 @@ crtc_new (ScreenInfo *info, RROutput id)
|
|
return crtc;
|
|
}
|
|
|
|
-static void
|
|
+static gboolean
|
|
crtc_initialize (GnomeRRCrtc *crtc,
|
|
- XRRScreenResources *res)
|
|
+ XRRScreenResources *res,
|
|
+ GError **error)
|
|
{
|
|
XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id);
|
|
GPtrArray *a;
|
|
@@ -1064,7 +1238,12 @@ crtc_initialize (GnomeRRCrtc *crtc,
|
|
if (!info)
|
|
{
|
|
/* FIXME: We need to reaquire the screen resources */
|
|
- return;
|
|
+ /* FIXME: can we actually catch BadRRCrtc, and does it make sense to emit that? */
|
|
+
|
|
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
|
|
+ _("could not get information about CRTC %d"),
|
|
+ (int) crtc->id);
|
|
+ return FALSE;
|
|
}
|
|
|
|
/* GnomeRRMode */
|
|
@@ -1102,6 +1281,8 @@ crtc_initialize (GnomeRRCrtc *crtc,
|
|
crtc->rotations = gnome_rr_rotation_from_xrotation (info->rotations);
|
|
|
|
XRRFreeCrtcInfo (info);
|
|
+
|
|
+ return TRUE;
|
|
}
|
|
|
|
static void
|
|
diff --git a/libgnome-desktop/libgnomeui/gnome-rr-config.h b/libgnome-desktop/libgnomeui/gnome-rr-config.h
|
|
index 6a8302d..a59db55 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,28 @@ struct GnomeRRConfig
|
|
};
|
|
|
|
GnomeRRConfig *gnome_rr_config_new_current (GnomeRRScreen *screen);
|
|
+GnomeRRConfig *gnome_rr_config_new_stored (GnomeRRScreen *screen,
|
|
+ GError **error);
|
|
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);
|
|
+ GError **error);
|
|
void gnome_rr_config_sanitize (GnomeRRConfig *configuration);
|
|
-gboolean gnome_rr_config_apply_stored (GnomeRRScreen *screen);
|
|
+gboolean gnome_rr_config_apply (GnomeRRConfig *configuration,
|
|
+ GnomeRRScreen *screen,
|
|
+ GError **error);
|
|
+gboolean gnome_rr_config_apply_stored (GnomeRRScreen *screen,
|
|
+ GError **error);
|
|
gboolean gnome_rr_config_applicable (GnomeRRConfig *configuration,
|
|
- GnomeRRScreen *screen);
|
|
+ GnomeRRScreen *screen,
|
|
+ GError **error);
|
|
+
|
|
+/* 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..38b1af8 100644
|
|
--- a/libgnome-desktop/libgnomeui/gnome-rr.h
|
|
+++ b/libgnome-desktop/libgnomeui/gnome-rr.h
|
|
@@ -48,14 +48,31 @@ typedef enum
|
|
GNOME_RR_REFLECT_Y = (1 << 5)
|
|
} GnomeRRRotation;
|
|
|
|
+/* Error codes */
|
|
+
|
|
+#define GNOME_RR_ERROR (gnome_rr_error_quark ())
|
|
+
|
|
+GQuark gnome_rr_error_quark (void);
|
|
+
|
|
+typedef enum {
|
|
+ GNOME_RR_ERROR_UNKNOWN, /* generic "fail" */
|
|
+ GNOME_RR_ERROR_NO_RANDR_EXTENSION, /* RANDR extension is not present */
|
|
+ GNOME_RR_ERROR_RANDR_ERROR, /* generic/undescribed error from the underlying XRR API */
|
|
+ GNOME_RR_ERROR_BOUNDS_ERROR, /* requested bounds of a CRTC are outside the maximum size */
|
|
+ GNOME_RR_ERROR_CRTC_ASSIGNMENT, /* could not assign CRTCs to outputs */
|
|
+ GNOME_RR_ERROR_NO_MATCHING_CONFIG, /* none of the saved configurations matched the current configuration */
|
|
+} GnomeRRError;
|
|
+
|
|
/* GnomeRRScreen */
|
|
GnomeRRScreen * gnome_rr_screen_new (GdkScreen *screen,
|
|
GnomeRRScreenChanged callback,
|
|
- gpointer data);
|
|
+ gpointer data,
|
|
+ GError **error);
|
|
void gnome_rr_screen_destroy (GnomeRRScreen *screen);
|
|
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,
|
|
@@ -63,7 +80,8 @@ void gnome_rr_screen_set_size (GnomeRRScreen *scree
|
|
int mm_height);
|
|
GnomeRRCrtc * gnome_rr_screen_get_crtc_by_id (GnomeRRScreen *screen,
|
|
guint32 id);
|
|
-gboolean gnome_rr_screen_refresh (GnomeRRScreen *screen);
|
|
+gboolean gnome_rr_screen_refresh (GnomeRRScreen *screen,
|
|
+ GError **error);
|
|
GnomeRROutput * gnome_rr_screen_get_output_by_id (GnomeRRScreen *screen,
|
|
guint32 id);
|
|
GnomeRROutput * gnome_rr_screen_get_output_by_name (GnomeRRScreen *screen,
|
|
@@ -109,7 +127,8 @@ gboolean gnome_rr_crtc_set_config (GnomeRRCrtc *crtc,
|
|
GnomeRRMode *mode,
|
|
GnomeRRRotation rotation,
|
|
GnomeRROutput **outputs,
|
|
- int n_outputs);
|
|
+ int n_outputs,
|
|
+ GError **error);
|
|
gboolean gnome_rr_crtc_can_drive_output (GnomeRRCrtc *crtc,
|
|
GnomeRROutput *output);
|
|
GnomeRRMode * gnome_rr_crtc_get_current_mode (GnomeRRCrtc *crtc);
|
|
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
index 3bf18ac..84c9122 100644
|
|
--- a/po/POTFILES.in
|
|
+++ b/po/POTFILES.in
|
|
@@ -7,3 +7,5 @@ libgnome-desktop/display-name.c
|
|
libgnome-desktop/gnome-desktop-item.c
|
|
libgnome-desktop/gnome-ditem-edit.c
|
|
libgnome-desktop/gnome-hint.c
|
|
+libgnome-desktop/gnome-rr.c
|
|
+libgnome-desktop/gnome-rr-config.c
|