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

19 20
#include "config.h"

Elliot Lee's avatar
Elliot Lee committed
21
#include <stdlib.h>
22

23
#include <gtk/gtk.h>
24 25
#include <gdk/gdkkeysyms.h>

26 27
#include "libgimpcolor/gimpcolor.h"

28 29
#include "display-types.h"
#include "gui/gui-types.h"
Sven Neumann's avatar
Sven Neumann committed
30

Michael Natterer's avatar
Michael Natterer committed
31 32 33 34
#include "base/pixel-region.h"
#include "base/temp-buf.h"
#include "base/tile-manager.h"

35 36
#include "paint-funcs/paint-funcs.h"

Michael Natterer's avatar
Michael Natterer committed
37
#include "core/gimp.h"
38
#include "core/gimpbuffer.h"
39
#include "core/gimpcontext.h"
Michael Natterer's avatar
Michael Natterer committed
40
#include "core/gimpedit.h"
41 42 43
#include "core/gimpimage.h"
#include "core/gimplayer.h"
#include "core/gimppattern.h"
Michael Natterer's avatar
Michael Natterer committed
44
#include "core/gimptoolinfo.h"
45

46
#include "tools/gimpbucketfilltool.h"
47
#include "tools/gimpfuzzyselecttool.h"
48
#include "tools/gimpmovetool.h"
49 50
#include "tools/tool_manager.h"

51
#include "widgets/gimpcursor.h"
Michael Natterer's avatar
Michael Natterer committed
52
#include "widgets/gimpdialogfactory.h"
Michael Natterer's avatar
Michael Natterer committed
53 54
#include "widgets/gimpwidgets-utils.h"

Michael Natterer's avatar
Michael Natterer committed
55
#include "gui/dialogs.h"
56 57 58
#include "gui/info-window.h"
#include "gui/layer-select.h"

59 60
#include "gimpdisplay.h"
#include "gimpdisplay-callbacks.h"
61
#include "gimpdisplay-foreach.h"
62 63 64
#include "gimpdisplay-selection.h"
#include "gimpdisplay-scale.h"
#include "gimpdisplay-scroll.h"
Michael Natterer's avatar
Michael Natterer committed
65
#include "gimpdisplayshell.h"
66

67
#include "devices.h"
Elliot Lee's avatar
Elliot Lee committed
68
#include "gimprc.h"
69
#include "undo.h"
Elliot Lee's avatar
Elliot Lee committed
70

71 72
#include "libgimp/gimpintl.h"

73

Elliot Lee's avatar
Elliot Lee committed
74
static void
Michael Natterer's avatar
Michael Natterer committed
75 76 77 78 79
gdisplay_redraw (GimpDisplayShell *shell,
		 gint              x,
		 gint              y,
		 gint              w,
		 gint              h)
Elliot Lee's avatar
Elliot Lee committed
80
{
81
  glong x1, y1, x2, y2;    /*  coordinate of rectangle corners  */
Elliot Lee's avatar
Elliot Lee committed
82 83 84

  x1 = x;
  y1 = y;
85 86 87
  x2 = (x + w);
  y2 = (y + h);

Michael Natterer's avatar
Michael Natterer committed
88 89 90 91
  x1 = CLAMP (x1, 0, shell->gdisp->disp_width);
  y1 = CLAMP (y1, 0, shell->gdisp->disp_height);
  x2 = CLAMP (x2, 0, shell->gdisp->disp_width);
  y2 = CLAMP (y2, 0, shell->gdisp->disp_height);
92

Elliot Lee's avatar
Elliot Lee committed
93 94
  if ((x2 - x1) && (y2 - y1))
    {
Michael Natterer's avatar
Michael Natterer committed
95 96 97 98
      gimp_display_shell_add_expose_area (shell,
                                          x1, y1,
                                          (x2 - x1), (y2 - y1));
      gimp_display_shell_flush (shell);
Elliot Lee's avatar
Elliot Lee committed
99 100 101
    }
}

102
static void
Michael Natterer's avatar
Michael Natterer committed
103
gdisplay_check_device_cursor (GimpDisplayShell *shell)
104
{
105
  GList *list;
106

107
  /*  gdk_devices_list() returns an internal list, so we shouldn't
108 109
   *  free it afterwards
   */
110
  for (list = gdk_devices_list (); list; list = g_list_next (list))
111
    {
112
      GdkDevice *device = (GdkDevice *) list->data;
113

114
      if (device == current_device)
115
	{
Michael Natterer's avatar
Michael Natterer committed
116
	  shell->draw_cursor = ! device->has_cursor;
117 118 119 120 121
	  break;
	}
    }
}

