gtkcolorsel.c 77.5 KB
Newer Older
1
/* GTK - The GIMP Toolkit
2
 * Copyright (C) 2000 Red Hat, Inc.
Elliot Lee's avatar
Elliot Lee committed
3 4 5
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16 17 18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
19
 */
20 21

/*
22
 * Modified by the GTK+ Team and others 1997-2001.  See the AUTHORS
23 24 25 26 27
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

28
#include "gdkconfig.h"
29
#include <math.h>
30

31
#include "gdk/gdkkeysyms.h"
Elliot Lee's avatar
Elliot Lee committed
32
#include "gtkcolorsel.h"
33
#include "gtkhsv.h"
Owen Taylor's avatar
Owen Taylor committed
34
#include "gtkwindow.h"
35 36 37 38
#include "gtkselection.h"
#include "gtkdnd.h"
#include "gtkdrawingarea.h"
#include "gtkhbox.h"
39
#include "gtkhbbox.h"
40 41 42 43
#include "gtkrc.h"
#include "gtkframe.h"
#include "gtktable.h"
#include "gtklabel.h"
44
#include "gtkmarshalers.h"
Manish Singh's avatar
Manish Singh committed
45
#include "gtkimage.h"
46 47 48 49 50 51
#include "gtkspinbutton.h"
#include "gtkrange.h"
#include "gtkhscale.h"
#include "gtkentry.h"
#include "gtkbutton.h"
#include "gtkhseparator.h"
52 53 54 55 56
#include "gtktooltips.h"
#include "gtkinvisible.h"
#include "gtkmenuitem.h"
#include "gtkmain.h"
#include "gtksettings.h"
57
#include "gtkintl.h"
58
#include "gtkimage.h"
59
#include "gtkstock.h"
Elliot Lee's avatar
Elliot Lee committed
60

61 62
#include <string.h>

63 64 65 66
/* Number of elements in the custom palatte */
#define GTK_CUSTOM_PALETTE_WIDTH 10
#define GTK_CUSTOM_PALETTE_HEIGHT 2

67 68 69 70 71 72 73
/* 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))


74
enum {
Elliot Lee's avatar
Elliot Lee committed
75 76 77 78
  COLOR_CHANGED,
  LAST_SIGNAL
};

79 80 81 82 83
enum {
  PROP_0,
  PROP_HAS_PALETTE,
  PROP_HAS_OPACITY_CONTROL,
  PROP_CURRENT_COLOR,
84
  PROP_CURRENT_ALPHA
85 86
};

87
enum {
88 89 90 91 92 93 94 95
  COLORSEL_RED = 0,
  COLORSEL_GREEN = 1,
  COLORSEL_BLUE = 2,
  COLORSEL_OPACITY = 3,
  COLORSEL_HUE,
  COLORSEL_SATURATION,
  COLORSEL_VALUE,
  COLORSEL_NUM_CHANNELS
Elliot Lee's avatar
Elliot Lee committed
96 97
};

98
typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
99

100
struct _ColorSelectionPrivate
Elliot Lee's avatar
Elliot Lee committed
101
{
102 103
  guint has_opacity : 1;
  guint has_palette : 1;
104 105
  guint changing : 1;
  guint default_set : 1;
106
  guint default_alpha_set : 1;
107
  
108 109
  gdouble color[COLORSEL_NUM_CHANNELS];
  gdouble old_color[COLORSEL_NUM_CHANNELS];
110
  
111 112 113 114 115 116 117 118 119 120 121 122
  GtkWidget *triangle_colorsel;
  GtkWidget *hue_spinbutton;
  GtkWidget *sat_spinbutton;
  GtkWidget *val_spinbutton;
  GtkWidget *red_spinbutton;
  GtkWidget *green_spinbutton;
  GtkWidget *blue_spinbutton;
  GtkWidget *opacity_slider;
  GtkWidget *opacity_label;
  GtkWidget *opacity_entry;
  GtkWidget *palette_frame;
  GtkWidget *hex_entry;
123
  
124
  /* The Palette code */
125 126
  GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
  
127 128 129 130 131
  /* The color_sample stuff */
  GtkWidget *sample_area;
  GtkWidget *old_sample;
  GtkWidget *cur_sample;
  GtkWidget *colorsel;
132 133 134 135 136 137

  /* Tooltips group */
  GtkTooltips *tooltips;

  /* Window for grabbing on */
  GtkWidget *dropper_grab_widget;
