gtk+ r20651 - in trunk: . gtk



Author: johan
Date: Fri Jun 20 15:01:31 2008
New Revision: 20651
URL: http://svn.gnome.org/viewvc/gtk+?rev=20651&view=rev

Log:
2008-06-20  Johan Dahlin  <jdahlin async com br>

    * gtk/gtkcolorsel.c: Modernize and order things as most
    other objects. Defines at the top, class init before init
    before gobject methods before object method before widget
    methods. No changes to the logic done.



Modified:
   trunk/ChangeLog
   trunk/gtk/gtkcolorsel.c

Modified: trunk/gtk/gtkcolorsel.c
==============================================================================
--- trunk/gtk/gtkcolorsel.c	(original)
+++ trunk/gtk/gtkcolorsel.c	Fri Jun 20 15:01:31 2008
@@ -26,9 +26,10 @@
  */
 
 #include <config.h>
-#include "gdkconfig.h"
 #include <math.h>
+#include <string.h>
 
+#include "gdkconfig.h"
 #include "gdk/gdkkeysyms.h"
 #include "gtkcolorsel.h"
 #include "gtkhsv.h"
@@ -60,18 +61,30 @@
 #include "gtkintl.h"
 #include "gtkalias.h"
 
-#include <string.h>
-
 /* Number of elements in the custom palatte */
 #define GTK_CUSTOM_PALETTE_WIDTH 10
 #define GTK_CUSTOM_PALETTE_HEIGHT 2
 
+#define CUSTOM_PALETTE_ENTRY_WIDTH   20
+#define CUSTOM_PALETTE_ENTRY_HEIGHT  20
+
+/* The cursor for the dropper */
+#define DROPPER_WIDTH 17
+#define DROPPER_HEIGHT 17
+#define DROPPER_X_HOT 2
+#define DROPPER_Y_HOT 16
+
+#define SAMPLE_WIDTH  64
+#define SAMPLE_HEIGHT 28
+#define CHECK_SIZE 16  
+#define BIG_STEP 20
+
 /* Conversion between 0->1 double and and guint16. See
  * scale_round() below for more general conversions
  */
 #define SCALE(i) (i / 65535.)
 #define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
-
+#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
 
 enum {
   COLOR_CHANGED,
@@ -163,7 +176,7 @@
 static void     gtk_color_selection_set_palette_color   (GtkColorSelection *colorsel,
                                                          gint               index,
                                                          GdkColor          *color);
-static void    set_focus_line_attributes                (GtkWidget         *drawing_area,
+static void     set_focus_line_attributes               (GtkWidget         *drawing_area,
 							 cairo_t           *cr,
 							 gint              *focus_width);
 static void     default_noscreen_change_palette_func    (const GdkColor    *colors,
@@ -176,6 +189,46 @@
 static void     make_all_relations                      (AtkObject         *atk_obj,
                                                          ColorSelectionPrivate *priv);
 
+static void 	hsv_changed                             (GtkWidget         *hsv,
+							 gpointer           data);
+static void 	get_screen_color                        (GtkWidget         *button);
+static void 	adjustment_changed                      (GtkAdjustment     *adjustment,
+							 gpointer           data);
+static void 	opacity_entry_changed                   (GtkWidget 	   *opacity_entry,
+							 gpointer  	    data);
+static void 	hex_changed                             (GtkWidget 	   *hex_entry,
+							 gpointer  	    data);
+static gboolean hex_focus_out                           (GtkWidget     	   *hex_entry, 
+							 GdkEventFocus 	   *event,
+							 gpointer      	    data);
+static void 	color_sample_new                        (GtkColorSelection *colorsel);
+static void 	make_label_spinbutton     		(GtkColorSelection *colorsel,
+	    				  		 GtkWidget        **spinbutton,
+	    				  		 gchar             *text,
+	    				  		 GtkWidget         *table,
+	    				  		 gint               i,
+	    				  		 gint               j,
+	    				  		 gint               channel_type,
+	    				  		 const gchar       *tooltip);
+static void 	make_palette_frame                      (GtkColorSelection *colorsel,
+							 GtkWidget         *table,
+							 gint               i,
+							 gint               j);
+static void 	set_selected_palette                    (GtkColorSelection *colorsel,
+							 int                x,
+							 int                y);
+static void 	set_focus_line_attributes               (GtkWidget 	   *drawing_area,
+							 cairo_t   	   *cr,
+							 gint      	   *focus_width);
+static gboolean mouse_press 		     	       	(GtkWidget         *invisible,
+                            		     	       	 GdkEventButton    *event,
+                            		     	       	 gpointer           data);
+static void  palette_change_notify_instance (GObject    *object,
+					     GParamSpec *pspec,
+					     gpointer    data);
+static void update_palette (GtkColorSelection *colorsel);
+static void shutdown_eyedropper (GtkWidget *widget);
+
 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
 
 static const gchar default_colors[] = "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90";
@@ -183,13 +236,6 @@
 static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
 static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
 
-/* The cursor for the dropper */
-#define DROPPER_WIDTH 17
-#define DROPPER_HEIGHT 17
-#define DROPPER_X_HOT 2
-#define DROPPER_Y_HOT 16
-
-
 static const guchar dropper_bits[] = {
   0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
   0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
@@ -204,1930 +250,1980 @@
   0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
   0x02, 0x00, 0x00, };
 
-
-/*
- *
- * The Sample Color
- *
- */
-#define SAMPLE_WIDTH  64
-#define SAMPLE_HEIGHT 28
-
-static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
-static void color_sample_update_samples (GtkColorSelection *colorsel);
+G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
 
 static void
-set_color_internal (GtkColorSelection *colorsel,
-		    gdouble           *color)
+gtk_color_selection_class_init (GtkColorSelectionClass *klass)
 {
-  ColorSelectionPrivate *priv;
-  gint i;
+  GObjectClass *gobject_class;
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
   
-  priv = colorsel->private_data;
-  priv->changing = TRUE;
-  priv->color[COLORSEL_RED] = color[0];
-  priv->color[COLORSEL_GREEN] = color[1];
-  priv->color[COLORSEL_BLUE] = color[2];
-  priv->color[COLORSEL_OPACITY] = color[3];
-  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
-		  priv->color[COLORSEL_GREEN],
-		  priv->color[COLORSEL_BLUE],
-		  &priv->color[COLORSEL_HUE],
-		  &priv->color[COLORSEL_SATURATION],
-		  &priv->color[COLORSEL_VALUE]);
-  if (priv->default_set == FALSE)
-    {
-      for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
-	priv->old_color[i] = priv->color[i];
-    }
-  priv->default_set = TRUE;
-  priv->default_alpha_set = TRUE;
-  update_color (colorsel);
-}
-
-static void
-set_color_icon (GdkDragContext *context,
-		gdouble        *colors)
-{
-  GdkPixbuf *pixbuf;
-  guint32 pixel;
-
-  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
-			   8, 48, 32);
-
-  pixel = (((UNSCALE (colors[COLORSEL_RED])   & 0xff00) << 16) |
-	   ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
-	   ((UNSCALE (colors[COLORSEL_BLUE])  & 0xff00)));
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = gtk_color_selection_finalize;
+  gobject_class->set_property = gtk_color_selection_set_property;
+  gobject_class->get_property = gtk_color_selection_get_property;
 
-  gdk_pixbuf_fill (pixbuf, pixel);
+  object_class = GTK_OBJECT_CLASS (klass);
+  object_class->destroy = gtk_color_selection_destroy;
   
-  gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
-  g_object_unref (pixbuf);
-}
-
-static void
-color_sample_drag_begin (GtkWidget      *widget,
-			 GdkDragContext *context,
-			 gpointer        data)
-{
-  GtkColorSelection *colorsel = data;
-  ColorSelectionPrivate *priv;
-  gdouble *colsrc;
+  widget_class = GTK_WIDGET_CLASS (klass);
+  widget_class->realize = gtk_color_selection_realize;
+  widget_class->unrealize = gtk_color_selection_unrealize;
+  widget_class->show_all = gtk_color_selection_show_all;
+  widget_class->grab_broken_event = gtk_color_selection_grab_broken;
   
-  priv = colorsel->private_data;
+  g_object_class_install_property (gobject_class,
+                                   PROP_HAS_OPACITY_CONTROL,
+                                   g_param_spec_boolean ("has-opacity-control",
+							 P_("Has Opacity Control"),
+							 P_("Whether the color selector should allow setting opacity"),
+							 FALSE,
+							 GTK_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_HAS_PALETTE,
+                                   g_param_spec_boolean ("has-palette",
+							 P_("Has palette"),
+							 P_("Whether a palette should be used"),
+							 FALSE,
+							 GTK_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_CURRENT_COLOR,
+                                   g_param_spec_boxed ("current-color",
+                                                       P_("Current Color"),
+                                                       P_("The current color"),
+                                                       GDK_TYPE_COLOR,
+                                                       GTK_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_CURRENT_ALPHA,
+                                   g_param_spec_uint ("current-alpha",
+						      P_("Current Alpha"),
+						      P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
+						      0, 65535, 65535,
+						      GTK_PARAM_READWRITE));
   
-  if (widget == priv->old_sample)
-    colsrc = priv->old_color;
-  else
-    colsrc = priv->color;
+  color_selection_signals[COLOR_CHANGED] =
+    g_signal_new (I_("color_changed"),
+		  G_OBJECT_CLASS_TYPE (object_class),
+		  G_SIGNAL_RUN_FIRST,
+		  G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);
 
-  set_color_icon (context, colsrc);
-}
+  gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
+                                                      P_("Custom palette"),
+                                                      P_("Palette to use in the color selector"),
+                                                      default_colors,
+                                                      GTK_PARAM_READWRITE));
 
-static void
-color_sample_drag_end (GtkWidget      *widget,
-		       GdkDragContext *context,
-		       gpointer        data)
-{
-  g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
+   g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
 }
 
 static void
-color_sample_drop_handle (GtkWidget        *widget,
-			  GdkDragContext   *context,
-			  gint              x,
-			  gint              y,
-			  GtkSelectionData *selection_data,
-			  guint             info,
-			  guint             time,
-			  gpointer          data)
+gtk_color_selection_init (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel = data;
+  GtkWidget *top_hbox;
+  GtkWidget *top_right_vbox;
+  GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
+  GtkAdjustment *adjust;
+  GtkWidget *picker_image;
+  gint i, j;
   ColorSelectionPrivate *priv;
-  guint16 *vals;
-  gdouble color[4];
-  priv = colorsel->private_data;
-  
-  /* This is currently a guint16 array of the format:
-   * R
-   * G
-   * B
-   * opacity
-   */
-  
-  if (selection_data->length < 0)
-    return;
-  
-  /* We accept drops with the wrong format, since the KDE color
-   * chooser incorrectly drops application/x-color with format 8.
-   */
-  if (selection_data->length != 8)
-    {
-      g_warning ("Received invalid color data\n");
-      return;
-    }
-  
-  vals = (guint16 *)selection_data->data;
+  AtkObject *atk_obj;
+  GList *focus_chain = NULL;
   
-  if (widget == priv->cur_sample)
-    {
-      color[0] = (gdouble)vals[0] / 0xffff;
-      color[1] = (gdouble)vals[1] / 0xffff;
-      color[2] = (gdouble)vals[2] / 0xffff;
-      color[3] = (gdouble)vals[3] / 0xffff;
-      
-      set_color_internal (colorsel, color);
-    }
-}
+  gtk_widget_push_composite_child ();
 
-static void
-color_sample_drag_handle (GtkWidget        *widget,
-			  GdkDragContext   *context,
-			  GtkSelectionData *selection_data,
-			  guint             info,
-			  guint             time,
-			  gpointer          data)
-{
-  GtkColorSelection *colorsel = data;
-  ColorSelectionPrivate *priv;
-  guint16 vals[4];
-  gdouble *colsrc;
+  priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
+  priv->changing = FALSE;
+  priv->default_set = FALSE;
+  priv->default_alpha_set = FALSE;
   
-  priv = colorsel->private_data;
+  top_hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
   
-  if (widget == priv->old_sample)
-    colsrc = priv->old_color;
-  else
-    colsrc = priv->color;
+  vbox = gtk_vbox_new (FALSE, 6);
+  priv->triangle_colorsel = gtk_hsv_new ();
+  g_signal_connect (priv->triangle_colorsel, "changed",
+                    G_CALLBACK (hsv_changed), colorsel);
+  gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
+  gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
+  gtk_widget_set_tooltip_text (priv->triangle_colorsel,
+                        _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."));
   
-  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
-  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
-  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
-  vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
+  hbox = gtk_hbox_new (FALSE, 6);
+  gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
   
-  gtk_selection_data_set (selection_data,
-			  gdk_atom_intern_static_string ("application/x-color"),
-			  16, (guchar *)vals, 8);
-}
+  frame = gtk_frame_new (NULL);
+  gtk_widget_set_size_request (frame, -1, 30);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  color_sample_new (colorsel);
+  gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
+  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+  
+  button = gtk_button_new ();
 
-/* which = 0 means draw old sample, which = 1 means draw new */
-static void
-color_sample_draw_sample (GtkColorSelection *colorsel, int which)
-{
-  GtkWidget *da;
-  gint x, y, wid, heig, goff;
-  ColorSelectionPrivate *priv;
-  cairo_t *cr;
+  gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
+  g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel); 
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (get_screen_color), NULL);
+  picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
+  gtk_container_add (GTK_CONTAINER (button), picker_image);
+  gtk_widget_show (GTK_WIDGET (picker_image));
+  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  gtk_widget_set_tooltip_text (button,
+                        _("Click the eyedropper, then click a color anywhere on your screen to select that color."));
   
-  g_return_if_fail (colorsel != NULL);
-  priv = colorsel->private_data;
+  top_right_vbox = gtk_vbox_new (FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
+  table = gtk_table_new (8, 6, FALSE);
+  gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 12);
   
-  g_return_if_fail (priv->sample_area != NULL);
-  if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
-    return;
+  make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
+                         _("Position on the color wheel."));
+  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
+  make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
+                         _("\"Deepness\" of the color."));
+  make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
+                         _("Brightness of the color."));
+  make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
+                         _("Amount of red light in the color."));
+  make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
+                         _("Amount of green light in the color."));
+  make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
+                         _("Amount of blue light in the color."));
+  gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4); 
 
