gnome-desktop/gnome-desktop-randr-gerror.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