138 139

  /* Connection to settings */
140
  gulong settings_connection;
Elliot Lee's avatar
Elliot Lee committed
141 142 143
};


144
static void gtk_color_selection_init		(GtkColorSelection	 *colorsel);
145
static void gtk_color_selection_class_init	(GtkColorSelectionClass	 *klass);
146
static void gtk_color_selection_destroy		(GtkObject		 *object);
147
static void gtk_color_selection_finalize        (GObject		 *object);
148
static void update_color			(GtkColorSelection	 *colorsel);
149 150 151 152 153 154 155 156
static void gtk_color_selection_set_property    (GObject                 *object,
					         guint                    prop_id,
					         const GValue            *value,
					         GParamSpec              *pspec);
static void gtk_color_selection_get_property    (GObject                 *object,
					         guint                    prop_id,
					         GValue                  *value,
					         GParamSpec              *pspec);
157

158 159
static void gtk_color_selection_realize         (GtkWidget               *widget);
static void gtk_color_selection_unrealize       (GtkWidget               *widget);
160
static void gtk_color_selection_show_all        (GtkWidget               *widget);
161

162 163 164
static void     gtk_color_selection_set_palette_color   (GtkColorSelection *colorsel,
                                                         gint               index,
                                                         GdkColor          *color);
165 166
static GdkGC   *get_focus_gc                            (GtkWidget         *drawing_area,
							 gint              *focus_width);
167 168 169 170
static void     default_noscreen_change_palette_func    (const GdkColor    *colors,
							 gint               n_colors);
static void     default_change_palette_func             (GdkScreen	   *screen,
							 const GdkColor    *colors,
171
							 gint               n_colors);
172

173
static gpointer parent_class = NULL;
174 175
static guint color_selection_signals[LAST_SIGNAL] = { 0 };

176
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";
177

178 179
static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
180 181 182 183 184 185 186 187

/* The cursor for the dropper */
#define DROPPER_WIDTH 17
#define DROPPER_HEIGHT 17
#define DROPPER_X_HOT 2
#define DROPPER_Y_HOT 16


Matthias Clasen's avatar
Matthias Clasen committed
188
static const guchar dropper_bits[] = {
189 190 191 192 193 194
  0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
  0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
  0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
  0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
  0xff, 0xff, 0x01, };

Matthias Clasen's avatar
Matthias Clasen committed
195
static const guchar dropper_mask[] = {
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
  0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
  0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
  0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
  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_draw_samples (GtkColorSelection *colorsel);
Elliot Lee's avatar
Elliot Lee committed
213

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
static void
set_color_internal (GtkColorSelection *colorsel,
		    gdouble           *color)
{
  ColorSelectionPrivate *priv;
  gint i;
  
  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);
}

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
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)));

  gdk_pixbuf_fill (pixbuf, pixel);
  
  gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
Manish Singh's avatar
Manish Singh committed
260
  g_object_unref (pixbuf);
261 262
}

263
static void
264 265 266
color_sample_drag_begin (GtkWidget      *widget,
			 GdkDragContext *context,
			 gpointer        data)
Elliot Lee's avatar
Elliot Lee committed
267
{
268 269 270
  GtkColorSelection *colorsel = data;
  ColorSelectionPrivate *priv;
  gdouble *colsrc;
271
  
272
  priv = colorsel->private_data;
273
  
274 275 276 277
  if (widget == priv->old_sample)
    colsrc = priv->old_color;
  else
    colsrc = priv->color;
278 279

  set_color_icon (context, colsrc);
Elliot Lee's avatar
Elliot Lee committed
280 281
}

282
static void
283 284 285
color_sample_drag_end (GtkWidget      *widget,
		       GdkDragContext *context,
		       gpointer        data)
Elliot Lee's avatar
Elliot Lee committed
286
{
Manish Singh's avatar
Manish Singh committed
287
  g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
288
}
Elliot Lee's avatar
Elliot Lee committed
289

