[PATCHES] Implement monitor labeling in the RANDR code



Dear lovers of multiple monitors,

Here are three patches (for gnome-desktop, gnome-settings-daemon, and
gnome-control-center, respectively).  I added a new unstable API for the
RANDR stuff, with an object called GnomeRRLabeler.

The idea is that in the gnome-display-properties capplet and in the tray
icon for RANDR, we want to make it easy for the user to see which
elements in the GUI correspond to each physical monitor.  GnomeRRLabeler
creates color-coded labels in each physical monitor (similar to KDE's
and MacOS's), and it lets apps query those colors so that they can paint
their own GUI elements.

GnomeRRLabeler lives in gnome-desktop.  In turn, gnome-settings-daemon
and gnome-control-center use GnomeRRLabeler's API.

Is this OK to commit?  I know freezes are in place, but this is so
sexy :)

Screenshot at http://www.gnome.org/~federico/misc/monitor-labels.png

Git repositories here:
http://gitorious.org/projects/gnome-desktop/repos/mainline
http://gitorious.org/projects/gnome-settings-daemon/repos/mainline
http://gitorious.org/projects/gnome-control-center/repos/mainline
(see the "monitor-labeling" branches in each of those repositories)

(No new translatable strings have been added).

  Federico

 libgnome-desktop/ChangeLog                     |   10 +
 libgnome-desktop/Makefile.am                   |    1 +
 libgnome-desktop/gnome-rr-labeler.c            |  362 ++++++++++++++++++++++++
 libgnome-desktop/libgnomeui/Makefile.am        |    3 +-
 libgnome-desktop/libgnomeui/gnome-rr-labeler.h |   53 ++++
 5 files changed, 428 insertions(+), 1 deletions(-)

diff --git a/libgnome-desktop/ChangeLog b/libgnome-desktop/ChangeLog
index 4394489..5f2699d 100644
--- a/libgnome-desktop/ChangeLog
+++ b/libgnome-desktop/ChangeLog
@@ -1,3 +1,13 @@
+2008-08-13  Federico Mena Quintero  <federico novell com>
+
+	* gnome-rr-labeler.[ch]: New files with a GnomeRRLabeler object.
+	When created against a GnomeRRConfig, this lets the user see which
+	physical monitor coresponds to each element in the user
+	interface.  It displays a color-coded label window on
+	the upper-left corner of each monitor.  Also, it lets callers
+	access the color-coding information so that they can color their
+	own GUI to configure monitors.
+
 2008-08-11  Federico Mena Quintero  <federico novell com>
 
 	* gnome-rr.c (gnome_rr_screen_destroy): New public function.  We
diff --git a/libgnome-desktop/Makefile.am b/libgnome-desktop/Makefile.am
index f8516ca..772a918 100644
--- a/libgnome-desktop/Makefile.am
+++ b/libgnome-desktop/Makefile.am
@@ -24,6 +24,7 @@ libgnome_desktop_2_la_SOURCES = \
 	display-name.c		\
 	gnome-rr.c		\
 	gnome-rr-config.c	\
+	gnome-rr-labeler.c	\
 	edid-parse.c		\
 	edid.h
 
