From 3ac794816a97ebf76b71dddd610220f19bf7191e Mon Sep 17 00:00:00 2001 From: Jehan Date: Sat, 14 Apr 2018 15:36:08 +0200 Subject: [PATCH] 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 da4d7ba67a..4325bf3f86 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 d5aababa8c..b00f975f04 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;