290 291 292 293 294 295 296 297 298 299 300 301 302 303
static void
color_sample_drop_handle (GtkWidget        *widget,
			  GdkDragContext   *context,
			  gint              x,
			  gint              y,
			  GtkSelectionData *selection_data,
			  guint             info,
			  guint             time,
			  gpointer          data)
{
  GtkColorSelection *colorsel = data;
  ColorSelectionPrivate *priv;
  guint16 *vals;
  gdouble color[4];
304
  priv = colorsel->private_data;
305
  
306 307 308 309 310 311
  /* This is currently a guint16 array of the format:
   * R
   * G
   * B
   * opacity
   */
312
  
313 314
  if (selection_data->length < 0)
    return;
315
  
316 317 318 319
  /* 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)
320 321 322
    {
      g_warning ("Received invalid color data\n");
      return;
Elliot Lee's avatar
Elliot Lee committed
323
    }
324
  
325
  vals = (guint16 *)selection_data->data;
326
  
327
  if (widget == priv->cur_sample)
328
    {
329 330 331 332
      color[0] = (gdouble)vals[0] / 0xffff;
      color[1] = (gdouble)vals[1] / 0xffff;
      color[2] = (gdouble)vals[2] / 0xffff;
      color[3] = (gdouble)vals[3] / 0xffff;
333
      
334
      set_color_internal (colorsel, color);
335 336 337 338
    }
}

static void
339 340 341 342 343 344
color_sample_drag_handle (GtkWidget        *widget,
			  GdkDragContext   *context,
			  GtkSelectionData *selection_data,
			  guint             info,
			  guint             time,
			  gpointer          data)
345
{
346 347 348 349
  GtkColorSelection *colorsel = data;
  ColorSelectionPrivate *priv;
  guint16 vals[4];
  gdouble *colsrc;
350
  
351
  priv = colorsel->private_data;
352
  
353 354 355 356
  if (widget == priv->old_sample)
    colsrc = priv->old_color;
  else
    colsrc = priv->color;
357
  
358 359 360
  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
361
  vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
362
  
363 364 365
  gtk_selection_data_set (selection_data,
			  gdk_atom_intern ("application/x-color", FALSE),
			  16, (guchar *)vals, 8);
Elliot Lee's avatar
Elliot Lee committed
366 367
}

368 369 370
/* which = 0 means draw old sample, which = 1 means draw new */
static void
color_sample_draw_sample (GtkColorSelection *colorsel, int which)
Elliot Lee's avatar
Elliot Lee committed
371
{
372 373 374 375 376 377
  GtkWidget *da;
  gint x, y, i, wid, heig, f, n, goff;
  guchar c[3 * 2], cc[3 * 4], *cp = c;
  gdouble o;
  guchar *buf;
  ColorSelectionPrivate *priv;
378
  
Elliot Lee's avatar
Elliot Lee committed
379
  g_return_if_fail (colorsel != NULL);
380
  priv = colorsel->private_data;
381
  
382 383 384
  g_return_if_fail (priv->sample_area != NULL);
  if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
    return;
385
  
386 387 388 389
  if (which == 0)
    {
      da = priv->old_sample;
      for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
390
	c[n] = (guchar) (UNSCALE (priv->old_color[i]) >> 8);
391 392 393 394 395 396
      goff = 0;
    }
  else
    {
      da = priv->cur_sample;
      for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
397
	c[n] = (guchar) (UNSCALE (priv->color[i]) >> 8);
398
      goff =  priv->old_sample->allocation.width % 32;
Elliot Lee's avatar
Elliot Lee committed
399
    }
400
  
401 402
  wid = da->allocation.width;
  heig = da->allocation.height;
403
  
404
  buf = g_new (guchar, 3 * wid * heig);
405
  
406 407 408 409 410 411 412 413
#if 0
  i = COLORSEL_RED;
  for (n = 0; n < 3; n++)
    {
      c[n] = (guchar) (255.0 * priv->old_color[i]);
      c[n + 3] = (guchar) (255.0 * priv->color[i++]);
    }
#endif
414
  
415
  if (priv->has_opacity)
Elliot Lee's avatar
Elliot Lee committed
416
    {
417
      o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY];
418
      
419 420 421 422 423 424
      for (n = 0; n < 3; n++)
	{
	  cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n]));
	  cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n]));
	}
      cp = cc;
Elliot Lee's avatar
Elliot Lee committed
425
    }
426
  
427 428
  i = 0;
  for (y = 0; y < heig; y++)
Elliot Lee's avatar
Elliot Lee committed
429
    {
430 431
      for (x = 0; x < wid; x++)
	{
432
	  if (priv->has_opacity)
433 434 435
	    f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16));
	  else
	    f = 0;
436
	  
437 438 439
	  for (n = 0; n < 3; n++)
	    buf[i++] = cp[n + f];
	}