diff --git a/libgnome-desktop/gnome-rr-labeler.c b/libgnome-desktop/gnome-rr-labeler.c
new file mode 100644
index 0000000..6b2c242
--- /dev/null
+++ b/libgnome-desktop/gnome-rr-labeler.c
@@ -0,0 +1,362 @@
+/* gnome-rr-labeler.c - Utility to label monitors to identify them
+ * while they are being configured.
+ *
+ * Copyright 2008, Novell, Inc.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Federico Mena-Quintero <federico novell com>
+ */
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+
+#include <config.h>
+#include "libgnomeui/gnome-rr-labeler.h"
+#include <gtk/gtk.h>
+
+struct _GnomeRRLabeler {
+	GObject parent;
+
+	GnomeRRConfig *config;
+
+	int num_outputs;
+
+	GdkColor *palette;
+	GtkWidget **windows;
+};
+
+struct _GnomeRRLabelerClass {
+	GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (GnomeRRLabeler, gnome_rr_labeler, G_TYPE_OBJECT);
+
+static void gnome_rr_labeler_finalize (GObject *object);
+
+static void
+gnome_rr_labeler_init (GnomeRRLabeler *labeler)
+{
+	/* nothing */
+}
+
+static void
+gnome_rr_labeler_class_init (GnomeRRLabelerClass *class)
+{
+	GObjectClass *object_class;
+
+	object_class = (GObjectClass *) class;
+
+	object_class->finalize = gnome_rr_labeler_finalize;
+}
+
+static void
+gnome_rr_labeler_finalize (GObject *object)
+{
+	GnomeRRLabeler *labeler;
+
+	labeler = GNOME_RR_LABELER (object);
+
+	/* We don't destroy the labeler->config (a GnomeRRConfig*) here; let our
+	 * caller do that instead.
+	 */
+
+	if (labeler->windows != NULL) {
+		gnome_rr_labeler_hide (labeler);
+		g_free (labeler->windows);
+		labeler->windows = NULL;
+	}
+
+	g_free (labeler->palette);
+	labeler->palette = NULL;
+
+	G_OBJECT_CLASS (gnome_rr_labeler_parent_class)->finalize (object);
+}
+
+static int
+count_outputs (GnomeRRConfig *config)
+{
+	int i;
+
+	for (i = 0; config->outputs[i] != NULL; i++)
+		;
+
+	return i;
+}
+
+/* hsv_to_rgb() stolen from gtk+/gtk/gtkhsv.c, sigh. */
+
+#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
+
+/* Converts from HSV to RGB */
+static void
+hsv_to_rgb (gdouble *h,
+	    gdouble *s,
+	    gdouble *v)
+{
+  gdouble hue, saturation, value;
+  gdouble f, p, q, t;
+
+  if (*s == 0.0)
+    {
+      *h = *v;
+      *s = *v;
+      *v = *v; /* heh */
+    }
+  else
+    {
+      hue = *h * 6.0;
+      saturation = *s;
+      value = *v;
+
+      if (hue == 6.0)
+	hue = 0.0;
+
+      f = hue - (int) hue;
+      p = value * (1.0 - saturation);
+      q = value * (1.0 - saturation * f);
+      t = value * (1.0 - saturation * (1.0 - f));
+
+      switch ((int) hue)
+	{
+	case 0:
+	  *h = value;
+	  *s = t;
+	  *v = p;
+	  break;
+
+	case 1:
+	  *h = q;
+	  *s = value;
+	  *v = p;
+	  break;
+
+	case 2:
+	  *h = p;
+	  *s = value;
+	  *v = t;
+	  break;
+
+	case 3:
+	  *h = p;
+	  *s = q;
+	  *v = value;
+	  break;
+
+	case 4:
+	  *h = t;
+	  *s = p;
+	  *v = value;
+	  break;
+
+	case 5:
+	  *h = value;
+	  *s = p;
+	  *v = q;
+	  break;
+
+	default:
+	  g_assert_not_reached ();
+	}
+    }
+}
+
+static void
+make_palette (GnomeRRLabeler *labeler)
+{
+	/* The idea is that we go around an hue color wheel.  We want to start
+	 * at red, go around to green/etc. and stop at blue --- because magenta
+	 * is evil.  Eeeeek, no magenta, please!
+	 *
+	 * Purple would be nice, though.  Remember that we are watered down
+	 * (i.e. low saturation), so that would be like Like berries with cream.
+	 * Mmmmm, berries.
+	 */
+	double start_hue;
+	double end_hue;
+	int i;
+
+	g_assert (labeler->num_outputs > 0);
+
+	labeler->palette = g_new (GdkColor, labeler->num_outputs);
+
+	start_hue = 0.0; /* red */
+	end_hue   = 2.0/3; /* blue */
+
+	for (i = 0; i < labeler->num_outputs; i++) {
+		double h, s, v;
+
+		h = start_hue + (end_hue - start_hue) / labeler->num_outputs * i;
+		s = 1.0 / 3;
+		v = 1.0;
+
+		hsv_to_rgb (&h, &s, &v);
+
+		labeler->palette[i].red   = (int) (65535 * h + 0.5);
+		labeler->palette[i].green = (int) (65535 * s + 0.5);
+		labeler->palette[i].blue  = (int) (65535 * v + 0.5);
+	}
+}
+
+#define LABEL_WINDOW_EDGE_THICKNESS 2
+#define LABEL_WINDOW_PADDING 12
+
+static gboolean
+label_window_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+	cairo_t *cr;
+	GdkColor *color;
+
+	color = g_object_get_data (G_OBJECT (widget), "color");
+
+	cr = gdk_cairo_create (widget->window);
+
+	/* edge outline */
+
+	cairo_set_source_rgb (cr, 0, 0, 0);
+	cairo_rectangle (cr,
+			 LABEL_WINDOW_EDGE_THICKNESS / 2.0,
+			 LABEL_WINDOW_EDGE_THICKNESS / 2.0,
+			 widget->allocation.width - LABEL_WINDOW_EDGE_THICKNESS,
+			 widget->allocation.height - LABEL_WINDOW_EDGE_THICKNESS);
+	cairo_set_line_width (cr, LABEL_WINDOW_EDGE_THICKNESS);
+	cairo_stroke (cr);
+
+	/* fill */
+
+	gdk_cairo_set_source_color (cr, color);
+	cairo_rectangle (cr,
+			 LABEL_WINDOW_EDGE_THICKNESS,
+			 LABEL_WINDOW_EDGE_THICKNESS,
+			 widget->allocation.width - LABEL_WINDOW_EDGE_THICKNESS * 2,
+			 widget->allocation.height - LABEL_WINDOW_EDGE_THICKNESS * 2);
+	cairo_fill (cr);
+
+	cairo_destroy (cr);
+
+	return FALSE;
+}
+
+static GtkWidget *
+create_label_window (GnomeRRLabeler *labeler, GnomeOutputInfo *output, GdkColor *color)
+{
+	GtkWidget *window;
+	GtkWidget *widget;
+
+	window = gtk_window_new (GTK_WINDOW_POPUP);
+	GTK_WIDGET_SET_FLAGS (window, GTK_APP_PAINTABLE);
+
+	gtk_container_set_border_width (GTK_CONTAINER (window), LABEL_WINDOW_PADDING + LABEL_WINDOW_EDGE_THICKNESS);
+
+	/* This is semi-dangerous.  The color is part of the labeler->palette
+	 * array.  Note that in gnome_rr_labeler_finalize(), we are careful to
+	 * free the palette only after we free the windows.
+	 */
+	g_object_set_data (G_OBJECT (window), "color", color);
+
+	g_signal_connect (window, "expose-event",
+			  G_CALLBACK (label_window_expose_event_cb), labeler);
+
+	widget = gtk_label_new (output->display_name);
+
+	gtk_container_add (GTK_CONTAINER (window), widget);
+
+	/* Should we center this at the top edge of the monitor, instead of using the upper-left corner? */
+	gtk_window_move (GTK_WINDOW (window), output->x, output->y);
+
+	gtk_widget_show_all (window);
+
+	return window;
+}
+
+static void
+create_label_windows (GnomeRRLabeler *labeler)
+{
+	int i;
+
+	/* FIXME: this doesn't handle cloned outputs yet */
+
+	labeler->windows = g_new (GtkWidget *, labeler->num_outputs);
+
+	for (i = 0; i < labeler->num_outputs; i++) {
+		if (labeler->config->outputs[i]->on) {
+			labeler->windows[i] = create_label_window (labeler, labeler->config->outputs[i], labeler->palette + i);
+		} else
+			labeler->windows[i] = NULL;
+	}
+}
+
+static void
+setup_from_config (GnomeRRLabeler *labeler)
+{
+	labeler->num_outputs = count_outputs (labeler->config);
+
+	make_palette (labeler);
+
+	create_label_windows (labeler);
+}
+
+GnomeRRLabeler *
+gnome_rr_labeler_new (GnomeRRConfig *config)
+{
+	GnomeRRLabeler *labeler;
+
+	g_return_val_if_fail (config != NULL, NULL);
+
+	labeler = g_object_new (GNOME_TYPE_RR_LABELER, NULL);
+	labeler->config = config;
+
+	setup_from_config (labeler);
+
+	return labeler;
+}
+
+void
+gnome_rr_labeler_hide (GnomeRRLabeler *labeler)
+{
+	int i;
+
+	g_return_if_fail (GNOME_IS_RR_LABELER (labeler));
+
+	for (i = 0; i < labeler->num_outputs; i++)
+		if (labeler->windows[i] != NULL) {
+			gtk_widget_destroy (labeler->windows[i]);
+			labeler->windows[i] = NULL;
+		}
+}
+
+void
+gnome_rr_labeler_get_color_for_output (GnomeRRLabeler *labeler, GnomeOutputInfo *output, GdkColor *color_out)
+{
+	int i;
+
+	g_return_if_fail (GNOME_IS_RR_LABELER (labeler));
+	g_return_if_fail (output != NULL);
+	g_return_if_fail (color_out != NULL);
+
+	for (i = 0; i < labeler->num_outputs; i++)
+		if (labeler->config->outputs[i] == output) {
+			*color_out = labeler->palette[i];
+			return;
+		}
+
+	g_warning ("trying to get the color for unknown GnomeOutputInfo %p; returning magenta!", output);
+
+	color_out->red   = 0xffff;
+	color_out->green = 0;
+	color_out->blue  = 0xffff;
+}
diff --git a/libgnome-desktop/libgnomeui/Makefile.am b/libgnome-desktop/libgnomeui/Makefile.am
index eb5b510..195bad2 100644
--- a/libgnome-desktop/libgnomeui/Makefile.am
+++ b/libgnome-desktop/libgnomeui/Makefile.am
@@ -4,4 +4,5 @@ libgnomeui_desktop_HEADERS =	\
 	gnome-hint.h		\
 	gnome-bg.h		\
 	gnome-rr.h		\
