[gimp] Bug 724692 - Canvas rotation stuck with specific order of actions.



commit 3ac794816a97ebf76b71dddd610220f19bf7191e
Author: Jehan <jehan girinstud io>
Date:   Sat Apr 14 15:36:08 2018 +0200

    Bug 724692 - Canvas rotation stuck with specific order of actions.
    
    Commit b279c2d217 was breaking a specific use case, which I oversaw:
    when space bar activates the move tool, you may want to release the
    space bar while mouse button is pressed, and expect to still be able to
    move the layer/selection/guide, but releasing space was stopping the
    move immediately. The move tool must only be deactivated when both space
    and button 1 are released, and the move itself must continue as long as
    button 1 is pressed (when started while space was pressed).
    
    As a nice side effect of this commit, panning and canvas rotation are
    also improved since now they can be continued while releasing space
    (respectively shift-space) if mouse button 1 was pressed, and up until
    the mouse button is released. Pressing space again, then releasing the
    mouse, back and forth, also work as expected (i.e. move tool stay
    activated though the move stops; and panning or rotation continue).
    
    Of course now we don't get anymore panning/rotation stuck while neither
    space nor mouse buttons are pressed (which was the original bug). At
    least one of these need to stay pressed for panning/rotation/move to
    stay activated. And initial activation is obviously always through
    (shift-)space only.

 app/display/gimpdisplayshell-tool-events.c |   54 ++++++++++++++++++++++------
 app/display/gimpdisplayshell.h             |    6 +++
 2 files changed, 49 insertions(+), 11 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index da4d7ba..4325bf3 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -100,7 +100,7 @@ static void       gimp_display_shell_handle_scrolling            (GimpDisplayShe
 
 static void       gimp_display_shell_space_pressed               (GimpDisplayShell   *shell,
                                                                   const GdkEvent     *event);
-static void       gimp_display_shell_space_released              (GimpDisplayShell   *shell,
+static void       gimp_display_shell_released                    (GimpDisplayShell   *shell,
                                                                   const GdkEvent     *event,
                                                                   const GimpCoords   *image_coords);
 
@@ -205,7 +205,9 @@ gimp_display_shell_events (GtkWidget        *widget,
             break;
 
           default:
-            if (shell->space_release_pending || shell->scrolling)
+            if (shell->space_release_pending   ||
+                shell->button1_release_pending ||
+                shell->scrolling)
               return TRUE;
             break;
           }
@@ -679,7 +681,9 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
         GdkModifierType  button_state;
 
         /*  ignore new mouse events  */
-        if (gimp->busy || shell->scrolling || shell->pointer_grabbed)
+        if (gimp->busy || shell->scrolling ||
+            shell->pointer_grabbed         ||
+            shell->button1_release_pending)
           return TRUE;
 
         button_state = gimp_display_shell_button_to_state (bevent->button);
@@ -846,6 +850,12 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
 
         gimp_display_shell_autoscroll_stop (shell);
 
+        if (bevent->button == 1 && shell->button1_release_pending)
+          {
+            gimp_display_shell_released (shell, event, NULL);
+            return TRUE;
+          }
+
         if (gimp->busy)
           return TRUE;
 
@@ -1263,7 +1273,10 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
 
               case GDK_KEY_space:
               case GDK_KEY_KP_Space:
-                gimp_display_shell_space_pressed (shell, event);
+                if (shell->button1_release_pending)
+                  shell->space_release_pending = TRUE;
+                else
+                  gimp_display_shell_space_pressed (shell, event);
                 return_val = TRUE;
                 break;
 
@@ -1364,7 +1377,20 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
               {
               case GDK_KEY_space:
               case GDK_KEY_KP_Space:
-                gimp_display_shell_space_released (shell, event, NULL);
+                if ((state & GDK_BUTTON1_MASK))
+                  {
+                    shell->button1_release_pending = TRUE;
+                    shell->space_release_pending   = FALSE;
+                    /* We need to ungrab the pointer in order to catch
+                     * button release events.
+                     */
+                    if (shell->pointer_grabbed)
+                      gimp_display_shell_pointer_ungrab (shell, event);
+                  }
+                else
+                  {
+                    gimp_display_shell_released (shell, event, NULL);
+                  }
                 return_val = TRUE;
                 break;
 
@@ -1535,7 +1561,11 @@ gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
   shell->rotate_drag_angle = 0.0;
   shell->scaling           = FALSE;
 
-  gimp_display_shell_pointer_ungrab (shell, event);
+  /* We may have ungrabbed the pointer when space was released while
+   * mouse was down, to be able to catch a GDK_BUTTON_RELEASE event.
+   */
+  if (shell->pointer_grabbed)
+    gimp_display_shell_pointer_ungrab (shell, event);
 }
 
 static void
@@ -1638,13 +1668,14 @@ gimp_display_shell_space_pressed (GimpDisplayShell *shell,
 }
 
 static void
-gimp_display_shell_space_released (GimpDisplayShell *shell,
-                                   const GdkEvent   *event,
-                                   const GimpCoords *image_coords)
+gimp_display_shell_released (GimpDisplayShell *shell,
+                             const GdkEvent   *event,
+                             const GimpCoords *image_coords)
 {
   Gimp *gimp = gimp_display_get_gimp (shell->display);
 
-  if (! shell->space_release_pending)
+  if (! shell->space_release_pending &&
+      ! shell->button1_release_pending)
     return;
 
   switch (shell->display->config->space_bar_action)
@@ -1684,7 +1715,8 @@ gimp_display_shell_space_released (GimpDisplayShell *shell,
 
   gimp_display_shell_keyboard_ungrab (shell, event);
 
-  shell->space_release_pending = FALSE;
+  shell->space_release_pending   = FALSE;
+  shell->button1_release_pending = FALSE;
 }
 
 static gboolean
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index d5aabab..b00f975 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -189,7 +189,13 @@ struct _GimpDisplayShell
 
   gboolean           inferior_ignore_mode;
 
+  /* Two states are possible when the shell is grabbed: it can be
+   * grabbed with space (or space+button1 which is the same state),
+   * then if space is released but button1 was still pressed, we wait
+   * for button1 to be released as well.
+   */
   gboolean           space_release_pending;
+  gboolean           button1_release_pending;
   const gchar       *space_shaded_tool;
 
   gboolean           scrolling;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]