Elliot Lee's avatar
Elliot Lee committed
440
    }
441
  
442 443 444 445 446 447 448
  gdk_draw_rgb_image (da->window,
		      da->style->black_gc,
		      0, 0,
		      wid, heig,
		      GDK_RGB_DITHER_NORMAL,
		      buf,
		      3*wid);
449 450
  
  
451
  g_free (buf);
Elliot Lee's avatar
Elliot Lee committed
452 453 454
}


455 456 457 458 459 460
static void
color_sample_draw_samples (GtkColorSelection *colorsel)
{
  color_sample_draw_sample (colorsel, 0);
  color_sample_draw_sample (colorsel, 1);
}
Elliot Lee's avatar
Elliot Lee committed
461

462
static gboolean
463 464 465
color_old_sample_expose (GtkWidget         *da,
			 GdkEventExpose    *event,
			 GtkColorSelection *colorsel)
466 467
{
  color_sample_draw_sample (colorsel, 0);
468
  return FALSE;
Elliot Lee's avatar
Elliot Lee committed
469 470
}

471

472
static gboolean
473 474 475
color_cur_sample_expose (GtkWidget         *da,
			 GdkEventExpose    *event,
			 GtkColorSelection *colorsel)
Elliot Lee's avatar
Elliot Lee committed
476
{
477
  color_sample_draw_sample (colorsel, 1);
478
  return FALSE;
479
}
480

481 482 483
static void
color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
{
484
  static const GtkTargetEntry targets[] = {
485 486
    { "application/x-color", 0 }
  };
487
  ColorSelectionPrivate *priv;
488
  priv = colorsel->private_data;
489
  
490
  gtk_drag_source_set (sample,
491 492 493
		       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
		       targets, 1,
		       GDK_ACTION_COPY | GDK_ACTION_MOVE);
494
  
Manish Singh's avatar
Manish Singh committed
495 496 497 498
  g_signal_connect (sample,
		    "drag_begin",
		    G_CALLBACK (color_sample_drag_begin),
		    colorsel);
499 500
  if (sample == priv->cur_sample)
    {
501
      
502 503 504 505 506 507
      gtk_drag_dest_set (sample,
			 GTK_DEST_DEFAULT_HIGHLIGHT |
			 GTK_DEST_DEFAULT_MOTION |
			 GTK_DEST_DEFAULT_DROP,
			 targets, 1,
			 GDK_ACTION_COPY);
508
      
Manish Singh's avatar
Manish Singh committed
509 510 511 512
      g_signal_connect (sample,
			"drag_end",
			G_CALLBACK (color_sample_drag_end),
			colorsel);
513
    }
514
  
Manish Singh's avatar
Manish Singh committed
515 516 517 518 519 520 521 522
  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);
523
  
Elliot Lee's avatar
Elliot Lee committed
524 525
}

526