-	gnome-rr-config.h
+	gnome-rr-config.h	\
+	gnome-rr-labeler.h
diff --git a/libgnome-desktop/libgnomeui/gnome-rr-labeler.h b/libgnome-desktop/libgnomeui/gnome-rr-labeler.h
new file mode 100644
index 0000000..5b751cc
--- /dev/null
+++ b/libgnome-desktop/libgnomeui/gnome-rr-labeler.h
@@ -0,0 +1,53 @@
+/* gnome-rr-labeler.h - Utility to label monitors to identify them
+ * while they are being configured.
+ *
+ * Copyright 2008, Novell, Inc.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Federico Mena-Quintero <federico novell com>
+ */
+
+#ifndef GNOME_RR_LABELER_H
+#define GNOME_RR_LABELER_H
+
+#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
+#error    GnomeRR is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnomerr.h
+#endif
+
+#include <libgnomeui/gnome-rr-config.h>
+
+#define GNOME_TYPE_RR_LABELER            (gnome_rr_labeler_get_type ())
+#define GNOME_RR_LABELER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_RR_LABELER, GnomeRRLabeler))
+#define GNOME_RR_LABELER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GNOME_TYPE_RR_LABELER, GnomeRRLabelerClass))
+#define GNOME_IS_RR_LABELER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_RR_LABELER))
+#define GNOME_IS_RR_LABELER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GNOME_TYPE_RR_LABELER))
+#define GNOME_RR_LABELER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GNOME_TYPE_RR_LABELER, GnomeRRLabelerClass))
+
+typedef struct _GnomeRRLabeler GnomeRRLabeler;
+typedef struct _GnomeRRLabelerClass GnomeRRLabelerClass;
+
+GType gnome_rr_labeler_get_type (void);
+
+GnomeRRLabeler *gnome_rr_labeler_new (GnomeRRConfig *config);
+
+void gnome_rr_labeler_hide (GnomeRRLabeler *labeler);
+
+void gnome_rr_labeler_get_color_for_output (GnomeRRLabeler *labeler, GnomeOutputInfo *output, GdkColor *color_out);
+
+#endif
 ChangeLog                           |   11 +++++++++
 plugins/xrandr/gsd-xrandr-manager.c |   40 +++++++++++++++++++++++++++++-----
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index e23f4e3..7975ca1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-08-13  Federico Mena Quintero  <federico novell com>
+
+	* plugins/xrandr/gsd-xrandr-manager.c (status_icon_popup_menu):
+	When the menu comes up, create a GnomeRRLabeler so that the user
+	can identify which physical monitors we are talking about.  This
+	will actually be visible in the popup menu once we implement the
+	rotation commands.
+	(status_icon_popup_menu_selection_done_cb): Hide and destroy the
+	GnomeRRLabeler.
+	(struct GsdXrandrManagerPrivate): New field "labeler".
+
 2008-08-12  Federico Mena Quintero  <federico novell com>
 
 	* configure.ac: For LIBSOUNDS, check for libgnomeui, not just libgnome.
diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index 62010fe..8ef91db 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -42,6 +42,7 @@
 
 #include <libgnomeui/gnome-rr-config.h>
 #include <libgnomeui/gnome-rr.h>
+#include <libgnomeui/gnome-rr-labeler.h>
 
 #ifdef HAVE_RANDR
 #include <X11/extensions/Xrandr.h>
@@ -76,6 +77,9 @@ struct GsdXrandrManagerPrivate
         gboolean client_filter_set;
 
         GtkStatusIcon *status_icon;
+        GtkWidget *popup_menu;
+        GnomeRRConfig *configuration;
+        GnomeRRLabeler *labeler;
         GConfClient *client;
         int notify_id;
 };
@@ -186,30 +190,54 @@ popup_menu_configure_display_cb (GtkMenuItem *item, gpointer data)
 }
 
 static void
+status_icon_popup_menu_selection_done_cb (GtkMenuShell *menu_shell, gpointer data)
+{
+        GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data);
+        struct GsdXrandrManagerPrivate *priv = manager->priv;
+
+        gtk_widget_destroy (priv->popup_menu);
+        priv->popup_menu = NULL;
+
+        gnome_rr_labeler_hide (priv->labeler);
+        g_object_unref (priv->labeler);
+        priv->labeler = NULL;
+
+        gnome_rr_config_free (priv->configuration);
+        priv->configuration = NULL;
+}
+
+static void
 status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timestamp)
 {
         struct GsdXrandrManagerPrivate *priv = manager->priv;
         GtkWidget *menu;
         GtkWidget *item;
 
-        menu = gtk_menu_new ();
+        g_assert (priv->popup_menu == NULL);
+        priv->popup_menu = gtk_menu_new ();
 
         item = gtk_menu_item_new_with_label (_("Screen Rotation"));
         gtk_widget_set_sensitive (item, FALSE);
         gtk_widget_show (item);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+        gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
 
         item = gtk_menu_item_new_with_mnemonic (_("_Configure Display Settings ..."));
         g_signal_connect (item, "activate",
                           G_CALLBACK (popup_menu_configure_display_cb), manager);
         gtk_widget_show (item);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+        gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
         /* FIXME */
 
-        g_signal_connect (menu, "selection-done",
-                          G_CALLBACK (gtk_widget_destroy), NULL);
+        g_signal_connect (priv->popup_menu, "selection-done",
+                          G_CALLBACK (status_icon_popup_menu_selection_done_cb), manager);
+
+        g_assert (priv->configuration == NULL);
+        priv->configuration = gnome_rr_config_new_current (priv->rw_screen);
+
+        g_assert (priv->labeler == NULL);
+        priv->labeler = gnome_rr_labeler_new (priv->configuration);
 
-        gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+        gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
                         gtk_status_icon_position_menu,
                         priv->status_icon, button, timestamp);
 }
 capplets/display/ChangeLog        |   13 +++++++++++++
 capplets/display/xrandr-capplet.c |   29 +++++++++++++++++++++++++----
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/capplets/display/ChangeLog b/capplets/display/ChangeLog
index df3f4ec..bb21b22 100644
--- a/capplets/display/ChangeLog
+++ b/capplets/display/ChangeLog
@@ -1,3 +1,16 @@
+2008-08-13  Federico Mena Quintero  <federico novell com>
+
+	* xrandr-capplet.c (paint_output): Instead of using hard-coded
+	colors for the rectangles that represent the monitors, get the
+	colors from the GnomeRRLabeler.
+
+2008-08-13  Federico Mena Quintero  <federico novell com>
+
+	* xrandr-capplet.c (on_screen_changed): Create a GnomeRRLabeler
+	based on the current screen configuration, so that the physical
+	monitors will be labeled while the capplet is up.
+	(struct App): New field "labeler".
+
 2008-08-11  Jens Granseuer  <jensgr gmx net>
 
 	* xrandr-capplet.c: (run_application): fail gracefully if we cannot
