From e9a8420fab88a1a1d666ccd8467bfcde61f11968 Mon Sep 17 00:00:00 2001 From: Soren Sandmann Pedersen Date: Feb 04 2008 14:00:21 +0000 Subject: Update randr capplet --- diff --git a/add-randr12-capplet.patch b/add-randr12-capplet.patch index e00bb3f..091c7b1 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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/edid.h 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,169 @@ +typedef unsigned char uchar; +typedef struct MonitorInfo MonitorInfo; @@ -173,7 +173,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/edid.h +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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/foo-marshal.c 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,279 @@ + +#include @@ -456,7 +456,7 @@ 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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/edid-parse.c 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,551 @@ +/* + * Copyright 2007 Red Hat, Inc. @@ -1011,7 +1011,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/edid-parse.c +} 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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/foo-marshal.h 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,63 @@ + +#ifndef __foo_marshal_MARSHAL_H__ @@ -1078,7 +1078,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/foo-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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/scrollarea.c 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,1902 @@ +#include /* For GDK_PARENT_RELATIVE_BG */ +#include "scrollarea.h" @@ -2984,8 +2984,8 @@ 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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,759 @@ ++++ gnome-control-center-2.21.90/capplets/display/monitor-db.c 2008-02-04 08:26:21.000000000 -0500 +@@ -0,0 +1,1197 @@ +#include +#include +#include @@ -3031,75 +3031,15 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + gpointer data, + GError **err); + -+typedef struct Parser Parser; -+ -+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, " \n"); -+ } -+ -+ g_string_append_printf (string, "\n"); -+} -+ -+static void -+emit_configurations (Configuration **configs, -+ GString *string) -+{ -+ int i; -+ -+ for (i = 0; configs[i] != NULL; ++i) -+ emit_configuration (configs[i], string); -+} -+ -+void -+configurations_dump (Configuration **configs) -+{ -+ GString *output = g_string_new (""); ++typedef struct CrtcAssignment CrtcAssignment; + -+ emit_configurations (configs, output); ++static void crtc_assignment_apply (CrtcAssignment *assign); ++static CrtcAssignment *crtc_assignment_new (RWScreen *screen, ++ Output **outputs); ++static void crtc_assignment_free (CrtcAssignment *assign); + -+ g_print ("%s\n", output->str); + -+ g_string_free (output, TRUE); -+} ++typedef struct Parser Parser; + +/* Parser for monitor configurations */ +struct Parser @@ -3174,7 +3114,8 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + 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) @@ -3201,6 +3142,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + 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)); @@ -3216,14 +3158,11 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + + if (strcmp (name, "output") == 0) + { ++ if (parser->output->rotation == 0) ++ parser->output->rotation = RW_ROTATION_0; ++ + g_ptr_array_add (parser->outputs, parser->output); + -+#if 0 -+ g_print ( -+ "%s output %s\n", parser->output->connected? -+ "Connected" : "Unconnected", parser->output->name); -+#endif -+ + parser->output = NULL; + } + else if (strcmp (name, "configuration") == 0) @@ -3297,6 +3236,39 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + + 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 */ @@ -3318,25 +3290,6 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + output_free (config->outputs[i]); +} + -+Configuration ** -+configurations_add (Configuration **configurations, -+ Configuration *configuration) -+{ -+ int i; -+ GPtrArray *a = g_ptr_array_new (); -+ -+ for (i = 0; configurations[i] != NULL; ++i) -+ g_ptr_array_add (a, configurations[i]); -+ -+ g_ptr_array_add (a, configuration); -+ -+ g_ptr_array_add (a, NULL); -+ -+ g_free (configurations); -+ -+ return (Configuration **)g_ptr_array_free (a, FALSE); -+} -+ +static void +parser_free (Parser *parser) +{ @@ -3374,7 +3327,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + g_free (parser); +} + -+Configuration ** ++static Configuration ** +configurations_read (const gchar *filename, GError **error) +{ + Parser *parser = g_new0 (Parser, 1); @@ -3394,13 +3347,20 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + 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); + @@ -3414,10 +3374,6 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + GPtrArray *a = g_ptr_array_new (); + int i; + RWOutput **rw_outputs = rw_screen_list_outputs (screen); -+ -+#if 0 -+ g_print ("New configuration:\n"); -+#endif + + for (i = 0; rw_outputs[i] != NULL; ++i) + { @@ -3435,6 +3391,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + output->width = -1; + output->height = -1; + output->rate = -1; ++ output->rotation = RW_ROTATION_0; + } + else + { @@ -3469,6 +3426,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + 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 + { @@ -3508,11 +3466,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + output->pref_height = 768; + } + } -+ -+#if 0 -+ g_print (" Output %s is %sconnected\n", output->name, output->connected? "" : "not "); -+#endif -+ ++ + g_ptr_array_add (a, output); + } + @@ -3525,7 +3479,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + return config; +} + -+void ++static void +configurations_free (Configuration **configurations) +{ + int i; @@ -3614,29 +3568,6 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + return NULL; +} + -+static void -+print_configuration (Configuration *c1) -+{ -+ int i; -+ -+ for (i = 0; c1->outputs[i] != NULL; ++i) -+ { -+ Output *output = c1->outputs[i]; -+ -+ g_print (" output %s\n", output->name); -+ g_print (" connected: %s (%s-%04x-%08x)\n", -+ output->connected? "yes" : "no", -+ strcmp (output->vendor, "") == 0? "none" : output->vendor, -+ output->product, output->serial); -+ g_print (" on %s (%d %d %d %d - %d)\n", -+ output->on? "yes" : "no", -+ output->x, output->y, -+ output->width, -+ output->height, -+ output->rate); -+ } -+} -+ +gboolean +configuration_match (Configuration *c1, Configuration *c2) +{ @@ -3651,21 +3582,27 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + if (!output2 || !output_match (output1, output2)) + return FALSE; + } ++ ++ return TRUE; ++} + -+#if 0 -+ g_print ("found existing config:\n"); ++gboolean ++configuration_applicable (Configuration *configuration, ++ RWScreen *screen) ++{ ++ CrtcAssignment *assign = crtc_assignment_new (screen, configuration->outputs); + -+ print_configuration (c1); ++ if (assign) ++ { ++ crtc_assignment_free (assign); + -+ g_print ("which is equal to current configuration:\n"); ++ return TRUE; ++ } + -+ print_configuration (c2); -+#endif -+ -+ return TRUE; ++ return FALSE; +} + -+Configuration * ++static Configuration * +configuration_find (Configuration **haystack, + Configuration *needle) +{ @@ -3704,21 +3641,89 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + g_get_home_dir(), ".gnome2", "monitors.xml", NULL)); +} + -+gboolean -+configurations_write (Configuration **configs, -+ const gchar *filename, -+ GError **error) ++static const char * ++get_rotation_name (RWRotation r) +{ -+ GString *output = g_string_new (""); -+ gboolean result; ++ 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"; + -+ emit_configurations (configs, output); ++ return "normal"; ++} + -+ result = g_file_set_contents (filename, output->str, -1, error); ++static const char * ++yes_no (int x) ++{ ++ return x? "yes" : "no"; ++} + -+ g_string_free (output, TRUE); ++static const char * ++get_reflect_x (RWRotation r) ++{ ++ return yes_no (r & RW_REFLECT_X); ++} + -+ return result; ++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 @@ -3745,1293 +3750,1474 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/monitor-db.c + + return g_file_set_contents (get_filename(), output->str, -1, err); +} -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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,95 @@ -+#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; -+ -+ gboolean connected; -+ char vendor[4]; -+ guint product; -+ guint serial; -+ double aspect; -+ int pref_width; -+ int pref_height; -+}; + -+struct Configuration ++static gboolean ++apply_configuration (Configuration *conf, RWScreen *screen) +{ -+ Output **outputs; -+}; -+ -+void configuration_free (Configuration *configuration); -+gboolean configuration_save (Configuration *configuration, -+ GError **err); -+Configuration *configuration_new_current (RWScreen *screen); -+gboolean configuration_match (Configuration *config1, -+ Configuration *config2); -+ -+/* Database management */ -+Configuration *configuration_find (Configuration **haystack, -+ Configuration *needle); -+Configuration **configurations_add (Configuration **configurations, -+ Configuration *configuration); -+Configuration **configurations_read (const gchar *filename, -+ GError **error); -+void configurations_free (Configuration **configurations); -+gboolean configurations_write (Configuration **configs, -+ const gchar *filename, -+ GError **error); -+ -+/* Three different types of settings -+ * -+ * - What the current setup actually *is* -+ * - What the setup *should* be according to the xml file -+ * - What the user is about to set -+ * -+ * A "Configuration" is a mapping from outputs to modes -+ * - It can be saved, which means any similar setups will be -+ * overwritten -+ * -+ * - It can be changed. -+ * -+ * - It can be created from the current X information -+ * -+ * - For each output it will report -+ * - whether the output is on -+ * - whether the output is connected -+ * - what modes are available -+ * -+ * It is possible to apply the best match in the database. -+ * -+ * if (configuration_apply_match (screen, ...)) -+ * ; -+ * -+ * Capplet: -+ * - Create new Setup from current -+ * - Allows user to modify it within hardware restrictions -+ * - On apply, saves and pokes -+ * - On hardware changes, replaces setup with new current -+ * -+ * Daemon -+ * - On login, search for match in database, applies -+ * - On poke, search for match in database, applies -+ * - On hardware change -+ * - Get old setup -+ * - Get new setup -+ * - If new setup is in database, apply -+ * - else, list monitors that have changed -+ * - connection status, turn those off -+ */ -+ ++ 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); + -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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,21 @@ -+#include -+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA -+#include ++ return TRUE; ++ } ++ else ++ { ++ g_print (" ... no assignment found\n"); ++ } + -+typedef struct Setting Setting; -+typedef struct CrtcInfo CrtcInfo; -+typedef struct CrtcAssignment CrtcAssignment; -+typedef struct Crtc Crtc; ++ return FALSE; ++} + -+struct Setting ++gboolean ++configuration_apply_stored (RWScreen *screen) +{ -+ RWOutput *output; -+ RWMode *mode; -+ int x; -+ int y; -+}; -+ -+void crtc_assignment_apply (CrtcAssignment *assign); -+CrtcAssignment *assign_crtcs (RWScreen *screen, -+ Setting **settings); -+void crtc_assignment_free (CrtcAssignment *assign); -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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,2 @@ -+/* This should go in g-s-d eventually */ -+void apply_stored_configuration (RWScreen *screen); -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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,829 @@ -+/* Monitor Settings. A preference panel for configuring monitors -+ * -+ * Copyright (C) 2007, 2008 Red Hat, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Author: Soren Sandmann -+ */ ++ 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; + -+#include -+#include -+#include -+#include -+#include "scrollarea.h" -+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA -+#include -+#include "edid.h" -+#include "monitor-db.h" -+#include "crtc.h" -+#include "apply.h" ++ 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); + -+typedef struct App App; ++ return result; ++} + -+struct App -+{ -+ RWScreen *screen; -+ Configuration *current_configuration; -+ Output *current_output; -+ -+ GtkWidget *dialog; -+ GtkWidget *resolution_combo; -+ GtkWidget *refresh_combo; -+ GtkWidget *rotation_combo; -+ GtkWidget *panel_checkbox; -+ GtkWidget *panel_label; -+ -+ GtkWidget *area; -+ gboolean ignore_gui_changes; -+}; + -+static void rebuild_gui (App *app); ++/* ++ * CRTC assignment ++ */ ++typedef struct CrtcInfo CrtcInfo; + -+static void -+show_error (const GError *err) ++struct CrtcInfo +{ -+ if (!err) -+ return; -+ -+ GtkWidget *dialog = gtk_message_dialog_new ( -+ NULL, -+ GTK_DIALOG_DESTROY_WITH_PARENT, -+ GTK_MESSAGE_WARNING, -+ GTK_BUTTONS_OK, err->message); -+ -+ gtk_window_set_title (GTK_WINDOW (dialog), ""); -+ -+ gtk_dialog_run (GTK_DIALOG (dialog)); -+ gtk_widget_destroy (dialog); -+} ++ RWMode *mode; ++ int x; ++ int y; ++ RWRotation rotation; ++ GPtrArray *outputs; ++}; + -+static gboolean -+init_app (App *app) ++struct CrtcAssignment +{ -+ return TRUE; -+} ++ RWScreen *screen; ++ GHashTable *info; ++}; + +static gboolean -+do_free (gpointer data) -+{ -+ g_free (data); -+ return FALSE; -+} -+ -+static gchar * -+idle_free (gchar *s) ++can_clone (CrtcInfo *info, ++ RWOutput *output) +{ -+ g_idle_add (do_free, s); ++ int i; + -+ return s; -+} ++ for (i = 0; i < info->outputs->len; ++i) ++ { ++ RWOutput *clone = info->outputs->pdata[i]; + -+static int -+compare_outputs (const void *p1, const void *p2) -+{ -+ Output *const *o1 = p1; -+ Output *const *o2 = p2; ++ if (!rw_output_can_clone (clone, output)) ++ return FALSE; ++ } + -+ return (**o1).x - (**o2).x; ++ return TRUE; +} + -+static void -+on_screen_changed (RWScreen *scr, -+ gpointer data) ++static gboolean ++crtc_assignment_assign (CrtcAssignment *assign, ++ RWCrtc *crtc, ++ RWMode *mode, ++ int x, ++ int y, ++ RWRotation rotation, ++ RWOutput *output) +{ -+ Configuration *current; -+ App *app = data; -+ int i; -+ Output *best; -+ -+ current = configuration_new_current (app->screen); ++ /* FIXME: We should reject stuff that is outside the screen ranges */ ++ ++ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); + -+ if (app->current_configuration && -+ configuration_match (current, app->current_configuration)) ++ if (!rw_crtc_can_drive_output (crtc, output) || ++ !rw_output_supports_mode (output, mode) || ++ !rw_crtc_supports_rotation (crtc, rotation)) + { -+ configuration_free (current); -+ return; ++ return FALSE; + } -+ -+ if (app->current_configuration) -+ configuration_free (app->current_configuration); -+ -+ app->current_configuration = current; -+ -+ /* Sort outputs according to X coordinate */ -+ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) -+ ; -+ -+ qsort (app->current_configuration->outputs, i, sizeof (Output *), -+ compare_outputs); + -+ /* Select an output */ -+ best = NULL; -+ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ if (info) + { -+ Output *output = app->current_configuration->outputs[i]; -+ -+ if (output->connected) ++ if (info->mode == mode && ++ info->x == x && ++ info->y == y && ++ info->rotation == rotation && ++ can_clone (info, output)) + { -+ char *cur_name = app->current_output? app->current_output->name : NULL; ++ g_ptr_array_add (info->outputs, output); + -+ if ((cur_name && strcmp (output->name, cur_name) == 0) || !best) -+ best = output; ++ return TRUE; + } + } -+ -+ app->current_output = best; -+ -+ rebuild_gui (app); -+} -+ -+static void -+on_viewport_changed (FooScrollArea *scroll_area, -+ GdkRectangle *old_viewport, -+ GdkRectangle *new_viewport) -+{ -+ foo_scroll_area_set_size (scroll_area, -+ new_viewport->width, -+ new_viewport->height); -+ -+ foo_scroll_area_invalidate (scroll_area); ++ 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 -+layout_set_font (PangoLayout *layout, const char *font) ++crtc_assignment_unassign (CrtcAssignment *assign, ++ RWCrtc *crtc, ++ RWOutput *output) +{ -+ PangoFontDescription *desc = -+ pango_font_description_from_string (font); ++ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); + -+ if (desc) ++ if (info) + { -+ pango_layout_set_font_description (layout, desc); ++ g_ptr_array_remove (info->outputs, output); + -+ pango_font_description_free (desc); ++ if (info->outputs->len == 0) ++ g_hash_table_remove (assign->info, crtc); + } +} + +static void -+clear_combo (GtkWidget *widget) ++crtc_assignment_free (CrtcAssignment *assign) +{ -+ GtkComboBox *box = GTK_COMBO_BOX (widget); -+ GtkTreeModel *model = gtk_combo_box_get_model (box); -+ if (!model) -+ { -+ g_print ("asdf\n"); -+ return; -+ } -+ GtkListStore *store = GTK_LIST_STORE (model); ++ g_hash_table_destroy (assign->info); + -+ gtk_list_store_clear (store); ++ g_free (assign); +} + +static void -+add_keys (GtkWidget *widget, -+ GHashTable *table, -+ const char *selected) ++configure_crtc (gpointer key, ++ gpointer value, ++ gpointer data) +{ -+ GtkComboBox *box = GTK_COMBO_BOX (widget); -+ GList *keys = g_hash_table_get_keys (table); -+ GList *values = g_hash_table_get_values (table); -+ GList *list; -+ gboolean did_select = FALSE; -+ GtkListStore *store = GTK_LIST_STORE (gtk_combo_box_get_model (box)); ++ RWCrtc *crtc = key; ++ CrtcInfo *info = value; ++ GTimer *timer = g_timer_new (); + -+ for (list = keys; list != NULL; list = list->next, values = values->next) -+ { -+ GtkTreeIter iter; -+ char *resolution = list->data; -+ RWMode *mode = values->data; ++ g_print ("Configuring crtc %x with ", rw_crtc_get_id (crtc)); + -+ gtk_list_store_append (store, &iter); ++ if (info->mode) ++ { ++ int n_outputs = info->outputs->len; + -+ if (mode) -+ { -+ int w, h; -+ -+ w = rw_mode_get_width (mode); -+ h = rw_mode_get_height (mode); -+ -+ gtk_list_store_set (store, &iter, -+ 0, resolution, -+ 1, w, -+ 2, h, -+ 3, rw_mode_get_freq (mode), -+ 4, w * h, -+ -1); -+ } -+ else -+ { -+ gtk_list_store_set (store, &iter, -+ 0, resolution, -+ 1, 0, -+ 2, 0, -+ 3, 0, -+ 4, 0, -+ -1); -+ } -+ -+ if (strcmp (selected, resolution) == 0) -+ { -+ gtk_combo_box_set_active_iter (box, &iter); -+ did_select = TRUE; -+ } ++ 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 (!did_select) -+ gtk_combo_box_set_active (box, 0); + -+ g_list_free (keys); ++ 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 RWMode ** -+get_current_modes (App *app) ++static gboolean ++crtc_is_rotated (CrtcInfo *info) +{ -+ RWOutput *output; -+ -+ if (!app->current_output) -+ return NULL; -+ -+ output = rw_screen_get_output_by_name ( -+ app->screen, app->current_output->name); -+ -+ if (!output) -+ return NULL; -+ -+ return rw_output_list_modes (output); ++ if ((info->rotation & RW_ROTATION_270) || ++ (info->rotation & RW_ROTATION_90)) ++ { ++ g_print ("rotated: %d\n", info->rotation); ++ return TRUE; ++ } ++ return FALSE; +} + +static void -+rebuild_rate_combo (App *app) ++crtc_assignment_apply (CrtcAssignment *assign) +{ -+ GHashTable *rates; -+ RWMode **modes; ++ 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; + -+ clear_combo (app->refresh_combo); -+ -+ gtk_widget_set_sensitive ( -+ app->refresh_combo, app->current_output && app->current_output->on); -+ -+ if (!(modes = get_current_modes (app))) -+ return; -+ -+ rates = g_hash_table_new_full ( -+ g_str_hash, g_str_equal, (GFreeFunc)g_free, NULL); -+ -+ for (i = 0; modes[i] != NULL; ++i) ++ /* Compute size of the screen */ ++ width = height = 1; ++ for (list = active_crtcs; list != NULL; list = list->next) + { -+ RWMode *mode = modes[i]; ++ 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 (rw_mode_get_width (mode) == app->current_output->width && -+ rw_mode_get_height (mode) == app->current_output->height) ++ if (crtc_is_rotated (info)) + { -+ char *rate; -+ -+ rate = g_strdup_printf ("%d Hz", -+ rw_mode_get_freq (mode)); -+ -+ g_hash_table_insert (rates, rate, mode); ++ int tmp = h; ++ h = w; ++ w = tmp; + } ++ ++ width = MAX (width, info->x + w); ++ height = MAX (height, info->y + h); + } ++ g_list_free (active_crtcs); + -+ add_keys (app->refresh_combo, rates, idle_free ( -+ g_strdup_printf ("%d Hz", -+ app->current_output->rate))); ++ g_print ("w, h: %d %d\n", width, height); ++ ++ rw_screen_get_ranges ( ++ assign->screen, &min_width, &max_width, &min_height, &max_height); + -+ g_hash_table_destroy (rates); ++ 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; + -+static void -+rebuild_resolution_combo (App *app) -+{ -+ GHashTable *resolutions; -+ int i; -+ RWMode **modes; ++ if (mode) ++ { ++ rw_crtc_get_position (crtc, &x, &y); + -+ clear_combo (app->resolution_combo); -+ -+ if (!(modes = get_current_modes (app))) -+ return; -+ -+ resolutions = g_hash_table_new_full ( -+ g_str_hash, g_str_equal, (GFreeFunc)g_free, NULL); -+ -+ for (i = 0; modes[i] != NULL; ++i) ++ 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) + { -+ RWMode *mode = modes[i]; -+ char *resolution = -+ g_strdup_printf ("%d x %d", -+ rw_mode_get_width (mode), -+ rw_mode_get_height (mode)); ++ RWCrtc *crtc = all_crtcs[i]; + -+ g_hash_table_insert (resolutions, resolution, mode); ++ if (!g_hash_table_lookup (assign->info, crtc)) ++ rw_crtc_set_config (crtc, 0, 0, NULL, RW_ROTATION_0, NULL, 0); + } + -+ g_hash_table_insert (resolutions, g_strdup ("Off"), NULL); -+ -+ /* Add resolutions */ -+ add_keys (app->resolution_combo, resolutions, -+ app->current_output->on ? -+ idle_free ( -+ g_strdup_printf ("%d x %d", -+ app->current_output->width, -+ app->current_output->height)) : "Off"); -+ -+ g_hash_table_destroy (resolutions); -+} -+ -+static void -+rebuild_gui (App *app) -+{ -+ gboolean sensitive; -+ -+ /* We would break spectacularly if we recursed, so -+ * just assert if that happens ++ /* 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. + */ -+ g_assert (app->ignore_gui_changes == FALSE); ++ timer = g_timer_new (); ++ g_print ("setting size to %d %d\n", width, height); + -+ app->ignore_gui_changes = TRUE; -+ -+ sensitive = app->current_output? TRUE : FALSE; ++ rw_screen_set_size (assign->screen, width, height, 300, 230); + -+#if 0 -+ g_print ("rebuild gui, is on: %d\n", app->current_output->on); -+#endif ++ gdk_flush (); + -+ rebuild_resolution_combo (app); -+ rebuild_rate_combo (app); ++ g_print ("time to set screen size: %f\n", g_timer_elapsed (timer, NULL)); + -+ gtk_widget_set_sensitive (app->resolution_combo, sensitive); ++ g_timer_reset (timer); ++ ++ g_hash_table_foreach (assign->info, configure_crtc, NULL); + -+#if 0 -+ g_print ("sensitive: %d, on: %d\n", sensitive, app->current_output->on); -+#endif -+ gtk_widget_set_sensitive (app->rotation_combo, sensitive); -+ gtk_widget_set_sensitive (app->panel_checkbox, sensitive); ++ gdk_flush (); ++ ++ g_print ("time to configure crtc's: %f\n", g_timer_elapsed (timer, NULL)); + -+ app->ignore_gui_changes = FALSE; ++ 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 -+get_mode (GtkWidget *widget, int *width, int *height, int *freq) ++real_assign_crtcs (RWScreen *screen, ++ Output **outputs, ++ CrtcAssignment *assignment) +{ -+ GtkTreeIter iter; -+ GtkTreeModel *model; -+ GtkComboBox *box = GTK_COMBO_BOX (widget); -+ int dummy; ++ RWCrtc **crtcs = rw_screen_list_crtcs (screen); ++ Output *output; ++ int i; + -+ if (!gtk_combo_box_get_active_iter (box, &iter)) -+ return FALSE; ++ output = *outputs; ++ if (!output) ++ return TRUE; + -+ if (!width) -+ width = &dummy; ++ /* 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; + -+ if (!height) -+ height = &dummy; ++ 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); + -+ if (!freq) -+ freq = &dummy; -+ -+ model = gtk_combo_box_get_model (box); -+ gtk_tree_model_get (model, &iter, -+ 1, width, -+ 2, height, -+ 3, freq, -+ -1); ++ g_print ("desired: %d x %d x %d\n", ++ output->width, output->height, output->rate); ++ } ++#endif ++ } ++ } + -+ return TRUE; ++ return FALSE; +} + +static void -+on_rate_changed (GtkComboBox *box, gpointer data) ++crtc_info_free (CrtcInfo *info) +{ -+ App *app = data; -+ int rate; -+ -+ if (!app->current_output) -+ return; -+ -+ if (get_mode (app->refresh_combo, NULL, NULL, &rate)) -+ app->current_output->rate = rate; -+ -+ foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); ++ g_ptr_array_free (info->outputs, TRUE); ++ g_free (info); +} + -+static void -+on_resolution_changed (GtkComboBox *box, gpointer data) ++static CrtcAssignment * ++crtc_assignment_new (RWScreen *screen, Output **outputs) +{ -+ App *app = data; -+ int width; -+ int height; -+ int i; -+ int x; ++ CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1); + -+ if (!app->current_output) -+ return; ++ assignment->info = g_hash_table_new_full ( ++ g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free); + -+ if (get_mode (app->resolution_combo, &width, &height, NULL)) ++ if (real_assign_crtcs (screen, outputs, assignment)) + { -+ app->current_output->width = width; -+ app->current_output->height = height; -+ -+ if (width == 0 || height == 0) -+ app->current_output->on = FALSE; -+ else -+ app->current_output->on = TRUE; ++ assignment->screen = screen; ++ ++ return assignment; + } -+ -+ if (app->current_configuration) ++ else + { -+ x = 0; -+ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) -+ { -+ Output *output = app->current_configuration->outputs[i]; -+ -+ if (output->connected) -+ { -+ output->x = x; -+ -+ x += output->width; -+ } -+ } ++ 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 08:26:21.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 08:26:21.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 08:26:21.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 08:26:21.000000000 -0500 +@@ -0,0 +1,948 @@ ++/* Monitor Settings. A preference panel for configuring monitors ++ * ++ * Copyright (C) 2007, 2008 Red Hat, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Author: Soren Sandmann ++ */ ++ ++#include ++#include ++#include ++#include ++#include "scrollarea.h" ++#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA ++#include ++#include "edid.h" ++#include "monitor-db.h" ++#include "crtc.h" ++#include "apply.h" ++ ++typedef struct App App; ++ ++struct App ++{ ++ RWScreen *screen; ++ Configuration *current_configuration; ++ Output *current_output; + -+ rebuild_rate_combo (app); ++ GtkWidget *dialog; ++ GtkListStore *resolution_store; ++ GtkWidget *resolution_combo; ++ GtkWidget *refresh_combo; ++ GtkWidget *rotation_combo; ++ GtkWidget *panel_checkbox; ++ GtkWidget *panel_label; + -+ foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); ++ GtkWidget *area; ++ gboolean ignore_gui_changes; ++}; ++ ++static void rebuild_gui (App *app); ++static void on_rate_changed (GtkComboBox *box, gpointer data); ++ ++static void ++show_error (const GError *err) ++{ ++ if (!err) ++ return; ++ ++ GtkWidget *dialog = gtk_message_dialog_new ( ++ NULL, ++ GTK_DIALOG_DESTROY_WITH_PARENT, ++ GTK_MESSAGE_WARNING, ++ GTK_BUTTONS_OK, err->message); ++ ++ gtk_window_set_title (GTK_WINDOW (dialog), ""); ++ ++ gtk_dialog_run (GTK_DIALOG (dialog)); ++ gtk_widget_destroy (dialog); ++} ++ ++static gboolean ++init_app (App *app) ++{ ++ return TRUE; ++} ++ ++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 int ++compare_outputs (const void *p1, const void *p2) ++{ ++ Output *const *o1 = p1; ++ Output *const *o2 = p2; ++ ++ return (**o1).x - (**o2).x; +} + +static void -+on_output_event (FooScrollArea *area, -+ FooScrollAreaEvent *event, -+ gpointer data) ++on_screen_changed (RWScreen *scr, ++ gpointer data) +{ -+ Output *output = data; -+ App *app = g_object_get_data (G_OBJECT (area), "app"); ++ Configuration *current; ++ App *app = data; ++ int i; ++ Output *best; + -+ if (event->type == FOO_BUTTON_PRESS) ++ current = configuration_new_current (app->screen); ++ ++ if (app->current_configuration && ++ configuration_match (current, app->current_configuration)) + { -+ app->current_output = output; ++ configuration_free (current); ++ return; ++ } ++ ++ if (app->current_configuration) ++ configuration_free (app->current_configuration); ++ ++ app->current_configuration = current; + -+ rebuild_gui (app); ++ /* Sort outputs according to X coordinate */ ++ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ ; + -+ foo_scroll_area_invalidate (area); ++ qsort (app->current_configuration->outputs, i, sizeof (Output *), ++ compare_outputs); ++ ++ /* Select an output */ ++ best = NULL; ++ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ { ++ Output *output = app->current_configuration->outputs[i]; ++ ++ if (output->connected) ++ { ++ char *cur_name = ++ app->current_output? app->current_output->name : NULL; ++ ++ if ((cur_name && strcmp (output->name, cur_name) == 0) || !best) ++ best = output; ++ } + } ++ ++ app->current_output = best; ++ ++ rebuild_gui (app); +} + -+#if 0 +static void -+on_canvas_event (FooScrollArea *area, -+ FooScrollAreaEvent *event, -+ gpointer data) ++on_viewport_changed (FooScrollArea *scroll_area, ++ GdkRectangle *old_viewport, ++ GdkRectangle *new_viewport) +{ -+ App *app = g_object_get_data (G_OBJECT (area), "app"); -+ -+ if (event->type == FOO_BUTTON_PRESS) ++ foo_scroll_area_set_size (scroll_area, ++ new_viewport->width, ++ new_viewport->height); ++ ++ foo_scroll_area_invalidate (scroll_area); ++} ++ ++static void ++layout_set_font (PangoLayout *layout, const char *font) ++{ ++ PangoFontDescription *desc = ++ pango_font_description_from_string (font); ++ ++ if (desc) + { -+ app->current_output = NULL; ++ pango_layout_set_font_description (layout, desc); + -+ rebuild_gui (app); ++ pango_font_description_free (desc); ++ } ++} + -+ foo_scroll_area_invalidate (area); ++static void ++clear_combo (GtkWidget *widget) ++{ ++ GtkComboBox *box = GTK_COMBO_BOX (widget); ++ GtkTreeModel *model = gtk_combo_box_get_model (box); ++ if (!model) ++ { ++ g_print ("asdf\n"); ++ return; + } ++ GtkListStore *store = GTK_LIST_STORE (model); ++ ++ gtk_list_store_clear (store); +} -+#endif + -+static PangoLayout * -+get_display_name (App *app, -+ Output *output) ++typedef struct +{ -+ RWOutput *rwout = rw_screen_get_output_by_name ( -+ app->screen, output->name); -+ const char *text = "Unknown"; ++ const char *text; ++ gboolean found; ++ GtkTreeIter iter; ++} ForeachInfo; + -+ if (rwout) -+ { -+ const guint8 *edid = rw_output_get_edid_data (rwout); ++static gboolean ++foreach (GtkTreeModel *model, ++ GtkTreePath *path, ++ GtkTreeIter *iter, ++ gpointer data) ++{ ++ ForeachInfo *info = data; ++ char *text = NULL; + -+ if (edid) -+ { -+ MonitorInfo *info = decode_edid (edid); ++ gtk_tree_model_get (model, iter, 0, &text, -1); + -+ text = idle_free (make_display_name (info)); -+ } ++ g_assert (text != NULL); ++ ++ if (strcmp (info->text, text) == 0) ++ { ++ info->found = TRUE; ++ info->iter = *iter; ++ return TRUE; + } + -+ return gtk_widget_create_pango_layout (GTK_WIDGET (app->area), text); ++ return FALSE; +} + +static void -+get_geometry (Output *output, int *w, int *h) ++add_key (GtkWidget *widget, ++ const char *text, ++ int width, int height, int rate, ++ RWRotation rotation) +{ -+ if (output->on) ++ ForeachInfo info; ++ GtkComboBox *box = GTK_COMBO_BOX (widget); ++ GtkTreeModel *model = gtk_combo_box_get_model (box); ++ GtkListStore *store = GTK_LIST_STORE (model); ++ gboolean retval; ++ ++ info.text = text; ++ info.found = FALSE; ++ ++ gtk_tree_model_foreach (model, foreach, &info); ++ ++ if (!info.found) + { -+ *h = output->height; -+ *w = output->width; ++ GtkTreeIter iter; ++ gtk_list_store_append (store, &iter); ++ ++ gtk_list_store_set (store, &iter, ++ 0, text, ++ 1, width, ++ 2, height, ++ 3, rate, ++ 4, width * height, ++ 5, rotation, ++ -1); ++ ++ retval = TRUE; + } + else + { -+ *h = output->pref_height; -+ *w = output->pref_width; ++ retval = FALSE; + } +} + -+static void -+on_area_paint (FooScrollArea *area, -+ cairo_t *cr, -+ GdkRectangle *extent, -+ GdkRegion *region, -+ gpointer data) ++static gboolean ++combo_select (GtkWidget *widget, const char *text) +{ -+ App *app = data; -+ GdkRectangle viewport; -+ int i; -+ int available; -+ int total_pixels; -+ int max_height; -+ double scale; -+ GList *connected_outputs = NULL; -+ GList *list; -+ int n_monitors; -+ -+ foo_scroll_area_get_viewport (area, &viewport); ++ GtkComboBox *box = GTK_COMBO_BOX (widget); ++ GtkTreeModel *model = gtk_combo_box_get_model (box); ++ ForeachInfo info; + -+ cairo_set_source_rgba (cr, 0.72, 0.78, 0.87, 1.0); ++ info.text = text; ++ info.found = FALSE; ++ ++ gtk_tree_model_foreach (model, foreach, &info); + -+ cairo_rectangle (cr, -+ viewport.x, viewport.y, -+ viewport.width, viewport.height); ++ if (!info.found) ++ return FALSE; + -+ cairo_fill_preserve (cr); ++ gtk_combo_box_set_active_iter (box, &info.iter); ++ return TRUE; ++} + -+#if 0 -+ foo_scroll_area_add_input_from_fill (area, cr, on_canvas_event, NULL); -+#endif ++static RWMode ** ++get_current_modes (App *app) ++{ ++ RWOutput *output; + -+ cairo_set_source_rgba (cr, 0.44, 0.59, 0.76, 1.0); ++ if (!app->current_output) ++ return NULL; + -+ cairo_stroke (cr); ++ output = rw_screen_get_output_by_name ( ++ app->screen, app->current_output->name); + -+ if (!app->current_configuration) ++ if (!output) ++ return NULL; ++ ++ return rw_output_list_modes (output); ++} ++ ++static void ++rebuild_rotation_combo (App *app) ++{ ++ typedef struct ++ { ++ RWRotation rotation; ++ const char * name; ++ } RotationInfo; ++ static const RotationInfo rotations[] = { ++ { RW_ROTATION_0, "Normal" }, ++ { RW_ROTATION_90, "Left" }, ++ { RW_ROTATION_270, "Right" }, ++ { RW_ROTATION_180, "Upside Down" }, ++ }; ++ const char *selection; ++ RWRotation current; ++ int i; ++ ++ clear_combo (app->rotation_combo); ++ ++ gtk_widget_set_sensitive ( ++ app->rotation_combo, app->current_output && app->current_output->on); ++ ++ if (!app->current_output) + return; + -+#define SPACE 36 -+#define MARGIN 24 ++ current = app->current_output->rotation; + -+ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ selection = NULL; ++ for (i = 0; i < G_N_ELEMENTS (rotations); ++i) + { -+ Output *output = app->current_configuration->outputs[i]; ++ const RotationInfo *info = &(rotations[i]); ++ ++ app->current_output->rotation = info->rotation; + -+ if (output->connected) -+ connected_outputs = g_list_prepend (connected_outputs, output); ++ if (configuration_applicable (app->current_configuration, app->screen)) ++ { ++ add_key (app->rotation_combo, info->name, 0, 0, 0, info->rotation); ++ ++ if (info->rotation == current) ++ selection = info->name; ++ } + } + -+ connected_outputs = g_list_reverse (connected_outputs); ++ app->current_output->rotation = current; + -+ n_monitors = g_list_length (connected_outputs); ++ if (!(selection && combo_select (app->rotation_combo, selection))) ++ combo_select (app->rotation_combo, "Normal"); ++} + -+ available = viewport.width - 2 * MARGIN - (n_monitors - 1) * SPACE; ++#define idle_free_printf(x) idle_free (g_strdup_printf (x)) + -+ total_pixels = 0; -+ max_height = 0; -+ for (list = connected_outputs; list != NULL; list = list->next) -+ { -+ Output *output = list->data; -+ int w, h; ++static void ++rebuild_rate_combo (App *app) ++{ ++ GHashTable *rates; ++ RWMode **modes; ++ int best; ++ int i; + -+ get_geometry (output, &w, &h); -+ -+ total_pixels += w; -+ max_height = MAX (max_height, h); -+ } ++ clear_combo (app->refresh_combo); + -+ scale = (double)available / total_pixels; ++ gtk_widget_set_sensitive ( ++ app->refresh_combo, app->current_output && app->current_output->on); + -+ scale = MIN ((double)(viewport.height - 2 * MARGIN) / max_height, scale); ++ if (!(modes = get_current_modes (app))) ++ return; + -+ int x = MARGIN; -+ for (list = connected_outputs; list != NULL; list = list->next) ++ rates = g_hash_table_new_full ( ++ g_str_hash, g_str_equal, (GFreeFunc)g_free, NULL); ++ ++ best = -1; ++ for (i = 0; modes[i] != NULL; ++i) + { -+ Output *output = list->data; -+ PangoLayout *layout = get_display_name (app, output); -+ int w, h; -+ -+ get_geometry (output, &w, &h); -+ -+ w = w * scale + 0.5; -+#if 0 -+ g_print ("%s (%p) geometry %d %d %d\n", output->name, output, -+ w, h, output->rate); -+#endif -+ -+ cairo_rectangle (cr, x, MARGIN, w, (int)( -+ h * scale + 0.5)); -+ -+ if (output->on) -+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); -+ else -+ cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 1.0); ++ RWMode *mode = modes[i]; ++ int width, height, rate; + -+ cairo_fill_preserve (cr); ++ width = rw_mode_get_width (mode); ++ height = rw_mode_get_height (mode); ++ rate = rw_mode_get_freq (mode); + -+ foo_scroll_area_add_input_from_fill (area, cr, on_output_event, -+ output); -+ -+ if (output == app->current_output) -+ cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 1.0); -+ else -+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); -+ cairo_stroke (cr); ++ if (width == app->current_output->width && ++ height == app->current_output->height) ++ { ++ add_key (app->refresh_combo, ++ idle_free (g_strdup_printf ("%d Hz", rate)), ++ 0, 0, rate, -1); + -+ cairo_move_to (cr, x + 40, MARGIN + 40); -+ cairo_set_source_rgb (cr, 0.2, 0.2, 0.8); -+ layout_set_font (layout, "Sans Bold 18"); -+ pango_cairo_show_layout (cr, layout); -+ g_object_unref (layout); -+ -+ x += w + SPACE; ++ if (rate > best) ++ best = rate; ++ } + } ++ ++ if (!combo_select (app->refresh_combo, idle_free (g_strdup_printf ("%d Hz", app->current_output->rate)))) ++ combo_select (app->refresh_combo, idle_free (g_strdup_printf ("%d Hz", best))); +} + +static void -+make_text_combo (GtkWidget *widget, int column) ++rebuild_resolution_combo (App *app) +{ -+ GtkComboBox *box = GTK_COMBO_BOX (widget); -+ GtkListStore *store = gtk_list_store_new ( -+ 5, -+ G_TYPE_STRING, /* Text */ -+ G_TYPE_INT, /* Width */ -+ G_TYPE_INT, /* Height */ -+ G_TYPE_INT, /* Frequency */ -+ G_TYPE_INT); /* Width * Height */ -+ GtkCellRenderer *cell; ++ int i; ++ RWMode **modes; ++ int best_w, best_h; ++ ++ clear_combo (app->resolution_combo); + -+ gtk_combo_box_set_model (box, GTK_TREE_MODEL (store)); ++ if (!(modes = get_current_modes (app))) ++ return; + -+ cell = gtk_cell_renderer_text_new (); -+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, TRUE); -+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (box), cell, -+ "text", 0, -+ NULL); ++ best_w = 0; ++ best_h = 0; ++ for (i = 0; modes[i] != NULL; ++i) ++ { ++ int width, height; ++ ++ width = rw_mode_get_width (modes[i]); ++ height = rw_mode_get_height (modes[i]); ++ ++ add_key (app->resolution_combo, ++ idle_free (g_strdup_printf ("%d x %d", width, height)), ++ width, height, 0, -1); ++ ++ if (width * height > best_w * best_h) ++ { ++ best_w = width; ++ best_h = height; ++ } ++ } + -+ if (column != -1) ++ if (!combo_select (app->resolution_combo, ++ idle_free ( ++ g_strdup_printf ("%d x %d", ++ app->current_output->width, ++ app->current_output->height)))) + { -+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), -+ column, -+ GTK_SORT_DESCENDING); ++ combo_select (app->resolution_combo, ++ idle_free ( ++ g_strdup_printf ("%d x %d", best_w, best_h))); + } +} + +static void -+apply (App *app) ++rebuild_gui (App *app) +{ -+ GError *err = NULL; ++ gboolean sensitive; ++ ++ /* We would break spectacularly if we recursed, so ++ * just assert if that happens ++ */ ++ g_assert (app->ignore_gui_changes == FALSE); + -+ if (configuration_save (app->current_configuration, &err)) -+ apply_stored_configuration (app->screen); ++ app->ignore_gui_changes = TRUE; ++ ++ sensitive = app->current_output? TRUE : FALSE; ++ ++#if 0 ++ g_print ("rebuild gui, is on: %d\n", app->current_output->on); ++#endif ++ ++ rebuild_resolution_combo (app); ++ rebuild_rate_combo (app); ++ rebuild_rotation_combo (app); ++ ++ gtk_widget_set_sensitive (app->resolution_combo, sensitive); ++ ++#if 0 ++ g_print ("sensitive: %d, on: %d\n", sensitive, app->current_output->on); ++#endif ++ gtk_widget_set_sensitive (app->rotation_combo, sensitive); ++ gtk_widget_set_sensitive (app->panel_checkbox, sensitive); ++ ++ app->ignore_gui_changes = FALSE; ++} ++ ++static gboolean ++get_mode (GtkWidget *widget, int *width, int *height, int *freq, RWRotation *rot) ++{ ++ GtkTreeIter iter; ++ GtkTreeModel *model; ++ GtkComboBox *box = GTK_COMBO_BOX (widget); ++ int dummy; ++ ++ if (!gtk_combo_box_get_active_iter (box, &iter)) ++ return FALSE; ++ ++ if (!width) ++ width = &dummy; ++ ++ if (!height) ++ height = &dummy; ++ ++ if (!freq) ++ freq = &dummy; ++ ++ if (!rot) ++ rot = (RWRotation *)&dummy; ++ ++ model = gtk_combo_box_get_model (box); ++ gtk_tree_model_get (model, &iter, ++ 1, width, ++ 2, height, ++ 3, freq, ++ 5, rot, ++ -1); ++ ++ return TRUE; ++ +} + -+static gboolean -+refresh (gpointer data) ++static void ++on_rotation_changed (GtkComboBox *box, gpointer data) +{ + App *app = data; -+ -+ rw_screen_refresh (app->screen); ++ RWRotation rotation; + -+ return TRUE; ++ if (!app->current_output) ++ return; ++ ++ if (get_mode (app->rotation_combo, NULL, NULL, NULL, &rotation)) ++ app->current_output->rotation = rotation; ++ ++ foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); +} + +static void -+run_application (App *app) ++on_rate_changed (GtkComboBox *box, gpointer data) +{ -+#ifndef GLADEDIR -+#define GLADEDIR "." -+#endif -+#define GLADE_FILE GLADEDIR "/display-capplet.glade" -+ GladeXML *xml; -+ GtkWidget *align; ++ App *app = data; ++ int rate; + -+ xml = glade_xml_new (GLADE_FILE, NULL, NULL); -+ if (!xml) -+ { -+ g_warning ("Could not open " GLADE_FILE); ++ if (!app->current_output) + return; -+ } -+ -+ app->screen = rw_screen_new (gdk_screen_get_default(), -+ on_screen_changed, app); + -+ app->dialog = glade_xml_get_widget (xml, "dialog"); ++ if (get_mode (app->refresh_combo, NULL, NULL, &rate, NULL)) ++ app->current_output->rate = rate; + -+ app->resolution_combo = glade_xml_get_widget (xml, "resolution_combo"); -+ g_signal_connect (app->resolution_combo, "changed", -+ G_CALLBACK (on_resolution_changed), app); ++ foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); ++} + -+ app->refresh_combo = glade_xml_get_widget (xml, "refresh_combo"); -+ g_signal_connect (app->refresh_combo, "changed", -+ G_CALLBACK (on_rate_changed), app); ++static void ++on_resolution_changed (GtkComboBox *box, gpointer data) ++{ ++ App *app = data; ++ int width; ++ int height; ++ int i; ++ int x; + -+ app->rotation_combo = glade_xml_get_widget (xml, "rotation_combo"); ++ if (!app->current_output) ++ return; + ++ if (get_mode (app->resolution_combo, &width, &height, NULL, NULL)) ++ { ++ app->current_output->width = width; ++ app->current_output->height = height; + -+ app->panel_checkbox = glade_xml_get_widget (xml, "panel_checkbox"); -+ app->panel_label = glade_xml_get_widget (xml, "panel_label"); -+ -+ make_text_combo (app->resolution_combo, 4); -+ make_text_combo (app->refresh_combo, 3); -+ make_text_combo (app->rotation_combo, -1); ++ if (width == 0 || height == 0) ++ app->current_output->on = FALSE; ++ else ++ app->current_output->on = TRUE; ++ } + -+ g_assert (app->panel_checkbox); ++ if (app->current_configuration) ++ { ++ x = 0; ++ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) ++ { ++ Output *output = app->current_configuration->outputs[i]; ++ ++ if (output->connected) ++ { ++ output->x = x; ++ ++ x += output->width; ++ } ++ } ++ } + -+ /* Scroll Area */ -+ app->area = (GtkWidget *)foo_scroll_area_new (); -+ -+ g_object_set_data (G_OBJECT (app->area), "app", app); ++ rebuild_rate_combo (app); ++ rebuild_rotation_combo (app); + -+ /* FIXME: this should be computed dynamically */ -+ foo_scroll_area_set_min_size (FOO_SCROLL_AREA (app->area), -1, 200); -+ gtk_widget_show (app->area); -+ g_signal_connect (app->area, "paint", -+ G_CALLBACK (on_area_paint), app); -+ g_signal_connect (app->area, "viewport_changed", -+ G_CALLBACK (on_viewport_changed), app); -+ -+ align = glade_xml_get_widget (xml, "align"); ++ foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); ++} + -+ gtk_container_add (GTK_CONTAINER (align), app->area); ++static void ++on_output_event (FooScrollArea *area, ++ FooScrollAreaEvent *event, ++ gpointer data) ++{ ++ Output *output = data; ++ App *app = g_object_get_data (G_OBJECT (area), "app"); + -+ g_timeout_add (3000, refresh, app); ++ if (event->type == FOO_BUTTON_PRESS) ++ { ++ app->current_output = output; + -+ on_screen_changed (app->screen, app); -+ rebuild_gui (app); ++ rebuild_gui (app); ++ ++ foo_scroll_area_invalidate (area); ++ } ++} + -+ gtk_widget_hide (app->panel_checkbox); -+ gtk_widget_hide (app->panel_label); ++#if 0 ++static void ++on_canvas_event (FooScrollArea *area, ++ FooScrollAreaEvent *event, ++ gpointer data) ++{ ++ App *app = g_object_get_data (G_OBJECT (area), "app"); + -+restart: -+ switch (gtk_dialog_run (GTK_DIALOG (app->dialog))) ++ if (event->type == FOO_BUTTON_PRESS) + { -+ default: -+ g_print ("Unknown response\n"); -+ /* Fall Through */ -+ case GTK_RESPONSE_DELETE_EVENT: -+ case GTK_RESPONSE_CLOSE: -+ g_print ("Close\n"); -+ break; ++ app->current_output = NULL; + -+ case GTK_RESPONSE_HELP: -+ g_print ("Help\n"); -+ goto restart; -+ break; ++ rebuild_gui (app); + -+ case GTK_RESPONSE_APPLY: -+ apply (app); -+ goto restart; -+ break; ++ foo_scroll_area_invalidate (area); + } -+ -+ gtk_widget_destroy (app->dialog); +} -+ -+int -+main (int argc, char **argv) -+{ -+ App *app; -+ GError *err = NULL; -+ -+#if 0 -+ bindtextdomain (GETTEXT_PACKAGE, DESKTOPEFFECTSLOCALEDIR); -+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); -+ textdomain (GETTEXT_PACKAGE); +#endif -+ -+ gtk_init (&argc, &argv); + -+ app = g_new0 (App, 1); ++static PangoLayout * ++get_display_name (App *app, ++ Output *output) ++{ ++ RWOutput *rwout = rw_screen_get_output_by_name ( ++ app->screen, output->name); ++ const char *text = "Unknown"; + -+ if (!init_app (app)) ++ if (rwout) + { -+ show_error (err); -+ return 0; -+ } ++ const guint8 *edid = rw_output_get_edid_data (rwout); + -+ 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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,317 @@ -+#include -+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA -+#include -+#include "crtc.h" ++ if (edid) ++ { ++ MonitorInfo *info = decode_edid (edid); + -+struct CrtcInfo -+{ -+ RWMode *mode; -+ int x; -+ int y; -+ GPtrArray *outputs; -+}; ++ text = idle_free (make_display_name (info)); ++ } ++ } + -+struct CrtcAssignment -+{ -+ RWScreen *screen; -+ GHashTable *info; -+}; ++ return gtk_widget_create_pango_layout (GTK_WIDGET (app->area), text); ++} + +static void -+mode_info_free (CrtcInfo *info) ++get_geometry (Output *output, int *w, int *h) +{ -+ g_ptr_array_free (info->outputs, TRUE); -+ g_free (info); ++ if (output->on) ++ { ++ *h = output->height; ++ *w = output->width; ++ } ++ else ++ { ++ *h = output->pref_height; ++ *w = output->pref_width; ++ } +} + -+static CrtcAssignment * -+crtc_assignment_new (void) ++static void ++on_area_paint (FooScrollArea *area, ++ cairo_t *cr, ++ GdkRectangle *extent, ++ GdkRegion *region, ++ gpointer data) +{ -+ CrtcAssignment *assign = g_new0 (CrtcAssignment, 1); ++ App *app = data; ++ GdkRectangle viewport; ++ int i; ++ int available; ++ int total_pixels; ++ int max_height; ++ double scale; ++ GList *connected_outputs = NULL; ++ GList *list; ++ int n_monitors; ++ ++ foo_scroll_area_get_viewport (area, &viewport); + -+ assign->info = g_hash_table_new_full (g_direct_hash, g_direct_equal, -+ NULL, (GFreeFunc)mode_info_free); ++ cairo_set_source_rgba (cr, 0.72, 0.78, 0.87, 1.0); + -+ return assign; -+} ++ cairo_rectangle (cr, ++ viewport.x, viewport.y, ++ viewport.width, viewport.height); ++ ++ cairo_fill_preserve (cr); ++ ++#if 0 ++ foo_scroll_area_add_input_from_fill (area, cr, on_canvas_event, NULL); ++#endif ++ ++ cairo_set_source_rgba (cr, 0.44, 0.59, 0.76, 1.0); ++ ++ cairo_stroke (cr); + -+static gboolean -+can_clone (CrtcInfo *info, -+ RWOutput *output) -+{ -+ int i; ++ if (!app->current_configuration) ++ return; ++ ++#define SPACE 36 ++#define MARGIN 24 + -+ for (i = 0; i < info->outputs->len; ++i) ++ for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) + { -+ RWOutput *clone = info->outputs->pdata[i]; ++ Output *output = app->current_configuration->outputs[i]; + -+ if (!rw_output_can_clone (clone, output)) -+ return FALSE; ++ if (output->connected) ++ connected_outputs = g_list_prepend (connected_outputs, output); + } + -+ return TRUE; -+} ++ connected_outputs = g_list_reverse (connected_outputs); ++ ++ n_monitors = g_list_length (connected_outputs); + -+static gboolean -+crtc_assignment_assign (CrtcAssignment *assign, -+ RWCrtc *crtc, -+ RWMode *mode, -+ int x, -+ int y, -+ RWOutput *output) -+{ -+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); ++ available = viewport.width - 2 * MARGIN - (n_monitors - 1) * SPACE; + -+ if (!rw_crtc_can_drive_output (crtc, output) || -+ !rw_output_supports_mode (output, mode)) ++ total_pixels = 0; ++ max_height = 0; ++ for (list = connected_outputs; list != NULL; list = list->next) + { -+ return FALSE; ++ Output *output = list->data; ++ int w, h; ++ ++ get_geometry (output, &w, &h); ++ ++ total_pixels += w; ++ max_height = MAX (max_height, h); + } + -+ if (info) ++ scale = (double)available / total_pixels; ++ ++ scale = MIN ((double)(viewport.height - 2 * MARGIN) / max_height, scale); ++ ++ int x = MARGIN; ++ for (list = connected_outputs; list != NULL; list = list->next) + { -+ if (info->mode == mode && -+ info->x == x && -+ info->y == y && -+ can_clone (info, output)) -+ { -+ g_ptr_array_add (info->outputs, output); ++ Output *output = list->data; ++ PangoLayout *layout = get_display_name (app, output); ++ int w, h; + -+ return TRUE; -+ } -+ } -+ else -+ { -+ CrtcInfo *info = g_new (CrtcInfo, 1); ++ get_geometry (output, &w, &h); + -+ info->mode = mode; -+ info->x = x; -+ info->y = y; -+ info->outputs = g_ptr_array_new (); ++ w = w * scale + 0.5; ++#if 0 ++ g_print ("%s (%p) geometry %d %d %d\n", output->name, output, ++ w, h, output->rate); ++#endif + -+ g_ptr_array_add (info->outputs, output); ++ cairo_rectangle (cr, x, MARGIN, w, (int)( ++ h * scale + 0.5)); ++ ++ if (output->on) ++ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); ++ else ++ cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 1.0); ++ ++ cairo_fill_preserve (cr); ++ ++ foo_scroll_area_add_input_from_fill (area, cr, on_output_event, ++ output); + -+ g_hash_table_insert (assign->info, crtc, info); -+ -+ return TRUE; -+ } ++ if (output == app->current_output) ++ cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 1.0); ++ else ++ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); ++ cairo_stroke (cr); + -+ return FALSE; ++ cairo_move_to (cr, x + 40, MARGIN + 40); ++ cairo_set_source_rgb (cr, 0.2, 0.2, 0.8); ++ layout_set_font (layout, "Sans Bold 18"); ++ pango_cairo_show_layout (cr, layout); ++ g_object_unref (layout); ++ ++ x += w + SPACE; ++ } +} + +static void -+crtc_assignment_unassign (CrtcAssignment *assign, -+ RWCrtc *crtc, -+ RWOutput *output) ++make_text_combo (GtkWidget *widget, int sort_column) +{ -+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); ++ GtkComboBox *box = GTK_COMBO_BOX (widget); ++ GtkListStore *store = gtk_list_store_new ( ++ 6, ++ G_TYPE_STRING, /* Text */ ++ G_TYPE_INT, /* Width */ ++ G_TYPE_INT, /* Height */ ++ G_TYPE_INT, /* Frequency */ ++ G_TYPE_INT, /* Width * Height */ ++ G_TYPE_INT); /* Rotation */ ++ ++ GtkCellRenderer *cell; + -+ if (info) -+ { -+ g_ptr_array_remove (info->outputs, output); ++ gtk_cell_layout_clear (GTK_CELL_LAYOUT (widget)); ++ ++ gtk_combo_box_set_model (box, GTK_TREE_MODEL (store)); + -+ if (info->outputs->len == 0) -+ g_hash_table_remove (assign->info, crtc); ++ cell = gtk_cell_renderer_text_new (); ++ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, TRUE); ++ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (box), cell, ++ "text", 0, ++ NULL); ++ ++ if (sort_column != -1) ++ { ++ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), ++ sort_column, ++ GTK_SORT_DESCENDING); + } +} + -+void -+crtc_assignment_free (CrtcAssignment *assign) ++static void ++apply (App *app) +{ -+ g_hash_table_destroy (assign->info); -+ -+ g_free (assign); ++ GError *err = NULL; ++ ++ if (configuration_save (app->current_configuration, &err)) ++ configuration_apply_stored (app->screen); +} + -+static void -+configure_crtc (gpointer key, -+ gpointer value, -+ gpointer data) ++static gboolean ++refresh (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 and %d outputs (%d %d %d %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)); -+ } -+ else -+ { -+ g_print ("no mode "); -+ } ++ App *app = data; + -+ if (rw_crtc_set_config (crtc, -+ info->x, info->y, -+ info->mode, -+ (RWOutput **)info->outputs->pdata, -+ info->outputs->len)) -+ { -+ g_print ("succeeded"); -+ } -+ else -+ { -+ g_print ("failed"); -+ } ++ rw_screen_refresh (app->screen); + -+ g_print (" in %f seconds\n", g_timer_elapsed (timer, NULL)); ++ return TRUE; +} + -+void -+crtc_assignment_apply (CrtcAssignment *assign) ++static void ++run_application (App *app) +{ -+ 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; ++#ifndef GLADEDIR ++#define GLADEDIR "." ++#endif ++#define GLADE_FILE GLADEDIR "/display-capplet.glade" ++ GladeXML *xml; ++ GtkWidget *align; + -+ /* Compute size of the screen */ -+ width = height = 1; -+ for (list = active_crtcs; list != NULL; list = list->next) ++ xml = glade_xml_new (GLADE_FILE, NULL, NULL); ++ if (!xml) + { -+ RWCrtc *crtc = list->data; -+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc); -+ -+ width = MAX (width, info->x + rw_mode_get_width (info->mode)); -+ height = MAX (height, info->y + rw_mode_get_height (info->mode)); ++ g_warning ("Could not open " GLADE_FILE); ++ return; + } -+ g_list_free (active_crtcs); -+ -+ 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; ++ app->screen = rw_screen_new (gdk_screen_get_default(), ++ on_screen_changed, app); + -+ if (mode) -+ { -+ rw_crtc_get_position (crtc, &x, &y); ++ app->dialog = glade_xml_get_widget (xml, "dialog"); + -+ if (x + rw_mode_get_width (mode) > width || -+ y + rw_mode_get_height (mode) > height) -+ { -+ rw_crtc_set_config (crtc, 0, 0, NULL, NULL, 0); -+ } -+ } -+ } ++ app->resolution_combo = glade_xml_get_widget (xml, "resolution_combo"); ++ g_signal_connect (app->resolution_combo, "changed", ++ G_CALLBACK (on_resolution_changed), app); + -+ /* 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, NULL, 0); -+ } ++ app->refresh_combo = glade_xml_get_widget (xml, "refresh_combo"); ++ g_signal_connect (app->refresh_combo, "changed", ++ G_CALLBACK (on_rate_changed), app); + -+ /* 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 -+ * 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); ++ app->rotation_combo = glade_xml_get_widget (xml, "rotation_combo"); ++ g_signal_connect (app->rotation_combo, "changed", ++ G_CALLBACK (on_rotation_changed), app); + -+ gdk_flush (); -+ -+ g_print ("time to set screen size: %f\n", g_timer_elapsed (timer, NULL)); ++ app->panel_checkbox = glade_xml_get_widget (xml, "panel_checkbox"); ++ app->panel_label = glade_xml_get_widget (xml, "panel_label"); + -+ g_timer_reset (timer); ++ make_text_combo (app->resolution_combo, 4); ++ make_text_combo (app->refresh_combo, 3); ++ make_text_combo (app->rotation_combo, -1); + -+ g_hash_table_foreach (assign->info, configure_crtc, NULL); ++ g_assert (app->panel_checkbox); ++ ++ /* Scroll Area */ ++ app->area = (GtkWidget *)foo_scroll_area_new (); + -+ gdk_flush (); ++ g_object_set_data (G_OBJECT (app->area), "app", app); + -+ g_print ("time to configure crtc's: %f\n", g_timer_elapsed (timer, NULL)); -+} ++ /* FIXME: this should be computed dynamically */ ++ foo_scroll_area_set_min_size (FOO_SCROLL_AREA (app->area), -1, 200); ++ gtk_widget_show (app->area); ++ g_signal_connect (app->area, "paint", ++ G_CALLBACK (on_area_paint), app); ++ g_signal_connect (app->area, "viewport_changed", ++ G_CALLBACK (on_viewport_changed), app); + -+/* 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, -+ Setting **settings, -+ CrtcAssignment *assignment) -+{ -+ RWCrtc **crtcs = rw_screen_list_crtcs (screen); -+ Setting *setting; -+ int i; ++ align = glade_xml_get_widget (xml, "align"); + -+ setting = *settings; -+ if (!setting) -+ return TRUE; ++ gtk_container_add (GTK_CONTAINER (align), app->area); + -+ /* It is always allowed for an output to be turned off */ -+ if (setting->mode == NULL) -+ { -+ return real_assign_crtcs (screen, settings + 1, assignment); -+ } ++ g_timeout_add (3000, refresh, app); ++ ++ on_screen_changed (app->screen, app); ++ rebuild_gui (app); ++ ++ gtk_widget_hide (app->panel_checkbox); ++ gtk_widget_hide (app->panel_label); + -+ for (i = 0; crtcs[i] != NULL; ++i) ++restart: ++ switch (gtk_dialog_run (GTK_DIALOG (app->dialog))) + { -+ RWCrtc *crtc = crtcs[i]; -+ -+ if (crtc_assignment_assign ( -+ assignment, crtc, setting->mode, -+ setting->x, setting->y, -+ setting->output)) -+ { -+ if (real_assign_crtcs (screen, settings + 1, assignment)) -+ return TRUE; -+ -+ crtc_assignment_unassign (assignment, crtc, setting->output); -+ } ++ default: ++ g_print ("Unknown response\n"); ++ /* Fall Through */ ++ case GTK_RESPONSE_DELETE_EVENT: ++ case GTK_RESPONSE_CLOSE: ++ g_print ("Close\n"); ++ break; ++ ++ case GTK_RESPONSE_HELP: ++ g_print ("Help\n"); ++ goto restart; ++ break; ++ ++ case GTK_RESPONSE_APPLY: ++ apply (app); ++ goto restart; ++ break; + } + -+ return FALSE; ++ gtk_widget_destroy (app->dialog); +} + -+CrtcAssignment * -+assign_crtcs (RWScreen *screen, Setting **settings) ++int ++main (int argc, char **argv) +{ -+ CrtcAssignment *assignment = crtc_assignment_new (); ++ App *app; ++ GError *err = NULL; ++ ++#if 0 ++ bindtextdomain (GETTEXT_PACKAGE, DESKTOPEFFECTSLOCALEDIR); ++ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); ++ textdomain (GETTEXT_PACKAGE); ++#endif ++ ++ gtk_init (&argc, &argv); ++ ++ app = g_new0 (App, 1); + -+ if (real_assign_crtcs (screen, settings, assignment)) ++ if (!init_app (app)) + { -+ assignment->screen = screen; -+ -+ return assignment; ++ show_error (err); ++ return 0; + } -+ else -+ { -+ crtc_assignment_free (assignment); ++ ++ run_application (app); + -+ return NULL; -+ } ++ 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 08:26:21.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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/display-capplet.glade 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,399 @@ + + @@ -5390,7 +5576,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/display-capplet + True + True + -+If you report bugs in this control panel (please do!), make sure you ++If you report bugs in this control panel (please do!), make sure you +attach the file + + /var/log/Xorg.0.log @@ -5434,7 +5620,7 @@ 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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/scrollarea.h 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,107 @@ +#include +#include @@ -5545,7 +5731,7 @@ diff -up /dev/null gnome-control-center-2.21.90/capplets/display/scrollarea.h +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-01-31 16:51:14.000000000 -0500 ++++ gnome-control-center-2.21.90/capplets/display/display-name.c 2008-02-04 08:26:21.000000000 -0500 @@ -0,0 +1,161 @@ +/* + * Copyright 2007 Red Hat, Inc. @@ -5742,217 +5928,9 @@ diff -up gnome-control-center-2.21.90/capplets/display/Makefile.am.add-randr12-c $(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-01-31 16:51:14.000000000 -0500 -@@ -0,0 +1,212 @@ ++++ gnome-control-center-2.21.90/capplets/display/apply.c 2008-02-04 08:26:21.000000000 -0500 +@@ -0,0 +1,4 @@ +#include "crtc.h" +#include "monitor-db.h" + -+/* This file should go in g-s-d eventually */ -+ -+static void -+push (GPtrArray *a, -+ RWOutput *output, -+ RWMode *mode, -+ int x, int y) -+{ -+ Setting *setting = g_new0 (Setting, 1); -+ -+ setting->output = output; -+ setting->mode = mode; -+ setting->x = x; -+ setting->y = y; -+ -+ g_ptr_array_add (a, setting); -+} -+ -+static void -+pop (GPtrArray *a) -+{ -+ g_free (g_ptr_array_remove_index (a, a->len - 1)); -+} -+ -+typedef gboolean (* ForeachFunc) (Setting **settings, gpointer data); -+ -+static gboolean -+foreach_setting_list (RWScreen *screen, -+ GPtrArray *settings, -+ Output **outputs, -+ ForeachFunc func, -+ gpointer data) -+{ -+ gboolean result; -+ -+ if (*outputs == NULL) -+ { -+ g_ptr_array_add (settings, NULL); -+ -+ result = func ((Setting **)settings->pdata, data); -+ -+ g_ptr_array_remove_index (settings, settings->len - 1); -+ } -+ else -+ { -+ Output *output = *outputs; -+ RWOutput *rw_output = rw_screen_get_output_by_name ( -+ screen, output->name); -+ RWMode **modes = rw_output_list_modes (rw_output); -+ int i; -+ -+ if (!output->connected || !output->on) -+ { -+#if 0 -+ g_print ("%s is not connected\n", output->name); -+#endif -+ push (settings, rw_output, NULL, 0, 0); -+ -+ result = foreach_setting_list (screen, settings, outputs + 1, func, data); -+ -+ pop (settings); -+ } -+ else -+ { -+ result = FALSE; -+ -+#if 0 -+ g_print ("%s modes (%p)\n", output->name, output); -+#endif -+ -+ for (i = 0; modes[i] != NULL; ++i) -+ { -+ RWMode *mode = modes[i]; -+ -+#if 0 -+ g_print ("%d x %d x %d match mode %d x %d x %d\n", -+ output->width, output->height, output->rate, -+ rw_mode_get_width (mode), -+ rw_mode_get_height (mode), -+ rw_mode_get_freq (mode)); -+#endif -+ -+ if (rw_mode_get_width (mode) == output->width && -+ rw_mode_get_height (mode) == output->height && -+ rw_mode_get_freq (mode) == output->rate) -+ { -+ push (settings, rw_output, mode, output->x, 0); -+ -+ result = foreach_setting_list ( -+ screen, settings, outputs + 1, func, data); -+ -+ pop (settings); -+ -+ if (result) -+ break; -+ } -+ } -+ } -+ } -+ -+ return result; -+} -+ -+static gboolean -+try_settings (Setting **settings, gpointer data) -+{ -+ RWScreen *screen = data; -+ CrtcAssignment *assignment; -+#if 0 -+ int i; -+#endif -+ -+#if 0 -+ g_print ("found setting\n"); -+#endif -+ -+ assignment = assign_crtcs (screen, settings); -+ -+#if 0 -+ for (i = 0; settings[i] != NULL; ++i) -+ { -+ RWMode *mode = settings[i]->mode; -+ -+ g_print ("%s => ", rw_output_get_name (settings[i]->output)); -+ -+ if (mode) -+ { -+ g_print ("%d x %d x %d\n", -+ rw_mode_get_width (mode), -+ rw_mode_get_height (mode), -+ rw_mode_get_freq (mode)); -+ } -+ else -+ { -+ g_print ("off\n"); -+ } -+ } -+#endif -+ -+ if (assignment) -+ { -+ crtc_assignment_apply (assignment); -+ -+ crtc_assignment_free (assignment); -+ -+ return TRUE; -+ } -+ else -+ { -+ return FALSE; -+ } -+} -+ -+/* This should go in g-s-d eventually */ -+void -+apply_stored_configuration (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; -+ -+ if ((found = configuration_find (configs, current))) -+ { -+ GPtrArray *array = g_ptr_array_new (); -+ -+ g_print ("found\n"); -+ -+ foreach_setting_list ( -+ screen, array, found->outputs, -+ try_settings, screen); -+ -+ g_ptr_array_free (array, TRUE); -+ } -+ else -+ { -+ g_print ("Not found\n"); -+ } -+ -+ configuration_free (current); -+ configurations_free (configs); -+ -+ g_free (file); -+} -+ -+/* Some potentially useful code */ -+ -+#if 0 -+ found = configuration_find (app->all_configurations, current); -+ if (found) -+ { -+ g_print ("config found\n"); -+ -+ configuration_free (current); -+ -+ current = found; -+ } -+ else -+ { -+ g_print ("config not found, adding\n"); -+ -+ app->all_configurations = configurations_add ( -+ app->all_configurations, current); -+ } -+ -+ g_assert (configuration_find (app->all_configurations, current)); -+ -+#endif ++/* Not used anymore */ diff --git a/control-center.spec b/control-center.spec index 7aed110..6d7f6b5 100644 --- a/control-center.spec +++ b/control-center.spec @@ -3,7 +3,7 @@ %define glib2_version 2.13.0 %define gtk2_version 2.11.6 %define gconf2_version 1.2.0 -%define gnome_desktop_version 2.21.90-2 +%define gnome_desktop_version 2.21.90-5 %define libgnome_version 2.3.0 %define libbonobo_version 2.3.0 %define libgnomeui_version 2.3.0 @@ -22,7 +22,7 @@ Summary: GNOME Control Center Name: control-center Version: 2.21.90 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 1 License: GPLv2+ and GFDL Group: User Interface/Desktops @@ -349,6 +349,9 @@ fi %dir %{_datadir}/gnome-control-center/keybindings %changelog +* Mon Feb 4 2008 Soren Sandmann - 2.21.90-6 +- Update randr capplet - now with rotation + * Thu Jan 29 2008 Soren Sandmann - 2.21.90-5 - Update randr capplet