527
static void
528
color_sample_new (GtkColorSelection *colorsel)
529
{
530
  ColorSelectionPrivate *priv;
531
  
532
  priv = colorsel->private_data;
533
  
534 535 536
  priv->sample_area = gtk_hbox_new (FALSE, 0);
  priv->old_sample = gtk_drawing_area_new ();
  priv->cur_sample = gtk_drawing_area_new ();
537 538 539 540 541 542

  /* We need enter/leave to do tooltips */
  gtk_widget_add_events (priv->old_sample,
                         GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
  gtk_widget_add_events (priv->cur_sample,
                         GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
543
  
544 545 546 547
  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);
548
  
Manish Singh's avatar
Manish Singh committed
549 550 551 552 553 554
  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);
555
  
556 557
  color_sample_setup_dnd (colorsel, priv->old_sample);
  color_sample_setup_dnd (colorsel, priv->cur_sample);
558 559 560 561 562 563 564 565 566

  gtk_tooltips_set_tip (priv->tooltips,
                        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."), NULL);


  gtk_tooltips_set_tip (priv->tooltips,
                        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."), NULL);
567
  
568
  gtk_widget_show_all (priv->sample_area);
Elliot Lee's avatar
Elliot Lee committed
569 570
}

571 572 573 574 575 576

/*
 *
 * The palette area code
 *
 */
577 578
#define CUSTOM_PALETTE_ENTRY_WIDTH   20
#define CUSTOM_PALETTE_ENTRY_HEIGHT  20
579

Elliot Lee's avatar
Elliot Lee committed
580
static void
581
palette_get_color (GtkWidget *drawing_area, gdouble *color)
Elliot Lee's avatar
Elliot Lee committed
582
{
583
  gdouble *color_val;
584
  
585
  g_return_if_fail (color != NULL);
586
  
Manish Singh's avatar
Manish Singh committed
587
  color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val");
588
  if (color_val == NULL)
Elliot Lee's avatar
Elliot Lee committed
589
    {
590 591 592 593 594 595
      /* Default to white for no good reason */
      color[0] = 1.0;
      color[1] = 1.0;
      color[2] = 1.0;
      color[3] = 1.0;
      return;
Elliot Lee's avatar
Elliot Lee committed
596
    }
597
  
598 599 600 601
  color[0] = color_val[0];
  color[1] = color_val[1];
  color[2] = color_val[2];
  color[3] = 1.0;
Elliot Lee's avatar
Elliot Lee committed
602 603
}

604
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
Elliot Lee's avatar
Elliot Lee committed
605
static void
606 607 608
palette_paint (GtkWidget    *drawing_area,
	       GdkRectangle *area,
	       gpointer      data)
Elliot Lee's avatar
Elliot Lee committed
609
{
610 611
  if (drawing_area->window == NULL)
    return;
612 613 614 615 616

  gdk_draw_rectangle (drawing_area->window,
                      drawing_area->style->bg_gc[GTK_STATE_NORMAL],
                      TRUE,
                      area->x, area->y, area->width, area->height);
617
  
618
  if (GTK_WIDGET_HAS_FOCUS (drawing_area))
619
    {
620 621
      gint focus_width;
      GdkGC *gc = get_focus_gc (drawing_area, &focus_width);
622
      gdk_draw_rectangle (drawing_area->window,
623 624 625 626
			  gc, FALSE, focus_width / 2, focus_width / 2,
			  drawing_area->allocation.width - focus_width,
			  drawing_area->allocation.height - focus_width);
      g_object_unref (gc);
Elliot Lee's avatar
Elliot Lee committed
627 628 629
    }
}

630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
static GdkGC *
get_focus_gc (GtkWidget *drawing_area,
	      gint      *focus_width)
{
  GdkGC *gc = gdk_gc_new (drawing_area->window);
  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)
    gdk_gc_copy (gc, drawing_area->style->black_gc);
  else
    gdk_gc_copy (gc, drawing_area->style->white_gc);

  gdk_gc_set_line_attributes (gc, *focus_width,
			      dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
			      GDK_CAP_BUTT, GDK_JOIN_MITER);

  if (dash_list[0])
655
    gdk_gc_set_dashes (gc, 0, dash_list, strlen ((char *)dash_list));
656

657 658
  g_free (dash_list);
  
659 660
  return gc;
}
Elliot Lee's avatar
Elliot Lee committed
661 662

static void
663 664 665
palette_drag_begin (GtkWidget      *widget,
		    GdkDragContext *context,
		    gpointer        data)
666 667
{
  gdouble colors[4];
668
  
669
  palette_get_color (widget, colors);
670
  set_color_icon (context, colors);
671 672
}

673
static void
674 675 676 677 678 679 680 681 682
palette_drag_handle (GtkWidget        *widget,
		     GdkDragContext   *context,
		     GtkSelectionData *selection_data,
		     guint             info,
		     guint             time,
		     gpointer          data)
{
  guint16 vals[4];
  gdouble colsrc[4];
683
  
684
  palette_get_color (widget, colsrc);
685
  
686 687 688 689
  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
  vals[3] = 0xffff;
690
  
691 692 693 694 695
  gtk_selection_data_set (selection_data,
			  gdk_atom_intern ("application/x-color", FALSE),
			  16, (guchar *)vals, 8);
}

696 697 698 699 700
static void
palette_drag_end (GtkWidget      *widget,
		  GdkDragContext *context,
		  gpointer        data)
{
Manish Singh's avatar
Manish Singh committed
701
  g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
702 703
}

704 705 706 707 708 709 710 711 712
static GdkColor *
get_current_colors (GtkColorSelection *colorsel)
{
  GtkSettings *settings;
  GdkColor *colors = NULL;
  gint n_colors = 0;
  gchar *palette;

  settings = gtk_widget_get_settings (GTK_WIDGET (colorsel));
713
  g_object_get (settings,
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
		"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;
}

744 745 746 747 748 749 750 751 752
/* Changes the model color */
static void
palette_change_color (GtkWidget         *drawing_area,
                      GtkColorSelection *colorsel,
                      gdouble           *color)
{
  gint x, y;
  ColorSelectionPrivate *priv;
  GdkColor gdk_color;
753 754
  GdkColor *current_colors;
  GdkScreen *screen;
755 756 757 758 759 760

  g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
  g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area));
  
  priv = colorsel->private_data;
  
761 762 763
  gdk_color.red = UNSCALE (color[0]);
  gdk_color.green = UNSCALE (color[1]);
  gdk_color.blue = UNSCALE (color[2]);
764 765

  x = 0;
766
  y = 0;			/* Quiet GCC */
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
  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;
        }

      ++x;
    }

 out:
  
  g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT);