-  if (which == 0)
-    {
-      da = priv->old_sample;
-      goff = 0;
-    }
-  else
-    {
-      da = priv->cur_sample;
-      goff =  priv->old_sample->allocation.width % 32;
-    }
+  priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:")); 
+  gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5); 
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5); 
+  adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0)); 
+  g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel); 
+  priv->opacity_slider = gtk_hscale_new (adjust);
+  gtk_widget_set_tooltip_text (priv->opacity_slider,
+                        _("Transparency of the color."));
+  gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
+                                 priv->opacity_slider);
+  gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
+  g_signal_connect (adjust, "value_changed",
+                    G_CALLBACK (adjustment_changed),
+                    GINT_TO_POINTER (COLORSEL_OPACITY));
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5); 
+  priv->opacity_entry = gtk_entry_new (); 
+  gtk_widget_set_tooltip_text (priv->opacity_entry,
+                        _("Transparency of the color."));
+  gtk_widget_set_size_request (priv->opacity_entry, 40, -1); 
 
-  cr = gdk_cairo_create (da->window);
+  g_signal_connect (priv->opacity_entry, "activate",
+                    G_CALLBACK (opacity_entry_changed), colorsel);
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
   
-  wid = da->allocation.width;
-  heig = da->allocation.height;
+  label = gtk_label_new_with_mnemonic (_("Color _name:"));
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  priv->hex_entry = gtk_entry_new ();
 
-  /* Below needs tweaking for non-power-of-two */  
-#define CHECK_SIZE 16  
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
+
+  g_signal_connect (priv->hex_entry, "activate",
+                    G_CALLBACK (hex_changed), colorsel);
+
+  g_signal_connect (priv->hex_entry, "focus_out_event",
+                    G_CALLBACK (hex_focus_out), colorsel);
+
+  gtk_widget_set_tooltip_text (priv->hex_entry,
+                        _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."));
   
-  if (priv->has_opacity)
-    {
-      /* Draw checks in background */
+  gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
+  gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
 
-      cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
-      cairo_rectangle (cr, 0, 0, wid, heig);
-      cairo_fill (cr);
+  focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
+  focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
+  focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
+  focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
+  focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
+  focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
+  focus_chain = g_list_append (focus_chain, priv->opacity_slider);
+  focus_chain = g_list_append (focus_chain, priv->opacity_entry);
+  focus_chain = g_list_append (focus_chain, priv->hex_entry);
+  gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
+  g_list_free (focus_chain);
 
-      cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
-      for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
-	for (y = 0; y < heig; y += CHECK_SIZE)
-	  if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
-	    cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
-      cairo_fill (cr);
+  /* Set up the palette */
+  table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 1);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 1);
+  for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
+    {
+      for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
+	{
+	  make_palette_frame (colorsel, table, i, j);
+	}
     }
+  set_selected_palette (colorsel, 0, 0);
+  priv->palette_frame = gtk_vbox_new (FALSE, 6);
+  label = gtk_label_new_with_mnemonic (_("_Palette:"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
 
-  if (which == 0)
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label),
+                                 priv->custom_palette[0][0]);
+  
+  gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
+  
+  gtk_widget_show_all (top_hbox);
+
+  /* hide unused stuff */
+  
+  if (priv->has_opacity == FALSE)
     {
-      cairo_set_source_rgba (cr,
-			     priv->old_color[COLORSEL_RED], 
-			     priv->old_color[COLORSEL_GREEN], 
-			     priv->old_color[COLORSEL_BLUE],
-			     priv->has_opacity ?
-			        priv->old_color[COLORSEL_OPACITY] : 1.0);
+      gtk_widget_hide (priv->opacity_label);
+      gtk_widget_hide (priv->opacity_slider);
+      gtk_widget_hide (priv->opacity_entry);
     }
-  else
+  
+  if (priv->has_palette == FALSE)
     {
-      cairo_set_source_rgba (cr,
-			     priv->color[COLORSEL_RED], 
-			     priv->color[COLORSEL_GREEN], 
-			     priv->color[COLORSEL_BLUE],
-			     priv->has_opacity ?
-			       priv->color[COLORSEL_OPACITY] : 1.0);
+      gtk_widget_hide (priv->palette_frame);
     }
 
-  cairo_rectangle (cr, 0, 0, wid, heig);
-  cairo_fill (cr);
+  atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
+  if (GTK_IS_ACCESSIBLE (atk_obj))
+    {
+      atk_object_set_name (atk_obj, _("Color Wheel"));
+      atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
+      make_all_relations (atk_obj, priv);
+    } 
 
-  cairo_destroy (cr);
+  gtk_widget_pop_composite_child ();
 }
 
-
+/* GObject methods */
 static void
-color_sample_update_samples (GtkColorSelection *colorsel)
-{
-  ColorSelectionPrivate *priv = colorsel->private_data;
-  gtk_widget_queue_draw (priv->old_sample);
-  gtk_widget_queue_draw (priv->cur_sample);
-}
-
-static gboolean
-color_old_sample_expose (GtkWidget         *da,
-			 GdkEventExpose    *event,
-			 GtkColorSelection *colorsel)
+gtk_color_selection_finalize (GObject *object)
 {
-  color_sample_draw_sample (colorsel, 0);
-  return FALSE;
+  G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
 }
 
-
-static gboolean
-color_cur_sample_expose (GtkWidget         *da,
-			 GdkEventExpose    *event,
-			 GtkColorSelection *colorsel)
+static void
+gtk_color_selection_set_property (GObject         *object,
+				  guint            prop_id,
+				  const GValue    *value,
+				  GParamSpec      *pspec)
 {
-  color_sample_draw_sample (colorsel, 1);
-  return FALSE;
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
+  
+  switch (prop_id)
+    {
+    case PROP_HAS_OPACITY_CONTROL:
+      gtk_color_selection_set_has_opacity_control (colorsel, 
+						   g_value_get_boolean (value));
+      break;
+    case PROP_HAS_PALETTE:
+      gtk_color_selection_set_has_palette (colorsel, 
+					   g_value_get_boolean (value));
+      break;
+    case PROP_CURRENT_COLOR:
+      gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
+      break;
+    case PROP_CURRENT_ALPHA:
+      gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+  
 }
 
 static void
-color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
+gtk_color_selection_get_property (GObject     *object,
+				  guint        prop_id,
+				  GValue      *value,
+				  GParamSpec  *pspec)
 {
-  static const GtkTargetEntry targets[] = {
-    { "application/x-color", 0 }
-  };
-  ColorSelectionPrivate *priv;
-  priv = colorsel->private_data;
-  
-  gtk_drag_source_set (sample,
-		       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
-		       targets, 1,
-		       GDK_ACTION_COPY | GDK_ACTION_MOVE);
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
+  GdkColor color;
   
-  g_signal_connect (sample,
-		    "drag_begin",
-		    G_CALLBACK (color_sample_drag_begin),
-		    colorsel);
-  if (sample == priv->cur_sample)
+  switch (prop_id)
     {
-      
-      gtk_drag_dest_set (sample,
-			 GTK_DEST_DEFAULT_HIGHLIGHT |
-			 GTK_DEST_DEFAULT_MOTION |
-			 GTK_DEST_DEFAULT_DROP,
-			 targets, 1,
-			 GDK_ACTION_COPY);
-      
-      g_signal_connect (sample,
-			"drag_end",
-			G_CALLBACK (color_sample_drag_end),
-			colorsel);
+    case PROP_HAS_OPACITY_CONTROL:
+      g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
+      break;
+    case PROP_HAS_PALETTE:
+      g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
+      break;
+    case PROP_CURRENT_COLOR:
+      gtk_color_selection_get_current_color (colorsel, &color);
+      g_value_set_boxed (value, &color);
+      break;
+    case PROP_CURRENT_ALPHA:
+      g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
     }
-  
-  g_signal_connect (sample,
-		    "drag_data_get",
-		    G_CALLBACK (color_sample_drag_handle),
-		    colorsel);
-  g_signal_connect (sample,
-		    "drag_data_received",
-		    G_CALLBACK (color_sample_drop_handle),
-		    colorsel);
-  
 }
 
+/* GtkObject methods */
 
 static void
-color_sample_new (GtkColorSelection *colorsel)
+gtk_color_selection_destroy (GtkObject *object)
 {
-  ColorSelectionPrivate *priv;
-  
-  priv = colorsel->private_data;
-  
-  priv->sample_area = gtk_hbox_new (FALSE, 0);
-  priv->old_sample = gtk_drawing_area_new ();
-  priv->cur_sample = gtk_drawing_area_new ();
+  GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
+  ColorSelectionPrivate *priv = cselection->private_data;
 
-  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
-		      TRUE, TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
-		      TRUE, TRUE, 0);
-  
-  g_signal_connect (priv->old_sample, "expose_event",
-		    G_CALLBACK (color_old_sample_expose),
-		    colorsel);
-  g_signal_connect (priv->cur_sample, "expose_event",
-		    G_CALLBACK (color_cur_sample_expose),
-		    colorsel);
-  
-  color_sample_setup_dnd (colorsel, priv->old_sample);
-  color_sample_setup_dnd (colorsel, priv->cur_sample);
+  if (priv->dropper_grab_widget)
+    {
+      gtk_widget_destroy (priv->dropper_grab_widget);
+      priv->dropper_grab_widget = NULL;
+    }
 
-  gtk_widget_set_tooltip_text (priv->old_sample,
-                        _("The previously-selected color, for comparison to the color you're selecting now. You can drag this color to a palette entry, or select this color as current by dragging it to the other color swatch alongside."));
+  GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
+}
 
+/* GtkWidget methods */
 
-  gtk_widget_set_tooltip_text (priv->cur_sample,
-                        _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."));
-  
-  gtk_widget_show_all (priv->sample_area);
+static void
+gtk_color_selection_realize (GtkWidget *widget)
+{
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
+  ColorSelectionPrivate *priv = colorsel->private_data;
+  GtkSettings *settings = gtk_widget_get_settings (widget);
+
+  priv->settings_connection =  g_signal_connect (settings,
+						 "notify::gtk-color-palette",
+						 G_CALLBACK (palette_change_notify_instance),
+						 widget);
+  update_palette (colorsel);
+
+  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
+}
+
+static void
+gtk_color_selection_unrealize (GtkWidget *widget)
+{
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
+  ColorSelectionPrivate *priv = colorsel->private_data;
+  GtkSettings *settings = gtk_widget_get_settings (widget);
+
+  g_signal_handler_disconnect (settings, priv->settings_connection);
+
+  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
+}
+
+/* We override show-all since we have internal widgets that
+ * shouldn't be shown when you call show_all(), like the
+ * palette and opacity sliders.
+ */
+static void
+gtk_color_selection_show_all (GtkWidget *widget)
+{
+  gtk_widget_show (widget);
 }
 
+static gboolean 
+gtk_color_selection_grab_broken (GtkWidget          *widget,
+				 GdkEventGrabBroken *event)
+{
+  shutdown_eyedropper (widget);
+
+  return TRUE;
+}
 
 /*
  *
- * The palette area code
+ * The Sample Color
  *
  */
-#define CUSTOM_PALETTE_ENTRY_WIDTH   20
-#define CUSTOM_PALETTE_ENTRY_HEIGHT  20
+
+static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
+static void color_sample_update_samples (GtkColorSelection *colorsel);
 
 static void
-palette_get_color (GtkWidget *drawing_area, gdouble *color)
+set_color_internal (GtkColorSelection *colorsel,
+		    gdouble           *color)
 {
-  gdouble *color_val;
-  
-  g_return_if_fail (color != NULL);
+  ColorSelectionPrivate *priv;
+  gint i;
   
-  color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
-  if (color_val == NULL)
+  priv = colorsel->private_data;
+  priv->changing = TRUE;
+  priv->color[COLORSEL_RED] = color[0];
+  priv->color[COLORSEL_GREEN] = color[1];
+  priv->color[COLORSEL_BLUE] = color[2];
+  priv->color[COLORSEL_OPACITY] = color[3];
+  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+		  priv->color[COLORSEL_GREEN],
+		  priv->color[COLORSEL_BLUE],
+		  &priv->color[COLORSEL_HUE],
+		  &priv->color[COLORSEL_SATURATION],
+		  &priv->color[COLORSEL_VALUE]);
+  if (priv->default_set == FALSE)
     {
-      /* Default to white for no good reason */
-      color[0] = 1.0;
-      color[1] = 1.0;
-      color[2] = 1.0;
-      color[3] = 1.0;
-      return;
+      for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
+	priv->old_color[i] = priv->color[i];
     }
-  
-  color[0] = color_val[0];
-  color[1] = color_val[1];
-  color[2] = color_val[2];
-  color[3] = 1.0;
+  priv->default_set = TRUE;
+  priv->default_alpha_set = TRUE;
+  update_color (colorsel);
 }
 
-#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
 static void
-palette_paint (GtkWidget    *drawing_area,
-	       GdkRectangle *area,
-	       gpointer      data)
+set_color_icon (GdkDragContext *context,
+		gdouble        *colors)
 {
-  cairo_t *cr;
-  gint focus_width;
-    
-  if (drawing_area->window == NULL)
-    return;
-
-  cr = gdk_cairo_create (drawing_area->window);
+  GdkPixbuf *pixbuf;
+  guint32 pixel;
 
-  gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
-  gdk_cairo_rectangle (cr, area);
-  cairo_fill (cr);
-  
-  if (GTK_WIDGET_HAS_FOCUS (drawing_area))
-    {
-      set_focus_line_attributes (drawing_area, cr, &focus_width);
+  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
+			   8, 48, 32);
 
-      cairo_rectangle (cr,
-		       focus_width / 2., focus_width / 2.,
-		       drawing_area->allocation.width - focus_width,
-		       drawing_area->allocation.height - focus_width);
-      cairo_stroke (cr);
-    }
+  pixel = (((UNSCALE (colors[COLORSEL_RED])   & 0xff00) << 16) |
+	   ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
+	   ((UNSCALE (colors[COLORSEL_BLUE])  & 0xff00)));
 