diff --git a/capplets/display/xrandr-capplet.c b/capplets/display/xrandr-capplet.c
index 23d3c5d..faa75a7 100644
--- a/capplets/display/xrandr-capplet.c
+++ b/capplets/display/xrandr-capplet.c
@@ -28,6 +28,7 @@
 #define GNOME_DESKTOP_USE_UNSTABLE_API
 #include <libgnomeui/gnome-rr.h>
 #include <libgnomeui/gnome-rr-config.h>
+#include <libgnomeui/gnome-rr-labeler.h>
 #include <gdk/gdkx.h>
 #include <X11/Xlib.h>
 #include <glib/gi18n.h>
@@ -40,6 +41,7 @@ struct App
 {
     GnomeRRScreen       *screen;
     GnomeRRConfig  *current_configuration;
+    GnomeRRLabeler *labeler;
     GnomeOutputInfo         *current_output;
 
     GtkWidget	   *dialog;
@@ -139,6 +141,13 @@ on_screen_changed (GnomeRRScreen *scr,
     qsort (app->current_configuration->outputs, i, sizeof (GnomeOutputInfo *),
 	   compare_outputs);
 
+    if (app->labeler) {
+	gnome_rr_labeler_hide (app->labeler);
+	g_object_unref (app->labeler);
+    }
+
+    app->labeler = gnome_rr_labeler_new (app->current_configuration);
+
 #if 0
     for (i = 0; app->current_configuration->outputs[i] != NULL; ++i)
     {
@@ -1351,6 +1360,8 @@ paint_output (App *app, cairo_t *cr, int i)
     PangoRectangle extent;
     GdkRectangle viewport;
     double angle;
+    GdkColor output_color;
+    double r, g, b;
 
     cairo_save (cr);
 
@@ -1420,10 +1431,20 @@ paint_output (App *app, cairo_t *cr, int i)
     cairo_rectangle (cr, x, y, w * scale + 0.5, h * scale + 0.5);
     cairo_clip_preserve (cr);
 
-    if (output->on)
-	cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
-    else
-	cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1.0);
+    gnome_rr_labeler_get_color_for_output (app->labeler, output, &output_color);
+    r = output_color.red / 65535.0;
+    g = output_color.green / 65535.0;
+    b = output_color.blue / 65535.0;
+
+    if (!output->on)
+    {
+	/* If the output is turned off, just darken the selected color */
+	r *= 0.2;
+	g *= 0.2;
+	b *= 0.2;
+    }
+
+    cairo_set_source_rgba (cr, r, g, b, 1.0);
 
     foo_scroll_area_add_input_from_fill (FOO_SCROLL_AREA (app->area),
 					 cr, on_output_event, output);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]