122
static int
123
key_to_state (gint key)
124 125
{
  switch (key)
126
    {
127 128
    case GDK_Alt_L:
    case GDK_Alt_R:
129
      return GDK_MOD1_MASK;
130 131
    case GDK_Shift_L:
    case GDK_Shift_R:
132
      return GDK_SHIFT_MASK;
133 134
    case GDK_Control_L:
    case GDK_Control_R:
135 136 137 138
      return GDK_CONTROL_MASK;
    default:
      return 0;
    }
139 140
}

Michael Natterer's avatar
Michael Natterer committed
141
static void
Michael Natterer's avatar
Michael Natterer committed
142 143
gdisplay_vscrollbar_update (GtkAdjustment    *adjustment,
			    GimpDisplayShell *shell)
Michael Natterer's avatar
Michael Natterer committed
144
{
Michael Natterer's avatar
Michael Natterer committed
145
  gimp_display_shell_scroll (shell, 0, (adjustment->value - shell->gdisp->offset_y));
Michael Natterer's avatar
Michael Natterer committed
146 147 148
}

static void
Michael Natterer's avatar
Michael Natterer committed
149 150
gdisplay_hscrollbar_update (GtkAdjustment    *adjustment,
			    GimpDisplayShell *shell)
Michael Natterer's avatar
Michael Natterer committed
151
{
Michael Natterer's avatar
Michael Natterer committed
152
  gimp_display_shell_scroll (shell, (adjustment->value - shell->gdisp->offset_x), 0);
Michael Natterer's avatar
Michael Natterer committed
153 154
}

155
gboolean
Michael Natterer's avatar
Michael Natterer committed
156 157 158
gdisplay_shell_events (GtkWidget        *widget,
		       GdkEvent         *event,
		       GimpDisplayShell *shell)
159 160 161 162
{
  switch (event->type)
    {
    case GDK_KEY_PRESS:
Michael Natterer's avatar
Michael Natterer committed
163
    case GDK_BUTTON_PRESS:
164
      /*  Setting the context's display automatically sets the image, too  */
Michael Natterer's avatar
Michael Natterer committed
165 166
      gimp_context_set_display (gimp_get_user_context (shell->gdisp->gimage->gimp),
				shell->gdisp);
Michael Natterer's avatar
Michael Natterer committed
167

168 169 170
      break;
    default:
      break;
171 172
    }

173 174 175
  return FALSE;
}

176
gboolean
Michael Natterer's avatar
Michael Natterer committed
177 178 179
gdisplay_canvas_events (GtkWidget        *canvas,
			GdkEvent         *event,
			GimpDisplayShell *shell)
Elliot Lee's avatar
Elliot Lee committed
180
{
Michael Natterer's avatar
Michael Natterer committed
181
  GimpDisplay     *gdisp;
182
  GimpTool        *active_tool;
183 184 185
  GdkEventExpose  *eevent;
  GdkEventMotion  *mevent;
  GdkEventButton  *bevent;
Michael Natterer's avatar
Michael Natterer committed
186
  GdkEventScroll  *sevent;
187
  GdkEventKey     *kevent;
188 189 190 191 192 193 194 195 196
  gdouble          tx             = 0;
  gdouble          ty             = 0;
  guint            state          = 0;
  gint             return_val     = FALSE;
  static gboolean  scrolling      = FALSE;
  static gint      scroll_start_x = 0;
  static gint      scroll_start_y = 0;
  static guint     key_signal_id  = 0;
  gboolean         update_cursor  = FALSE;
Elliot Lee's avatar
Elliot Lee committed
197

198
  if (! canvas->window)
scott's avatar
scott committed
199 200
    return FALSE;

Michael Natterer's avatar
Michael Natterer committed
201 202
  gdisp = shell->gdisp;

203 204
  active_tool = tool_manager_get_active (gdisp->gimage->gimp);

Elliot Lee's avatar
Elliot Lee committed
205
  /*  If this is the first event...  */
Michael Natterer's avatar
Michael Natterer committed
206
  if (! gdisp->select)
Elliot Lee's avatar
Elliot Lee committed
207 208
    {
      /*  create the selection object  */
Michael Natterer's avatar
Michael Natterer committed
209 210
      gdisp->select = selection_create (shell->canvas->window,
                                        gdisp,
Elliot Lee's avatar
Elliot Lee committed
211
					gdisp->gimage->height,
212 213
					gdisp->gimage->width, 
					gimprc.marching_speed);
Elliot Lee's avatar
Elliot Lee committed
214

Michael Natterer's avatar
Michael Natterer committed
215 216
      gdisp->disp_width  = shell->canvas->allocation.width;
      gdisp->disp_height = shell->canvas->allocation.height;
Elliot Lee's avatar
Elliot Lee committed
217

Michael Natterer's avatar
Michael Natterer committed
218
      /*  create GC for scrolling  */
Michael Natterer's avatar
Michael Natterer committed
219 220
      shell->scroll_gc = gdk_gc_new (shell->canvas->window);
      gdk_gc_set_exposures (shell->scroll_gc, TRUE);
221

Elliot Lee's avatar
Elliot Lee committed
222
      /*  set up the scrollbar observers  */
Michael Natterer's avatar
Michael Natterer committed
223
      g_signal_connect (G_OBJECT (shell->hsbdata), "value_changed",
224
                        G_CALLBACK (gdisplay_hscrollbar_update),
Michael Natterer's avatar
Michael Natterer committed
225 226
                        shell);
      g_signal_connect (G_OBJECT (shell->vsbdata), "value_changed",
227
                        G_CALLBACK (gdisplay_vscrollbar_update),
Michael Natterer's avatar
Michael Natterer committed
228
                        shell);
Elliot Lee's avatar
Elliot Lee committed
229 230

      /*  setup scale properly  */
Michael Natterer's avatar
Michael Natterer committed
231
      gimp_display_shell_scale_setup (shell);
Elliot Lee's avatar
Elliot Lee committed
232 233
    }

Michael Natterer's avatar
Michael Natterer committed
234
  /*  Find out what device the event occurred upon  */
235
  if (! gdisp->gimage->gimp->busy && devices_check_change (event))
Michael Natterer's avatar
Michael Natterer committed
236
    gdisplay_check_device_cursor (shell);
Michael Natterer's avatar
Michael Natterer committed
237

Elliot Lee's avatar
Elliot Lee committed
238 239 240 241
  switch (event->type)
    {
    case GDK_EXPOSE:
      eevent = (GdkEventExpose *) event;
242

Michael Natterer's avatar
Michael Natterer committed
243
      gdisplay_redraw (shell,
244 245
		       eevent->area.x, eevent->area.y,
		       eevent->area.width, eevent->area.height);
Elliot Lee's avatar
Elliot Lee committed
246 247 248
      break;

    case GDK_CONFIGURE:
Michael Natterer's avatar
Michael Natterer committed
249 250
      if ((gdisp->disp_width  != shell->canvas->allocation.width) ||
	  (gdisp->disp_height != shell->canvas->allocation.height))
Elliot Lee's avatar
Elliot Lee committed
251
	{
Michael Natterer's avatar
Michael Natterer committed
252 253
	  gdisp->disp_width  = shell->canvas->allocation.width;
	  gdisp->disp_height = shell->canvas->allocation.height;
254

Michael Natterer's avatar
Michael Natterer committed
255
	  gimp_display_shell_scale_resize (shell, FALSE, FALSE);
Elliot Lee's avatar
Elliot Lee committed
256 257 258
	}
      break;

259
    case GDK_LEAVE_NOTIFY:
260
      if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL)
Michael Natterer's avatar
Michael Natterer committed
261
	return TRUE;
Michael Natterer's avatar
Michael Natterer committed
262 263
      gimp_display_shell_update_cursor (shell, 0, 0);
      gtk_label_set_text (GTK_LABEL (shell->cursor_label), "");
264
      info_window_update_extended (gdisp, -1, -1);
265

266
    case GDK_PROXIMITY_OUT:
Michael Natterer's avatar
Michael Natterer committed
267
      shell->proximity = FALSE;
268 269
      break;

270
    case GDK_ENTER_NOTIFY:
271
      if (((GdkEventCrossing *) event)->mode != GDK_CROSSING_NORMAL)
Michael Natterer's avatar
Michael Natterer committed
272
	return TRUE;
273
      /* Actually, should figure out tx,ty here */
274 275
      break;

Elliot Lee's avatar
Elliot Lee committed
276 277 278 279
    case GDK_BUTTON_PRESS:
      bevent = (GdkEventButton *) event;
      state = bevent->state;

280
      /*  ignore new mouse events  */
281
      if (gdisp->gimage->gimp->busy)
282 283
	return TRUE;

Elliot Lee's avatar
Elliot Lee committed
284 285 286
      switch (bevent->button)
	{
	case 1:
287
	  state |= GDK_BUTTON1_MASK;
Elliot Lee's avatar
Elliot Lee committed
288
	  gtk_grab_add (canvas);
289 290

	  /* This is a hack to prevent other stuff being run in the middle of
291 292 293 294 295 296
	   * a tool operation (like changing image types.... brrrr). We just
	   * block all the keypress event. A better solution is to implement
	   * some sort of locking for images.
	   * Note that this is dependent on specific GTK behavior, and isn't
	   * guaranteed to work in future versions of GTK.
	   * -Yosh
297 298
	   */
	  if (key_signal_id == 0)
299 300 301 302
	    key_signal_id = g_signal_connect (G_OBJECT (canvas),
                                              "key_press_event",
                                              G_CALLBACK (gtk_true),
                                              NULL);
303

304
	  /* FIXME!!! This code is ugly */
305

306 307
	  if (active_tool && (GIMP_IS_MOVE_TOOL (active_tool) ||
			      ! gimp_image_is_empty (gdisp->gimage)))
Michael Natterer's avatar
Michael Natterer committed
308 309 310
	    {
	      if (active_tool->auto_snap_to)
		{
Michael Natterer's avatar
Michael Natterer committed
311 312 313
		  gimp_display_shell_snap_point (shell,
                                                 bevent->x, bevent->y,
                                                 &tx, &ty);
Michael Natterer's avatar
Michael Natterer committed
314 315 316 317 318
		  bevent->x = tx;
		  bevent->y = ty;
		  update_cursor = TRUE;
		}

319 320 321
	      /* reset the current tool if ... */
	      if ((/* it has no drawable */
		   ! active_tool->drawable ||
Michael Natterer's avatar
Michael Natterer committed
322

323
		   /* or a drawable different from the current one */
324
		   (gimp_image_active_drawable (gdisp->gimage) !=
325
		    active_tool->drawable)) &&
Michael Natterer's avatar
Michael Natterer committed
326

327 328
		  /* and doesn't want to be preserved across drawable changes */
		  ! active_tool->preserve)
Michael Natterer's avatar
Michael Natterer committed
329
		{
Michael Natterer's avatar
Michael Natterer committed
330 331
		  tool_manager_initialize_tool (gdisp->gimage->gimp,
						active_tool, gdisp);
332 333

		  active_tool = tool_manager_get_active (gdisp->gimage->gimp);
Michael Natterer's avatar
Michael Natterer committed
334 335
		}

336 337 338
	      /* otherwise set it's drawable if it has none */
	      else if (! active_tool->drawable)
		{
339 340
		  active_tool->drawable =
		    gimp_image_active_drawable (gdisp->gimage);
341
		}
342
	      
343
	      gimp_tool_button_press (active_tool, bevent, gdisp);
344
	    } 
Elliot Lee's avatar
Elliot Lee committed
345 346 347
	  break;

	case 2:
348 349 350 351 352 353 354 355 356 357 358 359 360 361
          {
            GdkCursor *cursor;

            state |= GDK_BUTTON2_MASK;

            scrolling      = TRUE;
            scroll_start_x = bevent->x + gdisp->offset_x;
            scroll_start_y = bevent->y + gdisp->offset_y;

            gtk_grab_add (canvas);

            cursor = gimp_cursor_new (GDK_FLEUR,
                                      GIMP_TOOL_CURSOR_NONE,
                                      GIMP_CURSOR_MODIFIER_NONE);
Michael Natterer's avatar
Michael Natterer committed
362
            gdk_window_set_cursor (shell->canvas->window, cursor);
363 364
            gdk_cursor_unref (cursor);
          }
Elliot Lee's avatar
Elliot Lee committed
365 366 367
	  break;

	case 3:
368
	  state |= GDK_BUTTON3_MASK;
Michael Natterer's avatar
Michael Natterer committed
369
	  gimp_item_factory_popup_with_data (shell->ifactory, gdisp->gimage);
370
	  return_val = TRUE;
Elliot Lee's avatar
Elliot Lee committed
371 372 373 374 375 376 377 378 379 380 381
	  break;

	default:
	  break;
	}
      break;

    case GDK_BUTTON_RELEASE:
      bevent = (GdkEventButton *) event;
      state = bevent->state;

Michael Natterer's avatar
Michael Natterer committed
382
      /*  ugly side condition: all operations which set busy cursors are
383 384 385 386 387 388
       *  invoked on BUTTON_RELEASE, thus no new BUTTON_PRESS events are
       *  accepted while Gimp is busy, thus it should be safe to block
       *  BUTTON_RELEASE.  --Mitch
       *
       *  ugly: fuzzy_select sets busy cursors while ACTIVE.
       */
389 390 391
      if (gdisp->gimage->gimp->busy &&
	  ! (GIMP_IS_FUZZY_SELECT_TOOL (active_tool)  &&
	     active_tool->state == ACTIVE))
392 393
	return TRUE;

Elliot Lee's avatar
Elliot Lee committed
394 395 396
      switch (bevent->button)
	{
	case 1:
397
	  state &= ~GDK_BUTTON1_MASK;
398

399 400 401
	  /* Lame hack. See above */
	  if (key_signal_id)
	    {
402
	      g_signal_handler_disconnect (G_OBJECT (canvas), key_signal_id);
403 404 405
	      key_signal_id = 0;
	    }

Elliot Lee's avatar
Elliot Lee committed
406
	  gtk_grab_remove (canvas);
407

408
	  if (active_tool && (GIMP_IS_MOVE_TOOL (active_tool) ||
409
			      ! gimp_image_is_empty (gdisp->gimage)))
410 411 412 413 414
	    {
	      if (active_tool->state == ACTIVE)
		{
		  if (active_tool->auto_snap_to)
		    {
Michael Natterer's avatar
Michael Natterer committed
415 416 417
		      gimp_display_shell_snap_point (shell,
                                                     bevent->x, bevent->y,
                                                     &tx, &ty);
418 419 420 421
		      bevent->x = tx;
		      bevent->y = ty;
		      update_cursor = TRUE;
		    }
422

423
		  gimp_tool_button_release (active_tool, bevent, gdisp);
424 425
		}
	    }
Elliot Lee's avatar
Elliot Lee committed
426 427 428
	  break;

	case 2:
429
	  state &= ~GDK_BUTTON2_MASK;
430
	  scrolling = FALSE;
Elliot Lee's avatar
Elliot Lee committed
431
	  gtk_grab_remove (canvas);
Michael Natterer's avatar
Michael Natterer committed
432 433 434 435 436
          gimp_display_shell_real_install_tool_cursor (shell,
                                                       shell->current_cursor,
                                                       shell->tool_cursor,
                                                       GIMP_CURSOR_MODIFIER_NONE,
                                                       TRUE);
Elliot Lee's avatar
Elliot Lee committed
437 438 439
	  break;

	case 3:
440
	  state &= ~GDK_BUTTON3_MASK;
Elliot Lee's avatar
Elliot Lee committed
441 442
	  break;

Michael Natterer's avatar
Michael Natterer committed
443
	default:
444
	  break;
Michael Natterer's avatar
Michael Natterer committed
445 446
	}
      break;
447

Michael Natterer's avatar
Michael Natterer committed
448 449 450
    case GDK_SCROLL:
      sevent = (GdkEventScroll *) event;
      state = sevent->state;
451

Michael Natterer's avatar
Michael Natterer committed
452 453 454
      if (state & GDK_SHIFT_MASK)
	{
	  if (sevent->direction == GDK_SCROLL_UP)
Michael Natterer's avatar
Michael Natterer committed
455
	    gimp_display_shell_scale (shell, GIMP_ZOOM_IN);
Michael Natterer's avatar
Michael Natterer committed
456
	  else
Michael Natterer's avatar
Michael Natterer committed
457
	    gimp_display_shell_scale (shell, GIMP_ZOOM_OUT);
Michael Natterer's avatar
Michael Natterer committed
458 459 460 461 462 463 464
	}
      else
	{
	  GtkAdjustment *adj;
	  gdouble        value;

	  if (state & GDK_CONTROL_MASK)
Michael Natterer's avatar
Michael Natterer committed
465
	    adj = shell->hsbdata;
Michael Natterer's avatar
Michael Natterer committed
466
	  else
Michael Natterer's avatar
Michael Natterer committed
467
	    adj = shell->vsbdata;
Michael Natterer's avatar
Michael Natterer committed
468 469 470 471 472 473 474

	  value = adj->value + ((sevent->direction == GDK_SCROLL_UP) ?
				-adj->page_increment / 2 :
				adj->page_increment / 2);
	  value = CLAMP (value, adj->lower, adj->upper - adj->page_size);

	  gtk_adjustment_set_value (adj, value);
Elliot Lee's avatar
Elliot Lee committed
475
	}
Michael Natterer's avatar
Michael Natterer committed
476 477

      return_val = TRUE;
Elliot Lee's avatar
Elliot Lee committed
478 479 480 481 482 483
      break;

    case GDK_MOTION_NOTIFY:
      mevent = (GdkEventMotion *) event;
      state = mevent->state;

484 485 486 487 488
      /*  for the same reason we block BUTTON_RELEASE,
       *  we block MOTION_NOTIFY.  --Mitch
       *
       *  ugly: fuzzy_select sets busy cursors while ACTIVE.
       */
489 490 491
      if (gdisp->gimage->gimp->busy &&
	  ! (GIMP_IS_FUZZY_SELECT_TOOL (active_tool) &&
	     active_tool->state == ACTIVE))
492
	return TRUE;
493

494 495 496
      /* Ask for the pointer position, but ignore it except for cursor
       * handling, so motion events sync with the button press/release events 
       */
Elliot Lee's avatar
Elliot Lee committed
497
      if (mevent->is_hint)
498
	{
499 500 501 502
#ifdef __GNUC__
#warning FIXME: replace gdk_input_window_get_pointer()
#endif
#if 0
503
	  gdk_input_window_get_pointer (canvas->window, current_device, &tx, &ty,
504
					NULL, NULL, NULL, NULL);
505
#endif
506
	}
507
      else
Elliot Lee's avatar
Elliot Lee committed
508
	{
509 510
	  tx = mevent->x;
	  ty = mevent->y;
Elliot Lee's avatar
Elliot Lee committed
511
	}
512
      update_cursor = TRUE;
Elliot Lee's avatar
Elliot Lee committed
513

Michael Natterer's avatar
Michael Natterer committed
514
      if (! shell->proximity)
515
	{
Michael Natterer's avatar
Michael Natterer committed
516 517
	  shell->proximity = TRUE;
	  gdisplay_check_device_cursor (shell);
518
	}
519

520
      if (active_tool && (GIMP_IS_MOVE_TOOL(active_tool) ||
521
			  ! gimp_image_is_empty (gdisp->gimage)) &&
Elliot Lee's avatar
Elliot Lee committed
522 523 524 525 526 527 528
	  (mevent->state & GDK_BUTTON1_MASK))
	{
	  if (active_tool->state == ACTIVE)
	    {
	      /*  if the first mouse button is down, check for automatic
	       *  scrolling...
	       */
529 530
	      if ((mevent->state & GDK_BUTTON1_MASK) &&
		  !active_tool->scroll_lock)
Elliot Lee's avatar
Elliot Lee committed
531
		{
Michael Natterer's avatar
Michael Natterer committed
532 533
		  if (mevent->x < 0                 ||
                      mevent->y < 0                 ||
Elliot Lee's avatar
Elliot Lee committed
534 535
		      mevent->x > gdisp->disp_width ||
		      mevent->y > gdisp->disp_height)
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
                    {
                      gdouble child_x, child_y;
                      gint    off_x, off_y;

                      off_x = off_y = 0;

                      /*  The cases for scrolling  */
                      if (mevent->x < 0)
                        off_x = mevent->x;
                      else if (mevent->x > gdisp->disp_width)
                        off_x = mevent->x - gdisp->disp_width;

                      if (mevent->y < 0)
                        off_y = mevent->y;
                      else if (mevent->y > gdisp->disp_height)
                        off_y = mevent->y - gdisp->disp_height;

Michael Natterer's avatar
Michael Natterer committed
553
                      if (gimp_display_shell_scroll (shell, off_x, off_y))
554 555 556 557 558
                        {
#ifdef __GNUC__
#warning FIXME: replace gdk_input_window_get_pointer()
#endif
#if 0
Michael Natterer's avatar
Michael Natterer committed
559
                          gdk_input_window_get_pointer (shell->canvas->window, mevent->deviceid,
560 561 562 563 564 565 566 567 568
                                                        &child_x, &child_y, 
                                                        NULL, NULL, NULL, NULL);

                          if (child_x == mevent->x && child_y == mevent->y)
                            /*  Put this event back on the queue -- so it keeps scrolling */
                            gdk_event_put ((GdkEvent *) mevent);
#endif
                        }
                    }
Elliot Lee's avatar
Elliot Lee committed
569 570 571 572
		}

	      if (active_tool->auto_snap_to)
		{
Michael Natterer's avatar
Michael Natterer committed
573 574 575
		  gimp_display_shell_snap_point (shell,
                                                 mevent->x, mevent->y,
                                                 &tx, &ty);
Elliot Lee's avatar
Elliot Lee committed
576 577
		  mevent->x = tx;
		  mevent->y = ty;
578
		  update_cursor = TRUE;
Elliot Lee's avatar
Elliot Lee committed
579 580
		}

581
	      gimp_tool_motion (active_tool, mevent, gdisp);
Elliot Lee's avatar
Elliot Lee committed
582 583
	    }
	}
584
      else if ((mevent->state & GDK_BUTTON2_MASK) && scrolling)
Elliot Lee's avatar
Elliot Lee committed
585
	{
Michael Natterer's avatar
Michael Natterer committed
586 587 588 589 590
          gimp_display_shell_scroll (shell,
                                     (scroll_start_x - mevent->x -
                                      gdisp->offset_x),
                                     (scroll_start_y - mevent->y -
                                     gdisp->offset_y));
Elliot Lee's avatar
Elliot Lee committed
591
	}
592

593
      if (/* Should we have a tool... */
594
	  active_tool && 
595 596 597
	  /* and this event is NOT driving
	   * button press handlers ...
	   */
598
	  !(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
599
        {
600 601 602
          /* ...then preconditions to modify a tool
	   * operator state have been met.
	   */
603
          gimp_tool_oper_update (active_tool, mevent, gdisp);
604 605
        }

Elliot Lee's avatar
Elliot Lee committed
606 607 608 609 610 611
      break;

    case GDK_KEY_PRESS:
      kevent = (GdkEventKey *) event;
      state = kevent->state;

612
      /*  ignore any key presses  */
613
      if (gdisp->gimage->gimp->busy)
614 615
	return TRUE;

Elliot Lee's avatar
Elliot Lee committed
616 617 618 619
      switch (kevent->keyval)
	{
	case GDK_Left: case GDK_Right:
	case GDK_Up: case GDK_Down:
620 621 622
	  if (active_tool && ! gimp_image_is_empty (gdisp->gimage))
	    gimp_tool_arrow_key (active_tool, kevent, gdisp);

Elliot Lee's avatar
Elliot Lee committed
623
	  return_val = TRUE;
624
	  break;
Elliot Lee's avatar
Elliot Lee committed
625 626

	case GDK_Tab:
627 628
	  if (kevent->state & GDK_MOD1_MASK &&
	      !gimp_image_is_empty (gdisp->gimage))
Elliot Lee's avatar
Elliot Lee committed
629
	    layer_select_init (gdisp->gimage, 1, kevent->time);
630 631

	  if (kevent->state & GDK_CONTROL_MASK &&
632
	      !gimp_image_is_empty (gdisp->gimage))
Elliot Lee's avatar
Elliot Lee committed
633
	    layer_select_init (gdisp->gimage, -1, kevent->time);
634 635

	  /* Hide or show all dialogs */
636
	  if (! kevent->state)
Michael Natterer's avatar
Michael Natterer committed
637 638
	    gimp_dialog_factories_toggle (global_dialog_factory,
					  "gimp:toolbox");
639

Elliot Lee's avatar
Elliot Lee committed
640 641 642 643 644 645
	  return_val = TRUE;
	  break;

	  /*  Update the state based on modifiers being pressed  */
	case GDK_Alt_L: case GDK_Alt_R:
	case GDK_Shift_L: case GDK_Shift_R:
646
	case GDK_Control_L: case GDK_Control_R:
647
	  state |= key_to_state (kevent->keyval);
648
	  /* For all modifier keys: call the tools modifier_key_func */
649
	  if (active_tool && !gimp_image_is_empty (gdisp->gimage))
Sven Neumann's avatar
Sven Neumann committed
650
	    {
651
#if 0
652
	      gdk_input_window_get_pointer (canvas->window, current_device,
653
					    &tx, &ty, NULL, NULL, NULL, NULL);
654
#endif
655
	      gimp_tool_modifier_key (active_tool, kevent, gdisp);
Sven Neumann's avatar
Sven Neumann committed
656 657
	      return_val = TRUE;
	    }
Elliot Lee's avatar
Elliot Lee committed
658 659 660 661 662 663 664 665
	  break;
	}
      break;

    case GDK_KEY_RELEASE:
      kevent = (GdkEventKey *) event;
      state = kevent->state;

666
      /*  ignore any key releases  */
667
      if (gdisp->gimage->gimp->busy)
668 669
	return TRUE;

Elliot Lee's avatar
Elliot Lee committed
670 671 672 673
      switch (kevent->keyval)
	{
	case GDK_Alt_L: case GDK_Alt_R:
	case GDK_Shift_L: case GDK_Shift_R:
674
	case GDK_Control_L: case GDK_Control_R:
675
	  state &= ~key_to_state (kevent->keyval);
676
	  /* For all modifier keys: call the tools modifier_key_func */
677
	  if (active_tool && !gimp_image_is_empty (gdisp->gimage))
Sven Neumann's avatar
Sven Neumann committed
678
	    {
679
#if 0
680
	      gdk_input_window_get_pointer (canvas->window, current_device,
681
	                                    &tx, &ty, NULL, NULL, NULL, NULL);
682
#endif
683
	      gimp_tool_modifier_key (active_tool, kevent, gdisp);
Sven Neumann's avatar
Sven Neumann committed
684 685
	      return_val = TRUE;
	    }
Elliot Lee's avatar
Elliot Lee committed
686 687 688 689 690 691 692 693 694 695
	  break;
	}

      return_val = TRUE;
      break;

    default:
      break;
    }

Michael Natterer's avatar
Michael Natterer committed
696
  /*  if we reached this point in gimp_busy mode, return now  */
697
  if (gdisp->gimage->gimp->busy)
698 699
    return TRUE;

700 701 702 703 704 705
  /*  Cursor update support
   *  no_cursor_updating is TRUE (=1) when
   *  <Toolbox>/File/Preferences.../Interface/...
   *  Image Windows/Disable Cursor Updating is TOGGLED ON
   */
  if (! gimprc.no_cursor_updating)
Elliot Lee's avatar
Elliot Lee committed
706
    {
707 708
      active_tool = tool_manager_get_active (gdisp->gimage->gimp);

709
      if (active_tool && !gimp_image_is_empty (gdisp->gimage) &&
Elliot Lee's avatar
Elliot Lee committed
710 711 712 713 714
	  !(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
	{
	  GdkEventMotion me;
	  me.x = tx;  me.y = ty;
	  me.state = state;
715
	  gimp_tool_cursor_update (active_tool, &me, gdisp);
Elliot Lee's avatar
Elliot Lee committed
716
	}
717
      else if (gimp_image_is_empty (gdisp->gimage))
718
	{
Michael Natterer's avatar
Michael Natterer committed
719 720 721 722
	  gimp_display_shell_install_tool_cursor (shell,
                                                  GIMP_BAD_CURSOR,
                                                  GIMP_TOOL_CURSOR_NONE,
                                                  GIMP_CURSOR_MODIFIER_NONE);
723
	}
Elliot Lee's avatar
Elliot Lee committed
724 725
    }

726
  if (update_cursor)
Michael Natterer's avatar
Michael Natterer committed
727
    gimp_display_shell_update_cursor (shell, tx, ty);
728

Elliot Lee's avatar
Elliot Lee committed
729 730 731
  return return_val;
}

732
gboolean
Michael Natterer's avatar
Michael Natterer committed
733 734 735
gdisplay_hruler_button_press (GtkWidget        *widget,
			      GdkEventButton   *event,
			      GimpDisplayShell *shell)
Elliot Lee's avatar
Elliot Lee committed
736
{
737
  GimpDisplay *gdisp;
Elliot Lee's avatar
Elliot Lee committed
738

Michael Natterer's avatar
Michael Natterer committed
739
  gdisp = shell->gdisp;
740

741
  if (gdisp->gimage->gimp->busy)
742 743
    return TRUE;

Elliot Lee's avatar
Elliot Lee committed
744 745
  if (event->button == 1)
    {
746 747
      GimpToolInfo *tool_info;
      GimpTool     *active_tool;
748

749 750
      tool_info = tool_manager_get_info_by_type (gdisp->gimage->gimp,
						 GIMP_TYPE_MOVE_TOOL);
751

752 753 754 755 756 757 758 759 760 761
      if (tool_info)
	{
	  gimp_context_set_tool (gimp_get_user_context (gdisp->gimage->gimp),
				 tool_info);

	  active_tool = tool_manager_get_active (gdisp->gimage->gimp);

	  if (active_tool)
	    {
	      gimp_move_tool_start_hguide (active_tool, gdisp);
Michael Natterer's avatar
Michael Natterer committed
762
	      gtk_grab_add (shell->canvas);
763 764
	    }
	}
Elliot Lee's avatar
Elliot Lee committed
765 766 767 768 769
    }

  return FALSE;
}

770
gboolean
Michael Natterer's avatar
Michael Natterer committed
771 772 773
gdisplay_vruler_button_press (GtkWidget        *widget,
			      GdkEventButton   *event,
			      GimpDisplayShell *shell)
Elliot Lee's avatar
Elliot Lee committed
774
{
775
  GimpDisplay *gdisp;
Elliot Lee's avatar
Elliot Lee committed
776

Michael Natterer's avatar
Michael Natterer committed
777
  gdisp = shell->gdisp;
778

779
  if (gdisp->gimage->gimp->busy)
780 781
    return TRUE;

Elliot Lee's avatar
Elliot Lee committed
782 783
  if (event->button == 1)
    {
784 785 786 787 788 789 790 791 792 793
      GimpToolInfo *tool_info;
      GimpTool     *active_tool;

      tool_info = tool_manager_get_info_by_type (gdisp->gimage->gimp,
						 GIMP_TYPE_MOVE_TOOL);

      if (tool_info)
	{
	  gimp_context_set_tool (gimp_get_user_context (gdisp->gimage->gimp),
				 tool_info);
794

795
	  active_tool = tool_manager_get_active (gdisp->gimage->gimp);
796

797 798 799
	  if (active_tool)
	    {
	      gimp_move_tool_start_vguide (active_tool, gdisp);
Michael Natterer's avatar
Michael Natterer committed
800
	      gtk_grab_add (shell->canvas);
801 802
	    }
	}
Elliot Lee's avatar
Elliot Lee committed
803 804 805 806
    }

  return FALSE;
}
807