diff --git a/add-randr12-capplet.patch b/add-randr12-capplet.patch index 49ddc60..c2d2a57 100644 --- a/add-randr12-capplet.patch +++ b/add-randr12-capplet.patch @@ -1,6 +1,6 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/edid.h ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/edid.h 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/edid.h 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,169 @@ +typedef unsigned char uchar; +typedef struct MonitorInfo MonitorInfo; @@ -172,8 +172,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/edid.h +MonitorInfo *decode_edid (const uchar *data); +char * make_display_name (const MonitorInfo *info); diff -up /dev/null gnome-control-center-2.21.90/capplets/display/foo-marshal.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/foo-marshal.c 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/foo-marshal.c 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,279 @@ + +#include @@ -455,8 +455,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/foo-marshal.c +} + diff -up /dev/null gnome-control-center-2.21.90/capplets/display/edid-parse.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/edid-parse.c 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/edid-parse.c 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,551 @@ +/* + * Copyright 2007 Red Hat, Inc. @@ -1010,8 +1010,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/edid-parse.c + return info; +} diff -up /dev/null gnome-control-center-2.21.90/capplets/display/foo-marshal.h ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/foo-marshal.h 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/foo-marshal.h 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,63 @@ + +#ifndef __foo_marshal_MARSHAL_H__ @@ -1077,8 +1077,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/foo-marshal.h +#endif /* __foo_marshal_MARSHAL_H__ */ + diff -up /dev/null gnome-control-center-2.21.90/capplets/display/scrollarea.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/scrollarea.c 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/scrollarea.c 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,1902 @@ +#include /* For GDK_PARENT_RELATIVE_BG */ +#include "scrollarea.h" @@ -2982,1281 +2982,10 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/scrollarea.c +} + +#endif -diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/monitor-db.c 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,1197 @@ -+#include -+#include -+#include -+#include "monitor-db.h" -+#include "edid.h" -+ -+/* Code to load and save monitor configurations -+ * -+ * A monitor configuration is a list of monitors and associated -+ * outputs, along with information about mode and rotation. -+ * -+ * A monitor is identified by a string like EDID-SUN-0x0567 -+ * which is decoded as "We got this information from EDID" - the manufacturer -+ * was "SUN" and the product code was 0x0567. -+ * -+ * Do we put this in gconf? -+ * -+ * The database itself is an XML file with entries like this: -+ * -+ * -+ * -+ * EDID-SUN-0x0567-12341234 -+ * -+ * on -+ * 1024 -+ * 768 -+ * 0 -+ * -+ * -+ * -+ * EDID-CMO-0x1210 -+ * -+ * <...> -+ * -+ * -+ * -+ * -+ */ -+ -+/* A helper wrapper around the GMarkup parser stuff */ -+static gboolean parse_file_gmarkup (const gchar *file, -+ const GMarkupParser *parser, -+ gpointer data, -+ GError **err); -+ -+typedef struct CrtcAssignment CrtcAssignment; -+ -+static void crtc_assignment_apply (CrtcAssignment *assign); -+static CrtcAssignment *crtc_assignment_new (RWScreen *screen, -+ Output **outputs); -+static void crtc_assignment_free (CrtcAssignment *assign); -+ -+ -+typedef struct Parser Parser; -+ -+/* Parser for monitor configurations */ -+struct Parser -+{ -+ Output *output; -+ Configuration *configuration; -+ GPtrArray *outputs; -+ GPtrArray *configurations; -+ GQueue *stack; -+}; -+ -+static int -+parse_int (const char *text) -+{ -+ return strtol (text, NULL, 0); -+} -+ -+static gboolean -+stack_is (Parser *parser, -+ const char *s1, -+ ...) -+{ -+ GList *stack = NULL; -+ const char *s; -+ GList *l1, *l2; -+ va_list args; -+ -+ stack = g_list_prepend (stack, (gpointer)s1); -+ -+ va_start (args, s1); -+ -+ s = va_arg (args, const char *); -+ while (s) -+ { -+ stack = g_list_prepend (stack, (gpointer)s); -+ s = va_arg (args, const char *); -+ } -+ -+ l1 = stack; -+ l2 = parser->stack->head; -+ -+ while (l1 && l2) -+ { -+ if (strcmp (l1->data, l2->data) != 0) -+ { -+ g_list_free (stack); -+ return FALSE; -+ } -+ -+ l1 = l1->next; -+ l2 = l2->next; -+ } -+ -+ g_list_free (stack); -+ -+ return (!l1 && !l2); -+} -+ -+static void -+handle_start_element (GMarkupParseContext *context, -+ const gchar *name, -+ const gchar **attr_names, -+ const gchar **attr_values, -+ gpointer user_data, -+ GError **err) -+{ -+ Parser *parser = user_data; -+ -+ if (strcmp (name, "output") == 0) -+ { -+ int i; -+ g_assert (parser->output == NULL); -+ -+ parser->output = g_new0 (Output, 1); -+ parser->output->rotation = 0; -+ -+ for (i = 0; attr_names[i] != NULL; ++i) -+ { -+ if (strcmp (attr_names[i], "name") == 0) -+ { -+ parser->output->name = g_strdup (attr_values[i]); -+ break; -+ } -+ } -+ -+ if (!parser->output->name) -+ { -+ /* This really shouldn't happen, but it's better to make -+ * something up than to crash later. -+ */ -+ g_warning ("Malformed monitor configuration file"); -+ -+ parser->output->name = g_strdup ("default"); -+ } -+ parser->output->connected = FALSE; -+ parser->output->on = FALSE; -+ } -+ else if (strcmp (name, "configuration") == 0) -+ { -+ g_assert (parser->configuration == NULL); -+ -+ parser->configuration = g_new0 (Configuration, 1); -+ parser->configuration->outputs = g_new0 (Output *, 1); -+ } -+ -+ g_queue_push_tail (parser->stack, g_strdup (name)); -+} -+ -+static void -+handle_end_element (GMarkupParseContext *context, -+ const gchar *name, -+ gpointer user_data, -+ GError **err) -+{ -+ Parser *parser = user_data; -+ -+ if (strcmp (name, "output") == 0) -+ { -+ if (parser->output->rotation == 0) -+ parser->output->rotation = RW_ROTATION_0; -+ -+ g_ptr_array_add (parser->outputs, parser->output); -+ -+ parser->output = NULL; -+ } -+ else if (strcmp (name, "configuration") == 0) -+ { -+ g_ptr_array_add (parser->outputs, NULL); -+ parser->configuration->outputs = -+ (Output **)g_ptr_array_free (parser->outputs, FALSE); -+ parser->outputs = g_ptr_array_new (); -+ g_ptr_array_add (parser->configurations, parser->configuration); -+ parser->configuration = NULL; -+ } -+ -+ g_free (g_queue_pop_tail (parser->stack)); -+} -+ -+static void -+handle_text (GMarkupParseContext *context, -+ const gchar *text, -+ gsize text_len, -+ gpointer user_data, -+ GError **err) -+{ -+ Parser *parser = user_data; -+ -+ if (stack_is (parser, "vendor", "output", "configuration", NULL)) -+ { -+ parser->output->connected = TRUE; -+ -+ strncpy (parser->output->vendor, text, 3); -+ parser->output->vendor[3] = 0; -+ } -+ else if (stack_is (parser, "product", "output", "configuration", NULL)) -+ { -+ parser->output->connected = TRUE; -+ -+ parser->output->product = parse_int (text); -+ } -+ else if (stack_is (parser, "serial", "output", "configuration", NULL)) -+ { -+ parser->output->connected = TRUE; -+ -+ parser->output->serial = parse_int (text); -+ } -+ else if (stack_is (parser, "width", "output", "configuration", NULL)) -+ { -+ parser->output->on = TRUE; -+ -+ parser->output->width = parse_int (text); -+ } -+ else if (stack_is (parser, "x", "output", "configuration", NULL)) -+ { -+ parser->output->on = TRUE; -+ -+ parser->output->x = parse_int (text); -+ } -+ else if (stack_is (parser, "y", "output", "configuration", NULL)) -+ { -+ parser->output->on = TRUE; -+ -+ parser->output->y = parse_int (text); -+ } -+ else if (stack_is (parser, "height", "output", "configuration", NULL)) -+ { -+ parser->output->on = TRUE; -+ -+ parser->output->height = parse_int (text); -+ } -+ else if (stack_is (parser, "rate", "output", "configuration", NULL)) -+ { -+ parser->output->on = TRUE; -+ -+ parser->output->rate = parse_int (text); -+ } -+ else if (stack_is (parser, "rotation", "output", "configuration", NULL)) -+ { -+ if (strcmp (text, "normal") == 0) -+ { -+ parser->output->rotation |= RW_ROTATION_0; -+ } -+ else if (strcmp (text, "left") == 0) -+ { -+ parser->output->rotation |= RW_ROTATION_90; -+ } -+ else if (strcmp (text, "upside_down") == 0) -+ { -+ parser->output->rotation |= RW_ROTATION_180; -+ } -+ else if (strcmp (text, "right") == 0) -+ { -+ parser->output->rotation |= RW_ROTATION_270; -+ } -+ } -+ else if (stack_is (parser, "reflect_x", "output", "configuration", NULL)) -+ { -+ if (strcmp (text, "yes") == 0) -+ { -+ parser->output->rotation |= RW_REFLECT_X; -+ } -+ } -+ else if (stack_is (parser, "reflect_y", "output", "configuration", NULL)) -+ { -+ if (strcmp (text, "yes") == 0) -+ { -+ parser->output->rotation |= RW_REFLECT_Y; -+ } -+ } -+ else -+ { -+ /* Ignore other properties so we can expand the format in the future */ -+ } -+} -+ -+static void -+output_free (Output *output) -+{ -+ g_free (output); -+} -+ -+void -+configuration_free (Configuration *config) -+{ -+ int i; -+ -+ for (i = 0; config->outputs[i] != NULL; ++i) -+ output_free (config->outputs[i]); -+} -+ -+static void -+parser_free (Parser *parser) -+{ -+ int i; -+ GList *list; -+ -+ if (parser->output) -+ output_free (parser->output); -+ -+ if (parser->configuration) -+ configuration_free (parser->configuration); -+ -+ for (i = 0; i < parser->outputs->len; ++i) -+ { -+ Output *output = parser->outputs->pdata[i]; -+ -+ output_free (output); -+ } -+ -+ g_ptr_array_free (parser->outputs, TRUE); -+ -+ for (i = 0; i < parser->configurations->len; ++i) -+ { -+ Configuration *config = parser->configurations->pdata[i]; -+ -+ configuration_free (config); -+ } -+ -+ g_ptr_array_free (parser->configurations, TRUE); -+ -+ for (list = parser->stack->head; list; list = list->next) -+ g_free (list->data); -+ g_queue_free (parser->stack); -+ -+ g_free (parser); -+} -+ -+static Configuration ** -+configurations_read (const gchar *filename, GError **error) -+{ -+ Parser *parser = g_new0 (Parser, 1); -+ Configuration **result; -+ GMarkupParser callbacks = { -+ handle_start_element, -+ handle_end_element, -+ handle_text, -+ NULL, /* passthrough */ -+ NULL, /* error */ -+ }; -+ -+ parser->configurations = g_ptr_array_new (); -+ parser->outputs = g_ptr_array_new (); -+ parser->stack = g_queue_new (); -+ -+ if (!parse_file_gmarkup (filename, &callbacks, parser, error)) -+ { -+ result = NULL; -+ -+ g_print ("parse error\n"); -+ -+ g_assert (parser->outputs); -+ goto out; -+ } -+ -+ g_assert (parser->outputs); -+ -+ g_ptr_array_add (parser->configurations, NULL); -+ result = (Configuration **)g_ptr_array_free (parser->configurations, FALSE); -+ parser->configurations = g_ptr_array_new (); -+ -+ g_assert (parser->outputs); -+out: -+ parser_free (parser); -+ -+ return result; -+} -+ -+Configuration * -+configuration_new_current (RWScreen *screen) -+{ -+ Configuration *config = g_new0 (Configuration, 1); -+ GPtrArray *a = g_ptr_array_new (); -+ int i; -+ RWOutput **rw_outputs = rw_screen_list_outputs (screen); -+ -+ for (i = 0; rw_outputs[i] != NULL; ++i) -+ { -+ RWOutput *rw_output = rw_outputs[i]; -+ Output *output = g_new0 (Output, 1); -+ RWMode *mode = NULL; -+ const guint8 *edid_data = rw_output_get_edid_data (rw_output); -+ RWCrtc *crtc; -+ -+ output->name = g_strdup (rw_output_get_name (rw_output)); -+ output->connected = rw_output_is_connected (rw_output); -+ -+ if (!output->connected) -+ { -+ output->width = -1; -+ output->height = -1; -+ output->rate = -1; -+ output->rotation = RW_ROTATION_0; -+ } -+ else -+ { -+ if (edid_data) -+ { -+ MonitorInfo *info = decode_edid (edid_data); -+ -+ memcpy (output->vendor, info->manufacturer_code, -+ sizeof (output->vendor)); -+ -+ output->product = info->product_code; -+ output->serial = info->serial_number; -+ output->aspect = info->aspect_ratio; -+ -+ g_free (info); -+ } -+ else -+ { -+ strcpy (output->vendor, "???"); -+ output->product = 0; -+ output->serial = 0; -+ } -+ -+ crtc = rw_output_get_crtc (rw_output); -+ -+ if (crtc) -+ { -+ output->on = TRUE; -+ -+ mode = rw_crtc_get_current_mode (crtc); -+ -+ output->width = rw_mode_get_width (mode); -+ output->height = rw_mode_get_height (mode); -+ output->rate = rw_mode_get_freq (mode); -+ output->rotation = rw_crtc_get_current_rotation (crtc); -+ } -+ else -+ { -+ output->on = FALSE; -+ } -+ -+ /* Get preferred size for the monitor */ -+ mode = rw_output_get_preferred_mode (rw_output); -+ -+ if (!mode) -+ { -+ RWMode **modes = rw_output_list_modes (rw_output); -+ -+ /* FIXME: we should pick the "best" mode here, where best is -+ * sorted wrt -+ * -+ * - closest aspect ratio -+ * - mode area -+ * - refresh rate -+ * - We may want to extend randrwrap so that get_preferred -+ * returns that - although that could also depend on -+ * the crtc. -+ */ -+ if (modes[0]) -+ mode = modes[0]; -+ } -+ -+ if (mode) -+ { -+ output->pref_width = rw_mode_get_width (mode); -+ output->pref_height = rw_mode_get_height (mode); -+ } -+ else -+ { -+ /* Pick some random numbers. This should basically never happen */ -+ output->pref_width = 1024; -+ output->pref_height = 768; -+ } -+ } -+ -+ g_ptr_array_add (a, output); -+ } -+ -+ g_ptr_array_add (a, NULL); -+ -+ config->outputs = (Output **)g_ptr_array_free (a, FALSE); -+ -+ g_assert (configuration_match (config, config)); -+ -+ return config; -+} -+ -+static void -+configurations_free (Configuration **configurations) -+{ -+ int i; -+ -+ for (i = 0; configurations[i] != NULL; ++i) -+ configuration_free (configurations[i]); -+ -+ g_free (configurations); -+} -+ -+static gboolean -+parse_file_gmarkup (const gchar *filename, -+ const GMarkupParser *parser, -+ gpointer data, -+ GError **err) -+{ -+ GMarkupParseContext *context = NULL; -+ gchar *contents = NULL; -+ gboolean result = TRUE; -+ guint len; -+ -+ if (!g_file_get_contents (filename, &contents, &len, err)) -+ { -+ result = FALSE; -+ goto out; -+ } -+ -+ context = g_markup_parse_context_new (parser, 0, data, NULL); -+ -+ if (!g_markup_parse_context_parse (context, contents, len, err)) -+ { -+ result = FALSE; -+ goto out; -+ } -+ -+ if (!g_markup_parse_context_end_parse (context, err)) -+ { -+ result = FALSE; -+ goto out; -+ } -+ -+out: -+ if (contents) -+ g_free (contents); -+ -+ if (context) -+ g_markup_parse_context_free (context); -+ -+ return result; -+} -+ -+static gboolean -+output_match (Output *output1, Output *output2) -+{ -+ if (strcmp (output1->name, output2->name) != 0) -+ return FALSE; -+ -+ if (strcmp (output1->vendor, output2->vendor) != 0) -+ return FALSE; -+ -+ if (output1->product != output2->product) -+ return FALSE; -+ -+ if (output1->serial != output2->serial) -+ return FALSE; -+ -+ if (output1->connected != output2->connected) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static Output * -+find_output (Configuration *config, const char *name) -+{ -+ int i; -+ -+ for (i = 0; config->outputs[i] != NULL; ++i) -+ { -+ Output *output = config->outputs[i]; -+ -+ if (strcmp (name, output->name) == 0) -+ return output; -+ } -+ -+ return NULL; -+} -+ -+gboolean -+configuration_match (Configuration *c1, Configuration *c2) -+{ -+ int i; -+ -+ for (i = 0; c1->outputs[i] != NULL; ++i) -+ { -+ Output *output1 = c1->outputs[i]; -+ Output *output2; -+ -+ output2 = find_output (c2, output1->name); -+ if (!output2 || !output_match (output1, output2)) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+gboolean -+configuration_applicable (Configuration *configuration, -+ RWScreen *screen) -+{ -+ CrtcAssignment *assign = crtc_assignment_new (screen, configuration->outputs); -+ -+ if (assign) -+ { -+ crtc_assignment_free (assign); -+ -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+static Configuration * -+configuration_find (Configuration **haystack, -+ Configuration *needle) -+{ -+ int i; -+ -+ for (i = 0; haystack[i] != NULL; ++i) -+ { -+ if (configuration_match (haystack[i], needle)) -+ return haystack[i]; -+ } -+ -+ return NULL; -+} -+ -+/* Database management */ -+static gboolean -+do_free (gpointer data) -+{ -+ g_free (data); -+ return FALSE; -+} -+ -+static gchar * -+idle_free (gchar *s) -+{ -+ g_idle_add (do_free, s); -+ -+ return s; -+} -+ -+static const gchar * -+get_filename (void) -+{ -+ return idle_free ( -+ g_build_filename ( -+ g_get_home_dir(), ".gnome2", "monitors.xml", NULL)); -+} -+ -+static const char * -+get_rotation_name (RWRotation r) -+{ -+ if (r & RW_ROTATION_0) -+ return "normal"; -+ if (r & RW_ROTATION_90) -+ return "left"; -+ if (r & RW_ROTATION_180) -+ return "upside_down"; -+ if (r & RW_ROTATION_270) -+ return "right"; -+ -+ return "normal"; -+} -+ -+static const char * -+yes_no (int x) -+{ -+ return x? "yes" : "no"; -+} -+ -+static const char * -+get_reflect_x (RWRotation r) -+{ -+ return yes_no (r & RW_REFLECT_X); -+} -+ -+static const char * -+get_reflect_y (RWRotation r) -+{ -+ return yes_no (r & RW_REFLECT_Y); -+} -+ -+static void -+emit_configuration (Configuration *config, -+ GString *string) -+{ -+ int j; -+ -+ g_string_append_printf (string, "\n"); -+ -+ for (j = 0; config->outputs[j] != NULL; ++j) -+ { -+ Output *output = config->outputs[j]; -+ -+ g_string_append_printf ( -+ string, " \n", output->name); -+ -+ if (output->connected && *output->vendor != '\0') -+ { -+ g_string_append_printf ( -+ string, " %s\n", output->vendor); -+ g_string_append_printf ( -+ string, " 0x%04x\n", output->product); -+ g_string_append_printf ( -+ string, " 0x%08x\n", output->serial); -+ } -+ -+ /* An unconnected output which is on does not make sense */ -+ if (output->connected && output->on) -+ { -+ g_string_append_printf ( -+ string, " %d\n", output->width); -+ g_string_append_printf ( -+ string, " %d\n", output->height); -+ g_string_append_printf ( -+ string, " %d\n", output->rate); -+ g_string_append_printf ( -+ string, " %d\n", output->x); -+ g_string_append_printf ( -+ string, " %d\n", output->y); -+ g_string_append_printf ( -+ string, " %s\n", get_rotation_name (output->rotation)); -+ g_string_append_printf ( -+ string, " %s\n", get_reflect_x (output->rotation)); -+ g_string_append_printf ( -+ string, " %s\n", get_reflect_y (output->rotation)); -+ } -+ -+ g_string_append_printf (string, " \n"); -+ } -+ -+ g_string_append_printf (string, "\n"); -+} -+ -+gboolean -+configuration_save (Configuration *configuration, GError **err) -+{ -+ Configuration **configurations; -+ GString *output = g_string_new(""); -+ int i; -+ -+ configurations = configurations_read (get_filename(), NULL); -+ -+ if (configurations) -+ { -+ for (i = 0; configurations[i] != NULL; ++i) -+ { -+ if (!configuration_match (configurations[i], configuration)) -+ emit_configuration (configurations[i], output); -+ } -+ -+ configurations_free (configurations); -+ } -+ -+ emit_configuration (configuration, output); -+ -+ return g_file_set_contents (get_filename(), output->str, -1, err); -+} -+ -+static gboolean -+apply_configuration (Configuration *conf, RWScreen *screen) -+{ -+ CrtcAssignment *assignment; -+ GTimer *timer; -+ -+ timer = g_timer_new (); -+ -+ assignment = crtc_assignment_new (screen, conf->outputs); -+ -+ g_print ("Computed CRTC assignment in %.2f ms\n", -+ 1000 * g_timer_elapsed (timer, NULL)); -+ -+ if (assignment) -+ { -+ crtc_assignment_apply (assignment); -+ -+ crtc_assignment_free (assignment); -+ -+ return TRUE; -+ } -+ else -+ { -+ g_print (" ... no assignment found\n"); -+ } -+ -+ return FALSE; -+} -+ -+gboolean -+configuration_apply_stored (RWScreen *screen) -+{ -+ char *file = g_build_filename ( -+ g_get_home_dir(), ".gnome2", "monitors.xml", NULL); -+ Configuration **configs = configurations_read (file, NULL); -+ Configuration *current = configuration_new_current (screen); -+ Configuration *found; -+ gboolean result; -+ -+ if (configs) -+ { -+ if ((found = configuration_find (configs, current))) -+ { -+ apply_configuration (found, screen); -+ result = TRUE; -+ } -+ else -+ { -+ result = FALSE; -+ g_print ("Not found\n"); -+ } -+ -+ configurations_free (configs); -+ } -+ -+ g_free (file); -+ configuration_free (current); -+ -+ return result; -+} -+ -+ -+/* -+ * CRTC assignment -+ */ -+typedef struct CrtcInfo CrtcInfo; -+ -+struct CrtcInfo -+{ -+ RWMode *mode; -+ int x; -+ int y; -+ RWRotation rotation; -+ GPtrArray *outputs; -+}; -+ -+struct CrtcAssignment -+{ -+ RWScreen *screen; -+ GHashTable *info; -+}; -+ -+static gboolean -+can_clone (CrtcInfo *info, -+ RWOutput *output) -+{ -+ int i; -+ -+ for (i = 0; i < info->outputs->len; ++i) -+ { -+ RWOutput *clone = info->outputs->pdata[i]; -+ -+ if (!rw_output_can_clone (clone, output)) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+crtc_assignment_assign (CrtcAssignment *assign, -+ RWCrtc *crtc, -+ RWMode *mode, -+ int x, -+ int y, -+ RWRotation rotation, -+ RWOutput *output) -+{ -+ /* FIXME: We should reject stuff that is outside the screen ranges */ -+ -+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); -+ -+ if (!rw_crtc_can_drive_output (crtc, output) || -+ !rw_output_supports_mode (output, mode) || -+ !rw_crtc_supports_rotation (crtc, rotation)) -+ { -+ return FALSE; -+ } -+ -+ if (info) -+ { -+ if (info->mode == mode && -+ info->x == x && -+ info->y == y && -+ info->rotation == rotation && -+ can_clone (info, output)) -+ { -+ g_ptr_array_add (info->outputs, output); -+ -+ return TRUE; -+ } -+ } -+ else -+ { -+ CrtcInfo *info = g_new (CrtcInfo, 1); -+ -+ info->mode = mode; -+ info->x = x; -+ info->y = y; -+ info->rotation = rotation; -+ info->outputs = g_ptr_array_new (); -+ -+ g_ptr_array_add (info->outputs, output); -+ -+ g_hash_table_insert (assign->info, crtc, info); -+ -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+static void -+crtc_assignment_unassign (CrtcAssignment *assign, -+ RWCrtc *crtc, -+ RWOutput *output) -+{ -+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); -+ -+ if (info) -+ { -+ g_ptr_array_remove (info->outputs, output); -+ -+ if (info->outputs->len == 0) -+ g_hash_table_remove (assign->info, crtc); -+ } -+} -+ -+static void -+crtc_assignment_free (CrtcAssignment *assign) -+{ -+ g_hash_table_destroy (assign->info); -+ -+ g_free (assign); -+} -+ -+static void -+configure_crtc (gpointer key, -+ gpointer value, -+ gpointer data) -+{ -+ RWCrtc *crtc = key; -+ CrtcInfo *info = value; -+ GTimer *timer = g_timer_new (); -+ -+ g_print ("Configuring crtc %x with ", rw_crtc_get_id (crtc)); -+ -+ if (info->mode) -+ { -+ int n_outputs = info->outputs->len; -+ -+ g_print ("mode %x, %d outputs (%d %d %d %d), and rotation %d ", -+ rw_mode_get_id (info->mode), -+ n_outputs, -+ info->x, info->y, -+ rw_mode_get_width (info->mode), -+ rw_mode_get_height (info->mode), -+ info->rotation); -+ } -+ else -+ { -+ g_print ("no mode "); -+ } -+ -+ if (rw_crtc_set_config (crtc, -+ info->x, info->y, -+ info->mode, -+ info->rotation, -+ (RWOutput **)info->outputs->pdata, -+ info->outputs->len)) -+ { -+ g_print ("succeeded"); -+ } -+ else -+ { -+ g_print ("failed"); -+ } -+ -+ g_print (" in %f seconds\n", g_timer_elapsed (timer, NULL)); -+} -+ -+static gboolean -+crtc_is_rotated (CrtcInfo *info) -+{ -+ if ((info->rotation & RW_ROTATION_270) || -+ (info->rotation & RW_ROTATION_90)) -+ { -+ g_print ("rotated: %d\n", info->rotation); -+ return TRUE; -+ } -+ return FALSE; -+} -+ -+static void -+crtc_assignment_apply (CrtcAssignment *assign) -+{ -+ GList *active_crtcs = g_hash_table_get_keys (assign->info); -+ RWCrtc **all_crtcs = rw_screen_list_crtcs (assign->screen); -+ GList *list; -+ int width, height; -+ GTimer *timer; -+ int i; -+ int min_width, max_width, min_height, max_height; -+ -+ /* Compute size of the screen */ -+ width = height = 1; -+ for (list = active_crtcs; list != NULL; list = list->next) -+ { -+ RWCrtc *crtc = list->data; -+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); -+ int w, h; -+ -+ w = rw_mode_get_width (info->mode); -+ h = rw_mode_get_height (info->mode); -+ -+ if (crtc_is_rotated (info)) -+ { -+ int tmp = h; -+ h = w; -+ w = tmp; -+ } -+ -+ width = MAX (width, info->x + w); -+ height = MAX (height, info->y + h); -+ } -+ g_list_free (active_crtcs); -+ -+ g_print ("w, h: %d %d\n", width, height); -+ -+ rw_screen_get_ranges ( -+ assign->screen, &min_width, &max_width, &min_height, &max_height); -+ -+ width = MAX (min_width, width); -+ width = MIN (max_width, width); -+ height = MAX (min_height, height); -+ height = MIN (max_height, height); -+ -+ /* Turn off all crtcs currently displaying outside the new screen */ -+ for (i = 0; all_crtcs[i] != NULL; ++i) -+ { -+ RWCrtc *crtc = all_crtcs[i]; -+ RWMode *mode = rw_crtc_get_current_mode (crtc); -+ int x, y; -+ -+ if (mode) -+ { -+ rw_crtc_get_position (crtc, &x, &y); -+ -+ if (x + rw_mode_get_width (mode) > width || -+ y + rw_mode_get_height (mode) > height) -+ { -+ rw_crtc_set_config (crtc, 0, 0, NULL, RW_ROTATION_0, NULL, 0); -+ } -+ } -+ } -+ -+ /* Turn off all CRTC's that are not in the assignment */ -+ for (i = 0; all_crtcs[i] != NULL; ++i) -+ { -+ RWCrtc *crtc = all_crtcs[i]; -+ -+ if (!g_hash_table_lookup (assign->info, crtc)) -+ rw_crtc_set_config (crtc, 0, 0, NULL, RW_ROTATION_0, NULL, 0); -+ } -+ -+ /* FIXME: What do we do about physical size? -+ * -+ * As far as this function is concerned, probably just pass the problem up to -+ * the callers. There, the best possibility might be to pick the sum of -+ * physical sizes, but the reality is that the physical size of an X screen is -+ * a meaningless concept in a randr 1.2 world. -+ */ -+ timer = g_timer_new (); -+ g_print ("setting size to %d %d\n", width, height); -+ -+ rw_screen_set_size (assign->screen, width, height, 300, 230); -+ -+ gdk_flush (); -+ -+ g_print ("time to set screen size: %f\n", g_timer_elapsed (timer, NULL)); -+ -+ g_timer_reset (timer); -+ -+ g_hash_table_foreach (assign->info, configure_crtc, NULL); -+ -+ gdk_flush (); -+ -+ g_print ("time to configure crtc's: %f\n", g_timer_elapsed (timer, NULL)); -+ -+ g_timer_destroy (timer); -+} -+ -+/* Check whether the given set of settings can be used -+ * at the same time -- ie. whether there is an assignment -+ * of CRTC's to outputs. -+ * -+ * Brute force - the number of objects involved is small -+ * enough that it doesn't matter. -+ */ -+static gboolean -+real_assign_crtcs (RWScreen *screen, -+ Output **outputs, -+ CrtcAssignment *assignment) -+{ -+ RWCrtc **crtcs = rw_screen_list_crtcs (screen); -+ Output *output; -+ int i; -+ -+ output = *outputs; -+ if (!output) -+ return TRUE; -+ -+ /* It is always allowed for an output to be turned off */ -+ if (!output->on) -+ { -+ return real_assign_crtcs (screen, outputs + 1, assignment); -+ } -+ -+ for (i = 0; crtcs[i] != NULL; ++i) -+ { -+ RWCrtc *crtc = crtcs[i]; -+ RWOutput *rw_output = rw_screen_get_output_by_name (screen, output->name); -+ RWMode **modes = rw_output_list_modes (rw_output); -+ int j; -+ -+ for (j = 0; modes[j] != NULL; ++j) -+ { -+ RWMode *mode = modes[j]; -+ -+ if (rw_mode_get_width (mode) == output->width && -+ rw_mode_get_height (mode) == output->height && -+ rw_mode_get_freq (mode) == output->rate) -+ { -+ if (crtc_assignment_assign ( -+ assignment, crtc, modes[j], -+ output->x, output->y, -+ output->rotation, -+ rw_output)) -+ { -+ if (real_assign_crtcs (screen, outputs + 1, assignment)) -+ return TRUE; -+ -+ crtc_assignment_unassign (assignment, crtc, rw_output); -+ } -+ } -+#if 0 -+ else -+ { -+ g_print ("rejected %d x %d x %d for %s\n", -+ rw_mode_get_width (mode), -+ rw_mode_get_height (mode), -+ rw_mode_get_freq (mode), -+ output->name); -+ -+ g_print ("desired: %d x %d x %d\n", -+ output->width, output->height, output->rate); -+ } -+#endif -+ } -+ } -+ -+ return FALSE; -+} -+ -+static void -+crtc_info_free (CrtcInfo *info) -+{ -+ g_ptr_array_free (info->outputs, TRUE); -+ g_free (info); -+} -+ -+static CrtcAssignment * -+crtc_assignment_new (RWScreen *screen, Output **outputs) -+{ -+ CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1); -+ -+ assignment->info = g_hash_table_new_full ( -+ g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free); -+ -+ if (real_assign_crtcs (screen, outputs, assignment)) -+ { -+ assignment->screen = screen; -+ -+ return assignment; -+ } -+ else -+ { -+ crtc_assignment_free (assignment); -+ -+ return NULL; -+ } -+} -diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.h ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/monitor-db.h 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,47 @@ -+#ifndef MONITOR_DB_H -+#define MONITOR_DB_H -+ -+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA -+#include -+#include -+ -+typedef struct Output Output; -+typedef struct Configuration Configuration; -+ -+struct Output -+{ -+ char * name; -+ -+ gboolean on; -+ int width; -+ int height; -+ int rate; -+ int x; -+ int y; -+ RWRotation rotation; -+ -+ gboolean connected; -+ char vendor[4]; -+ guint product; -+ guint serial; -+ double aspect; -+ int pref_width; -+ int pref_height; -+}; -+ -+struct Configuration -+{ -+ Output **outputs; -+}; -+ -+void configuration_free (Configuration *configuration); -+Configuration *configuration_new_current (RWScreen *screen); -+gboolean configuration_match (Configuration *config1, -+ Configuration *config2); -+gboolean configuration_save (Configuration *configuration, -+ GError **err); -+gboolean configuration_apply_stored (RWScreen *screen); -+gboolean configuration_applicable (Configuration *configuration, -+ RWScreen *screen); -+ -+#endif -diff -up /dev/null gnome-control-center-2.21.90/capplets/display/crtc.h ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/crtc.h 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,5 @@ -+#include -+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA -+#include -+ -+/* Not used anymore */ -diff -up /dev/null gnome-control-center-2.21.90/capplets/display/apply.h ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/apply.h 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,6 @@ -+/* This should go in g-s-d eventually */ -+#if 0 -+void apply_stored_configuration (RWScreen *screen); -+#endif -+ -+/* Not used anymore */ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/xrandr-capplet.c 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,958 @@ +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/xrandr-capplet.c 2008-02-12 15:00:00.000000000 -0500 +@@ -0,0 +1,989 @@ +/* Monitor Settings. A preference panel for configuring monitors + * + * Copyright (C) 2007, 2008 Red Hat, Inc. @@ -4286,9 +3015,9 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. +#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA +#include +#include "edid.h" -+#include "monitor-db.h" -+#include "crtc.h" -+#include "apply.h" ++#include ++#include ++#include + +typedef struct App App; + @@ -4313,6 +3042,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. +static void rebuild_gui (App *app); +static void on_rate_changed (GtkComboBox *box, gpointer data); + ++#if 0 +static void +show_error (const GError *err) +{ @@ -4330,12 +3060,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} -+ -+static gboolean -+init_app (App *app) -+{ -+ return TRUE; -+} ++#endif + +static gboolean +do_free (gpointer data) @@ -4384,6 +3109,14 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. + + app->current_configuration = current; + ++ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ { ++ Output *o = app->current_configuration->outputs[i]; ++ ++ g_print (" output: %d %d %d %d\n", o->x, o->y, o->width, o->height); ++ } ++ ++ g_print ("sorting\n"); + /* Sort outputs according to X coordinate */ + for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) + ; @@ -4391,6 +3124,13 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. + qsort (app->current_configuration->outputs, i, sizeof (Output *), + compare_outputs); + ++ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ { ++ Output *o = app->current_configuration->outputs[i]; ++ ++ g_print (" output: %d %d %d %d\n", o->x, o->y, o->width, o->height); ++ } ++ + /* Select an output */ + best = NULL; + for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) @@ -5077,13 +3817,40 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. + } +} + ++static Atom ++gnome_randr_atom (void) ++{ ++ static Atom atom = None; ++ ++ if (!atom) ++ { ++ atom = XInternAtom (gdk_x11_get_default_xdisplay(), ++ "_GNOME_RANDR_ATOM", FALSE); ++ } ++ ++ return atom; ++} ++ +static void +apply (App *app) +{ + GError *err = NULL; + + if (configuration_save (app->current_configuration, &err)) -+ configuration_apply_stored (app->screen); ++ { ++ XEvent message; ++ ++ message.xclient.type = ClientMessage; ++ message.xclient.message_type = gnome_randr_atom(); ++ message.xclient.format = 8; ++ ++ g_print ("Sending client message\n"); ++ ++ XSendEvent (gdk_x11_get_default_xdisplay(), ++ gdk_x11_get_default_root_xwindow(), ++ FALSE, ++ StructureNotifyMask, &message); ++ } +} + +static gboolean @@ -5193,7 +3960,6 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. +main (int argc, char **argv) +{ + App *app; -+ GError *err = NULL; + +#if 0 + bindtextdomain (GETTEXT_PACKAGE, DESKTOPEFFECTSLOCALEDIR); @@ -5205,29 +3971,13 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/xrandr-capplet. + + app = g_new0 (App, 1); + -+ if (!init_app (app)) -+ { -+ show_error (err); -+ return 0; -+ } -+ + run_application (app); + + return 0; +} -diff -up /dev/null gnome-control-center-2.21.90/capplets/display/crtc.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/crtc.c 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,6 @@ -+#include -+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA -+#include -+#include "crtc.h" -+ -+/* not used anymore */ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/display-capplet.glade ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/display-capplet.glade 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/display-capplet.glade 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,399 @@ + + @@ -5629,8 +4379,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/display-capplet + + diff -up /dev/null gnome-control-center-2.21.90/capplets/display/scrollarea.h ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/scrollarea.h 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/scrollarea.h 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,107 @@ +#include +#include @@ -5740,8 +4490,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/scrollarea.h + FooScrollAreaEvent *event); +void foo_scroll_area_end_auto_scroll (FooScrollArea *scroll_area); diff -up /dev/null gnome-control-center-2.21.90/capplets/display/display-name.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/display-name.c 2008-02-04 09:15:58.000000000 -0500 +--- /dev/null 2008-02-12 14:22:04.229654484 -0500 ++++ gnome-control-center-2.21.90/capplets/display/display-name.c 2008-02-12 15:00:00.000000000 -0500 @@ -0,0 +1,161 @@ +/* + * Copyright 2007 Red Hat, Inc. @@ -5906,8 +4656,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/display-name.c +} diff -up gnome-control-center-2.21.90/capplets/display/Makefile.am.add-randr12-capplet gnome-control-center-2.21.90/capplets/display/Makefile.am --- gnome-control-center-2.21.90/capplets/display/Makefile.am.add-randr12-capplet 2008-01-29 07:22:35.000000000 -0500 -+++ gnome-control-center-2.21.90/capplets/display/Makefile.am 2008-02-04 09:05:39.000000000 -0500 -@@ -1,9 +1,27 @@ ++++ gnome-control-center-2.21.90/capplets/display/Makefile.am 2008-02-12 14:57:41.000000000 -0500 +@@ -1,9 +1,21 @@ # This is used in GNOMECC_CAPPLETS_CFLAGS cappletname = display @@ -5919,28 +4669,14 @@ diff -up gnome-control-center-2.21.90/capplets/display/Makefile.am.add-randr12-c -gnome_display_properties_SOURCES = main.c +gnome_display_properties_SOURCES = \ + xrandr-capplet.c \ -+ monitor-db.c \ + display-name.c \ + edid-parse.c \ + scrollarea.c \ -+ crtc.c \ -+ apply.c \ + foo-marshal.c \ -+ monitor-db.h \ + edid.h \ + scrollarea.h \ -+ crtc.h \ -+ apply.h \ + foo-marshal.h + gnome_display_properties_LDFLAGS = -export-dynamic gnome_display_properties_LDADD = \ $(DISPLAY_CAPPLET_LIBS) \ -diff -up /dev/null gnome-control-center-2.21.90/capplets/display/apply.c ---- /dev/null 2008-01-30 11:34:25.225700292 -0500 -+++ gnome-control-center-2.21.90/capplets/display/apply.c 2008-02-04 09:15:58.000000000 -0500 -@@ -0,0 +1,4 @@ -+#include "crtc.h" -+#include "monitor-db.h" -+ -+/* Not used anymore */ diff --git a/control-center.spec b/control-center.spec index ee1d027..ad3be60 100644 --- a/control-center.spec +++ b/control-center.spec @@ -54,7 +54,7 @@ Obsoletes: gnome fontilus Conflicts: desktop-backgrounds-basic < 2.0-27 Conflicts: desktop-backgrounds-extended < 2.0-27 -Requires: gnome-settings-daemon +Requires: gnome-settings-daemon >= 2.21.91-3 Requires: redhat-menus >= %{redhat_menus_version} Requires: gnome-icon-theme Requires: libgail-gnome @@ -349,6 +349,9 @@ fi %dir %{_datadir}/gnome-control-center/keybindings %changelog +* Tue Feb 12 2008 Soren Sandmann - 2.21.90-8 +- Update randr capplet + * Mon Feb 4 2008 Soren Sandmann - 2.21.90-7 - Update randr capplet