785
  current_colors = get_current_colors (colorsel);
786 787
  current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color;

788 789 790 791 792 793
  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)
    {
Owen Taylor's avatar
Owen Taylor committed
794
      if (screen != gdk_screen_get_default ())
795 796 797 798 799 800 801 802 803
	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);

  g_free (current_colors);
804 805 806
}

/* Changes the view color */
807
static void
808 809 810
palette_set_color (GtkWidget         *drawing_area,
		   GtkColorSelection *colorsel,
		   gdouble           *color)
811 812
{
  gdouble *new_color = g_new (double, 4);
813
  GdkColor gdk_color;
814
  
815 816 817
  gdk_color.red = UNSCALE (color[0]);
  gdk_color.green = UNSCALE (color[1]);
  gdk_color.blue = UNSCALE (color[2]);
818 819

  gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color);
820
  
Manish Singh's avatar
Manish Singh committed
821
  if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0)
822 823 824 825 826 827 828 829
    {
      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);
830
      
Manish Singh's avatar
Manish Singh committed
831 832 833 834 835 836 837 838
      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);
839
      
Manish Singh's avatar
Manish Singh committed
840 841
      g_object_set_data (G_OBJECT (drawing_area), "color_set",
			 GINT_TO_POINTER (1));
842
    }
843

844 845 846 847
  new_color[0] = color[0];
  new_color[1] = color[1];
  new_color[2] = color[2];
  new_color[3] = 1.0;
848
  
849
  g_object_set_data_full (G_OBJECT (drawing_area), "color_val", new_color, (GDestroyNotify)g_free);
850 851
}

852
static gboolean
853 854 855
palette_expose (GtkWidget      *drawing_area,
		GdkEventExpose *event,
		gpointer        data)
856
{
857
  if (drawing_area->window == NULL)
858
    return FALSE;
859 860
  
  palette_paint (drawing_area, &(event->area), data);
861 862
  
  return FALSE;
863 864 865 866 867 868 869 870 871 872 873 874
}

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;
875
  GdkScreen *screen;
876 877 878 879 880 881 882 883 884 885 886 887 888 889
  
  widget = GTK_WIDGET (user_data);
  
  g_return_if_fail (GTK_WIDGET_REALIZED (widget));

  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 */
890 891 892
  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));
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
}

static void
save_color_selected (GtkWidget *menuitem,
                     gpointer   data)
{
  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);  
}

static void
do_popup (GtkColorSelection *colorsel,
          GtkWidget         *drawing_area,
          guint32            timestamp)
{
  GtkWidget *menu;
  GtkWidget *mi;
  
  g_object_set_data (G_OBJECT (drawing_area),
                     "gtk-color-sel",
                     colorsel);
  
  menu = gtk_menu_new ();

927
  mi = gtk_menu_item_new_with_mnemonic (_("_Save color here"));
928

Manish Singh's avatar
Manish Singh committed
929 930 931
  g_signal_connect (mi, "activate",
                    G_CALLBACK (save_color_selected),
                    drawing_area);
932 933 934 935 936 937 938 939 940 941 942
  
  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);
}


943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
static gboolean
palette_enter (GtkWidget        *drawing_area,
	       GdkEventCrossing *event,
	       gpointer        data)
{
  g_object_set_data (G_OBJECT (drawing_area),
		     "gtk-colorsel-have-pointer",
		     GUINT_TO_POINTER (TRUE));

  return FALSE;
}

static gboolean
palette_leave (GtkWidget        *drawing_area,
	       GdkEventCrossing *event,
	       gpointer        data)
{
  g_object_set_data (G_OBJECT (drawing_area),
		     "gtk-colorsel-have-pointer",
		     NULL);

  return FALSE;
}

