]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcolorsel.c
Do nothing on empty string, quietly.
[~andy/gtk] / gtk / gtkcolorsel.c
index b625dd5225a4f04e70145afd53d91c691df77b61..eb660b9d4746f9936d9d796c9a6f4b468aa84192 100644 (file)
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
+#include <stdlib.h>
+#include <stdio.h>
 #include <math.h>
+#include <gdk/gdk.h>
 #include "gtkcolorsel.h"
+#include "gtkwindow.h"
+#include "gtkhbbox.h"
+#include "gtkdnd.h"
+#include "gtkselection.h"
 
 /*
  * If you change the way the color values are stored,
  * across all the color info (currently RGBA). - Elliot
  */
 
+#ifndef M_PI
+#define M_PI    3.14159265358979323846
+#endif /* M_PI */
+
 #define DEGTORAD(a) (2.0*M_PI*a/360.0)
 #define SQR(a) (a*a)
 
 #define SAMPLE_WIDTH  WHEEL_WIDTH+VALUE_WIDTH+5
 #define SAMPLE_HEIGHT 28
 
+static void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
+static void gtk_color_selection_init (GtkColorSelection *colorsel);
+static void gtk_color_selection_dialog_class_init(GtkColorSelectionDialogClass *klass);
+static void gtk_color_selection_dialog_init(GtkColorSelectionDialog *colorseldiag);
 
 enum
 {
@@ -105,7 +121,8 @@ static void gtk_color_selection_rgb_updater       (GtkWidget         *widget,
 static void gtk_color_selection_opacity_updater   (GtkWidget         *widget,
                                                    gpointer           data);
 static void gtk_color_selection_realize           (GtkWidget         *widget);
-static void gtk_color_selection_destroy           (GtkObject         *object);
+static void gtk_color_selection_unrealize         (GtkWidget         *widget);
+static void gtk_color_selection_finalize          (GtkObject         *object);
 static void gtk_color_selection_color_changed     (GtkColorSelection *colorsel);
 static void gtk_color_selection_update_input      (GtkWidget         *scale,
                                                    GtkWidget         *entry,
@@ -130,12 +147,23 @@ static gint gtk_color_selection_wheel_events      (GtkWidget          *area,
 static gint gtk_color_selection_wheel_timeout     (GtkColorSelection  *colorsel);
 static void gtk_color_selection_sample_resize     (GtkWidget          *widget,
                                                    gpointer            data);
-static void gtk_color_selection_drop_handle       (GtkWidget          *widget,
-                                                  GdkEvent           *event,
-                                                  GtkWidget          *theclorsel);
-static void gtk_color_selection_drag_handle       (GtkWidget          *widget,
-                                                  GdkEvent           *event,
-                                                  GtkWidget          *thecolorsel);
+static void gtk_color_selection_drag_begin        (GtkWidget          *widget,
+                                                  GdkDragContext     *context,
+                                                  gpointer            data);
+static void gtk_color_selection_drop_handle       (GtkWidget          *widget, 
+                                                  GdkDragContext     *context,
+                                                  gint                x,
+                                                  gint                y,
+                                                  GtkSelectionData   *selection_data,
+                                                  guint               info,
+                                                  guint               time,
+                                                  gpointer            data);
+static void gtk_color_selection_drag_handle       (GtkWidget        *widget, 
+                                                  GdkDragContext   *context,
+                                                  GtkSelectionData *selection_data,
+                                                  guint             info,
+                                                  guint             time,
+                                                  gpointer          data);
 static void gtk_color_selection_draw_wheel_marker (GtkColorSelection  *colorsel);
 static void gtk_color_selection_draw_wheel_frame  (GtkColorSelection  *colorsel);
 static void gtk_color_selection_draw_value_marker (GtkColorSelection  *colorsel);
@@ -155,20 +183,20 @@ static void gtk_color_selection_hsv_to_rgb        (gdouble  h, gdouble  s, gdoub
 static void gtk_color_selection_rgb_to_hsv        (gdouble  r, gdouble  g, gdouble  b,
                                                   gdouble *h, gdouble *s, gdouble *v);
 
-static void gtk_color_selection_dialog_destroy    (GtkObject *object);
-
 
 static GtkVBoxClass *color_selection_parent_class = NULL;
 static GtkWindowClass *color_selection_dialog_parent_class = NULL;
 
 
-static gint color_selection_signals[LAST_SIGNAL] = {0};
+static guint color_selection_signals[LAST_SIGNAL] = {0};
+
+static const gchar     *value_index_key = "gtk-value-index";
 
 
 #define SF GtkSignalFunc
 
 
-scale_val_type scale_vals[NUM_CHANNELS] =
+static const scale_val_type scale_vals[NUM_CHANNELS] =
 {
   {"Hue:",        0.0, 360.0, 1.00, 10.00, (SF) gtk_color_selection_hsv_updater},
   {"Saturation:", 0.0,   1.0, 0.01,  0.01, (SF) gtk_color_selection_hsv_updater},
@@ -180,19 +208,22 @@ scale_val_type scale_vals[NUM_CHANNELS] =
 };
 
 guint
-gtk_color_selection_get_type ()
+gtk_color_selection_get_type (void)
 {
   static guint color_selection_type = 0;
 
   if (!color_selection_type)
     {
-      GtkTypeInfo colorsel_info =
+      static const GtkTypeInfo colorsel_info =
       {
-       "color selection widget",
+       "GtkColorSelection",
        sizeof (GtkColorSelection),
        sizeof (GtkColorSelectionClass),
        (GtkClassInitFunc) gtk_color_selection_class_init,
        (GtkObjectInitFunc) gtk_color_selection_init,
+       /* reserved_1 */ NULL,
+       /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
       };
 
       color_selection_type = gtk_type_unique (gtk_vbox_get_type (), &colorsel_info);
@@ -201,7 +232,7 @@ gtk_color_selection_get_type ()
   return color_selection_type;
 }
 
-void
+static void
 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
 {
   GtkObjectClass *object_class;
@@ -219,16 +250,17 @@ gtk_color_selection_class_init (GtkColorSelectionClass *klass)
                     GTK_RUN_FIRST,
                      object_class->type,
                     GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
-                     gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
+                     gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);
 
   gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
 
-  object_class->destroy = gtk_color_selection_destroy;
+  object_class->finalize = gtk_color_selection_finalize;
 
   widget_class->realize = gtk_color_selection_realize;
+  widget_class->unrealize = gtk_color_selection_unrealize;
 }
 
-void
+static void
 gtk_color_selection_init (GtkColorSelection *colorsel)
 {
   GtkWidget *frame, *hbox, *vbox, *hbox2, *label, *table;
@@ -256,7 +288,7 @@ gtk_color_selection_init (GtkColorSelection *colorsel)
   colorsel->policy = GTK_UPDATE_CONTINUOUS;
 
   hbox = gtk_hbox_new (FALSE, 5);
-  gtk_container_border_width (GTK_CONTAINER (hbox), 5);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
   gtk_container_add (GTK_CONTAINER (colorsel), hbox);
 
   vbox = gtk_vbox_new (FALSE, 5);
@@ -292,7 +324,7 @@ gtk_color_selection_init (GtkColorSelection *colorsel)
 
   frame = gtk_frame_new (NULL);
   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-  gtk_container_border_width (GTK_CONTAINER (frame), 0);
+  gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
   gtk_box_pack_start (GTK_BOX (hbox2), frame, FALSE, TRUE, 0);
   gtk_widget_show (frame);
 
@@ -388,11 +420,11 @@ gtk_color_selection_init (GtkColorSelection *colorsel)
       gtk_signal_connect_object (GTK_OBJECT (adj), "value_changed",
                                  scale_vals[n].updater, (gpointer) colorsel->scales[n]);
       gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_GtkColorSelection", (gpointer) colorsel);
-      gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_ValueIndex", (gpointer) n);
+      gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), value_index_key, GINT_TO_POINTER (n));
       gtk_signal_connect_object (GTK_OBJECT (colorsel->entries[n]), "changed",
                                  scale_vals[n].updater, (gpointer) colorsel->entries[n]);
       gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_GtkColorSelection", (gpointer) colorsel);
-      gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_ValueIndex", (gpointer) n);
+      gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), value_index_key, GINT_TO_POINTER (n));
     }
 
   colorsel->opacity_label = label;
@@ -447,7 +479,7 @@ gtk_color_selection_set_color (GtkColorSelection *colorsel,
       colorsel->values[n] = color[i++];
     }
 
-  if (colorsel->use_opacity == TRUE)
+  if (colorsel->use_opacity)
     {
       colorsel->old_values[OPACITY] = colorsel->values[OPACITY];
       colorsel->values[OPACITY] = color[i];
@@ -476,7 +508,7 @@ gtk_color_selection_get_color (GtkColorSelection *colorsel,
 
   for (n = RED; n <= BLUE; n++)
     color[i++] = colorsel->values[n];
-  if (colorsel->use_opacity == TRUE)
+  if (colorsel->use_opacity)
     color[i] = colorsel->values[OPACITY];
 }
 
@@ -484,7 +516,10 @@ static void
 gtk_color_selection_realize (GtkWidget         *widget)
 {
   GtkColorSelection *colorsel;
-  gchar *type_accept_list[] = {"application/x-color"};
+
+  static const GtkTargetEntry targets[] = {
+    { "application/x-color", 0 }
+  };
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_COLOR_SELECTION (widget));
@@ -494,22 +529,63 @@ gtk_color_selection_realize (GtkWidget         *widget)
   if (GTK_WIDGET_CLASS (color_selection_parent_class)->realize)
     (*GTK_WIDGET_CLASS (color_selection_parent_class)->realize) (widget);
 
-  gtk_widget_dnd_drag_set (colorsel->sample_area,
-                          1, type_accept_list, 1);
-  gtk_widget_dnd_drop_set (colorsel->sample_area,
-                          1, type_accept_list, 1, 0);
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
-                           "drop_data_available_event",
-                           GTK_SIGNAL_FUNC (gtk_color_selection_drop_handle),
-                           colorsel);
-  gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
-                           "drag_request_event",
-                           GTK_SIGNAL_FUNC (gtk_color_selection_drag_handle),
-                           colorsel);
+  gtk_drag_dest_set (colorsel->sample_area,
+                      GTK_DEST_DEFAULT_HIGHLIGHT |
+                      GTK_DEST_DEFAULT_MOTION |
+                      GTK_DEST_DEFAULT_DROP,
+                      targets, 1,
+                      GDK_ACTION_COPY);
+
+  gtk_drag_source_set (colorsel->sample_area, 
+                      GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+                      targets, 1,
+                      GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
+                     "drag_begin",
+                     GTK_SIGNAL_FUNC (gtk_color_selection_drag_begin),
+                     colorsel);
+  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
+                     "drag_data_get",
+                     GTK_SIGNAL_FUNC (gtk_color_selection_drag_handle),
+                     colorsel);
+  gtk_signal_connect (GTK_OBJECT (colorsel->sample_area),
+                     "drag_data_received",
+                     GTK_SIGNAL_FUNC (gtk_color_selection_drop_handle),
+                     colorsel);
 }
 
 static void
-gtk_color_selection_destroy (GtkObject *object)
+gtk_color_selection_unrealize (GtkWidget      *widget)
+{
+  GtkColorSelection *colorsel;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_COLOR_SELECTION (widget));
+
+  colorsel = GTK_COLOR_SELECTION (widget);
+
+  if (colorsel->value_gc != NULL)
+    {
+      gdk_gc_unref (colorsel->value_gc);
+      colorsel->value_gc = NULL;
+    }
+  if (colorsel->wheel_gc != NULL)
+    {
+      gdk_gc_unref (colorsel->wheel_gc);
+      colorsel->wheel_gc = NULL;
+    }
+  if (colorsel->sample_gc != NULL)
+    {
+      gdk_gc_unref (colorsel->sample_gc);
+      colorsel->sample_gc = NULL;
+    }
+
+  (* GTK_WIDGET_CLASS (color_selection_parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_color_selection_finalize (GtkObject *object)
 {
   GtkColorSelection *colorsel;
 
@@ -525,8 +601,7 @@ gtk_color_selection_destroy (GtkObject *object)
   if (colorsel->sample_buf != NULL)
     g_free (colorsel->sample_buf);
 
-  if (GTK_OBJECT_CLASS (color_selection_parent_class)->destroy)
-    (*GTK_OBJECT_CLASS (color_selection_parent_class)->destroy) (object);
+  (*GTK_OBJECT_CLASS (color_selection_parent_class)->finalize) (object);
 }
 
 static void
@@ -622,7 +697,7 @@ gtk_color_selection_hsv_updater (GtkWidget *widget,
   if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
     {
       colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-      i = (gint) gtk_object_get_data (GTK_OBJECT (widget), "_ValueIndex");
+      i = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), value_index_key));
 
       if (GTK_IS_SCALE (widget))
        {
@@ -672,7 +747,7 @@ gtk_color_selection_rgb_updater (GtkWidget *widget,
   if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
     {
       colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
-      i = (gint) gtk_object_get_data (GTK_OBJECT (widget), "_ValueIndex");
+      i = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), value_index_key));
 
       if (GTK_IS_SCALE (widget))
        {
@@ -730,13 +805,13 @@ gtk_color_selection_set_opacity (GtkColorSelection *colorsel,
 
   colorsel->use_opacity = use_opacity;
 
-  if (use_opacity == FALSE && GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
+  if (!use_opacity && GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
     {
       gtk_widget_hide (colorsel->opacity_label);
       gtk_widget_hide (colorsel->scales[OPACITY]);
       gtk_widget_hide (colorsel->entries[OPACITY]);
     }
-  else if (use_opacity == TRUE && !GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
+  else if (use_opacity && !GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
     {
       gtk_widget_show (colorsel->opacity_label);
       gtk_widget_show (colorsel->scales[OPACITY]);
@@ -778,39 +853,98 @@ gtk_color_selection_sample_resize (GtkWidget *widget,
 }
 
 static void
-gtk_color_selection_drop_handle (GtkWidget *widget, GdkEvent *event,
-                                GtkWidget *thecolorsel)
+gtk_color_selection_drag_begin (GtkWidget      *widget,
+                               GdkDragContext *context,
+                               gpointer        data)
+{
+  GtkColorSelection *colorsel = data;
+  GtkWidget *window;
+  gdouble colors[4];
+  GdkColor bg;
+
+  window = gtk_window_new(GTK_WINDOW_POPUP);
+  gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
+  gtk_widget_set_usize (window, 48, 32);
+  gtk_widget_realize (window);
+
+  gtk_color_selection_get_color (colorsel, colors);
+  bg.red = 0xffff * colors[0];
+  bg.green = 0xffff * colors[1];
+  bg.blue = 0xffff * colors[2];
+
+  gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
+  gdk_window_set_background (window->window, &bg);
+
+  gtk_drag_set_icon_widget (context, window, -2, -2);
+}
+
+static void
+gtk_color_selection_drop_handle (GtkWidget        *widget, 
+                                GdkDragContext   *context,
+                                gint              x,
+                                gint              y,
+                                GtkSelectionData *selection_data,
+                                guint             info,
+                                guint             time,
+                                gpointer          data)
 {
-  /* This is currently a gdouble array of the format (I think):
-     use_opacity
+  GtkColorSelection *colorsel = data;
+  guint16 *vals;
+  gdouble colors[4];
+
+  /* This is currently a guint16 array of the format:
      R
      G
      B
      opacity
   */
-  gdouble *v = event->dropdataavailable.data;
-  gtk_color_selection_set_opacity(GTK_COLOR_SELECTION(thecolorsel),
-                                 (v[0]==1.0)?TRUE:FALSE);
-  gtk_color_selection_set_color(GTK_COLOR_SELECTION(thecolorsel),
-                               v + 1);
-  g_free(event->dropdataavailable.data);
-  g_free(event->dropdataavailable.data_type);
+
+  if (selection_data->length < 0)
+    return;
+
+  if ((selection_data->format != 16) || 
+      (selection_data->length != 8))
+    {
+      g_warning ("Received invalid color data\n");
+      return;
+    }
+  
+  vals = (guint16 *)selection_data->data;
+
+  colors[0] = (gdouble)vals[0] / 0xffff;
+  colors[1] = (gdouble)vals[1] / 0xffff;
+  colors[2] = (gdouble)vals[2] / 0xffff;
+  colors[3] = (gdouble)vals[3] / 0xffff;
+  
+  gtk_color_selection_set_color(colorsel, colors);
 }
 
 static void
-gtk_color_selection_drag_handle (GtkWidget *widget, GdkEvent *event,
-                                GtkWidget *thecolorsel)
+gtk_color_selection_drag_handle (GtkWidget        *widget, 
+                                GdkDragContext   *context,
+                                GtkSelectionData *selection_data,
+                                guint             info,
+                                guint             time,
+                                gpointer          data)
 {
-  gdouble sendvals[(BLUE - RED + 1) + 3];
+  GtkColorSelection *colorsel = data;
+  guint16 vals[4];
+  gdouble colors[4];
+
+  gtk_color_selection_get_color(colorsel, colors);
 
-  sendvals[0] = (GTK_COLOR_SELECTION(thecolorsel)->use_opacity)?1.0:0.0;
-  gtk_color_selection_get_color(GTK_COLOR_SELECTION(thecolorsel),
-                               sendvals + 1);
+  vals[0] = colors[0] * 0xffff;
+  vals[1] = colors[1] * 0xffff;
+  vals[2] = colors[2] * 0xffff;
+  vals[3] = colorsel->use_opacity ? colors[3] * 0xffff : 0xffff;
 
-  gtk_widget_dnd_data_set(widget,
-                         event,
-                         (gpointer)sendvals,
-                         sizeof(sendvals));
+  g_print ("%x %x\n", vals[0], vals[4]);
+  g_print ("%g\n", colorsel->values[OPACITY]);
+  g_print ("%d\n", colorsel->use_opacity);
+
+  gtk_selection_data_set (selection_data,
+                         gdk_atom_intern ("application/x-color", FALSE),
+                         16, (guchar *)vals, 8);
 }
 
 static void
@@ -892,11 +1026,15 @@ static gint
 gtk_color_selection_value_timeout (GtkColorSelection *colorsel)
 {
   gint x, y;
-
+  
+  GDK_THREADS_ENTER ();
+  
   gdk_window_get_pointer (colorsel->value_area->window, &x, &y, NULL);
   gtk_color_selection_update_value (colorsel, y);
   gtk_color_selection_color_changed (colorsel);
 
+  GDK_THREADS_LEAVE ();
+
   return (TRUE);
 }
 
@@ -909,14 +1047,15 @@ gtk_color_selection_value_events (GtkWidget *area,
 
   colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
 
+  if (colorsel->value_gc == NULL)
+    colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
+
   switch (event->type)
     {
     case GDK_MAP:
       gtk_color_selection_draw_value_marker (colorsel);
       break;
     case GDK_EXPOSE:
-      if (colorsel->value_gc == NULL)
-       colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
       gtk_color_selection_draw_value_marker (colorsel);
       break;
     case GDK_BUTTON_PRESS:
@@ -926,7 +1065,7 @@ gtk_color_selection_value_events (GtkWidget *area,
       break;
     case GDK_BUTTON_RELEASE:
       gtk_grab_remove (area);
-      if (colorsel->timer_active == TRUE)
+      if (colorsel->timer_active)
        gtk_timeout_remove (colorsel->timer_tag);
       colorsel->timer_active = FALSE;
 
@@ -938,6 +1077,13 @@ gtk_color_selection_value_events (GtkWidget *area,
       gtk_color_selection_color_changed (colorsel);
       break;
     case GDK_MOTION_NOTIFY:
+      /* Even though we select BUTTON_MOTION_MASK, we seem to need
+       * to occasionally get events without buttons pressed.
+       */
+      if (!(event->motion.state &
+           (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
+       return FALSE;
+      
       y = event->motion.y;
 
       if (event->motion.is_hint || (event->motion.window != area->window))
@@ -950,7 +1096,7 @@ gtk_color_selection_value_events (GtkWidget *area,
          gtk_color_selection_color_changed (colorsel);
          break;
        case GTK_UPDATE_DELAYED:
-         if (colorsel->timer_active == TRUE)
+         if (colorsel->timer_active)
            gtk_timeout_remove (colorsel->timer_tag);
 
          colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
@@ -989,7 +1135,14 @@ gtk_color_selection_wheel_events (GtkWidget *area,
   gint x, y;
 
   colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
-
+  
+  if (colorsel->wheel_gc == NULL)
+    colorsel->wheel_gc = gdk_gc_new (colorsel->wheel_area->window);
+  if (colorsel->sample_gc == NULL)
+    colorsel->sample_gc = gdk_gc_new (colorsel->sample_area->window);
+  if (colorsel->value_gc == NULL)
+    colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
+  
   switch (event->type)
     {
     case GDK_MAP:
@@ -998,12 +1151,6 @@ gtk_color_selection_wheel_events (GtkWidget *area,
       gtk_color_selection_draw_sample (colorsel, TRUE);
       break;
     case GDK_EXPOSE:
-      if (colorsel->wheel_gc == NULL)
-       colorsel->wheel_gc = gdk_gc_new (colorsel->wheel_area->window);
-      if (colorsel->sample_gc == NULL)
-       colorsel->sample_gc = gdk_gc_new (colorsel->sample_area->window);
-      if (colorsel->value_gc == NULL)
-       colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
       gtk_color_selection_draw_wheel_marker (colorsel);
       gtk_color_selection_draw_wheel_frame (colorsel);
       break;
@@ -1014,7 +1161,7 @@ gtk_color_selection_wheel_events (GtkWidget *area,
       break;
     case GDK_BUTTON_RELEASE:
       gtk_grab_remove (area);
-      if (colorsel->timer_active == TRUE)
+      if (colorsel->timer_active)
        gtk_timeout_remove (colorsel->timer_tag);
       colorsel->timer_active = FALSE;
 
@@ -1028,6 +1175,13 @@ gtk_color_selection_wheel_events (GtkWidget *area,
       gtk_color_selection_color_changed (colorsel);
       break;
     case GDK_MOTION_NOTIFY:
+      /* Even though we select BUTTON_MOTION_MASK, we seem to need
+       * to occasionally get events without buttons pressed.
+       */
+      if (!(event->motion.state &
+           (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
+       return FALSE;
+      
       x = event->motion.x;
       y = event->motion.y;
 
@@ -1041,7 +1195,7 @@ gtk_color_selection_wheel_events (GtkWidget *area,
          gtk_color_selection_color_changed (colorsel);
          break;
        case GTK_UPDATE_DELAYED:
-         if (colorsel->timer_active == TRUE)
+         if (colorsel->timer_active)
            gtk_timeout_remove (colorsel->timer_tag);
          colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
                                                 (GtkFunction) gtk_color_selection_wheel_timeout,
@@ -1101,7 +1255,7 @@ gtk_color_selection_draw_value_bar (GtkColorSelection *colorsel,
       v -= sv;
     }
 
-  gtk_widget_draw (colorsel->value_area, NULL);
+  gtk_widget_queue_draw (colorsel->value_area);
 }
 
 static void
@@ -1110,7 +1264,7 @@ gtk_color_selection_draw_wheel_frame (GtkColorSelection *colorsel)
   GtkStyle *style;
   gint w, h;
 
-  style = gtk_widget_get_style (GTK_WIDGET (colorsel));
+  style = gtk_widget_get_style (colorsel->wheel_area);
 
   w = colorsel->wheel_area->allocation.width;
   h = colorsel->wheel_area->allocation.height;
@@ -1133,7 +1287,7 @@ gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
   gint x, y, i, wid, heig, n;
   gdouble cx, cy, h, s, c[3];
   guchar bg[3];
-  GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (colorsel));
+  GtkStyle *style = gtk_widget_get_style (colorsel->wheel_area);
 
   wid = colorsel->wheel_area->allocation.width;
   heig = colorsel->wheel_area->allocation.height;
@@ -1158,7 +1312,7 @@ gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
       i = 0;
       for (x = 0; x < wid; x++)
        {
-         if (gtk_color_selection_eval_wheel (x, y, cx, cy, &h, &s) == TRUE)
+         if (gtk_color_selection_eval_wheel (x, y, cx, cy, &h, &s))
            {
              for (n = 0; n < 3; n++)
                colorsel->wheel_buf[i++] = bg[n];
@@ -1174,7 +1328,39 @@ gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
       gtk_preview_draw_row (GTK_PREVIEW (colorsel->wheel_area), colorsel->wheel_buf, 0, y, wid);
     }
 
-  gtk_widget_draw (colorsel->wheel_area, NULL);
+  if (colorsel->wheel_area->window)
+     {
+       GdkPixmap *pm = NULL;
+       GdkGC     *pmgc = NULL;
+       GdkColor   col;
+       gint w, h;
+       
+       pm = gdk_pixmap_new (colorsel->wheel_area->window, wid, heig, 1);
+       pmgc = gdk_gc_new (pm);
+       
+       col.pixel = 0;
+       gdk_gc_set_foreground(pmgc, &col);
+       gdk_draw_rectangle(pm, pmgc, TRUE, 0, 0, wid, heig);
+       col.pixel = 1;
+       
+       gdk_gc_set_foreground(pmgc, &col);
+       gdk_draw_arc (pm, pmgc, TRUE, 0, 0, wid, heig, 0, 360*64);
+
+       w = colorsel->wheel_area->allocation.width;
+       h = colorsel->wheel_area->allocation.height;
+       
+       gdk_draw_arc (pm, pmgc,
+                     FALSE, 1, 1, w - 1, h - 1, 30 * 64, 180 * 64);
+       gdk_draw_arc (pm, pmgc,
+                     FALSE, 0, 0, w, h, 30 * 64, 180 * 64);
+       gdk_draw_arc (pm, pmgc,
+                     FALSE, 1, 1, w - 1, h - 1, 210 * 64, 180 * 64);
+       gdk_draw_arc (pm, pmgc,
+                     FALSE, 0, 0, w, h, 210 * 64, 180 * 64);
+       gdk_window_shape_combine_mask(colorsel->wheel_area->window, pm, 0, 0);
+       gdk_pixmap_unref(pm);
+       gdk_gc_destroy(pmgc);
+     }
 }
 
 static void
@@ -1204,7 +1390,7 @@ gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
       c[n + 3] = (guchar) (255.0 * colorsel->values[i++]);
     }
 
-  if (colorsel->use_opacity == TRUE)
+  if (colorsel->use_opacity)
     {
       o = colorsel->values[OPACITY];
       oldo = colorsel->old_values[OPACITY];
@@ -1239,7 +1425,7 @@ gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
       gtk_preview_draw_row (GTK_PREVIEW (colorsel->sample_area), colorsel->sample_buf, 0, y, wid);
     }
 
-  gtk_widget_draw (colorsel->sample_area, NULL);
+  gtk_widget_queue_draw (colorsel->sample_area);
 }
 
 static gint
@@ -1247,12 +1433,13 @@ gtk_color_selection_eval_wheel (gint     x,  gint     y,
                                gdouble  cx, gdouble  cy,
                                gdouble *h,  gdouble *s)
 {
-  gdouble d, r, rx, ry, l;
+  gdouble r, rx, ry;
 
-  rx = (gdouble) x - cx;
-  ry = (gdouble) y - cy;
+  rx = ((gdouble) x - cx);
+  ry = ((gdouble) y - cy);
 
-  d = (SQR (cy) * SQR (rx) + SQR (cx) * SQR (ry) - SQR (cx) * SQR (cy));
+  rx = rx/cx;
+  ry = ry/cy;
 
   r = sqrt (SQR (rx) + SQR (ry));
 
@@ -1261,16 +1448,17 @@ gtk_color_selection_eval_wheel (gint     x,  gint     y,
   else
     *h = 0.0;
 
-  l = sqrt (SQR ((cx * cos (*h + 0.5 * M_PI))) + SQR ((cy * sin (*h + 0.5 * M_PI))));
-  *s = r / l;
+  *s = r;
   *h = 360.0 * (*h) / (2.0 * M_PI) + 180;
 
   if (*s == 0.0)
     *s = 0.00001;
   else if (*s > 1.0)
-    *s = 1.0;
-
-  return ((d > 0.0));
+    {
+      *s = 1.0;
+      return TRUE;
+    }
+  return FALSE;
 }
 
 static void
@@ -1386,7 +1574,7 @@ gtk_color_selection_rgb_to_hsv (gdouble  r, gdouble  g, gdouble  b,
 /***************************/
 
 guint
-gtk_color_selection_dialog_get_type ()
+gtk_color_selection_dialog_get_type (void)
 {
   static guint color_selection_dialog_type = 0;
 
@@ -1394,11 +1582,14 @@ gtk_color_selection_dialog_get_type ()
     {
       GtkTypeInfo colorsel_diag_info =
       {
-       "color selection dialog",
+       "GtkColorSelectionDialog",
        sizeof (GtkColorSelectionDialog),
        sizeof (GtkColorSelectionDialogClass),
        (GtkClassInitFunc) gtk_color_selection_dialog_class_init,
        (GtkObjectInitFunc) gtk_color_selection_dialog_init,
+       /* reserved_1 */ NULL,
+       /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
       };
 
       color_selection_dialog_type = gtk_type_unique (gtk_window_get_type (), &colorsel_diag_info);
@@ -1407,25 +1598,23 @@ gtk_color_selection_dialog_get_type ()
   return color_selection_dialog_type;
 }
 
-void
-gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *class)
+static void
+gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass)
 {
   GtkObjectClass *object_class;
 
-  object_class = (GtkObjectClass*) class;
+  object_class = (GtkObjectClass*) klass;
 
   color_selection_dialog_parent_class = gtk_type_class (gtk_window_get_type ());
-
-  object_class->destroy = gtk_color_selection_dialog_destroy;
 }
 
-void
+static void
 gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag)
 {
   GtkWidget *action_area, *frame;
 
   colorseldiag->main_vbox = gtk_vbox_new (FALSE, 10);
-  gtk_container_border_width (GTK_CONTAINER (colorseldiag), 10);
+  gtk_container_set_border_width (GTK_CONTAINER (colorseldiag), 10);
   gtk_container_add (GTK_CONTAINER (colorseldiag), colorseldiag->main_vbox);
   gtk_widget_show (colorseldiag->main_vbox);
 
@@ -1438,7 +1627,9 @@ gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag)
   gtk_container_add (GTK_CONTAINER (frame), colorseldiag->colorsel);
   gtk_widget_show (colorseldiag->colorsel);
 
-  action_area = gtk_hbox_new (TRUE, 10);
+  action_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(action_area), GTK_BUTTONBOX_END);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(action_area), 5);
   gtk_box_pack_end (GTK_BOX (colorseldiag->main_vbox), action_area, FALSE, FALSE, 0);
   gtk_widget_show (action_area);
 
@@ -1469,18 +1660,3 @@ gtk_color_selection_dialog_new (const gchar *title)
 
   return GTK_WIDGET (colorseldiag);
 }
-
-static void
-gtk_color_selection_dialog_destroy (GtkObject *object)
-{
-  GtkColorSelectionDialog *colorseldiag;
-
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_COLOR_SELECTION_DIALOG (object));
-
-  colorseldiag = GTK_COLOR_SELECTION_DIALOG (object);
-
-
-  if (GTK_OBJECT_CLASS (color_selection_dialog_parent_class)->destroy)
-    (*GTK_OBJECT_CLASS (color_selection_dialog_parent_class)->destroy) (object);
-}