-  cairo_destroy (cr);
+  gdk_pixbuf_fill (pixbuf, pixel);
+  
+  gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
+  g_object_unref (pixbuf);
 }
 
 static void
-set_focus_line_attributes (GtkWidget *drawing_area,
-			   cairo_t   *cr,
-			   gint      *focus_width)
+color_sample_drag_begin (GtkWidget      *widget,
+			 GdkDragContext *context,
+			 gpointer        data)
 {
-  gdouble color[4];
-  gint8 *dash_list;
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  gdouble *colsrc;
   
-  gtk_widget_style_get (drawing_area,
-			"focus-line-width", focus_width,
-			"focus-line-pattern", (gchar *)&dash_list,
-			NULL);
-      
-  palette_get_color (drawing_area, color);
-
-  if (INTENSITY (color[0], color[1], color[2]) > 0.5)
-    cairo_set_source_rgb (cr, 0., 0., 0.);
+  priv = colorsel->private_data;
+  
+  if (widget == priv->old_sample)
+    colsrc = priv->old_color;
   else
-    cairo_set_source_rgb (cr, 1., 1., 1.);
+    colsrc = priv->color;
 
-  cairo_set_line_width (cr, *focus_width);
+  set_color_icon (context, colsrc);
+}
 
-  if (dash_list[0])
-    {
-      gint n_dashes = strlen (dash_list);
-      gdouble *dashes = g_new (gdouble, n_dashes);
-      gdouble total_length = 0;
-      gdouble dash_offset;
-      gint i;
-
-      for (i = 0; i < n_dashes; i++)
-	{
-	  dashes[i] = dash_list[i];
-	  total_length += dash_list[i];
-	}
-
-      /* The dash offset here aligns the pattern to integer pixels
-       * by starting the dash at the right side of the left border
-       * Negative dash offsets in cairo don't work
-       * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
-       */
-      dash_offset = - *focus_width / 2.;
-      while (dash_offset < 0)
-	dash_offset += total_length;
-      
-      cairo_set_dash (cr, dashes, n_dashes, dash_offset);
-      g_free (dashes);
-    }
-
-  g_free (dash_list);
-}
+static void
+color_sample_drag_end (GtkWidget      *widget,
+		       GdkDragContext *context,
+		       gpointer        data)
+{
+  g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
+}
 
 static void
-palette_drag_begin (GtkWidget      *widget,
-		    GdkDragContext *context,
-		    gpointer        data)
+color_sample_drop_handle (GtkWidget        *widget,
+			  GdkDragContext   *context,
+			  gint              x,
+			  gint              y,
+			  GtkSelectionData *selection_data,
+			  guint             info,
+			  guint             time,
+			  gpointer          data)
 {
-  gdouble colors[4];
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
+  guint16 *vals;
+  gdouble color[4];
+  priv = colorsel->private_data;
   
-  palette_get_color (widget, colors);
-  set_color_icon (context, colors);
+  /* This is currently a guint16 array of the format:
+   * R
+   * G
+   * B
+   * opacity
+   */
+  
+  if (selection_data->length < 0)
+    return;
+  
+  /* We accept drops with the wrong format, since the KDE color
+   * chooser incorrectly drops application/x-color with format 8.
+   */
+  if (selection_data->length != 8)
+    {
+      g_warning ("Received invalid color data\n");
+      return;
+    }
+  
+  vals = (guint16 *)selection_data->data;
+  
+  if (widget == priv->cur_sample)
+    {
+      color[0] = (gdouble)vals[0] / 0xffff;
+      color[1] = (gdouble)vals[1] / 0xffff;
+      color[2] = (gdouble)vals[2] / 0xffff;
+      color[3] = (gdouble)vals[3] / 0xffff;
+      
+      set_color_internal (colorsel, color);
+    }
 }
 
 static void
-palette_drag_handle (GtkWidget        *widget,
-		     GdkDragContext   *context,
-		     GtkSelectionData *selection_data,
-		     guint             info,
-		     guint             time,
-		     gpointer          data)
+color_sample_drag_handle (GtkWidget        *widget,
+			  GdkDragContext   *context,
+			  GtkSelectionData *selection_data,
+			  guint             info,
+			  guint             time,
+			  gpointer          data)
 {
+  GtkColorSelection *colorsel = data;
+  ColorSelectionPrivate *priv;
   guint16 vals[4];
-  gdouble colsrc[4];
+  gdouble *colsrc;
   
-  palette_get_color (widget, colsrc);
+  priv = colorsel->private_data;
+  
+  if (widget == priv->old_sample)
+    colsrc = priv->old_color;
+  else
+    colsrc = priv->color;
   
   vals[0] = colsrc[COLORSEL_RED] * 0xffff;
   vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
   vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
-  vals[3] = 0xffff;
+  vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
   
   gtk_selection_data_set (selection_data,
 			  gdk_atom_intern_static_string ("application/x-color"),
 			  16, (guchar *)vals, 8);
 }
 
+/* which = 0 means draw old sample, which = 1 means draw new */
 static void
-palette_drag_end (GtkWidget      *widget,
-		  GdkDragContext *context,
-		  gpointer        data)
-{
-  g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
-}
-
-static GdkColor *
-get_current_colors (GtkColorSelection *colorsel)
+color_sample_draw_sample (GtkColorSelection *colorsel, int which)
 {
-  GtkSettings *settings;
-  GdkColor *colors = NULL;
-  gint n_colors = 0;
-  gchar *palette;
-
-  settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
-  g_object_get (settings,
-		"gtk-color-palette", &palette,
-		NULL);
+  GtkWidget *da;
+  gint x, y, wid, heig, goff;
+  ColorSelectionPrivate *priv;
+  cairo_t *cr;
   
-  if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
+  g_return_if_fail (colorsel != NULL);
+  priv = colorsel->private_data;
+  
+  g_return_if_fail (priv->sample_area != NULL);
+  if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
+    return;
+
+  if (which == 0)
     {
-      gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
+      da = priv->old_sample;
+      goff = 0;
     }
   else
     {
-      /* If there are less colors provided than the number of slots in the
-       * color selection, we fill in the rest from the defaults.
-       */
-      if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
-	{
-	  GdkColor *tmp_colors = colors;
-	  gint tmp_n_colors = n_colors;
-	  
-	  gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
-	  memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
-
-	  g_free (tmp_colors);
-	}
+      da = priv->cur_sample;
+      goff =  priv->old_sample->allocation.width % 32;
     }
 
-  g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
-  g_free (palette);
+  cr = gdk_cairo_create (da->window);
   
-  return colors;
-}
-
-/* Changes the model color */
-static void
-palette_change_color (GtkWidget         *drawing_area,
-                      GtkColorSelection *colorsel,
-                      gdouble           *color)
-{
-  gint x, y;
-  ColorSelectionPrivate *priv;
-  GdkColor gdk_color;
-  GdkColor *current_colors;
-  GdkScreen *screen;
+  wid = da->allocation.width;
+  heig = da->allocation.height;
 
-  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
-  g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
-  
-  priv = colorsel->private_data;
+  /* Below needs tweaking for non-power-of-two */  
   
-  gdk_color.red = UNSCALE (color[0]);
-  gdk_color.green = UNSCALE (color[1]);
-  gdk_color.blue = UNSCALE (color[2]);
-  gdk_color.pixel = 0;
-
-  x = 0;
-  y = 0;			/* Quiet GCC */
-  while (x < GTK_CUSTOM_PALETTE_WIDTH)
+  if (priv->has_opacity)
     {
-      y = 0;
-      while (y < GTK_CUSTOM_PALETTE_HEIGHT)
-        {
-          if (priv->custom_palette[x][y] == drawing_area)
-            goto out;
-          
-          ++y;
-        }
-
-      ++x;
-    }
+      /* Draw checks in background */
 
- out:
-  
-  g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
+      cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
+      cairo_rectangle (cr, 0, 0, wid, heig);
+      cairo_fill (cr);
 
-  current_colors = get_current_colors (colorsel);
-  current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
+      cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
+      for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE)
+	for (y = 0; y < heig; y += CHECK_SIZE)
+	  if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
+	    cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
+      cairo_fill (cr);
+    }
 
-  screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
-  if (change_palette_hook != default_change_palette_func)
-    (* change_palette_hook) (screen, current_colors, 
-			     GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
-  else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
+  if (which == 0)
     {
-      if (screen != gdk_screen_get_default ())
-	g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
-      (* noscreen_change_palette_hook) (current_colors, 
-					GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
+      cairo_set_source_rgba (cr,
+			     priv->old_color[COLORSEL_RED], 
+			     priv->old_color[COLORSEL_GREEN], 
+			     priv->old_color[COLORSEL_BLUE],
+			     priv->has_opacity ?
+			        priv->old_color[COLORSEL_OPACITY] : 1.0);
     }
   else
-    (* change_palette_hook) (screen, current_colors, 
-			     GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
+    {
+      cairo_set_source_rgba (cr,
+			     priv->color[COLORSEL_RED], 
+			     priv->color[COLORSEL_GREEN], 
+			     priv->color[COLORSEL_BLUE],
+			     priv->has_opacity ?
+			       priv->color[COLORSEL_OPACITY] : 1.0);
+    }
 
-  g_free (current_colors);
+  cairo_rectangle (cr, 0, 0, wid, heig);
+  cairo_fill (cr);
+
+  cairo_destroy (cr);
 }
 
-/* Changes the view color */
+
 static void
-palette_set_color (GtkWidget         *drawing_area,
-		   GtkColorSelection *colorsel,
-		   gdouble           *color)
+color_sample_update_samples (GtkColorSelection *colorsel)
 {
-  gdouble *new_color = g_new (double, 4);
-  GdkColor gdk_color;
-  
-  gdk_color.red = UNSCALE (color[0]);
-  gdk_color.green = UNSCALE (color[1]);
-  gdk_color.blue = UNSCALE (color[2]);
+  ColorSelectionPrivate *priv = colorsel->private_data;
+  gtk_widget_queue_draw (priv->old_sample);
+  gtk_widget_queue_draw (priv->cur_sample);
+}
 
-  gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
-  
-  if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
-    {
-      static const GtkTargetEntry targets[] = {
-	{ "application/x-color", 0 }
-      };
-      gtk_drag_source_set (drawing_area,
-			   GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
-			   targets, 1,
-			   GDK_ACTION_COPY | GDK_ACTION_MOVE);
-      
-      g_signal_connect (drawing_area,
-			"drag_begin",
-			G_CALLBACK (palette_drag_begin),
-			colorsel);
-      g_signal_connect (drawing_area,
-			"drag_data_get",
-			G_CALLBACK (palette_drag_handle),
-			colorsel);
-      
-      g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
-			 GINT_TO_POINTER (1));
-    }
-
-  new_color[0] = color[0];
-  new_color[1] = color[1];
-  new_color[2] = color[2];
-  new_color[3] = 1.0;
-  
-  g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
+static gboolean
+color_old_sample_expose (GtkWidget         *da,
+			 GdkEventExpose    *event,
+			 GtkColorSelection *colorsel)
+{
+  color_sample_draw_sample (colorsel, 0);
+  return FALSE;
 }
 
+
 static gboolean
-palette_expose (GtkWidget      *drawing_area,
-		GdkEventExpose *event,
-		gpointer        data)
+color_cur_sample_expose (GtkWidget         *da,
+			 GdkEventExpose    *event,
+			 GtkColorSelection *colorsel)
 {
-  if (drawing_area->window == NULL)
-    return FALSE;
-  
-  palette_paint (drawing_area, &(event->area), data);
-  
+  color_sample_draw_sample (colorsel, 1);
   return FALSE;
 }
 
 static void
-popup_position_func (GtkMenu   *menu,
-                     gint      *x,
-                     gint      *y,
-                     gboolean  *push_in,
-                     gpointer	user_data)
+color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
 {
-  GtkWidget *widget;
-  GtkRequisition req;      
-  gint root_x, root_y;
-  GdkScreen *screen;
+  static const GtkTargetEntry targets[] = {
+    { "application/x-color", 0 }
+  };
+  ColorSelectionPrivate *priv;
+  priv = colorsel->private_data;
   
-  widget = GTK_WIDGET (user_data);
+  gtk_drag_source_set (sample,
+		       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+		       targets, 1,
+		       GDK_ACTION_COPY | GDK_ACTION_MOVE);
   
-  g_return_if_fail (GTK_WIDGET_REALIZED (widget));
-
-  gdk_window_get_origin (widget->window, &root_x, &root_y);
+  g_signal_connect (sample,
+		    "drag_begin",
+		    G_CALLBACK (color_sample_drag_begin),
+		    colorsel);
+  if (sample == priv->cur_sample)
+    {
+      
+      gtk_drag_dest_set (sample,
+			 GTK_DEST_DEFAULT_HIGHLIGHT |
+			 GTK_DEST_DEFAULT_MOTION |
+			 GTK_DEST_DEFAULT_DROP,
+			 targets, 1,
+			 GDK_ACTION_COPY);
+      
+      g_signal_connect (sample,
+			"drag_end",
+			G_CALLBACK (color_sample_drag_end),
+			colorsel);
+    }
+  
+  g_signal_connect (sample,
+		    "drag_data_get",
+		    G_CALLBACK (color_sample_drag_handle),
+		    colorsel);
+  g_signal_connect (sample,
+		    "drag_data_received",
+		    G_CALLBACK (color_sample_drop_handle),
+		    colorsel);
   
-  gtk_widget_size_request (GTK_WIDGET (menu), &req);
-
-  /* Put corner of menu centered on color cell */
-  *x = root_x + widget->allocation.width / 2;
-  *y = root_y + widget->allocation.height / 2;
-
-  /* Ensure sanity */
-  screen = gtk_widget_get_screen (widget);
-  *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
-  *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
 }
 
+
 static void
-save_color_selected (GtkWidget *menuitem,
-                     gpointer   data)
+color_sample_new (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel;
-  GtkWidget *drawing_area;
   ColorSelectionPrivate *priv;
-
-  drawing_area = GTK_WIDGET (data);
   
-  colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
-                                                     "gtk-color-sel"));
-
   priv = colorsel->private_data;
   
-  palette_change_color (drawing_area, colorsel, priv->color);  
-}
+  priv->sample_area = gtk_hbox_new (FALSE, 0);
+  priv->old_sample = gtk_drawing_area_new ();
+  priv->cur_sample = gtk_drawing_area_new ();
 
-static void
-do_popup (GtkColorSelection *colorsel,
-          GtkWidget         *drawing_area,
-          guint32            timestamp)
-{
-  GtkWidget *menu;
-  GtkWidget *mi;
+  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
+		      TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
+		      TRUE, TRUE, 0);
   
-  g_object_set_data (G_OBJECT (drawing_area),
-                     I_("gtk-color-sel"),
-                     colorsel);
+  g_signal_connect (priv->old_sample, "expose_event",
+		    G_CALLBACK (color_old_sample_expose),
+		    colorsel);
+  g_signal_connect (priv->cur_sample, "expose_event",
+		    G_CALLBACK (color_cur_sample_expose),
+		    colorsel);
   
-  menu = gtk_menu_new ();
-
-  mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
+  color_sample_setup_dnd (colorsel, priv->old_sample);
+  color_sample_setup_dnd (colorsel, priv->cur_sample);
 
-  g_signal_connect (mi, "activate",
-                    G_CALLBACK (save_color_selected),
-                    drawing_area);
-  
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+  gtk_widget_set_tooltip_text (priv->old_sample,
+                        _("The previously-selected color, for comparison to the color you're selecting now. You can drag this color to a palette entry, or select this color as current by dragging it to the other color swatch alongside."));
 
-  gtk_widget_show_all (mi);
 
-  gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
-                  popup_position_func, drawing_area,
-                  3, timestamp);
+  gtk_widget_set_tooltip_text (priv->cur_sample,
+                        _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."));
+  
+  gtk_widget_show_all (priv->sample_area);
 }
 
 
-static gboolean
-palette_enter (GtkWidget        *drawing_area,
-	       GdkEventCrossing *event,
-	       gpointer        data)
-{
-  g_object_set_data (G_OBJECT (drawing_area),
-		     I_("gtk-colorsel-have-pointer"),
-		     GUINT_TO_POINTER (TRUE));
-
-  return FALSE;
-}
+/*
+ *
+ * The palette area code
+ *
+ */
 
-static gboolean
-palette_leave (GtkWidget        *drawing_area,
-	       GdkEventCrossing *event,
-	       gpointer        data)
+static void
+palette_get_color (GtkWidget *drawing_area, gdouble *color)
 {
-  g_object_set_data (G_OBJECT (drawing_area),
-		     I_("gtk-colorsel-have-pointer"),
-		     NULL);
-
-  return FALSE;
+  gdouble *color_val;
+  
+  g_return_if_fail (color != NULL);
+  
+  color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
+  if (color_val == NULL)
+    {
+      /* Default to white for no good reason */
+      color[0] = 1.0;
+      color[1] = 1.0;
+      color[2] = 1.0;
+      color[3] = 1.0;
+      return;
+    }
+  
+  color[0] = color_val[0];
+  color[1] = color_val[1];
+  color[2] = color_val[2];
+  color[3] = 1.0;
 }
 
-static gboolean
-palette_press (GtkWidget      *drawing_area,
-	       GdkEventButton *event,
-	       gpointer        data)
+static void
+palette_paint (GtkWidget    *drawing_area,
+	       GdkRectangle *area,
+	       gpointer      data)
 {
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
+  cairo_t *cr;
+  gint focus_width;
+    
+  if (drawing_area->window == NULL)
+    return;
 
-  gtk_widget_grab_focus (drawing_area);
+  cr = gdk_cairo_create (drawing_area->window);
+
+  gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]);
+  gdk_cairo_rectangle (cr, area);
+  cairo_fill (cr);
   
-  if (event->button == 3 &&
-      event->type == GDK_BUTTON_PRESS)
+  if (GTK_WIDGET_HAS_FOCUS (drawing_area))
     {
-      do_popup (colorsel, drawing_area, event->time);
-      return TRUE;
+      set_focus_line_attributes (drawing_area, cr, &focus_width);
+
+      cairo_rectangle (cr,
+		       focus_width / 2., focus_width / 2.,
+		       drawing_area->allocation.width - focus_width,
+		       drawing_area->allocation.height - focus_width);
+      cairo_stroke (cr);
     }
 
-  return FALSE;
+  cairo_destroy (cr);
 }
 
-static gboolean
-palette_release (GtkWidget      *drawing_area,
-		 GdkEventButton *event,
-		 gpointer        data)
+static void
+set_focus_line_attributes (GtkWidget *drawing_area,
+			   cairo_t   *cr,
+			   gint      *focus_width)
 {
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
-
-  gtk_widget_grab_focus (drawing_area);
-
-  if (event->button == 1 &&
-      g_object_get_data (G_OBJECT (drawing_area),
-			 "gtk-colorsel-have-pointer") != NULL)
+  gdouble color[4];
+  gint8 *dash_list;
+  
+  gtk_widget_style_get (drawing_area,
+			"focus-line-width", focus_width,
+			"focus-line-pattern", (gchar *)&dash_list,
+			NULL);
+      
+  palette_get_color (drawing_area, color);
+
+  if (INTENSITY (color[0], color[1], color[2]) > 0.5)
+    cairo_set_source_rgb (cr, 0., 0., 0.);
+  else
+    cairo_set_source_rgb (cr, 1., 1., 1.);
+
+  cairo_set_line_width (cr, *focus_width);
+
+  if (dash_list[0])
     {
-      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
-        {
-          gdouble color[4];
-          palette_get_color (drawing_area, color);
-          set_color_internal (colorsel, color);
-        }
+      gint n_dashes = strlen (dash_list);
+      gdouble *dashes = g_new (gdouble, n_dashes);
+      gdouble total_length = 0;
+      gdouble dash_offset;
+      gint i;
+
+      for (i = 0; i < n_dashes; i++)
+	{
+	  dashes[i] = dash_list[i];
+	  total_length += dash_list[i];
+	}
+
+      /* The dash offset here aligns the pattern to integer pixels
+       * by starting the dash at the right side of the left border
+       * Negative dash offsets in cairo don't work
+       * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
+       */
+      dash_offset = - *focus_width / 2.;
+      while (dash_offset < 0)
+	dash_offset += total_length;
+      
+      cairo_set_dash (cr, dashes, n_dashes, dash_offset);
+      g_free (dashes);
     }
 
-  return FALSE;
+  g_free (dash_list);
 }
 
 static void
-palette_drop_handle (GtkWidget        *widget,
+palette_drag_begin (GtkWidget      *widget,
+		    GdkDragContext *context,
+		    gpointer        data)
+{
+  gdouble colors[4];
+  
+  palette_get_color (widget, colors);
+  set_color_icon (context, colors);
+}
+
+static void
+palette_drag_handle (GtkWidget        *widget,
 		     GdkDragContext   *context,
-		     gint              x,
-		     gint              y,
 		     GtkSelectionData *selection_data,
 		     guint             info,
 		     guint             time,
 		     gpointer          data)
 {
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
-  guint16 *vals;
-  gdouble color[4];
-  
-  if (selection_data->length < 0)
-    return;
+  guint16 vals[4];
+  gdouble colsrc[4];
   
-  /* We accept drops with the wrong format, since the KDE color
-   * chooser incorrectly drops application/x-color with format 8.
-   */
-  if (selection_data->length != 8)
-    {
-      g_warning ("Received invalid color data\n");
-      return;
-    }
+  palette_get_color (widget, colsrc);
   
-  vals = (guint16 *)selection_data->data;
+  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
+  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
+  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
+  vals[3] = 0xffff;
   
-  color[0] = (gdouble)vals[0] / 0xffff;
-  color[1] = (gdouble)vals[1] / 0xffff;
-  color[2] = (gdouble)vals[2] / 0xffff;
-  color[3] = (gdouble)vals[3] / 0xffff;
-  palette_change_color (widget, colorsel, color);
-  set_color_internal (colorsel, color);
+  gtk_selection_data_set (selection_data,
+			  gdk_atom_intern_static_string ("application/x-color"),
+			  16, (guchar *)vals, 8);
 }
 
-static gint
-palette_activate (GtkWidget   *widget,
-		  GdkEventKey *event,
-		  gpointer     data)
+static void
+palette_drag_end (GtkWidget      *widget,
+		  GdkDragContext *context,
+		  gpointer        data)
 {
-  /* should have a drawing area subclass with an activate signal */
-  if ((event->keyval == GDK_space) ||
-      (event->keyval == GDK_Return) ||
-      (event->keyval == GDK_ISO_Enter) ||
-      (event->keyval == GDK_KP_Enter) ||
-      (event->keyval == GDK_KP_Space))
-    {
-      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
-        {
-          gdouble color[4];
-          palette_get_color (widget, color);
-          set_color_internal (GTK_COLOR_SELECTION (data), color);
-        }
-      return TRUE;
-    }
-  
-  return FALSE;
+  g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
 }
 
-static gboolean
-palette_popup (GtkWidget *widget,
-               gpointer   data)
+static GdkColor *
+get_current_colors (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
+  GtkSettings *settings;
+  GdkColor *colors = NULL;
+  gint n_colors = 0;
+  gchar *palette;
 
-  do_popup (colorsel, widget, GDK_CURRENT_TIME);
-  return TRUE;
+  settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
+  g_object_get (settings,
+		"gtk-color-palette", &palette,
+		NULL);
+  
+  if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors))
+    {
+      gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
+    }
+  else
+    {
+      /* If there are less colors provided than the number of slots in the
+       * color selection, we fill in the rest from the defaults.
+       */
+      if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT))
+	{
+	  GdkColor *tmp_colors = colors;
+	  gint tmp_n_colors = n_colors;
+	  
+	  gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors);
+	  memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors);
+
+	  g_free (tmp_colors);
+	}
+    }
+
+  g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
+  g_free (palette);
+  
+  return colors;
 }
-               
 
-static GtkWidget*
-palette_new (GtkColorSelection *colorsel)
+/* Changes the model color */
+static void
+palette_change_color (GtkWidget         *drawing_area,
+                      GtkColorSelection *colorsel,
+                      gdouble           *color)
 {
-  GtkWidget *retval;
+  gint x, y;
   ColorSelectionPrivate *priv;
-  
-  static const GtkTargetEntry targets[] = {
-    { "application/x-color", 0 }
-  };
+  GdkColor gdk_color;
+  GdkColor *current_colors;
+  GdkScreen *screen;
 
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+  g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
+  
   priv = colorsel->private_data;
   
-  retval = gtk_drawing_area_new ();
+  gdk_color.red = UNSCALE (color[0]);
+  gdk_color.green = UNSCALE (color[1]);
+  gdk_color.blue = UNSCALE (color[2]);
+  gdk_color.pixel = 0;
 
-  GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
-  
-  g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0)); 
-  gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
-                         | GDK_BUTTON_RELEASE_MASK
-                         | GDK_EXPOSURE_MASK
-                         | GDK_ENTER_NOTIFY_MASK
-                         | GDK_LEAVE_NOTIFY_MASK);
-  
-  g_signal_connect (retval, "expose_event",
-		    G_CALLBACK (palette_expose), colorsel);
-  g_signal_connect (retval, "button_press_event",
-		    G_CALLBACK (palette_press), colorsel);
-  g_signal_connect (retval, "button_release_event",
-		    G_CALLBACK (palette_release), colorsel);
-  g_signal_connect (retval, "enter_notify_event",
-		    G_CALLBACK (palette_enter), colorsel);
-  g_signal_connect (retval, "leave_notify_event",
-		    G_CALLBACK (palette_leave), colorsel);
-  g_signal_connect (retval, "key_press_event",
-		    G_CALLBACK (palette_activate), colorsel);
-  g_signal_connect (retval, "popup_menu",
-		    G_CALLBACK (palette_popup), colorsel);
-  
-  gtk_drag_dest_set (retval,
-		     GTK_DEST_DEFAULT_HIGHLIGHT |
-		     GTK_DEST_DEFAULT_MOTION |
-		     GTK_DEST_DEFAULT_DROP,
-		     targets, 1,
-		     GDK_ACTION_COPY);
-  
-  g_signal_connect (retval, "drag_end",
-                    G_CALLBACK (palette_drag_end), NULL);
-  g_signal_connect (retval, "drag_data_received",
-                    G_CALLBACK (palette_drop_handle), colorsel);
+  x = 0;
+  y = 0;			/* Quiet GCC */
+  while (x < GTK_CUSTOM_PALETTE_WIDTH)
+    {
+      y = 0;
+      while (y < GTK_CUSTOM_PALETTE_HEIGHT)
+        {
+          if (priv->custom_palette[x][y] == drawing_area)
+            goto out;
+          
+          ++y;
+        }
 
-  gtk_widget_set_tooltip_text (retval,
-                        _("Click this palette entry to make it the current color. To change this entry, drag a color swatch here or right-click it and select \"Save color here.\""));
-  return retval;
-}
+      ++x;
+    }
 
+ out:
+  
+  g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);
 
-/*
- *
- * The actual GtkColorSelection widget
- *
- */
+  current_colors = get_current_colors (colorsel);
+  current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;
 