static gboolean
968 969 970 971 972 973 974 975
palette_press (GtkWidget      *drawing_area,
	       GdkEventButton *event,
	       gpointer        data)
{
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);

  gtk_widget_grab_focus (drawing_area);
  
976
  if (event->button == 3 &&
977
      event->type == GDK_BUTTON_PRESS)
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
    {
      do_popup (colorsel, drawing_area, event->time);
      return TRUE;
    }

  return FALSE;
}

static gboolean
palette_release (GtkWidget      *drawing_area,
		 GdkEventButton *event,
		 gpointer        data)
{
  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)
    {
Manish Singh's avatar
Manish Singh committed
999
      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0)
1000 1001 1002
        {
          gdouble color[4];
          palette_get_color (drawing_area, color);
1003
          set_color_internal (colorsel, color);
1004 1005
        }
    }
1006 1007

  return FALSE;
1008 1009
}

1010
static void
1011 1012 1013 1014 1015 1016 1017 1018
palette_drop_handle (GtkWidget        *widget,
		     GdkDragContext   *context,
		     gint              x,
		     gint              y,
		     GtkSelectionData *selection_data,
		     guint             info,
		     guint             time,
		     gpointer          data)
Elliot Lee's avatar
Elliot Lee committed
1019
{
1020
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1021
  guint16 *vals;
1022
  gdouble color[4];
1023
  
1024 1025
  if (selection_data->length < 0)
    return;
1026
  
1027 1028 1029 1030
  /* 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)
1031 1032 1033 1034
    {
      g_warning ("Received invalid color data\n");
      return;
    }
1035
  
1036
  vals = (guint16 *)selection_data->data;
1037
  
1038 1039 1040 1041
  color[0] = (gdouble)vals[0] / 0xffff;
  color[1] = (gdouble)vals[1] / 0xffff;
  color[2] = (gdouble)vals[2] / 0xffff;
  color[3] = (gdouble)vals[3] / 0xffff;
1042 1043
  palette_change_color (widget, colorsel, color);
  set_color_internal (colorsel, color);
1044 1045
}

1046 1047 1048 1049
static gint
palette_activate (GtkWidget   *widget,
		  GdkEventKey *event,
		  gpointer     data)
1050
{
1051
  /* should have a drawing area subclass with an activate signal */
1052 1053 1054 1055
  if ((event->keyval == GDK_space) ||
      (event->keyval == GDK_Return) ||
      (event->keyval == GDK_KP_Enter) ||
      (event->keyval == GDK_KP_Space))
1056
    {
Manish Singh's avatar
Manish Singh committed
1057
      if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0)
1058 1059 1060
        {
          gdouble color[4];
          palette_get_color (widget, color);
1061
          set_color_internal (GTK_COLOR_SELECTION (data), color);
1062
        }
1063
      return TRUE;
1064
    }
1065
  
1066
  return FALSE;
Elliot Lee's avatar
Elliot Lee committed
1067 1068
}

1069
static gboolean
1070 1071 1072 1073 1074 1075
palette_popup (GtkWidget *widget,
               gpointer   data)
{
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);

  do_popup (colorsel, widget, GDK_CURRENT_TIME);
1076
  return TRUE;
1077 1078 1079
}
               

1080
static GtkWidget*
1081
palette_new (GtkColorSelection *colorsel)
Elliot Lee's avatar
Elliot Lee committed
1082
{
1083
  GtkWidget *retval;
1084
  ColorSelectionPrivate *priv;
1085 1086 1087 1088
  
  static const GtkTargetEntry targets[] = {
    { "application/x-color", 0 }
  };
1089 1090

  priv = colorsel->private_data;
1091
  
1092
  retval = gtk_drawing_area_new ();
1093 1094 1095

  GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS);
  
Manish Singh's avatar
Manish Singh committed
1096
  g_object_set_data (G_OBJECT (retval), "color_set", GINT_TO_POINTER (0)); 
1097 1098 1099 1100 1101
  gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK
                         | GDK_BUTTON_RELEASE_MASK
                         | GDK_EXPOSURE_MASK
                         | GDK_ENTER_NOTIFY_MASK
                         | GDK_LEAVE_NOTIFY_MASK);
1102
  
Manish Singh's avatar
Manish Singh committed
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
  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);
1117
  
