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