-static GdkCursor *
-make_picker_cursor (GdkScreen *screen)
-{
-  GdkCursor *cursor;
+  screen = gtk_widget_get_screen (GTK_WIDGET (colorsel));
+  if (change_palette_hook != default_change_palette_func)
+    (* change_palette_hook) (screen, current_colors, 
+			     GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
+  else if (noscreen_change_palette_hook != default_noscreen_change_palette_func)
+    {
+      if (screen != gdk_screen_get_default ())
+	g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen.");
+      (* noscreen_change_palette_hook) (current_colors, 
+					GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
+    }
+  else
+    (* change_palette_hook) (screen, current_colors, 
+			     GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT);
 
-  cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
-				     "color-picker");
+  g_free (current_colors);
+}
 
-  if (!cursor)
-    {
-      GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
-      GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
-      GdkWindow *window;
-      GdkPixmap *pixmap, *mask;
+/* Changes the view color */
+static void
+palette_set_color (GtkWidget         *drawing_area,
+		   GtkColorSelection *colorsel,
+		   gdouble           *color)
+{
+  gdouble *new_color = g_new (double, 4);
+  GdkColor gdk_color;
+  
+  gdk_color.red = UNSCALE (color[0]);
+  gdk_color.green = UNSCALE (color[1]);
+  gdk_color.blue = UNSCALE (color[2]);
 
-      window = gdk_screen_get_root_window (screen);
-      
-      pixmap =
-	gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
-				     DROPPER_WIDTH, DROPPER_HEIGHT);
-      
-      mask =
-	gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
-				     DROPPER_WIDTH, DROPPER_HEIGHT);
+  gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
+  
+  if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
+    {
+      static const GtkTargetEntry targets[] = {
+	{ "application/x-color", 0 }
+      };
+      gtk_drag_source_set (drawing_area,
+			   GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+			   targets, 1,
+			   GDK_ACTION_COPY | GDK_ACTION_MOVE);
       
-      cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
-					   DROPPER_X_HOT, DROPPER_Y_HOT);
+      g_signal_connect (drawing_area,
+			"drag_begin",
+			G_CALLBACK (palette_drag_begin),
+			colorsel);
+      g_signal_connect (drawing_area,
+			"drag_data_get",
+			G_CALLBACK (palette_drag_handle),
+			colorsel);
       
-      g_object_unref (pixmap);
-      g_object_unref (mask);
+      g_object_set_data (G_OBJECT (drawing_area), I_("color_set"),
+			 GINT_TO_POINTER (1));
     }
-      
-  return cursor;
+
+  new_color[0] = color[0];
+  new_color[1] = color[1];
+  new_color[2] = color[2];
+  new_color[3] = 1.0;
+  
+  g_object_set_data_full (G_OBJECT (drawing_area), I_("color_val"), new_color, (GDestroyNotify)g_free);
 }
 
-static void
-grab_color_at_mouse (GdkScreen *screen,
-		     gint       x_root,
-		     gint       y_root,
-		     gpointer   data)
+static gboolean
+palette_expose (GtkWidget      *drawing_area,
+		GdkEventExpose *event,
+		gpointer        data)
 {
-  GdkImage *image;
-  guint32 pixel;
-  GtkColorSelection *colorsel = data;
-  ColorSelectionPrivate *priv;
-  GdkColor color;
-  GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
-  GdkWindow *root_window = gdk_screen_get_root_window (screen);
+  if (drawing_area->window == NULL)
+    return FALSE;
   
-  priv = colorsel->private_data;
+  palette_paint (drawing_area, &(event->area), data);
   
-  image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
-  if (!image)
-    {
-      gint x, y;
-      GdkDisplay *display = gdk_screen_get_display (screen);
-      GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y);
-      if (!window)
-	return;
-      image = gdk_drawable_get_image (window, x, y, 1, 1);
-      if (!image)
-	return;
-    }
-  pixel = gdk_image_get_pixel (image, 0, 0);
-  g_object_unref (image);
+  return FALSE;
+}
 
-  gdk_colormap_query_color (colormap, pixel, &color);
+static void
+popup_position_func (GtkMenu   *menu,
+                     gint      *x,
+                     gint      *y,
+                     gboolean  *push_in,
+                     gpointer	user_data)
+{
+  GtkWidget *widget;
+  GtkRequisition req;      
+  gint root_x, root_y;
+  GdkScreen *screen;
   
-  priv->color[COLORSEL_RED] = SCALE (color.red);
-  priv->color[COLORSEL_GREEN] = SCALE (color.green);
-  priv->color[COLORSEL_BLUE] = SCALE (color.blue);
+  widget = GTK_WIDGET (user_data);
   
-  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
-		  priv->color[COLORSEL_GREEN],
-		  priv->color[COLORSEL_BLUE],
-		  &priv->color[COLORSEL_HUE],
-		  &priv->color[COLORSEL_SATURATION],
-		  &priv->color[COLORSEL_VALUE]);
+  g_return_if_fail (GTK_WIDGET_REALIZED (widget));
 
-  update_color (colorsel);
+  gdk_window_get_origin (widget->window, &root_x, &root_y);
+  
+  gtk_widget_size_request (GTK_WIDGET (menu), &req);
+
+  /* Put corner of menu centered on color cell */
+  *x = root_x + widget->allocation.width / 2;
+  *y = root_y + widget->allocation.height / 2;
+
+  /* Ensure sanity */
+  screen = gtk_widget_get_screen (widget);
+  *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
+  *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
 }
 
 static void
-shutdown_eyedropper (GtkWidget *widget)
+save_color_selected (GtkWidget *menuitem,
+                     gpointer   data)
 {
   GtkColorSelection *colorsel;
+  GtkWidget *drawing_area;
   ColorSelectionPrivate *priv;
-  GdkDisplay *display = gtk_widget_get_display (widget);
 
-  colorsel = GTK_COLOR_SELECTION (widget);
-  priv = colorsel->private_data;    
-
-  if (priv->has_grab)
-    {
-      gdk_display_keyboard_ungrab (display, priv->grab_time);
-      gdk_display_pointer_ungrab (display, priv->grab_time);
-      gtk_grab_remove (priv->dropper_grab_widget);
+  drawing_area = GTK_WIDGET (data);
+  
+  colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area),
+                                                     "gtk-color-sel"));
 
-      priv->has_grab = FALSE;
-    }
+  priv = colorsel->private_data;
+  
+  palette_change_color (drawing_area, colorsel, priv->color);  
 }
 
-static gboolean 
-gtk_color_selection_grab_broken (GtkWidget          *widget,
-				 GdkEventGrabBroken *event)
+static void
+do_popup (GtkColorSelection *colorsel,
+          GtkWidget         *drawing_area,
+          guint32            timestamp)
 {
-  shutdown_eyedropper (widget);
+  GtkWidget *menu;
+  GtkWidget *mi;
+  
+  g_object_set_data (G_OBJECT (drawing_area),
+                     I_("gtk-color-sel"),
+                     colorsel);
+  
+  menu = gtk_menu_new ();
 
-  return TRUE;
+  mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
+
+  g_signal_connect (mi, "activate",
+                    G_CALLBACK (save_color_selected),
+                    drawing_area);
+  
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+
+  gtk_widget_show_all (mi);
+
+  gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+                  popup_position_func, drawing_area,
+                  3, timestamp);
 }
 
-static void
-mouse_motion (GtkWidget      *invisible,
-	      GdkEventMotion *event,
-	      gpointer        data)
+
+static gboolean
+palette_enter (GtkWidget        *drawing_area,
+	       GdkEventCrossing *event,
+	       gpointer        data)
 {
-  grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
-		       event->x_root, event->y_root, data); 
+  g_object_set_data (G_OBJECT (drawing_area),
+		     I_("gtk-colorsel-have-pointer"),
+		     GUINT_TO_POINTER (TRUE));
+
+  return FALSE;
 }
 
 static gboolean
-mouse_release (GtkWidget      *invisible,
-	       GdkEventButton *event,
+palette_leave (GtkWidget        *drawing_area,
+	       GdkEventCrossing *event,
 	       gpointer        data)
 {
-  /* GtkColorSelection *colorsel = data; */
+  g_object_set_data (G_OBJECT (drawing_area),
+		     I_("gtk-colorsel-have-pointer"),
+		     NULL);
 
-  if (event->button != 1)
-    return FALSE;
+  return FALSE;
+}
 
-  grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
-		       event->x_root, event->y_root, data);
+static gboolean
+palette_press (GtkWidget      *drawing_area,
+	       GdkEventButton *event,
+	       gpointer        data)
+{
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
 
-  shutdown_eyedropper (GTK_WIDGET (data));
+  gtk_widget_grab_focus (drawing_area);
   
-  g_signal_handlers_disconnect_by_func (invisible,
-					mouse_motion,
-					data);
-  g_signal_handlers_disconnect_by_func (invisible,
-					mouse_release,
-					data);
+  if (event->button == 3 &&
+      event->type == GDK_BUTTON_PRESS)
+    {
+      do_popup (colorsel, drawing_area, event->time);
+      return TRUE;
+    }
 
-  return TRUE;
+  return FALSE;
 }
 
-/* Helper Functions */
-
-static gboolean mouse_press (GtkWidget      *invisible,
-                             GdkEventButton *event,
-                             gpointer        data);
-
-#define BIG_STEP 20
-
 static gboolean
-key_press (GtkWidget   *invisible,
-           GdkEventKey *event,
-           gpointer     data)
-{  
-  GdkDisplay *display = gtk_widget_get_display (invisible);
-  GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
-  guint state = event->state & gtk_accelerator_get_default_mod_mask ();
-  gint x, y;
-  gint dx, dy;
-
-  gdk_display_get_pointer (display, NULL, &x, &y, NULL);
-
-  dx = 0;
-  dy = 0;
-
-  switch (event->keyval) 
-    {
-    case GDK_space:
-    case GDK_Return:
-    case GDK_ISO_Enter:
-    case GDK_KP_Enter:
-    case GDK_KP_Space:
-      grab_color_at_mouse (screen, x, y, data);
-      /* fall through */
-
-    case GDK_Escape:
-      shutdown_eyedropper (data);
-      
-      g_signal_handlers_disconnect_by_func (invisible,
-					    mouse_press,
-					    data);
-      g_signal_handlers_disconnect_by_func (invisible,
-					    key_press,
-					    data);
-      
-      return TRUE;
-
-#if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
-    case GDK_Up:
-    case GDK_KP_Up:
-      dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
-      break;
-
-    case GDK_Down:
-    case GDK_KP_Down:
-      dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
-      break;
-
-    case GDK_Left:
-    case GDK_KP_Left:
-      dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
-      break;
-
-    case GDK_Right:
-    case GDK_KP_Right:
-      dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
-      break;
-#endif
-
-    default:
-      return FALSE;
-    }
-
-  gdk_display_warp_pointer (display, screen, x + dx, y + dy);
-  
-  return TRUE;
+palette_release (GtkWidget      *drawing_area,
+		 GdkEventButton *event,
+		 gpointer        data)
+{
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
 
-}
+  gtk_widget_grab_focus (drawing_area);
 
-static gboolean
-mouse_press (GtkWidget      *invisible,
-	     GdkEventButton *event,
-	     gpointer        data)
-{
-  /* GtkColorSelection *colorsel = data; */
-  
-  if (event->type == GDK_BUTTON_PRESS &&
-      event->button == 1)
+  if (event->button == 1 &&
+      g_object_get_data (G_OBJECT (drawing_area),
+			 "gtk-colorsel-have-pointer") != NULL)
     {
-      g_signal_connect (invisible, "motion_notify_event",
-                        G_CALLBACK (mouse_motion),
-                        data);
-      g_signal_connect (invisible, "button_release_event",
-                        G_CALLBACK (mouse_release),
-                        data);
-      g_signal_handlers_disconnect_by_func (invisible,
-					    mouse_press,
-					    data);
-      g_signal_handlers_disconnect_by_func (invisible,
-					    key_press,
-					    data);
-      return TRUE;
+      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
+        {
+          gdouble color[4];
+          palette_get_color (drawing_area, color);
+          set_color_internal (colorsel, color);
+        }
     }
 
   return FALSE;
 }
 
-/* when the button is clicked */
 static void
-get_screen_color (GtkWidget *button)
+palette_drop_handle (GtkWidget        *widget,
+		     GdkDragContext   *context,
+		     gint              x,
+		     gint              y,
+		     GtkSelectionData *selection_data,
+		     guint             info,
+		     guint             time,
+		     gpointer          data)
 {
-  GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
-  ColorSelectionPrivate *priv = colorsel->private_data;
-  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
-  GdkCursor *picker_cursor;
-  GdkGrabStatus grab_status;
-  GtkWidget *grab_widget, *toplevel;
-
-  guint32 time = gtk_get_current_event_time ();
-  
-  if (priv->dropper_grab_widget == NULL)
-    {
-      grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
-      gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
-      gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
-      gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
-      gtk_widget_show (grab_widget);
-
-      gtk_widget_add_events (grab_widget,
-                             GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
-      
-      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
+  guint16 *vals;
+  gdouble color[4];
   
-      if (GTK_IS_WINDOW (toplevel))
-	{
-	  if (GTK_WINDOW (toplevel)->group)
-	    gtk_window_group_add_window (GTK_WINDOW (toplevel)->group, 
-					 GTK_WINDOW (grab_widget));
-	}
-
-      priv->dropper_grab_widget = grab_widget;
-    }
-
-  if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
-                         FALSE, time) != GDK_GRAB_SUCCESS)
+  if (selection_data->length < 0)
     return;
   
-  picker_cursor = make_picker_cursor (screen);
-  grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
-				  FALSE,
-				  GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
-				  NULL,
-				  picker_cursor,
-				  time);
-  gdk_cursor_unref (picker_cursor);
-  
-  if (grab_status != GDK_GRAB_SUCCESS)
+  /* We accept drops with the wrong format, since the KDE color
+   * chooser incorrectly drops application/x-color with format 8.
+   */
+  if (selection_data->length != 8)
     {
-      gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
+      g_warning ("Received invalid color data\n");
       return;
     }
-
-  gtk_grab_add (priv->dropper_grab_widget);
-  priv->grab_time = time;
-  priv->has_grab = TRUE;
   
-  g_signal_connect (priv->dropper_grab_widget, "button_press_event",
-                    G_CALLBACK (mouse_press), colorsel);
-  g_signal_connect (priv->dropper_grab_widget, "key_press_event",
-                    G_CALLBACK (key_press), colorsel);
+  vals = (guint16 *)selection_data->data;
+  
+  color[0] = (gdouble)vals[0] / 0xffff;
+  color[1] = (gdouble)vals[1] / 0xffff;
+  color[2] = (gdouble)vals[2] / 0xffff;
+  color[3] = (gdouble)vals[3] / 0xffff;
+  palette_change_color (widget, colorsel, color);
+  set_color_internal (colorsel, color);
 }
 
-static void
-hex_changed (GtkWidget *hex_entry,
-	     gpointer   data)
+static gint
+palette_activate (GtkWidget   *widget,
+		  GdkEventKey *event,
+		  gpointer     data)
 {
-  GtkColorSelection *colorsel;
-  ColorSelectionPrivate *priv;
-  GdkColor color;
-  gchar *text;
-  
-  colorsel = GTK_COLOR_SELECTION (data);
-  priv = colorsel->private_data;
-  
-  if (priv->changing)
-    return;
-  
-  text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
-  if (gdk_color_parse (text, &color))
+  /* should have a drawing area subclass with an activate signal */
+  if ((event->keyval == GDK_space) ||
+      (event->keyval == GDK_Return) ||
+      (event->keyval == GDK_ISO_Enter) ||
+      (event->keyval == GDK_KP_Enter) ||
+      (event->keyval == GDK_KP_Space))
     {
-      priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
-      priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
-      priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
-      gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
-		      priv->color[COLORSEL_GREEN],
-		      priv->color[COLORSEL_BLUE],
-		      &priv->color[COLORSEL_HUE],
-		      &priv->color[COLORSEL_SATURATION],
-		      &priv->color[COLORSEL_VALUE]);
-      update_color (colorsel);
+      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
+        {
+          gdouble color[4];
+          palette_get_color (widget, color);
+          set_color_internal (GTK_COLOR_SELECTION (data), color);
+        }
+      return TRUE;
     }
-  g_free (text);
+  
+  return FALSE;
 }
 
 static gboolean
-hex_focus_out (GtkWidget     *hex_entry, 
-	       GdkEventFocus *event,
-	       gpointer       data)
+palette_popup (GtkWidget *widget,
+               gpointer   data)
 {
-  hex_changed (hex_entry, data);
-  
-  return FALSE;
+  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
+
+  do_popup (colorsel, widget, GDK_CURRENT_TIME);
+  return TRUE;
 }
+               
 
-static void
-hsv_changed (GtkWidget *hsv,
-	     gpointer   data)
+static GtkWidget*
+palette_new (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel;
+  GtkWidget *retval;
   ColorSelectionPrivate *priv;
   
-  colorsel = GTK_COLOR_SELECTION (data);
-  priv = colorsel->private_data;
-  
-  if (priv->changing)
-    return;
+  static const GtkTargetEntry targets[] = {
+    { "application/x-color", 0 }
+  };
+
+  priv = colorsel->private_data;
   
-  gtk_hsv_get_color (GTK_HSV (hsv),
-		     &priv->color[COLORSEL_HUE],
-		     &priv->color[COLORSEL_SATURATION],
-		     &priv->color[COLORSEL_VALUE]);
-  gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
-		  priv->color[COLORSEL_SATURATION],
-		  priv->color[COLORSEL_VALUE],
-		  &priv->color[COLORSEL_RED],
-		  &priv->color[COLORSEL_GREEN],
-		  &priv->color[COLORSEL_BLUE]);
-  update_color (colorsel);
-}
+  retval = gtk_drawing_area_new ();
 
-static void
-adjustment_changed (GtkAdjustment *adjustment,
-		    gpointer       data)
-{
-  GtkColorSelection *colorsel;
-  ColorSelectionPrivate *priv;
+  GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
   
-  colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
-  priv = colorsel->private_data;
+  g_object_set_data (G_OBJECT (retval), I_("color_set"), GINT_TO_POINTER (0)); 
+  gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
+                         | GDK_BUTTON_RELEASE_MASK
+                         | GDK_EXPOSURE_MASK
+                         | GDK_ENTER_NOTIFY_MASK
+                         | GDK_LEAVE_NOTIFY_MASK);
   
-  if (priv->changing)
-    return;
+  g_signal_connect (retval, "expose_event",
+		    G_CALLBACK (palette_expose), colorsel);
+  g_signal_connect (retval, "button_press_event",
+		    G_CALLBACK (palette_press), colorsel);
+  g_signal_connect (retval, "button_release_event",
+		    G_CALLBACK (palette_release), colorsel);
+  g_signal_connect (retval, "enter_notify_event",
+		    G_CALLBACK (palette_enter), colorsel);
+  g_signal_connect (retval, "leave_notify_event",
+		    G_CALLBACK (palette_leave), colorsel);
+  g_signal_connect (retval, "key_press_event",
+		    G_CALLBACK (palette_activate), colorsel);
+  g_signal_connect (retval, "popup_menu",
+		    G_CALLBACK (palette_popup), colorsel);
   
-  switch (GPOINTER_TO_INT (data))
+  gtk_drag_dest_set (retval,
+		     GTK_DEST_DEFAULT_HIGHLIGHT |
+		     GTK_DEST_DEFAULT_MOTION |
+		     GTK_DEST_DEFAULT_DROP,
+		     targets, 1,
+		     GDK_ACTION_COPY);
+  
+  g_signal_connect (retval, "drag_end",
+                    G_CALLBACK (palette_drag_end), NULL);
+  g_signal_connect (retval, "drag_data_received",
+                    G_CALLBACK (palette_drop_handle), colorsel);
+
+  gtk_widget_set_tooltip_text (retval,
+                        _("Click this palette entry to make it the current color. To change this entry, drag a color swatch here or right-click it and select \"Save color here.\""));
+  return retval;
+}
+
+
+/*
+ *
+ * The actual GtkColorSelection widget
+ *
+ */
+
+static GdkCursor *
+make_picker_cursor (GdkScreen *screen)
+{
+  GdkCursor *cursor;
+
+  cursor = gdk_cursor_new_from_name (gdk_screen_get_display (screen),
+				     "color-picker");
+
+  if (!cursor)
     {
-    case COLORSEL_SATURATION:
-    case COLORSEL_VALUE:
-      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
-      gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
-		      priv->color[COLORSEL_SATURATION],
-		      priv->color[COLORSEL_VALUE],
-		      &priv->color[COLORSEL_RED],
-		      &priv->color[COLORSEL_GREEN],
-		      &priv->color[COLORSEL_BLUE]);
-      break;
-    case COLORSEL_HUE:
-      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
-      gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
-		      priv->color[COLORSEL_SATURATION],
-		      priv->color[COLORSEL_VALUE],
-		      &priv->color[COLORSEL_RED],
-		      &priv->color[COLORSEL_GREEN],
-		      &priv->color[COLORSEL_BLUE]);
-      break;
-    case COLORSEL_RED:
-    case COLORSEL_GREEN:
-    case COLORSEL_BLUE:
-      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
+      GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
+      GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
+      GdkWindow *window;
+      GdkPixmap *pixmap, *mask;
+
+      window = gdk_screen_get_root_window (screen);
       
-      gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
-		      priv->color[COLORSEL_GREEN],
-		      priv->color[COLORSEL_BLUE],
-		      &priv->color[COLORSEL_HUE],
-		      &priv->color[COLORSEL_SATURATION],
-		      &priv->color[COLORSEL_VALUE]);
-      break;
-    default:
-      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
-      break;
+      pixmap =
+	gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
+				     DROPPER_WIDTH, DROPPER_HEIGHT);
+      
+      mask =
+	gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
+				     DROPPER_WIDTH, DROPPER_HEIGHT);
+      
+      cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
+					   DROPPER_X_HOT, DROPPER_Y_HOT);
+      
+      g_object_unref (pixmap);
+      g_object_unref (mask);
     }
-  update_color (colorsel);
+      
+  return cursor;
 }
 
-static void 
-opacity_entry_changed (GtkWidget *opacity_entry,
-		       gpointer   data)
+static void
+grab_color_at_mouse (GdkScreen *screen,
+		     gint       x_root,
+		     gint       y_root,
+		     gpointer   data)
 {
-  GtkColorSelection *colorsel;
+  GdkImage *image;
+  guint32 pixel;
+  GtkColorSelection *colorsel = data;
   ColorSelectionPrivate *priv;
-  GtkAdjustment *adj;
-  gchar *text;
+  GdkColor color;
+  GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
+  GdkWindow *root_window = gdk_screen_get_root_window (screen);
   
-  colorsel = GTK_COLOR_SELECTION (data);
   priv = colorsel->private_data;
   
-  if (priv->changing)
-    return;
+  image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
+  if (!image)
+    {
+      gint x, y;
+      GdkDisplay *display = gdk_screen_get_display (screen);
+      GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y);
+      if (!window)
+	return;
+      image = gdk_drawable_get_image (window, x, y, 1, 1);
+      if (!image)
+	return;
+    }
+  pixel = gdk_image_get_pixel (image, 0, 0);
+  g_object_unref (image);
+
+  gdk_colormap_query_color (colormap, pixel, &color);
   
-  text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
-  adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
-  gtk_adjustment_set_value (adj, g_strtod (text, NULL)); 
+  priv->color[COLORSEL_RED] = SCALE (color.red);
+  priv->color[COLORSEL_GREEN] = SCALE (color.green);
+  priv->color[COLORSEL_BLUE] = SCALE (color.blue);
   
+  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+		  priv->color[COLORSEL_GREEN],
+		  priv->color[COLORSEL_BLUE],
+		  &priv->color[COLORSEL_HUE],
+		  &priv->color[COLORSEL_SATURATION],
+		  &priv->color[COLORSEL_VALUE]);
+
   update_color (colorsel);
-  
-  g_free (text);
 }
 
 static void
-make_label_spinbutton (GtkColorSelection *colorsel,
-		       GtkWidget        **spinbutton,
-		       gchar             *text,
-		       GtkWidget         *table,
-		       gint               i,
-		       gint               j,
-		       gint               channel_type,
-                       const gchar       *tooltip)
+shutdown_eyedropper (GtkWidget *widget)
 {
-  GtkWidget *label;
-  GtkAdjustment *adjust;
-
-  if (channel_type == COLORSEL_HUE)
-    {
-      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
-    }
-  else if (channel_type == COLORSEL_SATURATION ||
-	   channel_type == COLORSEL_VALUE)
-    {
-      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
-    }
-  else
-    {
-      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
-    }
-  g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
-  *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
+  GdkDisplay *display = gtk_widget_get_display (widget);
 
-  gtk_widget_set_tooltip_text (*spinbutton, tooltip);  
+  colorsel = GTK_COLOR_SELECTION (widget);
+  priv = colorsel->private_data;    
 
-  g_signal_connect (adjust, "value_changed",
-                    G_CALLBACK (adjustment_changed),
-                    GINT_TO_POINTER (channel_type));
-  label = gtk_label_new_with_mnemonic (text);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
+  if (priv->has_grab)
+    {
+      gdk_display_keyboard_ungrab (display, priv->grab_time);
+      gdk_display_pointer_ungrab (display, priv->grab_time);
+      gtk_grab_remove (priv->dropper_grab_widget);
 
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
-  gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
+      priv->has_grab = FALSE;
+    }
 }
 
 static void
-make_palette_frame (GtkColorSelection *colorsel,
-		    GtkWidget         *table,
-		    gint               i,
-		    gint               j)
+mouse_motion (GtkWidget      *invisible,
+	      GdkEventMotion *event,
+	      gpointer        data)
 {
-  GtkWidget *frame;
-  ColorSelectionPrivate *priv;
-  
-  priv = colorsel->private_data;
-  frame = gtk_frame_new (NULL);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-  priv->custom_palette[i][j] = palette_new (colorsel);
-  gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
-  gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
-  gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
+  grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
+		       event->x_root, event->y_root, data); 
 }
 
-/* Set the palette entry [x][y] to be the currently selected one. */
-static void 
-set_selected_palette (GtkColorSelection *colorsel, int x, int y)
+static gboolean
+mouse_release (GtkWidget      *invisible,
+	       GdkEventButton *event,
+	       gpointer        data)
 {
-  ColorSelectionPrivate *priv = colorsel->private_data; 
+  /* GtkColorSelection *colorsel = data; */
 
-  gtk_widget_grab_focus (priv->custom_palette[x][y]);
-}
+  if (event->button != 1)
+    return FALSE;
 
-static double
-scale_round (double val, double factor)
-{
-  val = floor (val * factor + 0.5);
-  val = MAX (val, 0);
-  val = MIN (val, factor);
-  return val;
-}
+  grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event),
+		       event->x_root, event->y_root, data);
 
-static void
-update_color (GtkColorSelection *colorsel)
-{
-  ColorSelectionPrivate *priv = colorsel->private_data;
-  gchar entryval[12];
-  gchar opacity_text[32];
-  gchar *ptr;
-  
-  priv->changing = TRUE;
-  color_sample_update_samples (colorsel);
-  
-  gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
-		     priv->color[COLORSEL_HUE],
-		     priv->color[COLORSEL_SATURATION],
-		     priv->color[COLORSEL_VALUE]);
-  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
-			    (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
-			    scale_round (priv->color[COLORSEL_HUE], 360));
-  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
-			    (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
-			    scale_round (priv->color[COLORSEL_SATURATION], 100));
-  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
-			    (GTK_SPIN_BUTTON (priv->val_spinbutton)),
-			    scale_round (priv->color[COLORSEL_VALUE], 100));
-  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
-			    (GTK_SPIN_BUTTON (priv->red_spinbutton)),
-			    scale_round (priv->color[COLORSEL_RED], 255));
-  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
-			    (GTK_SPIN_BUTTON (priv->green_spinbutton)),
-			    scale_round (priv->color[COLORSEL_GREEN], 255));
-  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
-			    (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
-			    scale_round (priv->color[COLORSEL_BLUE], 255));
-  gtk_adjustment_set_value (gtk_range_get_adjustment
-			    (GTK_RANGE (priv->opacity_slider)),
-			    scale_round (priv->color[COLORSEL_OPACITY], 255));
-  
-  g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
-  gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
-  
-  g_snprintf (entryval, 11, "#%2X%2X%2X",
-	      (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
-	      (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
-	      (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
+  shutdown_eyedropper (GTK_WIDGET (data));
   
-  for (ptr = entryval; *ptr; ptr++)
-    if (*ptr == ' ')
-      *ptr = '0';
-  gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
-  priv->changing = FALSE;
+  g_signal_handlers_disconnect_by_func (invisible,
+					mouse_motion,
+					data);
+  g_signal_handlers_disconnect_by_func (invisible,
+					mouse_release,
+					data);
 
-  g_object_ref (colorsel);
-  
-  g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
-  
-  g_object_freeze_notify (G_OBJECT (colorsel));
-  g_object_notify (G_OBJECT (colorsel), "current-color");
-  g_object_notify (G_OBJECT (colorsel), "current-alpha");
-  g_object_thaw_notify (G_OBJECT (colorsel));
-  
-  g_object_unref (colorsel);
+  return TRUE;
 }
 
-static void
-update_palette (GtkColorSelection *colorsel)
-{
-  GdkColor *current_colors;
-  gint i, j;
+/* Helper Functions */
 
-  current_colors = get_current_colors (colorsel);
-  
-  for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
+static gboolean
+key_press (GtkWidget   *invisible,
+           GdkEventKey *event,
+           gpointer     data)
+{  
+  GdkDisplay *display = gtk_widget_get_display (invisible);
+  GdkScreen *screen = gdk_event_get_screen ((GdkEvent *)event);
+  guint state = event->state & gtk_accelerator_get_default_mod_mask ();
+  gint x, y;
+  gint dx, dy;
+
+  gdk_display_get_pointer (display, NULL, &x, &y, NULL);
+
+  dx = 0;
+  dy = 0;
+
+  switch (event->keyval) 
     {
-      for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
-	{
-          gint index;
+    case GDK_space:
+    case GDK_Return:
+    case GDK_ISO_Enter:
+    case GDK_KP_Enter:
+    case GDK_KP_Space:
+      grab_color_at_mouse (screen, x, y, data);
+      /* fall through */
 
-          index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
-          
-          gtk_color_selection_set_palette_color (colorsel,
-                                                 index,
-                                                 &current_colors[index]);
-	}
-    }
+    case GDK_Escape:
+      shutdown_eyedropper (data);
+      
+      g_signal_handlers_disconnect_by_func (invisible,
+					    mouse_press,
+					    data);
+      g_signal_handlers_disconnect_by_func (invisible,
+					    key_press,
+					    data);
+      
+      return TRUE;
 
-  g_free (current_colors);
-}
+#if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32
+    case GDK_Up:
+    case GDK_KP_Up:
+      dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
+      break;
 
-static void
-palette_change_notify_instance (GObject    *object,
-                                GParamSpec *pspec,
-                                gpointer    data)
-{
-  update_palette (GTK_COLOR_SELECTION (data));
-}
+    case GDK_Down:
+    case GDK_KP_Down:
+      dy = state == GDK_MOD1_MASK ? BIG_STEP : 1;
+      break;
+
+    case GDK_Left:
+    case GDK_KP_Left:
+      dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1;
+      break;
+
+    case GDK_Right:
+    case GDK_KP_Right:
+      dx = state == GDK_MOD1_MASK ? BIG_STEP : 1;
+      break;
+#endif
+
+    default:
+      return FALSE;
+    }
+
+  gdk_display_warp_pointer (display, screen, x + dx, y + dy);
+  
+  return TRUE;
 
-static void
-default_noscreen_change_palette_func (const GdkColor *colors,
-				      gint            n_colors)
-{
-  default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
 }
 
-static void
-default_change_palette_func (GdkScreen	    *screen,
-			     const GdkColor *colors,
-                             gint            n_colors)
+static gboolean
+mouse_press (GtkWidget      *invisible,
+	     GdkEventButton *event,
+	     gpointer        data)
 {
-  gchar *str;
+  /* GtkColorSelection *colorsel = data; */
   
-  str = gtk_color_selection_palette_to_string (colors, n_colors);
-
-  gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
-                                    "gtk-color-palette",
-                                    str,
-                                    "gtk_color_selection_palette_to_string");
+  if (event->type == GDK_BUTTON_PRESS &&
+      event->button == 1)
+    {
+      g_signal_connect (invisible, "motion_notify_event",
+                        G_CALLBACK (mouse_motion),
+                        data);
+      g_signal_connect (invisible, "button_release_event",
+                        G_CALLBACK (mouse_release),
+                        data);
+      g_signal_handlers_disconnect_by_func (invisible,
+					    mouse_press,
+					    data);
+      g_signal_handlers_disconnect_by_func (invisible,
+					    key_press,
+					    data);
+      return TRUE;
+    }
 
-  g_free (str);
+  return FALSE;
 }
 
-G_DEFINE_TYPE (GtkColorSelection, gtk_color_selection, GTK_TYPE_VBOX)
-
+/* when the button is clicked */
 static void
-gtk_color_selection_class_init (GtkColorSelectionClass *klass)
+get_screen_color (GtkWidget *button)
 {
-  GObjectClass *gobject_class;
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-  
-  gobject_class = G_OBJECT_CLASS (klass);
-  object_class = GTK_OBJECT_CLASS (klass);
-  widget_class = GTK_WIDGET_CLASS (klass);
-  
-  object_class->destroy = gtk_color_selection_destroy;
-  gobject_class->finalize = gtk_color_selection_finalize;
-  
-  gobject_class->set_property = gtk_color_selection_set_property;
-  gobject_class->get_property = gtk_color_selection_get_property;
+  GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL");
+  ColorSelectionPrivate *priv = colorsel->private_data;
+  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
+  GdkCursor *picker_cursor;
+  GdkGrabStatus grab_status;
+  GtkWidget *grab_widget, *toplevel;
 
-  widget_class->realize = gtk_color_selection_realize;
-  widget_class->unrealize = gtk_color_selection_unrealize;
-  widget_class->show_all = gtk_color_selection_show_all;
-  widget_class->grab_broken_event = gtk_color_selection_grab_broken;
+  guint32 time = gtk_get_current_event_time ();
   
-  g_object_class_install_property (gobject_class,
-                                   PROP_HAS_OPACITY_CONTROL,
-                                   g_param_spec_boolean ("has-opacity-control",
-							 P_("Has Opacity Control"),
-							 P_("Whether the color selector should allow setting opacity"),
-							 FALSE,
-							 GTK_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-                                   PROP_HAS_PALETTE,
-                                   g_param_spec_boolean ("has-palette",
-							 P_("Has palette"),
-							 P_("Whether a palette should be used"),
-							 FALSE,
-							 GTK_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-                                   PROP_CURRENT_COLOR,
-                                   g_param_spec_boxed ("current-color",
-                                                       P_("Current Color"),
-                                                       P_("The current color"),
-                                                       GDK_TYPE_COLOR,
-                                                       GTK_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class,
-                                   PROP_CURRENT_ALPHA,
-                                   g_param_spec_uint ("current-alpha",
-						      P_("Current Alpha"),
-						      P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
-						      0, 65535, 65535,
-						      GTK_PARAM_READWRITE));
+  if (priv->dropper_grab_widget == NULL)
+    {
+      grab_widget = gtk_window_new (GTK_WINDOW_POPUP);
+      gtk_window_set_screen (GTK_WINDOW (grab_widget), screen);
+      gtk_window_resize (GTK_WINDOW (grab_widget), 1, 1);
+      gtk_window_move (GTK_WINDOW (grab_widget), -100, -100);
+      gtk_widget_show (grab_widget);
+
+      gtk_widget_add_events (grab_widget,
+                             GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
+      
+      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (colorsel));
   
-  color_selection_signals[COLOR_CHANGED] =
-    g_signal_new (I_("color_changed"),
-		  G_OBJECT_CLASS_TYPE (object_class),
-		  G_SIGNAL_RUN_FIRST,
-		  G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
-		  NULL, NULL,
-		  _gtk_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
+      if (GTK_IS_WINDOW (toplevel))
+	{
+	  if (GTK_WINDOW (toplevel)->group)
+	    gtk_window_group_add_window (GTK_WINDOW (toplevel)->group, 
+					 GTK_WINDOW (grab_widget));
+	}
 
-  gtk_settings_install_property (g_param_spec_string ("gtk-color-palette",
-                                                      P_("Custom palette"),
-                                                      P_("Palette to use in the color selector"),
-                                                      default_colors,
-                                                      GTK_PARAM_READWRITE));
+      priv->dropper_grab_widget = grab_widget;
+    }
 
-   g_type_class_add_private (gobject_class, sizeof (ColorSelectionPrivate));
-}
+  if (gdk_keyboard_grab (priv->dropper_grab_widget->window,
+                         FALSE, time) != GDK_GRAB_SUCCESS)
+    return;
+  
+  picker_cursor = make_picker_cursor (screen);
+  grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window,
+				  FALSE,
+				  GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
+				  NULL,
+				  picker_cursor,
+				  time);
+  gdk_cursor_unref (picker_cursor);
+  
+  if (grab_status != GDK_GRAB_SUCCESS)
+    {
+      gdk_display_keyboard_ungrab (gtk_widget_get_display (button), time);
+      return;
+    }
 
-/* widget functions */
+  gtk_grab_add (priv->dropper_grab_widget);
+  priv->grab_time = time;
+  priv->has_grab = TRUE;
+  
+  g_signal_connect (priv->dropper_grab_widget, "button_press_event",
+                    G_CALLBACK (mouse_press), colorsel);
+  g_signal_connect (priv->dropper_grab_widget, "key_press_event",
+                    G_CALLBACK (key_press), colorsel);
+}
 
 static void
-gtk_color_selection_init (GtkColorSelection *colorsel)
+hex_changed (GtkWidget *hex_entry,
+	     gpointer   data)
 {
-  GtkWidget *top_hbox;
-  GtkWidget *top_right_vbox;
-  GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
-  GtkAdjustment *adjust;
-  GtkWidget *picker_image;
-  gint i, j;
+  GtkColorSelection *colorsel;
   ColorSelectionPrivate *priv;
-  AtkObject *atk_obj;
-  GList *focus_chain = NULL;
-  
-  gtk_widget_push_composite_child ();
-
-  priv = colorsel->private_data = G_TYPE_INSTANCE_GET_PRIVATE (colorsel, GTK_TYPE_COLOR_SELECTION, ColorSelectionPrivate);
-  priv->changing = FALSE;
-  priv->default_set = FALSE;
-  priv->default_alpha_set = FALSE;
-  
-  top_hbox = gtk_hbox_new (FALSE, 12);
-  gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
-  
-  vbox = gtk_vbox_new (FALSE, 6);
-  priv->triangle_colorsel = gtk_hsv_new ();
-  g_signal_connect (priv->triangle_colorsel, "changed",
-                    G_CALLBACK (hsv_changed), colorsel);
-  gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
-  gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
-  gtk_widget_set_tooltip_text (priv->triangle_colorsel,
-                        _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."));
+  GdkColor color;
+  gchar *text;
   
-  hbox = gtk_hbox_new (FALSE, 6);
-  gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  colorsel = GTK_COLOR_SELECTION (data);
+  priv = colorsel->private_data;
   
-  frame = gtk_frame_new (NULL);
-  gtk_widget_set_size_request (frame, -1, 30);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-  color_sample_new (colorsel);
-  gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
-  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+  if (priv->changing)
+    return;
   
-  button = gtk_button_new ();
+  text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
+  if (gdk_color_parse (text, &color))
+    {
+      priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0);
+      priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0);
+      priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0);
+      gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+		      priv->color[COLORSEL_GREEN],
+		      priv->color[COLORSEL_BLUE],
+		      &priv->color[COLORSEL_HUE],
+		      &priv->color[COLORSEL_SATURATION],
+		      &priv->color[COLORSEL_VALUE]);
+      update_color (colorsel);
+    }
+  g_free (text);
+}
 
-  gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
-  g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel); 
-  g_signal_connect (button, "clicked",
-                    G_CALLBACK (get_screen_color), NULL);
-  picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
-  gtk_container_add (GTK_CONTAINER (button), picker_image);
-  gtk_widget_show (GTK_WIDGET (picker_image));
-  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+static gboolean
+hex_focus_out (GtkWidget     *hex_entry, 
+	       GdkEventFocus *event,
+	       gpointer       data)
+{
+  hex_changed (hex_entry, data);
+  
+  return FALSE;
+}
 
-  gtk_widget_set_tooltip_text (button,
-                        _("Click the eyedropper, then click a color anywhere on your screen to select that color."));
+static void
+hsv_changed (GtkWidget *hsv,
+	     gpointer   data)
+{
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
   
-  top_right_vbox = gtk_vbox_new (FALSE, 6);
-  gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
-  table = gtk_table_new (8, 6, FALSE);
-  gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
-  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+  colorsel = GTK_COLOR_SELECTION (data);
+  priv = colorsel->private_data;
   
-  make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
-                         _("Position on the color wheel."));
-  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
-  make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("_Saturation:"), table, 0, 1, COLORSEL_SATURATION,
-                         _("\"Deepness\" of the color."));
-  make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
-                         _("Brightness of the color."));
-  make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
-                         _("Amount of red light in the color."));
-  make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
-                         _("Amount of green light in the color."));
-  make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
-                         _("Amount of blue light in the color."));
-  gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4); 
-
-  priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:")); 
-  gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 0.0, 0.5); 
-  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5); 
-  adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0)); 
-  g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel); 
-  priv->opacity_slider = gtk_hscale_new (adjust);
-  gtk_widget_set_tooltip_text (priv->opacity_slider,
-                        _("Transparency of the color."));
-  gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
-                                 priv->opacity_slider);
-  gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
-  g_signal_connect (adjust, "value_changed",
-                    G_CALLBACK (adjustment_changed),
-                    GINT_TO_POINTER (COLORSEL_OPACITY));
-  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5); 
-  priv->opacity_entry = gtk_entry_new (); 
-  gtk_widget_set_tooltip_text (priv->opacity_entry,
-                        _("Transparency of the color."));
-  gtk_widget_set_size_request (priv->opacity_entry, 40, -1); 
-
-  g_signal_connect (priv->opacity_entry, "activate",
-                    G_CALLBACK (opacity_entry_changed), colorsel);
-  gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
+  if (priv->changing)
+    return;
   
-  label = gtk_label_new_with_mnemonic (_("Color _name:"));
-  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  priv->hex_entry = gtk_entry_new ();
-
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);
-
-  g_signal_connect (priv->hex_entry, "activate",
-                    G_CALLBACK (hex_changed), colorsel);
-
-  g_signal_connect (priv->hex_entry, "focus_out_event",
-                    G_CALLBACK (hex_focus_out), colorsel);
+  gtk_hsv_get_color (GTK_HSV (hsv),
+		     &priv->color[COLORSEL_HUE],
+		     &priv->color[COLORSEL_SATURATION],
+		     &priv->color[COLORSEL_VALUE]);
+  gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
+		  priv->color[COLORSEL_SATURATION],
+		  priv->color[COLORSEL_VALUE],
+		  &priv->color[COLORSEL_RED],
+		  &priv->color[COLORSEL_GREEN],
+		  &priv->color[COLORSEL_BLUE]);
+  update_color (colorsel);
+}
 
-  gtk_widget_set_tooltip_text (priv->hex_entry,
-                        _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."));
+static void
+adjustment_changed (GtkAdjustment *adjustment,
+		    gpointer       data)
+{
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
   
-  gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
-  gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
-
-  focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
-  focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
-  focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
-  focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
-  focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
-  focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
-  focus_chain = g_list_append (focus_chain, priv->opacity_slider);
-  focus_chain = g_list_append (focus_chain, priv->opacity_entry);
-  focus_chain = g_list_append (focus_chain, priv->hex_entry);
-  gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
-  g_list_free (focus_chain);
-
-  /* Set up the palette */
-  table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
-  gtk_table_set_row_spacings (GTK_TABLE (table), 1);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 1);
-  for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
+  colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL"));
+  priv = colorsel->private_data;
+  
+  if (priv->changing)
+    return;
+  
+  switch (GPOINTER_TO_INT (data))
     {
-      for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
-	{
-	  make_palette_frame (colorsel, table, i, j);
-	}
+    case COLORSEL_SATURATION:
+    case COLORSEL_VALUE:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100;
+      gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
+		      priv->color[COLORSEL_SATURATION],
+		      priv->color[COLORSEL_VALUE],
+		      &priv->color[COLORSEL_RED],
+		      &priv->color[COLORSEL_GREEN],
+		      &priv->color[COLORSEL_BLUE]);
+      break;
+    case COLORSEL_HUE:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
+      gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
+		      priv->color[COLORSEL_SATURATION],
+		      priv->color[COLORSEL_VALUE],
+		      &priv->color[COLORSEL_RED],
+		      &priv->color[COLORSEL_GREEN],
+		      &priv->color[COLORSEL_BLUE]);
+      break;
+    case COLORSEL_RED:
+    case COLORSEL_GREEN:
+    case COLORSEL_BLUE:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
+      
+      gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
+		      priv->color[COLORSEL_GREEN],
+		      priv->color[COLORSEL_BLUE],
+		      &priv->color[COLORSEL_HUE],
+		      &priv->color[COLORSEL_SATURATION],
+		      &priv->color[COLORSEL_VALUE]);
+      break;
+    default:
+      priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
+      break;
     }
-  set_selected_palette (colorsel, 0, 0);
-  priv->palette_frame = gtk_vbox_new (FALSE, 6);
-  label = gtk_label_new_with_mnemonic (_("_Palette:"));
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
+  update_color (colorsel);
+}
 
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label),
-                                 priv->custom_palette[0][0]);
+static void 
+opacity_entry_changed (GtkWidget *opacity_entry,
+		       gpointer   data)
+{
+  GtkColorSelection *colorsel;
+  ColorSelectionPrivate *priv;
+  GtkAdjustment *adj;
+  gchar *text;
   
-  gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
+  colorsel = GTK_COLOR_SELECTION (data);
+  priv = colorsel->private_data;
   
-  gtk_widget_show_all (top_hbox);
-
-  /* hide unused stuff */
+  if (priv->changing)
+    return;
   
-  if (priv->has_opacity == FALSE)
+  text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
+  adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
+  gtk_adjustment_set_value (adj, g_strtod (text, NULL)); 
+  
+  update_color (colorsel);
+  
+  g_free (text);
+}
+
+static void
+make_label_spinbutton (GtkColorSelection *colorsel,
+		       GtkWidget        **spinbutton,
+		       gchar             *text,
+		       GtkWidget         *table,
+		       gint               i,
+		       gint               j,
+		       gint               channel_type,
+                       const gchar       *tooltip)
+{
+  GtkWidget *label;
+  GtkAdjustment *adjust;
+
+  if (channel_type == COLORSEL_HUE)
+    {
+      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
+    }
+  else if (channel_type == COLORSEL_SATURATION ||
+	   channel_type == COLORSEL_VALUE)
     {
-      gtk_widget_hide (priv->opacity_label);
-      gtk_widget_hide (priv->opacity_slider);
-      gtk_widget_hide (priv->opacity_entry);
+      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0));
     }
-  
-  if (priv->has_palette == FALSE)
+  else
     {
-      gtk_widget_hide (priv->palette_frame);
+      adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
     }
+  g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
+  *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
 
-  atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
-  if (GTK_IS_ACCESSIBLE (atk_obj))
-    {
-      atk_object_set_name (atk_obj, _("Color Wheel"));
-      atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
-      make_all_relations (atk_obj, priv);
-    } 
+  gtk_widget_set_tooltip_text (*spinbutton, tooltip);  
 
-  gtk_widget_pop_composite_child ();
+  g_signal_connect (adjust, "value_changed",
+                    G_CALLBACK (adjustment_changed),
+                    GINT_TO_POINTER (channel_type));
+  label = gtk_label_new_with_mnemonic (text);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton);
+
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
+  gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
 }
 
 static void
-gtk_color_selection_destroy (GtkObject *object)
+make_palette_frame (GtkColorSelection *colorsel,
+		    GtkWidget         *table,
+		    gint               i,
+		    gint               j)
 {
-  GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
-  ColorSelectionPrivate *priv = cselection->private_data;
+  GtkWidget *frame;
+  ColorSelectionPrivate *priv;
+  
+  priv = colorsel->private_data;
+  frame = gtk_frame_new (NULL);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  priv->custom_palette[i][j] = palette_new (colorsel);
+  gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
+  gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
+  gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
+}
 
-  if (priv->dropper_grab_widget)
-    {
-      gtk_widget_destroy (priv->dropper_grab_widget);
-      priv->dropper_grab_widget = NULL;
-    }
+/* Set the palette entry [x][y] to be the currently selected one. */
+static void 
+set_selected_palette (GtkColorSelection *colorsel, int x, int y)
+{
+  ColorSelectionPrivate *priv = colorsel->private_data; 
 
-  GTK_OBJECT_CLASS (gtk_color_selection_parent_class)->destroy (object);
+  gtk_widget_grab_focus (priv->custom_palette[x][y]);
 }
 
-static void
-gtk_color_selection_finalize (GObject *object)
+static double
+scale_round (double val, double factor)
 {
-  G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
+  val = floor (val * factor + 0.5);
+  val = MAX (val, 0);
+  val = MIN (val, factor);
+  return val;
 }
 
 static void
-gtk_color_selection_realize (GtkWidget *widget)
+update_color (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
   ColorSelectionPrivate *priv = colorsel->private_data;
-  GtkSettings *settings = gtk_widget_get_settings (widget);
-
-  priv->settings_connection =  g_signal_connect (settings,
-						 "notify::gtk-color-palette",
-						 G_CALLBACK (palette_change_notify_instance),
-						 widget);
-  update_palette (colorsel);
+  gchar entryval[12];
+  gchar opacity_text[32];
+  gchar *ptr;
+  
+  priv->changing = TRUE;
+  color_sample_update_samples (colorsel);
+  
+  gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
+		     priv->color[COLORSEL_HUE],
+		     priv->color[COLORSEL_SATURATION],
+		     priv->color[COLORSEL_VALUE]);
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+			    (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
+			    scale_round (priv->color[COLORSEL_HUE], 360));
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+			    (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
+			    scale_round (priv->color[COLORSEL_SATURATION], 100));
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+			    (GTK_SPIN_BUTTON (priv->val_spinbutton)),
+			    scale_round (priv->color[COLORSEL_VALUE], 100));
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+			    (GTK_SPIN_BUTTON (priv->red_spinbutton)),
+			    scale_round (priv->color[COLORSEL_RED], 255));
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+			    (GTK_SPIN_BUTTON (priv->green_spinbutton)),
+			    scale_round (priv->color[COLORSEL_GREEN], 255));
+  gtk_adjustment_set_value (gtk_spin_button_get_adjustment
+			    (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
+			    scale_round (priv->color[COLORSEL_BLUE], 255));
+  gtk_adjustment_set_value (gtk_range_get_adjustment
+			    (GTK_RANGE (priv->opacity_slider)),
+			    scale_round (priv->color[COLORSEL_OPACITY], 255));
+  
+  g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255));
+  gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
+  
+  g_snprintf (entryval, 11, "#%2X%2X%2X",
+	      (guint) (scale_round (priv->color[COLORSEL_RED], 255)),
+	      (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)),
+	      (guint) (scale_round (priv->color[COLORSEL_BLUE], 255)));
+  
+  for (ptr = entryval; *ptr; ptr++)
+    if (*ptr == ' ')
+      *ptr = '0';
+  gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
+  priv->changing = FALSE;
 
-  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
+  g_object_ref (colorsel);
+  
+  g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0);
+  
+  g_object_freeze_notify (G_OBJECT (colorsel));
+  g_object_notify (G_OBJECT (colorsel), "current-color");
+  g_object_notify (G_OBJECT (colorsel), "current-alpha");
+  g_object_thaw_notify (G_OBJECT (colorsel));
+  
+  g_object_unref (colorsel);
 }
 
 static void
-gtk_color_selection_unrealize (GtkWidget *widget)
+update_palette (GtkColorSelection *colorsel)
 {
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
-  ColorSelectionPrivate *priv = colorsel->private_data;
-  GtkSettings *settings = gtk_widget_get_settings (widget);
+  GdkColor *current_colors;
+  gint i, j;
 
-  g_signal_handler_disconnect (settings, priv->settings_connection);
+  current_colors = get_current_colors (colorsel);
+  
+  for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++)
+    {
+      for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++)
+	{
+          gint index;
 
-  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
+          index = i * GTK_CUSTOM_PALETTE_WIDTH + j;
+          
+          gtk_color_selection_set_palette_color (colorsel,
+                                                 index,
+                                                 &current_colors[index]);
+	}
+    }
+
+  g_free (current_colors);
 }
 
-/* We override show-all since we have internal widgets that
- * shouldn't be shown when you call show_all(), like the
- * palette and opacity sliders.
- */
 static void
-gtk_color_selection_show_all (GtkWidget *widget)
+palette_change_notify_instance (GObject    *object,
+                                GParamSpec *pspec,
+                                gpointer    data)
 {
-  gtk_widget_show (widget);
+  update_palette (GTK_COLOR_SELECTION (data));
+}
+
+static void
+default_noscreen_change_palette_func (const GdkColor *colors,
+				      gint            n_colors)
+{
+  default_change_palette_func (gdk_screen_get_default (), colors, n_colors);
+}
+
+static void
+default_change_palette_func (GdkScreen	    *screen,
+			     const GdkColor *colors,
+                             gint            n_colors)
+{
+  gchar *str;
+  
+  str = gtk_color_selection_palette_to_string (colors, n_colors);
+
+  gtk_settings_set_string_property (gtk_settings_get_for_screen (screen),
+                                    "gtk-color-palette",
+                                    str,
+                                    "gtk_color_selection_palette_to_string");
+
+  g_free (str);
 }
 
 /**
@@ -2585,67 +2681,6 @@
   return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
 }
 
-static void
-gtk_color_selection_set_property (GObject         *object,
-				  guint            prop_id,
-				  const GValue    *value,
-				  GParamSpec      *pspec)
-{
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
-  
-  switch (prop_id)
-    {
-    case PROP_HAS_OPACITY_CONTROL:
-      gtk_color_selection_set_has_opacity_control (colorsel, 
-						   g_value_get_boolean (value));
-      break;
-    case PROP_HAS_PALETTE:
-      gtk_color_selection_set_has_palette (colorsel, 
-					   g_value_get_boolean (value));
-      break;
-    case PROP_CURRENT_COLOR:
-      gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value));
-      break;
-    case PROP_CURRENT_ALPHA:
-      gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-  
-}
-
-static void
-gtk_color_selection_get_property (GObject     *object,
-				  guint        prop_id,
-				  GValue      *value,
-				  GParamSpec  *pspec)
-{
-  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
-  GdkColor color;
-  
-  switch (prop_id)
-    {
-    case PROP_HAS_OPACITY_CONTROL:
-      g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
-      break;
-    case PROP_HAS_PALETTE:
-      g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
-      break;
-    case PROP_CURRENT_COLOR:
-      gtk_color_selection_get_current_color (colorsel, &color);
-      g_value_set_boxed (value, &color);
-      break;
-    case PROP_CURRENT_ALPHA:
-      g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
 
 /**
  * gtk_color_selection_palette_from_string:



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