1118 1119 1120 1121 1122 1123
  gtk_drag_dest_set (retval,
		     GTK_DEST_DEFAULT_HIGHLIGHT |
		     GTK_DEST_DEFAULT_MOTION |
		     GTK_DEST_DEFAULT_DROP,
		     targets, 1,
		     GDK_ACTION_COPY);
1124
  
Manish Singh's avatar
Manish Singh committed
1125 1126 1127 1128
  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);
1129 1130 1131

  gtk_tooltips_set_tip (priv->tooltips,
                        retval,
Havoc Pennington's avatar
Havoc Pennington committed
1132
                        _("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.\""),
1133
                        NULL);
1134 1135
  return retval;
}
1136

Elliot Lee's avatar
Elliot Lee committed
1137

1138 1139 1140 1141 1142
/*
 *
 * The actual GtkColorSelection widget
 *
 */
Elliot Lee's avatar
Elliot Lee committed
1143

1144 1145
static GdkCursor *
make_picker_cursor (GdkScreen *screen)
Elliot Lee's avatar
Elliot Lee committed
1146
{
1147
  GdkCursor *cursor;
Manish Singh's avatar
Manish Singh committed
1148 1149 1150
  GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
  GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 };
  GdkWindow *window = gdk_screen_get_root_window (screen);
1151
  
1152
  GdkPixmap *pixmap =
Manish Singh's avatar
Manish Singh committed
1153 1154
    gdk_bitmap_create_from_data (window, (gchar *) dropper_bits,
				 DROPPER_WIDTH, DROPPER_HEIGHT);
1155

1156
  GdkPixmap *mask =
Manish Singh's avatar
Manish Singh committed
1157 1158
    gdk_bitmap_create_from_data (window, (gchar *) dropper_mask,
				 DROPPER_WIDTH, DROPPER_HEIGHT);
1159

Manish Singh's avatar
Manish Singh committed
1160 1161
  cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg,
				       DROPPER_X_HOT, DROPPER_Y_HOT);
1162
  
Manish Singh's avatar
Manish Singh committed
1163 1164
  g_object_unref (pixmap);
  g_object_unref (mask);
1165 1166

  return cursor;
Elliot Lee's avatar
Elliot Lee committed
1167 1168 1169
}

static void
1170
grab_color_at_mouse (GdkScreen *screen,
1171 1172 1173
		     gint       x_root,
		     gint       y_root,
		     gpointer   data)
Elliot Lee's avatar
Elliot Lee committed
1174
{
1175 1176 1177 1178
  GdkImage *image;
  guint32 pixel;
  GtkColorSelection *colorsel = data;
  ColorSelectionPrivate *priv;
1179
  GdkColor color;
1180 1181
  GdkColormap *colormap = gdk_screen_get_system_colormap (screen);
  GdkWindow *root_window = gdk_screen_get_root_window (screen);
1182
  
1183
  priv = colorsel->private_data;
1184
  
Manish Singh's avatar
Manish Singh committed
1185
  image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1);
1186
  pixel = gdk_image_get_pixel (image, 0, 0);
Manish Singh's avatar
Manish Singh committed
1187
  g_object_unref (image);
1188 1189 1190

  gdk_colormap_query_color (colormap, pixel, &color);
  
1191 1192 1193
  priv->color[COLORSEL_RED] = SCALE (color.red);
  priv->color[COLORSEL_GREEN] = SCALE (color.green);
  priv->color[COLORSEL_BLUE] = SCALE (color.blue);
1194
  
1195 1196 1197 1198 1199 1200
  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]);
1201

1202 1203
  update_color (colorsel);
}
Elliot Lee's avatar
Elliot Lee committed
1204

1205
static void
1206 1207 1208 1209
shutdown_eyedropper (GtkWidget *widget)
{
  GtkColorSelection *colorsel;
  ColorSelectionPrivate *priv;
1210 1211
  GdkDisplay *display = gtk_widget_get_display (widget);
  guint32 time = gtk_get_current_event_time ();
1212 1213 1214 1215

  colorsel = GTK_COLOR_SELECTION (widget);
  priv = colorsel->private_data;    

1216 1217
  gdk_display_keyboard_ungrab (display, time);
  gdk_display_pointer_ungrab (display, time);
1218 1219 1220 1221 1222
  gtk_grab_remove (priv->dropper_grab_widget);
}

static void
mouse_motion (GtkWidget      *invisible,
1223 1224
	      GdkEventMotion *event,
	      gpointer        data)
1225
{
1226 1227
  grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *