1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22 #include <gdk/gdkkeysyms.h>
23
24 #include "libgimpwidgets/gimpwidgets.h"
25
26 #include "display-types.h"
27 #include "tools/tools-types.h"
28
29 #include "config/gimpdisplayconfig.h"
30
31 #include "core/gimp.h"
32 #include "core/gimp-filter-history.h"
33 #include "core/gimpcontext.h"
34 #include "core/gimpimage.h"
35 #include "core/gimpimage-pick-item.h"
36 #include "core/gimpitem.h"
37
38 #include "widgets/gimpcontrollers.h"
39 #include "widgets/gimpcontrollerkeyboard.h"
40 #include "widgets/gimpcontrollermouse.h"
41 #include "widgets/gimpcontrollerwheel.h"
42 #include "widgets/gimpdeviceinfo.h"
43 #include "widgets/gimpdeviceinfo-coords.h"
44 #include "widgets/gimpdevicemanager.h"
45 #include "widgets/gimpdevices.h"
46 #include "widgets/gimpdialogfactory.h"
47 #include "widgets/gimpuimanager.h"
48 #include "widgets/gimpwidgets-utils.h"
49
50 #include "tools/gimpguidetool.h"
51 #include "tools/gimpmovetool.h"
52 #include "tools/gimpsamplepointtool.h"
53 #include "tools/gimptoolcontrol.h"
54 #include "tools/tool_manager.h"
55
56 #include "gimpcanvas.h"
57 #include "gimpdisplay.h"
58 #include "gimpdisplayshell.h"
59 #include "gimpdisplayshell-autoscroll.h"
60 #include "gimpdisplayshell-cursor.h"
61 #include "gimpdisplayshell-grab.h"
62 #include "gimpdisplayshell-layer-select.h"
63 #include "gimpdisplayshell-rotate.h"
64 #include "gimpdisplayshell-scale.h"
65 #include "gimpdisplayshell-scroll.h"
66 #include "gimpdisplayshell-tool-events.h"
67 #include "gimpdisplayshell-transform.h"
68 #include "gimpimagewindow.h"
69 #include "gimpmotionbuffer.h"
70 #include "gimpstatusbar.h"
71
72 #include "gimp-intl.h"
73 #include "gimp-log.h"
74
75
76 /* local function prototypes */
77
78 static gboolean gimp_display_shell_canvas_tool_events_internal (GtkWidget *canvas,
79 GdkEvent *event,
80 GimpDisplayShell *shell,
81 GdkEvent **next_event);
82
83 static GdkModifierType
84 gimp_display_shell_key_to_state (gint key);
85 static GdkModifierType
86 gimp_display_shell_button_to_state (gint button);
87
88 static void gimp_display_shell_proximity_in (GimpDisplayShell *shell);
89 static void gimp_display_shell_proximity_out (GimpDisplayShell *shell);
90
91 static void gimp_display_shell_check_device_cursor (GimpDisplayShell *shell);
92
93 static void gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
94 const GdkEvent *event,
95 GdkModifierType state,
96 gint x,
97 gint y);
98 static void gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
99 const GdkEvent *event);
100 static void gimp_display_shell_handle_scrolling (GimpDisplayShell *shell,
101 GdkModifierType state,
102 gint x,
103 gint y);
104
105 static void gimp_display_shell_space_pressed (GimpDisplayShell *shell,
106 const GdkEvent *event);
107 static void gimp_display_shell_released (GimpDisplayShell *shell,
108 const GdkEvent *event,
109 const GimpCoords *image_coords);
110
111 static gboolean gimp_display_shell_tab_pressed (GimpDisplayShell *shell,
112 const GdkEventKey *event);
113
114 static void gimp_display_shell_update_focus (GimpDisplayShell *shell,
115 gboolean focus_in,
116 const GimpCoords *image_coords,
117 GdkModifierType state);
118 static void gimp_display_shell_update_cursor (GimpDisplayShell *shell,
119 const GimpCoords *display_coords,
120 const GimpCoords *image_coords,
121 GdkModifierType state,
122 gboolean update_software_cursor);
123
124 static gboolean gimp_display_shell_initialize_tool (GimpDisplayShell *shell,
125 const GimpCoords *image_coords,
126 GdkModifierType state);
127
128 static void gimp_display_shell_get_event_coords (GimpDisplayShell *shell,
129 const GdkEvent *event,
130 GimpCoords *display_coords,
131 GdkModifierType *state,
132 guint32 *time);
133 static void gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell,
134 const GimpCoords *display_coords,
135 GimpCoords *image_coords,
136 gboolean *update_software_cursor);
137
138 static GdkEvent * gimp_display_shell_compress_motion (GdkEvent *initial_event,
139 GdkEvent **next_event);
140
141
142 /* public functions */
143
144 gboolean
gimp_display_shell_events(GtkWidget * widget,GdkEvent * event,GimpDisplayShell * shell)145 gimp_display_shell_events (GtkWidget *widget,
146 GdkEvent *event,
147 GimpDisplayShell *shell)
148 {
149 Gimp *gimp;
150 gboolean set_display = FALSE;
151
152 /* are we in destruction? */
153 if (! shell->display || ! gimp_display_get_shell (shell->display))
154 return TRUE;
155
156 gimp = gimp_display_get_gimp (shell->display);
157
158 switch (event->type)
159 {
160 case GDK_KEY_PRESS:
161 case GDK_KEY_RELEASE:
162 {
163 GdkEventKey *kevent = (GdkEventKey *) event;
164
165 if (gimp->busy)
166 return TRUE;
167
168 /* do not process most key events while BUTTON1 is down. We do this
169 * so tools keep the modifier state they were in when BUTTON1 was
170 * pressed and to prevent accelerators from being invoked.
171 */
172 if (kevent->state & GDK_BUTTON1_MASK)
173 {
174 if (kevent->keyval == GDK_KEY_Shift_L ||
175 kevent->keyval == GDK_KEY_Shift_R ||
176 kevent->keyval == GDK_KEY_Control_L ||
177 kevent->keyval == GDK_KEY_Control_R ||
178 kevent->keyval == GDK_KEY_Alt_L ||
179 kevent->keyval == GDK_KEY_Alt_R ||
180 kevent->keyval == GDK_KEY_Meta_L ||
181 kevent->keyval == GDK_KEY_Meta_R ||
182 kevent->keyval == GDK_KEY_space ||
183 kevent->keyval == GDK_KEY_KP_Space)
184 {
185 break;
186 }
187
188 return TRUE;
189 }
190
191 switch (kevent->keyval)
192 {
193 case GDK_KEY_Left: case GDK_KEY_Right:
194 case GDK_KEY_Up: case GDK_KEY_Down:
195 case GDK_KEY_space:
196 case GDK_KEY_KP_Space:
197 case GDK_KEY_Tab:
198 case GDK_KEY_KP_Tab:
199 case GDK_KEY_ISO_Left_Tab:
200 case GDK_KEY_Alt_L: case GDK_KEY_Alt_R:
201 case GDK_KEY_Shift_L: case GDK_KEY_Shift_R:
202 case GDK_KEY_Control_L: case GDK_KEY_Control_R:
203 case GDK_KEY_Meta_L: case GDK_KEY_Meta_R:
204 case GDK_KEY_Return:
205 case GDK_KEY_KP_Enter:
206 case GDK_KEY_ISO_Enter:
207 case GDK_KEY_BackSpace:
208 case GDK_KEY_Escape:
209 break;
210
211 default:
212 if (shell->space_release_pending ||
213 shell->button1_release_pending ||
214 shell->scrolling)
215 return TRUE;
216 break;
217 }
218
219 set_display = TRUE;
220 break;
221 }
222
223 case GDK_BUTTON_PRESS:
224 case GDK_SCROLL:
225 set_display = TRUE;
226 break;
227
228 case GDK_FOCUS_CHANGE:
229 {
230 GdkEventFocus *fevent = (GdkEventFocus *) event;
231
232 if (fevent->in && shell->display->config->activate_on_focus)
233 set_display = TRUE;
234 }
235 break;
236
237 default:
238 break;
239 }
240
241 /* Setting the context's display automatically sets the image, too */
242 if (set_display)
243 gimp_context_set_display (gimp_get_user_context (gimp), shell->display);
244
245 return FALSE;
246 }
247
248 static gboolean
gimp_display_shell_canvas_no_image_events(GtkWidget * canvas,GdkEvent * event,GimpDisplayShell * shell)249 gimp_display_shell_canvas_no_image_events (GtkWidget *canvas,
250 GdkEvent *event,
251 GimpDisplayShell *shell)
252 {
253 switch (event->type)
254 {
255 case GDK_2BUTTON_PRESS:
256 {
257 GdkEventButton *bevent = (GdkEventButton *) event;
258 if (bevent->button == 1)
259 {
260 GimpImageWindow *window = gimp_display_shell_get_window (shell);
261 GimpUIManager *manager = gimp_image_window_get_ui_manager (window);
262
263 gimp_ui_manager_activate_action (manager, "file", "file-open");
264 }
265 return TRUE;
266 }
267 break;
268
269 case GDK_BUTTON_PRESS:
270 if (gdk_event_triggers_context_menu (event))
271 {
272 gimp_ui_manager_ui_popup (shell->popup_manager,
273 "/dummy-menubar/image-popup",
274 GTK_WIDGET (shell),
275 NULL, NULL, NULL, NULL);
276 return TRUE;
277 }
278 break;
279
280 case GDK_KEY_PRESS:
281 {
282 GdkEventKey *kevent = (GdkEventKey *) event;
283
284 if (kevent->keyval == GDK_KEY_Tab ||
285 kevent->keyval == GDK_KEY_KP_Tab ||
286 kevent->keyval == GDK_KEY_ISO_Left_Tab)
287 {
288 return gimp_display_shell_tab_pressed (shell, kevent);
289 }
290 }
291 break;
292
293 default:
294 break;
295 }
296
297 return FALSE;
298 }
299
300 gboolean
gimp_display_shell_canvas_tool_events(GtkWidget * canvas,GdkEvent * event,GimpDisplayShell * shell)301 gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
302 GdkEvent *event,
303 GimpDisplayShell *shell)
304 {
305 GdkEvent *next_event = NULL;
306 gboolean return_val;
307
308 g_return_val_if_fail (gtk_widget_get_realized (canvas), FALSE);
309
310 return_val = gimp_display_shell_canvas_tool_events_internal (canvas,
311 event, shell,
312 &next_event);
313
314 if (next_event)
315 {
316 gtk_main_do_event (next_event);
317
318 gdk_event_free (next_event);
319 }
320
321 return return_val;
322 }
323
324 void
gimp_display_shell_canvas_grab_notify(GtkWidget * canvas,gboolean was_grabbed,GimpDisplayShell * shell)325 gimp_display_shell_canvas_grab_notify (GtkWidget *canvas,
326 gboolean was_grabbed,
327 GimpDisplayShell *shell)
328 {
329 GimpDisplay *display;
330 GimpImage *image;
331 Gimp *gimp;
332
333 /* are we in destruction? */
334 if (! shell->display || ! gimp_display_get_shell (shell->display))
335 return;
336
337 display = shell->display;
338 gimp = gimp_display_get_gimp (display);
339 image = gimp_display_get_image (display);
340
341 if (! image)
342 return;
343
344 GIMP_LOG (TOOL_EVENTS, "grab_notify (display %p): was_grabbed = %s",
345 display, was_grabbed ? "TRUE" : "FALSE");
346
347 if (! was_grabbed)
348 {
349 if (! gimp_image_is_empty (image))
350 {
351 GimpTool *active_tool = tool_manager_get_active (gimp);
352
353 if (active_tool && active_tool->focus_display == display)
354 {
355 tool_manager_modifier_state_active (gimp, 0, display);
356 }
357 }
358 }
359 }
360
361 void
gimp_display_shell_buffer_stroke(GimpMotionBuffer * buffer,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpDisplayShell * shell)362 gimp_display_shell_buffer_stroke (GimpMotionBuffer *buffer,
363 const GimpCoords *coords,
364 guint32 time,
365 GdkModifierType state,
366 GimpDisplayShell *shell)
367 {
368 GimpDisplay *display = shell->display;
369 Gimp *gimp = gimp_display_get_gimp (display);
370 GimpTool *active_tool;
371
372 active_tool = tool_manager_get_active (gimp);
373
374 if (active_tool &&
375 gimp_tool_control_is_active (active_tool->control))
376 {
377 tool_manager_motion_active (gimp,
378 coords, time, state,
379 display);
380 }
381 }
382
383 void
gimp_display_shell_buffer_hover(GimpMotionBuffer * buffer,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpDisplayShell * shell)384 gimp_display_shell_buffer_hover (GimpMotionBuffer *buffer,
385 const GimpCoords *coords,
386 GdkModifierType state,
387 gboolean proximity,
388 GimpDisplayShell *shell)
389 {
390 GimpDisplay *display = shell->display;
391 Gimp *gimp = gimp_display_get_gimp (display);
392 GimpTool *active_tool;
393
394 active_tool = tool_manager_get_active (gimp);
395
396 if (active_tool &&
397 ! gimp_tool_control_is_active (active_tool->control))
398 {
399 tool_manager_oper_update_active (gimp,
400 coords, state, proximity,
401 display);
402 }
403 }
404
405 static gboolean
gimp_display_shell_ruler_button_press(GtkWidget * widget,GdkEventButton * event,GimpDisplayShell * shell,GimpOrientationType orientation)406 gimp_display_shell_ruler_button_press (GtkWidget *widget,
407 GdkEventButton *event,
408 GimpDisplayShell *shell,
409 GimpOrientationType orientation)
410 {
411 GimpDisplay *display = shell->display;
412
413 if (display->gimp->busy)
414 return TRUE;
415
416 if (! gimp_display_get_image (display))
417 return TRUE;
418
419 if (event->type == GDK_BUTTON_PRESS && event->button == 1)
420 {
421 GimpTool *active_tool = tool_manager_get_active (display->gimp);
422
423 if (active_tool)
424 {
425 gimp_display_shell_update_focus (shell, TRUE,
426 NULL, event->state);
427
428 if (gimp_display_shell_pointer_grab (shell, NULL, 0))
429 {
430 if (gimp_display_shell_keyboard_grab (shell,
431 (GdkEvent *) event))
432 {
433 if (event->state & gimp_get_toggle_behavior_mask ())
434 {
435 gimp_sample_point_tool_start_new (active_tool, display);
436 }
437 else
438 {
439 gimp_guide_tool_start_new (active_tool, display,
440 orientation);
441 }
442
443 return TRUE;
444 }
445 else
446 {
447 gimp_display_shell_pointer_ungrab (shell, NULL);
448 }
449 }
450 }
451 }
452
453 return FALSE;
454 }
455
456 gboolean
gimp_display_shell_hruler_button_press(GtkWidget * widget,GdkEventButton * event,GimpDisplayShell * shell)457 gimp_display_shell_hruler_button_press (GtkWidget *widget,
458 GdkEventButton *event,
459 GimpDisplayShell *shell)
460 {
461 return gimp_display_shell_ruler_button_press (widget, event, shell,
462 GIMP_ORIENTATION_HORIZONTAL);
463 }
464
465 gboolean
gimp_display_shell_vruler_button_press(GtkWidget * widget,GdkEventButton * event,GimpDisplayShell * shell)466 gimp_display_shell_vruler_button_press (GtkWidget *widget,
467 GdkEventButton *event,
468 GimpDisplayShell *shell)
469 {
470 return gimp_display_shell_ruler_button_press (widget, event, shell,
471 GIMP_ORIENTATION_VERTICAL);
472 }
473
474
475 /* private functions */
476
477 static gboolean
gimp_display_shell_canvas_tool_events_internal(GtkWidget * canvas,GdkEvent * event,GimpDisplayShell * shell,GdkEvent ** next_event)478 gimp_display_shell_canvas_tool_events_internal (GtkWidget *canvas,
479 GdkEvent *event,
480 GimpDisplayShell *shell,
481 GdkEvent **next_event)
482 {
483 GimpDisplay *display;
484 GimpImage *image;
485 Gimp *gimp;
486 GimpCoords display_coords;
487 GimpCoords image_coords;
488 GdkModifierType state;
489 guint32 time;
490 gboolean device_changed = FALSE;
491 gboolean return_val = FALSE;
492 gboolean update_sw_cursor = FALSE;
493
494 *next_event = NULL;
495
496 /* are we in destruction? */
497 if (! shell->display || ! gimp_display_get_shell (shell->display))
498 return TRUE;
499
500 /* set the active display before doing any other canvas event processing */
501 if (gimp_display_shell_events (canvas, event, shell))
502 return TRUE;
503
504 /* events on overlays have a different window, but these windows'
505 * user_data can still be the canvas, we need to check manually if
506 * the event's window and the canvas' window are different.
507 */
508 if (event->any.window != gtk_widget_get_window (canvas))
509 {
510 GtkWidget *event_widget;
511
512 gdk_window_get_user_data (event->any.window, (gpointer) &event_widget);
513
514 /* if the event came from a different window than the canvas',
515 * check if it came from a canvas child and bail out.
516 */
517 if (gtk_widget_get_ancestor (event_widget, GIMP_TYPE_CANVAS))
518 return FALSE;
519 }
520
521 display = shell->display;
522 gimp = gimp_display_get_gimp (display);
523 image = gimp_display_get_image (display);
524
525 if (! image)
526 return gimp_display_shell_canvas_no_image_events (canvas, event, shell);
527
528 GIMP_LOG (TOOL_EVENTS, "event (display %p): %s",
529 display, gimp_print_event (event));
530
531 /* See bug 771444 */
532 if (shell->pointer_grabbed &&
533 event->type == GDK_MOTION_NOTIFY)
534 {
535 GimpDeviceManager *manager = gimp_devices_get_manager (gimp);
536 GimpDeviceInfo *info;
537
538 info = gimp_device_manager_get_current_device (manager);
539
540 if (info->device != event->motion.device)
541 return FALSE;
542 }
543
544 /* Find out what device the event occurred upon */
545 if (! gimp->busy &&
546 ! shell->inferior_ignore_mode &&
547 gimp_devices_check_change (gimp, event))
548 {
549 gimp_display_shell_check_device_cursor (shell);
550 device_changed = TRUE;
551 }
552
553 gimp_display_shell_get_event_coords (shell, event,
554 &display_coords,
555 &state, &time);
556 gimp_display_shell_untransform_event_coords (shell,
557 &display_coords, &image_coords,
558 &update_sw_cursor);
559
560 /* If the device (and maybe the tool) has changed, update the new
561 * tool's state
562 */
563 if (device_changed && gtk_widget_has_focus (canvas))
564 {
565 gimp_display_shell_update_focus (shell, TRUE,
566 &image_coords, state);
567 }
568
569 switch (event->type)
570 {
571 case GDK_ENTER_NOTIFY:
572 {
573 GdkEventCrossing *cevent = (GdkEventCrossing *) event;
574
575 if (shell->inferior_ignore_mode &&
576 cevent->subwindow == NULL &&
577 cevent->mode == GDK_CROSSING_NORMAL)
578 {
579 shell->inferior_ignore_mode = FALSE;
580 gtk_widget_set_extension_events (shell->canvas,
581 GDK_EXTENSION_EVENTS_ALL);
582 }
583
584 if (cevent->mode != GDK_CROSSING_NORMAL)
585 return TRUE;
586
587 /* ignore enter notify while we have a grab */
588 if (shell->pointer_grabbed)
589 return TRUE;
590
591 gimp_display_shell_proximity_in (shell);
592 update_sw_cursor = TRUE;
593
594 tool_manager_oper_update_active (gimp,
595 &image_coords, state,
596 shell->proximity,
597 display);
598 }
599 break;
600
601 case GDK_LEAVE_NOTIFY:
602 {
603 GdkEventCrossing *cevent = (GdkEventCrossing *) event;
604
605 if (! shell->inferior_ignore_mode &&
606 cevent->subwindow == NULL &&
607 cevent->mode == GDK_CROSSING_NORMAL &&
608 cevent->detail == GDK_NOTIFY_INFERIOR)
609 {
610 shell->inferior_ignore_mode = TRUE;
611 gtk_widget_set_extension_events (shell->canvas,
612 GDK_EXTENSION_EVENTS_NONE);
613 }
614
615 if (cevent->mode != GDK_CROSSING_NORMAL)
616 return TRUE;
617
618 /* ignore leave notify while we have a grab */
619 if (shell->pointer_grabbed)
620 return TRUE;
621
622 gimp_display_shell_proximity_out (shell);
623
624 tool_manager_oper_update_active (gimp,
625 &image_coords, state,
626 shell->proximity,
627 display);
628 }
629 break;
630
631 case GDK_PROXIMITY_IN:
632 gimp_display_shell_proximity_in (shell);
633
634 tool_manager_oper_update_active (gimp,
635 &image_coords, state,
636 shell->proximity,
637 display);
638 break;
639
640 case GDK_PROXIMITY_OUT:
641 gimp_display_shell_proximity_out (shell);
642
643 tool_manager_oper_update_active (gimp,
644 &image_coords, state,
645 shell->proximity,
646 display);
647 break;
648
649 case GDK_FOCUS_CHANGE:
650 {
651 GdkEventFocus *fevent = (GdkEventFocus *) event;
652
653 if (fevent->in)
654 {
655 if (G_UNLIKELY (! gtk_widget_has_focus (canvas)))
656 g_warning ("%s: FOCUS_IN but canvas has no focus", G_STRFUNC);
657
658 /* ignore focus changes while we have a grab */
659 if (shell->pointer_grabbed)
660 return TRUE;
661
662 /* press modifier keys when the canvas gets the focus */
663 gimp_display_shell_update_focus (shell, TRUE,
664 &image_coords, state);
665 }
666 else
667 {
668 if (G_UNLIKELY (gtk_widget_has_focus (canvas)))
669 g_warning ("%s: FOCUS_OUT but canvas has focus", G_STRFUNC);
670
671 /* ignore focus changes while we have a grab */
672 if (shell->pointer_grabbed)
673 return TRUE;
674
675 /* release modifier keys when the canvas loses the focus */
676 gimp_display_shell_update_focus (shell, FALSE,
677 &image_coords, 0);
678 }
679 }
680 break;
681
682 case GDK_BUTTON_PRESS:
683 {
684 GdkEventButton *bevent = (GdkEventButton *) event;
685 GdkModifierType button_state;
686
687 /* ignore new mouse events */
688 if (gimp->busy || shell->scrolling ||
689 shell->pointer_grabbed ||
690 shell->button1_release_pending)
691 return TRUE;
692
693 button_state = gimp_display_shell_button_to_state (bevent->button);
694
695 state |= button_state;
696
697 /* ignore new buttons while another button is down */
698 if (((state & (GDK_BUTTON1_MASK)) && (state & (GDK_BUTTON2_MASK |
699 GDK_BUTTON3_MASK))) ||
700 ((state & (GDK_BUTTON2_MASK)) && (state & (GDK_BUTTON1_MASK |
701 GDK_BUTTON3_MASK))) ||
702 ((state & (GDK_BUTTON3_MASK)) && (state & (GDK_BUTTON1_MASK |
703 GDK_BUTTON2_MASK))))
704 return TRUE;
705
706 /* focus the widget if it isn't; if the toplevel window
707 * already has focus, this will generate a FOCUS_IN on the
708 * canvas immediately, therefore we do this before logging
709 * the BUTTON_PRESS.
710 */
711 if (! gtk_widget_has_focus (canvas))
712 gtk_widget_grab_focus (canvas);
713
714 /* if the toplevel window didn't have focus, the above
715 * gtk_widget_grab_focus() didn't set the canvas' HAS_FOCUS
716 * flags, and didn't trigger a FOCUS_IN, but the tool needs
717 * to be set up correctly regardless, so simply do the
718 * same things here, it's safe to do them redundantly.
719 */
720 gimp_display_shell_update_focus (shell, TRUE,
721 &image_coords, state);
722 gimp_display_shell_update_cursor (shell, &display_coords,
723 &image_coords, state & ~button_state,
724 FALSE);
725
726 if (gdk_event_triggers_context_menu (event))
727 {
728 GimpUIManager *ui_manager;
729 const gchar *ui_path;
730
731 ui_manager = tool_manager_get_popup_active (gimp,
732 &image_coords, state,
733 display,
734 &ui_path);
735
736 if (ui_manager)
737 {
738 gimp_ui_manager_ui_popup (ui_manager,
739 ui_path,
740 GTK_WIDGET (shell),
741 NULL, NULL, NULL, NULL);
742 }
743 else
744 {
745 gimp_ui_manager_ui_popup (shell->popup_manager,
746 "/dummy-menubar/image-popup",
747 GTK_WIDGET (shell),
748 NULL, NULL, NULL, NULL);
749 }
750 }
751 else if (bevent->button == 1)
752 {
753 if (! gimp_display_shell_pointer_grab (shell, NULL, 0))
754 return TRUE;
755
756 if (! shell->space_release_pending)
757 if (! gimp_display_shell_keyboard_grab (shell, event))
758 {
759 gimp_display_shell_pointer_ungrab (shell, NULL);
760 return TRUE;
761 }
762
763 if (gimp_display_shell_initialize_tool (shell,
764 &image_coords, state))
765 {
766 GimpCoords last_motion;
767
768 /* Use the last evaluated velocity&direction instead of the
769 * button_press event's ones because the click is
770 * usually at the same spot as the last motion event
771 * which would give us bogus derivate dynamics.
772 */
773 gimp_motion_buffer_begin_stroke (shell->motion_buffer, time,
774 &last_motion);
775
776 image_coords.velocity = last_motion.velocity;
777 image_coords.direction = last_motion.direction;
778
779 tool_manager_button_press_active (gimp,
780 &image_coords,
781 time, state,
782 GIMP_BUTTON_PRESS_NORMAL,
783 display);
784 }
785 }
786 else if (bevent->button == 2)
787 {
788 gimp_display_shell_start_scrolling (shell, NULL, state,
789 bevent->x, bevent->y);
790 }
791
792 return_val = TRUE;
793 }
794 break;
795
796 case GDK_2BUTTON_PRESS:
797 {
798 GdkEventButton *bevent = (GdkEventButton *) event;
799 GimpTool *active_tool;
800
801 if (gimp->busy)
802 return TRUE;
803
804 active_tool = tool_manager_get_active (gimp);
805
806 if (bevent->button == 1 &&
807 active_tool &&
808 gimp_tool_control_is_active (active_tool->control) &&
809 gimp_tool_control_get_wants_double_click (active_tool->control))
810 {
811 tool_manager_button_press_active (gimp,
812 &image_coords,
813 time, state,
814 GIMP_BUTTON_PRESS_DOUBLE,
815 display);
816 }
817
818 /* don't update the cursor again on double click */
819 return TRUE;
820 }
821 break;
822
823 case GDK_3BUTTON_PRESS:
824 {
825 GdkEventButton *bevent = (GdkEventButton *) event;
826 GimpTool *active_tool;
827
828 if (gimp->busy)
829 return TRUE;
830
831 active_tool = tool_manager_get_active (gimp);
832
833 if (bevent->button == 1 &&
834 active_tool &&
835 gimp_tool_control_is_active (active_tool->control) &&
836 gimp_tool_control_get_wants_triple_click (active_tool->control))
837 {
838 tool_manager_button_press_active (gimp,
839 &image_coords,
840 time, state,
841 GIMP_BUTTON_PRESS_TRIPLE,
842 display);
843 }
844
845 /* don't update the cursor again on triple click */
846 return TRUE;
847 }
848 break;
849
850 case GDK_BUTTON_RELEASE:
851 {
852 GdkEventButton *bevent = (GdkEventButton *) event;
853 GimpTool *active_tool;
854
855 gimp_display_shell_autoscroll_stop (shell);
856
857 if (bevent->button == 1 && shell->button1_release_pending)
858 {
859 gimp_display_shell_released (shell, event, NULL);
860 return TRUE;
861 }
862
863 if (gimp->busy)
864 return TRUE;
865
866 active_tool = tool_manager_get_active (gimp);
867
868 state &= ~gimp_display_shell_button_to_state (bevent->button);
869
870 if (bevent->button == 1)
871 {
872 if (! shell->pointer_grabbed || shell->scrolling)
873 return TRUE;
874
875 if (! shell->space_release_pending)
876 gimp_display_shell_keyboard_ungrab (shell, event);
877
878 if (active_tool &&
879 (! gimp_image_is_empty (image) ||
880 gimp_tool_control_get_handle_empty_image (active_tool->control)))
881 {
882 gimp_motion_buffer_end_stroke (shell->motion_buffer);
883
884 if (gimp_tool_control_is_active (active_tool->control))
885 {
886 tool_manager_button_release_active (gimp,
887 &image_coords,
888 time, state,
889 display);
890 }
891 }
892
893 /* update the tool's modifier state because it didn't get
894 * key events while BUTTON1 was down
895 */
896 if (gtk_widget_has_focus (canvas))
897 gimp_display_shell_update_focus (shell, TRUE,
898 &image_coords, state);
899 else
900 gimp_display_shell_update_focus (shell, FALSE,
901 &image_coords, 0);
902
903 gimp_display_shell_pointer_ungrab (shell, NULL);
904 }
905 else if (bevent->button == 2)
906 {
907 if (shell->scrolling)
908 gimp_display_shell_stop_scrolling (shell, NULL);
909 }
910 else if (bevent->button == 3)
911 {
912 /* nop */
913 }
914 else
915 {
916 GdkEventButton *bevent = (GdkEventButton *) event;
917 GimpController *mouse = gimp_controllers_get_mouse (gimp);
918
919 if (!(shell->scrolling || shell->pointer_grabbed) &&
920 mouse && gimp_controller_mouse_button (GIMP_CONTROLLER_MOUSE (mouse),
921 bevent))
922 {
923 return TRUE;
924 }
925 }
926
927 return_val = TRUE;
928 }
929 break;
930
931 case GDK_SCROLL:
932 {
933 GdkEventScroll *sevent = (GdkEventScroll *) event;
934 GimpController *wheel = gimp_controllers_get_wheel (gimp);
935
936 if (! wheel ||
937 ! gimp_controller_wheel_scroll (GIMP_CONTROLLER_WHEEL (wheel),
938 sevent))
939 {
940 GdkScrollDirection direction = sevent->direction;
941
942 if (state & gimp_get_toggle_behavior_mask ())
943 {
944 switch (direction)
945 {
946 case GDK_SCROLL_UP:
947 gimp_display_shell_scale (shell,
948 GIMP_ZOOM_IN,
949 0.0,
950 GIMP_ZOOM_FOCUS_POINTER);
951 break;
952
953 case GDK_SCROLL_DOWN:
954 gimp_display_shell_scale (shell,
955 GIMP_ZOOM_OUT,
956 0.0,
957 GIMP_ZOOM_FOCUS_POINTER);
958 break;
959
960 default:
961 break;
962 }
963 }
964 else
965 {
966 GtkAdjustment *adj = NULL;
967 gdouble value;
968
969 if (state & GDK_SHIFT_MASK)
970 switch (direction)
971 {
972 case GDK_SCROLL_UP: direction = GDK_SCROLL_LEFT; break;
973 case GDK_SCROLL_DOWN: direction = GDK_SCROLL_RIGHT; break;
974 case GDK_SCROLL_LEFT: direction = GDK_SCROLL_UP; break;
975 case GDK_SCROLL_RIGHT: direction = GDK_SCROLL_DOWN; break;
976 }
977
978 switch (direction)
979 {
980 case GDK_SCROLL_LEFT:
981 case GDK_SCROLL_RIGHT:
982 adj = shell->hsbdata;
983 break;
984
985 case GDK_SCROLL_UP:
986 case GDK_SCROLL_DOWN:
987 adj = shell->vsbdata;
988 break;
989 }
990
991 value = (gtk_adjustment_get_value (adj) +
992 ((direction == GDK_SCROLL_UP ||
993 direction == GDK_SCROLL_LEFT) ?
994 -gtk_adjustment_get_page_increment (adj) / 2 :
995 gtk_adjustment_get_page_increment (adj) / 2));
996 value = CLAMP (value,
997 gtk_adjustment_get_lower (adj),
998 gtk_adjustment_get_upper (adj) -
999 gtk_adjustment_get_page_size (adj));
1000
1001 gtk_adjustment_set_value (adj, value);
1002 }
1003 }
1004
1005 gimp_display_shell_untransform_event_coords (shell,
1006 &display_coords,
1007 &image_coords,
1008 &update_sw_cursor);
1009
1010 tool_manager_oper_update_active (gimp,
1011 &image_coords, state,
1012 shell->proximity,
1013 display);
1014
1015 return_val = TRUE;
1016 }
1017 break;
1018
1019 case GDK_MOTION_NOTIFY:
1020 {
1021 GdkEventMotion *mevent = (GdkEventMotion *) event;
1022 GdkEvent *compressed_motion = NULL;
1023 GimpMotionMode motion_mode = GIMP_MOTION_MODE_EXACT;
1024 GimpTool *active_tool;
1025
1026 if (gimp->busy)
1027 return TRUE;
1028
1029 active_tool = tool_manager_get_active (gimp);
1030
1031 if (active_tool)
1032 motion_mode = gimp_tool_control_get_motion_mode (active_tool->control);
1033
1034 if (shell->scrolling ||
1035 motion_mode == GIMP_MOTION_MODE_COMPRESS)
1036 {
1037 compressed_motion = gimp_display_shell_compress_motion (event,
1038 next_event);
1039
1040 if (compressed_motion && ! shell->scrolling)
1041 {
1042 gimp_display_shell_get_event_coords (shell,
1043 compressed_motion,
1044 &display_coords,
1045 &state, &time);
1046 gimp_display_shell_untransform_event_coords (shell,
1047 &display_coords,
1048 &image_coords,
1049 NULL);
1050 }
1051 }
1052
1053 /* call proximity_in() here because the pointer might already
1054 * be in proximity when the canvas starts to receive events,
1055 * like when a new image has been created into an empty
1056 * display
1057 */
1058 gimp_display_shell_proximity_in (shell);
1059 update_sw_cursor = TRUE;
1060
1061 if (shell->scrolling)
1062 {
1063 GdkEventMotion *me = (compressed_motion ?
1064 (GdkEventMotion *) compressed_motion :
1065 mevent);
1066
1067 gimp_display_shell_handle_scrolling (shell, state, me->x, me->y);
1068 }
1069 else if (state & GDK_BUTTON1_MASK)
1070 {
1071 if (active_tool &&
1072 gimp_tool_control_is_active (active_tool->control) &&
1073 (! gimp_image_is_empty (image) ||
1074 gimp_tool_control_get_handle_empty_image (active_tool->control)))
1075 {
1076 GdkTimeCoord **history_events;
1077 gint n_history_events;
1078 guint32 last_motion_time;
1079
1080 /* if the first mouse button is down, check for automatic
1081 * scrolling...
1082 */
1083 if ((mevent->x < 0 ||
1084 mevent->y < 0 ||
1085 mevent->x > shell->disp_width ||
1086 mevent->y > shell->disp_height) &&
1087 ! gimp_tool_control_get_scroll_lock (active_tool->control))
1088 {
1089 gimp_display_shell_autoscroll_start (shell, state, mevent);
1090 }
1091
1092 /* gdk_device_get_history() has several quirks. First
1093 * is that events with borderline timestamps at both
1094 * ends are included. Because of that we need to add 1
1095 * to lower border. The second is due to poor X event
1096 * resolution. We need to do -1 to ensure that the
1097 * amount of events between timestamps is final or
1098 * risk losing some.
1099 */
1100 last_motion_time =
1101 gimp_motion_buffer_get_last_motion_time (shell->motion_buffer);
1102
1103 if (motion_mode == GIMP_MOTION_MODE_EXACT &&
1104 shell->display->config->use_event_history &&
1105 gdk_device_get_history (mevent->device, mevent->window,
1106 last_motion_time + 1,
1107 mevent->time - 1,
1108 &history_events,
1109 &n_history_events))
1110 {
1111 GimpDeviceInfo *device;
1112 gint i;
1113
1114 device = gimp_device_info_get_by_device (mevent->device);
1115
1116 for (i = 0; i < n_history_events; i++)
1117 {
1118 gimp_device_info_get_time_coords (device,
1119 history_events[i],
1120 &display_coords);
1121
1122 gimp_display_shell_untransform_event_coords (shell,
1123 &display_coords,
1124 &image_coords,
1125 NULL);
1126
1127 /* Early removal of useless events saves CPU time.
1128 */
1129 if (gimp_motion_buffer_motion_event (shell->motion_buffer,
1130 &image_coords,
1131 history_events[i]->time,
1132 TRUE))
1133 {
1134 gimp_motion_buffer_request_stroke (shell->motion_buffer,
1135 state,
1136 history_events[i]->time);
1137 }
1138 }
1139
1140 gdk_device_free_history (history_events, n_history_events);
1141 }
1142 else
1143 {
1144 gboolean event_fill = (motion_mode == GIMP_MOTION_MODE_EXACT);
1145
1146 /* Early removal of useless events saves CPU time.
1147 */
1148 if (gimp_motion_buffer_motion_event (shell->motion_buffer,
1149 &image_coords,
1150 time,
1151 event_fill))
1152 {
1153 gimp_motion_buffer_request_stroke (shell->motion_buffer,
1154 state,
1155 time);
1156 }
1157 }
1158 }
1159 }
1160
1161 if (! (state &
1162 (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
1163 {
1164 /* Early removal of useless events saves CPU time.
1165 * Pass event_fill = FALSE since we are only hovering.
1166 */
1167 if (gimp_motion_buffer_motion_event (shell->motion_buffer,
1168 &image_coords,
1169 time,
1170 FALSE))
1171 {
1172 gimp_motion_buffer_request_hover (shell->motion_buffer,
1173 state,
1174 shell->proximity);
1175 }
1176 }
1177
1178 if (compressed_motion)
1179 gdk_event_free (compressed_motion);
1180
1181 return_val = TRUE;
1182 }
1183 break;
1184
1185 case GDK_KEY_PRESS:
1186 {
1187 GdkEventKey *kevent = (GdkEventKey *) event;
1188 GimpTool *active_tool;
1189
1190 active_tool = tool_manager_get_active (gimp);
1191
1192 if (state & GDK_BUTTON1_MASK)
1193 {
1194 if (kevent->keyval == GDK_KEY_Alt_L ||
1195 kevent->keyval == GDK_KEY_Alt_R ||
1196 kevent->keyval == GDK_KEY_Shift_L ||
1197 kevent->keyval == GDK_KEY_Shift_R ||
1198 kevent->keyval == GDK_KEY_Control_L ||
1199 kevent->keyval == GDK_KEY_Control_R ||
1200 kevent->keyval == GDK_KEY_Meta_L ||
1201 kevent->keyval == GDK_KEY_Meta_R)
1202 {
1203 GdkModifierType key;
1204
1205 key = gimp_display_shell_key_to_state (kevent->keyval);
1206 state |= key;
1207
1208 if (active_tool &&
1209 gimp_tool_control_is_active (active_tool->control) &&
1210 ! gimp_image_is_empty (image))
1211 {
1212 tool_manager_active_modifier_state_active (gimp, state,
1213 display);
1214 }
1215 }
1216 }
1217 else
1218 {
1219 gboolean arrow_key = FALSE;
1220
1221 tool_manager_focus_display_active (gimp, display);
1222
1223 if (gimp_tool_control_get_wants_all_key_events (active_tool->control))
1224 {
1225 if (tool_manager_key_press_active (gimp, kevent, display))
1226 {
1227 /* FIXME: need to do some of the stuff below, like
1228 * calling oper_update()
1229 */
1230
1231 return TRUE;
1232 }
1233 }
1234
1235 if (! gtk_widget_has_focus (shell->canvas))
1236 {
1237 /* The event was in an overlay widget and not handled
1238 * there, make sure the overlay widgets are keyboard
1239 * navigatable by letting the generic widget handlers
1240 * deal with the event.
1241 */
1242 return FALSE;
1243 }
1244
1245 if (gimp_display_shell_key_to_state (kevent->keyval) == GDK_MOD1_MASK)
1246 /* Make sure the picked layer is reset. */
1247 shell->picked_layer = NULL;
1248
1249 switch (kevent->keyval)
1250 {
1251 case GDK_KEY_Left:
1252 case GDK_KEY_Right:
1253 case GDK_KEY_Up:
1254 case GDK_KEY_Down:
1255 arrow_key = TRUE;
1256
1257 case GDK_KEY_Return:
1258 case GDK_KEY_KP_Enter:
1259 case GDK_KEY_ISO_Enter:
1260 case GDK_KEY_BackSpace:
1261 case GDK_KEY_Escape:
1262 if (! gimp_image_is_empty (image))
1263 return_val = tool_manager_key_press_active (gimp,
1264 kevent,
1265 display);
1266
1267 if (! return_val)
1268 {
1269 GimpController *keyboard = gimp_controllers_get_keyboard (gimp);
1270
1271 if (keyboard)
1272 return_val =
1273 gimp_controller_keyboard_key_press (GIMP_CONTROLLER_KEYBOARD (keyboard),
1274 kevent);
1275 }
1276
1277 /* always swallow arrow keys, we don't want focus keynav */
1278 if (! return_val)
1279 return_val = arrow_key;
1280 break;
1281
1282 case GDK_KEY_space:
1283 case GDK_KEY_KP_Space:
1284 if (shell->button1_release_pending)
1285 shell->space_release_pending = TRUE;
1286 else
1287 gimp_display_shell_space_pressed (shell, event);
1288 return_val = TRUE;
1289 break;
1290
1291 case GDK_KEY_Tab:
1292 case GDK_KEY_KP_Tab:
1293 case GDK_KEY_ISO_Left_Tab:
1294 gimp_display_shell_tab_pressed (shell, kevent);
1295 return_val = TRUE;
1296 break;
1297
1298 /* Update the state based on modifiers being pressed */
1299 case GDK_KEY_Alt_L: case GDK_KEY_Alt_R:
1300 case GDK_KEY_Shift_L: case GDK_KEY_Shift_R:
1301 case GDK_KEY_Control_L: case GDK_KEY_Control_R:
1302 case GDK_KEY_Meta_L: case GDK_KEY_Meta_R:
1303 {
1304 GdkModifierType key;
1305
1306 key = gimp_display_shell_key_to_state (kevent->keyval);
1307 state |= key;
1308
1309 if (! gimp_image_is_empty (image))
1310 tool_manager_modifier_state_active (gimp, state, display);
1311 }
1312 break;
1313 }
1314
1315 tool_manager_oper_update_active (gimp,
1316 &image_coords, state,
1317 shell->proximity,
1318 display);
1319 }
1320 }
1321 break;
1322
1323 case GDK_KEY_RELEASE:
1324 {
1325 GdkEventKey *kevent = (GdkEventKey *) event;
1326 GimpTool *active_tool;
1327
1328 active_tool = tool_manager_get_active (gimp);
1329
1330 if (gimp_display_shell_key_to_state (kevent->keyval) == GDK_MOD1_MASK &&
1331 shell->picked_layer)
1332 {
1333 GimpStatusbar *statusbar;
1334
1335 statusbar = gimp_display_shell_get_statusbar (shell);
1336 gimp_statusbar_pop_temp (statusbar);
1337
1338 shell->picked_layer = NULL;
1339 }
1340
1341 if ((state & GDK_BUTTON1_MASK) &&
1342 (! shell->space_release_pending ||
1343 (kevent->keyval != GDK_KEY_space &&
1344 kevent->keyval != GDK_KEY_KP_Space)))
1345 {
1346 if (kevent->keyval == GDK_KEY_Alt_L ||
1347 kevent->keyval == GDK_KEY_Alt_R ||
1348 kevent->keyval == GDK_KEY_Shift_L ||
1349 kevent->keyval == GDK_KEY_Shift_R ||
1350 kevent->keyval == GDK_KEY_Control_L ||
1351 kevent->keyval == GDK_KEY_Control_R ||
1352 kevent->keyval == GDK_KEY_Meta_L ||
1353 kevent->keyval == GDK_KEY_Meta_R)
1354 {
1355 GdkModifierType key;
1356
1357 key = gimp_display_shell_key_to_state (kevent->keyval);
1358 state &= ~key;
1359
1360 if (active_tool &&
1361 gimp_tool_control_is_active (active_tool->control) &&
1362 ! gimp_image_is_empty (image))
1363 {
1364 tool_manager_active_modifier_state_active (gimp, state,
1365 display);
1366 }
1367 }
1368 }
1369 else
1370 {
1371 tool_manager_focus_display_active (gimp, display);
1372
1373 if (gimp_tool_control_get_wants_all_key_events (active_tool->control))
1374 {
1375 if (tool_manager_key_release_active (gimp, kevent, display))
1376 {
1377 /* FIXME: need to do some of the stuff below, like
1378 * calling oper_update()
1379 */
1380
1381 return TRUE;
1382 }
1383 }
1384
1385 if (! gtk_widget_has_focus (shell->canvas))
1386 {
1387 /* The event was in an overlay widget and not handled
1388 * there, make sure the overlay widgets are keyboard
1389 * navigatable by letting the generic widget handlers
1390 * deal with the event.
1391 */
1392 return FALSE;
1393 }
1394
1395 switch (kevent->keyval)
1396 {
1397 case GDK_KEY_space:
1398 case GDK_KEY_KP_Space:
1399 if ((state & GDK_BUTTON1_MASK))
1400 {
1401 shell->button1_release_pending = TRUE;
1402 shell->space_release_pending = FALSE;
1403 /* We need to ungrab the pointer in order to catch
1404 * button release events.
1405 */
1406 if (shell->pointer_grabbed)
1407 gimp_display_shell_pointer_ungrab (shell, event);
1408 }
1409 else
1410 {
1411 gimp_display_shell_released (shell, event, NULL);
1412 }
1413 return_val = TRUE;
1414 break;
1415
1416 /* Update the state based on modifiers being pressed */
1417 case GDK_KEY_Alt_L: case GDK_KEY_Alt_R:
1418 case GDK_KEY_Shift_L: case GDK_KEY_Shift_R:
1419 case GDK_KEY_Control_L: case GDK_KEY_Control_R:
1420 case GDK_KEY_Meta_L: case GDK_KEY_Meta_R:
1421 {
1422 GdkModifierType key;
1423
1424 key = gimp_display_shell_key_to_state (kevent->keyval);
1425 state &= ~key;
1426
1427 /* For all modifier keys: call the tools
1428 * modifier_state *and* oper_update method so tools
1429 * can choose if they are interested in the press
1430 * itself or only in the resulting state
1431 */
1432 if (! gimp_image_is_empty (image))
1433 tool_manager_modifier_state_active (gimp, state, display);
1434 }
1435 break;
1436 }
1437
1438 tool_manager_oper_update_active (gimp,
1439 &image_coords, state,
1440 shell->proximity,
1441 display);
1442 }
1443 }
1444 break;
1445
1446 default:
1447 break;
1448 }
1449
1450 /* if we reached this point in gimp_busy mode, return now */
1451 if (gimp->busy)
1452 return return_val;
1453
1454 /* cursor update */
1455 gimp_display_shell_update_cursor (shell, &display_coords, &image_coords,
1456 state, update_sw_cursor);
1457
1458 return return_val;
1459 }
1460
1461 static GdkModifierType
gimp_display_shell_key_to_state(gint key)1462 gimp_display_shell_key_to_state (gint key)
1463 {
1464 /* FIXME: need some proper GDK API to figure this */
1465
1466 switch (key)
1467 {
1468 case GDK_KEY_Alt_L:
1469 case GDK_KEY_Alt_R:
1470 return GDK_MOD1_MASK;
1471
1472 case GDK_KEY_Shift_L:
1473 case GDK_KEY_Shift_R:
1474 return GDK_SHIFT_MASK;
1475
1476 case GDK_KEY_Control_L:
1477 case GDK_KEY_Control_R:
1478 return GDK_CONTROL_MASK;
1479
1480 #ifdef GDK_WINDOWING_QUARTZ
1481 case GDK_KEY_Meta_L:
1482 case GDK_KEY_Meta_R:
1483 return GDK_MOD2_MASK;
1484 #endif
1485
1486 default:
1487 return 0;
1488 }
1489 }
1490
1491 static GdkModifierType
gimp_display_shell_button_to_state(gint button)1492 gimp_display_shell_button_to_state (gint button)
1493 {
1494 if (button == 1)
1495 return GDK_BUTTON1_MASK;
1496 else if (button == 2)
1497 return GDK_BUTTON2_MASK;
1498 else if (button == 3)
1499 return GDK_BUTTON3_MASK;
1500
1501 return 0;
1502 }
1503
1504 static void
gimp_display_shell_proximity_in(GimpDisplayShell * shell)1505 gimp_display_shell_proximity_in (GimpDisplayShell *shell)
1506 {
1507 if (! shell->proximity)
1508 {
1509 shell->proximity = TRUE;
1510
1511 gimp_display_shell_check_device_cursor (shell);
1512 }
1513 }
1514
1515 static void
gimp_display_shell_proximity_out(GimpDisplayShell * shell)1516 gimp_display_shell_proximity_out (GimpDisplayShell *shell)
1517 {
1518 if (shell->proximity)
1519 {
1520 shell->proximity = FALSE;
1521
1522 gimp_display_shell_clear_software_cursor (shell);
1523 }
1524 }
1525
1526 static void
gimp_display_shell_check_device_cursor(GimpDisplayShell * shell)1527 gimp_display_shell_check_device_cursor (GimpDisplayShell *shell)
1528 {
1529 GimpDeviceManager *manager;
1530 GimpDeviceInfo *current_device;
1531
1532 manager = gimp_devices_get_manager (shell->display->gimp);
1533
1534 current_device = gimp_device_manager_get_current_device (manager);
1535
1536 shell->draw_cursor = ! gimp_device_info_has_cursor (current_device);
1537 }
1538
1539 static void
gimp_display_shell_start_scrolling(GimpDisplayShell * shell,const GdkEvent * event,GdkModifierType state,gint x,gint y)1540 gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
1541 const GdkEvent *event,
1542 GdkModifierType state,
1543 gint x,
1544 gint y)
1545 {
1546 g_return_if_fail (! shell->scrolling);
1547
1548 gimp_display_shell_pointer_grab (shell, event, GDK_POINTER_MOTION_MASK);
1549
1550 shell->scrolling = TRUE;
1551 shell->scroll_start_x = x;
1552 shell->scroll_start_y = y;
1553 shell->scroll_last_x = x;
1554 shell->scroll_last_y = y;
1555 shell->rotating = (state & gimp_get_extend_selection_mask ()) ? TRUE : FALSE;
1556 shell->rotate_drag_angle = shell->rotate_angle;
1557 shell->scaling = (state & gimp_get_toggle_behavior_mask ()) ? TRUE : FALSE;
1558 shell->layer_picking = (state & GDK_MOD1_MASK) ? TRUE : FALSE;
1559
1560 if (shell->rotating)
1561 {
1562 gimp_display_shell_set_override_cursor (shell,
1563 (GimpCursorType) GDK_EXCHANGE);
1564 }
1565 else if (shell->scaling)
1566 {
1567 gimp_display_shell_set_override_cursor (shell,
1568 (GimpCursorType) GIMP_CURSOR_ZOOM);
1569 }
1570 else if (shell->layer_picking)
1571 {
1572 GimpImage *image = gimp_display_get_image (shell->display);
1573 GimpLayer *layer;
1574 GimpCoords image_coords;
1575 GimpCoords display_coords;
1576 guint32 time;
1577
1578 gimp_display_shell_set_override_cursor (shell,
1579 (GimpCursorType) GIMP_CURSOR_CROSSHAIR);
1580
1581 gimp_display_shell_get_event_coords (shell, event,
1582 &display_coords,
1583 &state, &time);
1584 gimp_display_shell_untransform_event_coords (shell,
1585 &display_coords, &image_coords,
1586 NULL);
1587 layer = gimp_image_pick_layer (image,
1588 (gint) image_coords.x,
1589 (gint) image_coords.y,
1590 shell->picked_layer);
1591
1592 if (layer && ! gimp_image_get_floating_selection (image))
1593 {
1594 if (layer != gimp_image_get_active_layer (image))
1595 {
1596 GimpStatusbar *statusbar;
1597
1598 gimp_image_set_active_layer (image, layer);
1599
1600 statusbar = gimp_display_shell_get_statusbar (shell);
1601 gimp_statusbar_push_temp (statusbar, GIMP_MESSAGE_INFO,
1602 GIMP_ICON_LAYER,
1603 _("Layer picked: '%s'"),
1604 gimp_object_get_name (layer));
1605 }
1606 shell->picked_layer = layer;
1607 }
1608 }
1609 else
1610 gimp_display_shell_set_override_cursor (shell,
1611 (GimpCursorType) GDK_FLEUR);
1612 }
1613
1614 static void
gimp_display_shell_stop_scrolling(GimpDisplayShell * shell,const GdkEvent * event)1615 gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
1616 const GdkEvent *event)
1617 {
1618 g_return_if_fail (shell->scrolling);
1619
1620 gimp_display_shell_unset_override_cursor (shell);
1621
1622 shell->scrolling = FALSE;
1623 shell->scroll_start_x = 0;
1624 shell->scroll_start_y = 0;
1625 shell->scroll_last_x = 0;
1626 shell->scroll_last_y = 0;
1627 shell->rotating = FALSE;
1628 shell->rotate_drag_angle = 0.0;
1629 shell->scaling = FALSE;
1630 shell->layer_picking = FALSE;
1631
1632 /* We may have ungrabbed the pointer when space was released while
1633 * mouse was down, to be able to catch a GDK_BUTTON_RELEASE event.
1634 */
1635 if (shell->pointer_grabbed)
1636 gimp_display_shell_pointer_ungrab (shell, event);
1637 }
1638
1639 static void
gimp_display_shell_handle_scrolling(GimpDisplayShell * shell,GdkModifierType state,gint x,gint y)1640 gimp_display_shell_handle_scrolling (GimpDisplayShell *shell,
1641 GdkModifierType state,
1642 gint x,
1643 gint y)
1644 {
1645 g_return_if_fail (shell->scrolling);
1646
1647 if (shell->rotating)
1648 {
1649 gboolean constrain = (state & GDK_CONTROL_MASK) ? TRUE : FALSE;
1650
1651 gimp_display_shell_rotate_drag (shell,
1652 shell->scroll_last_x,
1653 shell->scroll_last_y,
1654 x,
1655 y,
1656 constrain);
1657 }
1658 else if (shell->scaling)
1659 {
1660 gimp_display_shell_scale_drag (shell,
1661 shell->scroll_start_x,
1662 shell->scroll_start_y,
1663 shell->scroll_last_x - x,
1664 shell->scroll_last_y - y);
1665 }
1666 else if (shell->layer_picking)
1667 {
1668 /* Do nothing. We only pick the layer on click. */
1669 }
1670 else
1671 {
1672 gimp_display_shell_scroll (shell,
1673 shell->scroll_last_x - x,
1674 shell->scroll_last_y - y);
1675 }
1676
1677 shell->scroll_last_x = x;
1678 shell->scroll_last_y = y;
1679 }
1680
1681 static void
gimp_display_shell_space_pressed(GimpDisplayShell * shell,const GdkEvent * event)1682 gimp_display_shell_space_pressed (GimpDisplayShell *shell,
1683 const GdkEvent *event)
1684 {
1685 Gimp *gimp = gimp_display_get_gimp (shell->display);
1686
1687 if (shell->space_release_pending || shell->scrolling)
1688 return;
1689
1690 if (! gimp_display_shell_keyboard_grab (shell, event))
1691 return;
1692
1693 switch (shell->display->config->space_bar_action)
1694 {
1695 case GIMP_SPACE_BAR_ACTION_NONE:
1696 break;
1697
1698 case GIMP_SPACE_BAR_ACTION_PAN:
1699 {
1700 GimpDeviceManager *manager;
1701 GimpDeviceInfo *current_device;
1702 GimpCoords coords;
1703 GdkModifierType state = 0;
1704
1705 manager = gimp_devices_get_manager (gimp);
1706 current_device = gimp_device_manager_get_current_device (manager);
1707
1708 gimp_device_info_get_device_coords (current_device,
1709 gtk_widget_get_window (shell->canvas),
1710 &coords);
1711 gdk_event_get_state (event, &state);
1712
1713 gimp_display_shell_start_scrolling (shell, event, state,
1714 coords.x, coords.y);
1715 }
1716 break;
1717
1718 case GIMP_SPACE_BAR_ACTION_MOVE:
1719 {
1720 GimpTool *active_tool = tool_manager_get_active (gimp);
1721
1722 if (active_tool || ! GIMP_IS_MOVE_TOOL (active_tool))
1723 {
1724 GdkModifierType state;
1725
1726 shell->space_shaded_tool =
1727 gimp_object_get_name (active_tool->tool_info);
1728
1729 gimp_context_set_tool (gimp_get_user_context (gimp),
1730 gimp_get_tool_info (gimp, "gimp-move-tool"));
1731
1732 gdk_event_get_state (event, &state);
1733
1734 gimp_display_shell_update_focus (shell, TRUE,
1735 NULL, state);
1736 }
1737 }
1738 break;
1739 }
1740
1741 shell->space_release_pending = TRUE;
1742 }
1743
1744 static void
gimp_display_shell_released(GimpDisplayShell * shell,const GdkEvent * event,const GimpCoords * image_coords)1745 gimp_display_shell_released (GimpDisplayShell *shell,
1746 const GdkEvent *event,
1747 const GimpCoords *image_coords)
1748 {
1749 Gimp *gimp = gimp_display_get_gimp (shell->display);
1750
1751 if (! shell->space_release_pending &&
1752 ! shell->button1_release_pending)
1753 return;
1754
1755 switch (shell->display->config->space_bar_action)
1756 {
1757 case GIMP_SPACE_BAR_ACTION_NONE:
1758 break;
1759
1760 case GIMP_SPACE_BAR_ACTION_PAN:
1761 gimp_display_shell_stop_scrolling (shell, event);
1762 break;
1763
1764 case GIMP_SPACE_BAR_ACTION_MOVE:
1765 if (shell->space_shaded_tool)
1766 {
1767 gimp_context_set_tool (gimp_get_user_context (gimp),
1768 gimp_get_tool_info (gimp,
1769 shell->space_shaded_tool));
1770 shell->space_shaded_tool = NULL;
1771
1772 if (gtk_widget_has_focus (shell->canvas))
1773 {
1774 GdkModifierType state;
1775
1776 gdk_event_get_state (event, &state);
1777
1778 gimp_display_shell_update_focus (shell, TRUE,
1779 image_coords, state);
1780 }
1781 else
1782 {
1783 gimp_display_shell_update_focus (shell, FALSE,
1784 image_coords, 0);
1785 }
1786 }
1787 break;
1788 }
1789
1790 gimp_display_shell_keyboard_ungrab (shell, event);
1791
1792 shell->space_release_pending = FALSE;
1793 shell->button1_release_pending = FALSE;
1794 }
1795
1796 static gboolean
gimp_display_shell_tab_pressed(GimpDisplayShell * shell,const GdkEventKey * kevent)1797 gimp_display_shell_tab_pressed (GimpDisplayShell *shell,
1798 const GdkEventKey *kevent)
1799 {
1800 GimpImageWindow *window = gimp_display_shell_get_window (shell);
1801 GimpUIManager *manager = gimp_image_window_get_ui_manager (window);
1802 GimpImage *image = gimp_display_get_image (shell->display);
1803
1804 if (kevent->state & GDK_CONTROL_MASK)
1805 {
1806 if (image && ! gimp_image_is_empty (image))
1807 {
1808 if (kevent->keyval == GDK_KEY_Tab ||
1809 kevent->keyval == GDK_KEY_KP_Tab)
1810 gimp_display_shell_layer_select_init (shell,
1811 1, kevent->time);
1812 else
1813 gimp_display_shell_layer_select_init (shell,
1814 -1, kevent->time);
1815
1816 return TRUE;
1817 }
1818 }
1819 else if (kevent->state & GDK_MOD1_MASK)
1820 {
1821 if (image)
1822 {
1823 if (kevent->keyval == GDK_KEY_Tab ||
1824 kevent->keyval == GDK_KEY_KP_Tab)
1825 gimp_ui_manager_activate_action (manager, "windows",
1826 "windows-show-display-next");
1827 else
1828 gimp_ui_manager_activate_action (manager, "windows",
1829 "windows-show-display-previous");
1830
1831 return TRUE;
1832 }
1833 }
1834 else
1835 {
1836 gimp_ui_manager_activate_action (manager, "windows",
1837 "windows-hide-docks");
1838
1839 return TRUE;
1840 }
1841
1842 return FALSE;
1843 }
1844
1845 static void
gimp_display_shell_update_focus(GimpDisplayShell * shell,gboolean focus_in,const GimpCoords * image_coords,GdkModifierType state)1846 gimp_display_shell_update_focus (GimpDisplayShell *shell,
1847 gboolean focus_in,
1848 const GimpCoords *image_coords,
1849 GdkModifierType state)
1850 {
1851 Gimp *gimp = gimp_display_get_gimp (shell->display);
1852
1853 if (focus_in)
1854 {
1855 tool_manager_focus_display_active (gimp, shell->display);
1856 tool_manager_modifier_state_active (gimp, state, shell->display);
1857 }
1858 else
1859 {
1860 tool_manager_focus_display_active (gimp, NULL);
1861 }
1862
1863 if (image_coords)
1864 tool_manager_oper_update_active (gimp,
1865 image_coords, state,
1866 shell->proximity,
1867 shell->display);
1868 }
1869
1870 static void
gimp_display_shell_update_cursor(GimpDisplayShell * shell,const GimpCoords * display_coords,const GimpCoords * image_coords,GdkModifierType state,gboolean update_software_cursor)1871 gimp_display_shell_update_cursor (GimpDisplayShell *shell,
1872 const GimpCoords *display_coords,
1873 const GimpCoords *image_coords,
1874 GdkModifierType state,
1875 gboolean update_software_cursor)
1876 {
1877 GimpDisplay *display = shell->display;
1878 Gimp *gimp = gimp_display_get_gimp (display);
1879 GimpImage *image = gimp_display_get_image (display);
1880 GimpTool *active_tool;
1881
1882 if (! shell->display->config->cursor_updating)
1883 return;
1884
1885 active_tool = tool_manager_get_active (gimp);
1886
1887 if (active_tool)
1888 {
1889 if ((! gimp_image_is_empty (image) ||
1890 gimp_tool_control_get_handle_empty_image (active_tool->control)) &&
1891 ! (state & (GDK_BUTTON1_MASK |
1892 GDK_BUTTON2_MASK |
1893 GDK_BUTTON3_MASK)))
1894 {
1895 tool_manager_cursor_update_active (gimp,
1896 image_coords, state,
1897 display);
1898 }
1899 else if (gimp_image_is_empty (image) &&
1900 ! gimp_tool_control_get_handle_empty_image (active_tool->control))
1901 {
1902 gimp_display_shell_set_cursor (shell,
1903 GIMP_CURSOR_MOUSE,
1904 gimp_tool_control_get_tool_cursor (active_tool->control),
1905 GIMP_CURSOR_MODIFIER_BAD);
1906 }
1907 }
1908 else
1909 {
1910 gimp_display_shell_set_cursor (shell,
1911 GIMP_CURSOR_MOUSE,
1912 GIMP_TOOL_CURSOR_NONE,
1913 GIMP_CURSOR_MODIFIER_BAD);
1914 }
1915
1916 if (update_software_cursor)
1917 {
1918 GimpCursorPrecision precision = GIMP_CURSOR_PRECISION_PIXEL_CENTER;
1919
1920 if (active_tool)
1921 precision = gimp_tool_control_get_precision (active_tool->control);
1922
1923 gimp_display_shell_update_software_cursor (shell,
1924 precision,
1925 (gint) display_coords->x,
1926 (gint) display_coords->y,
1927 image_coords->x,
1928 image_coords->y);
1929 }
1930 }
1931
1932 static gboolean
gimp_display_shell_initialize_tool(GimpDisplayShell * shell,const GimpCoords * image_coords,GdkModifierType state)1933 gimp_display_shell_initialize_tool (GimpDisplayShell *shell,
1934 const GimpCoords *image_coords,
1935 GdkModifierType state)
1936 {
1937 GimpDisplay *display = shell->display;
1938 GimpImage *image = gimp_display_get_image (display);
1939 Gimp *gimp = gimp_display_get_gimp (display);
1940 gboolean initialized = FALSE;
1941 GimpTool *active_tool;
1942
1943 active_tool = tool_manager_get_active (gimp);
1944
1945 if (active_tool &&
1946 (! gimp_image_is_empty (image) ||
1947 gimp_tool_control_get_handle_empty_image (active_tool->control)))
1948 {
1949 /* initialize the current tool if it has no drawable */
1950 if (! active_tool->drawable)
1951 {
1952 initialized = tool_manager_initialize_active (gimp, display);
1953 }
1954 else if ((active_tool->drawable !=
1955 gimp_image_get_active_drawable (image)) &&
1956 (! gimp_tool_control_get_preserve (active_tool->control) &&
1957 (gimp_tool_control_get_dirty_mask (active_tool->control) &
1958 GIMP_DIRTY_ACTIVE_DRAWABLE)))
1959 {
1960 GimpProcedure *procedure = g_object_get_data (G_OBJECT (active_tool),
1961 "gimp-gegl-procedure");
1962
1963 if (image == gimp_item_get_image (GIMP_ITEM (active_tool->drawable)))
1964 {
1965 /* When changing between drawables if the *same* image,
1966 * stop the tool using its dirty action, so it doesn't
1967 * get committed on tool change, in case its dirty action
1968 * is HALT. This is a pure "probably better this way"
1969 * decision because the user is likely changing their
1970 * mind or was simply on the wrong layer. See bug #776370.
1971 *
1972 * See also issues #1180 and #1202 for cases where we
1973 * actually *don't* want to halt the tool here, but rather
1974 * commit it, hence the use of the tool's dirty action.
1975 */
1976 tool_manager_control_active (
1977 gimp,
1978 gimp_tool_control_get_dirty_action (active_tool->control),
1979 active_tool->display);
1980 }
1981
1982 if (procedure)
1983 {
1984 /* We can't just recreate an operation tool, we must
1985 * make sure the right stuff gets set on it, so
1986 * re-activate the procedure that created it instead of
1987 * just calling gimp_context_tool_changed(). See
1988 * GimpGeglProcedure and bug #776370.
1989 */
1990 GimpImageWindow *window;
1991 GimpUIManager *manager;
1992
1993 window = gimp_display_shell_get_window (shell);
1994 manager = gimp_image_window_get_ui_manager (window);
1995
1996 gimp_filter_history_add (gimp, procedure);
1997 gimp_ui_manager_activate_action (manager, "filters",
1998 "filters-reshow");
1999
2000 /* the procedure already initialized the tool; don't
2001 * reinitialize it below, since this can lead to errors.
2002 */
2003 initialized = TRUE;
2004 }
2005 else
2006 {
2007 /* create a new one, deleting the current */
2008 gimp_context_tool_changed (gimp_get_user_context (gimp));
2009 }
2010
2011 /* make sure the newly created tool has the right state */
2012 gimp_display_shell_update_focus (shell, TRUE, image_coords, state);
2013
2014 if (! initialized)
2015 initialized = tool_manager_initialize_active (gimp, display);
2016 }
2017 else
2018 {
2019 initialized = TRUE;
2020 }
2021 }
2022
2023 return initialized;
2024 }
2025
2026 static void
gimp_display_shell_get_event_coords(GimpDisplayShell * shell,const GdkEvent * event,GimpCoords * display_coords,GdkModifierType * state,guint32 * time)2027 gimp_display_shell_get_event_coords (GimpDisplayShell *shell,
2028 const GdkEvent *event,
2029 GimpCoords *display_coords,
2030 GdkModifierType *state,
2031 guint32 *time)
2032 {
2033 Gimp *gimp = gimp_display_get_gimp (shell->display);
2034 GimpDeviceManager *manager;
2035 GimpDeviceInfo *current_device;
2036
2037 manager = gimp_devices_get_manager (gimp);
2038 current_device = gimp_device_manager_get_current_device (manager);
2039
2040 gimp_device_info_get_event_coords (current_device,
2041 gtk_widget_get_window (shell->canvas),
2042 event,
2043 display_coords);
2044
2045 gimp_device_info_get_event_state (current_device,
2046 gtk_widget_get_window (shell->canvas),
2047 event,
2048 state);
2049
2050 *time = gdk_event_get_time (event);
2051 }
2052
2053 static void
gimp_display_shell_untransform_event_coords(GimpDisplayShell * shell,const GimpCoords * display_coords,GimpCoords * image_coords,gboolean * update_software_cursor)2054 gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell,
2055 const GimpCoords *display_coords,
2056 GimpCoords *image_coords,
2057 gboolean *update_software_cursor)
2058 {
2059 Gimp *gimp = gimp_display_get_gimp (shell->display);
2060 GimpTool *active_tool;
2061
2062 /* GimpCoords passed to tools are ALWAYS in image coordinates */
2063 gimp_display_shell_untransform_coords (shell,
2064 display_coords,
2065 image_coords);
2066
2067 active_tool = tool_manager_get_active (gimp);
2068
2069 if (active_tool && gimp_tool_control_get_snap_to (active_tool->control))
2070 {
2071 gint x, y, width, height;
2072
2073 gimp_tool_control_get_snap_offsets (active_tool->control,
2074 &x, &y, &width, &height);
2075
2076 if (gimp_display_shell_snap_coords (shell,
2077 image_coords,
2078 x, y, width, height))
2079 {
2080 if (update_software_cursor)
2081 *update_software_cursor = TRUE;
2082 }
2083 }
2084 }
2085
2086 /* gimp_display_shell_compress_motion:
2087 *
2088 * This function walks the GDK event queue, seeking motion events at the
2089 * front of the queue corresponding to the same widget as, and having
2090 * similar characteristics to, `initial_event`. If it finds any it will
2091 * remove them from the queue, and return the most recent motion event.
2092 * Otherwise it will return NULL.
2093 *
2094 * If `*next_event` is non-NULL upon return, the caller must dispatch and
2095 * free this event after handling the motion event.
2096 *
2097 * The gimp_display_shell_compress_motion function source may be re-used under
2098 * the XFree86-style license. <adam@gimp.org>
2099 */
2100 static GdkEvent *
gimp_display_shell_compress_motion(GdkEvent * initial_event,GdkEvent ** next_event)2101 gimp_display_shell_compress_motion (GdkEvent *initial_event,
2102 GdkEvent **next_event)
2103 {
2104 GdkEvent *last_motion = NULL;
2105 GtkWidget *widget;
2106
2107 *next_event = NULL;
2108
2109 if (initial_event->any.type != GDK_MOTION_NOTIFY)
2110 return NULL;
2111
2112 widget = gtk_get_event_widget (initial_event);
2113
2114 while (gdk_events_pending ())
2115 {
2116 GdkEvent *event = gdk_event_get ();
2117
2118 if (!event)
2119 {
2120 /* Do nothing */
2121 }
2122 else if ((gtk_get_event_widget (event) == widget) &&
2123 (event->any.type == GDK_MOTION_NOTIFY) &&
2124 (event->any.window == initial_event->any.window) &&
2125 (event->motion.state == initial_event->motion.state) &&
2126 (event->motion.device == initial_event->motion.device))
2127 {
2128 /* Discard previous motion event */
2129 if (last_motion)
2130 gdk_event_free (last_motion);
2131
2132 last_motion = event;
2133 }
2134 else
2135 {
2136 /* Let the caller dispatch the event */
2137 *next_event = event;
2138
2139 break;
2140 }
2141 }
2142
2143 return last_motion;
2144 }
2145