diff --git a/app/tools/gimptool.c b/app/tools/gimptool.c index 52370cdfd3..53981c1aaa 100644 --- a/app/tools/gimptool.c +++ b/app/tools/gimptool.c @@ -138,6 +138,7 @@ static void gimp_tool_options_notify (GimpToolOptions *options, const GParamSpec *pspec, GimpTool *tool); static void gimp_tool_clear_status (GimpTool *tool); +static void gimp_tool_release (GimpTool *tool); G_DEFINE_TYPE_WITH_CODE (GimpTool, gimp_tool, GIMP_TYPE_OBJECT, @@ -649,6 +650,8 @@ gimp_tool_control (GimpTool *tool, { g_return_if_fail (GIMP_IS_TOOL (tool)); + g_object_ref (tool); + switch (action) { case GIMP_TOOL_ACTION_PAUSE: @@ -674,6 +677,8 @@ gimp_tool_control (GimpTool *tool, break; case GIMP_TOOL_ACTION_COMMIT: + gimp_tool_release (tool); + GIMP_TOOL_GET_CLASS (tool)->control (tool, action, display); /* always HALT after COMMIT here and not in each tool individually; @@ -685,6 +690,8 @@ gimp_tool_control (GimpTool *tool, /* pass through */ case GIMP_TOOL_ACTION_HALT: + gimp_tool_release (tool); + GIMP_TOOL_GET_CLASS (tool)->control (tool, action, display); if (gimp_tool_control_is_active (tool->control)) @@ -693,6 +700,8 @@ gimp_tool_control (GimpTool *tool, gimp_tool_clear_status (tool); break; } + + g_object_unref (tool); } void @@ -716,6 +725,10 @@ gimp_tool_button_press (GimpTool *tool, tool->button_press_state = state; tool->active_modifier_state = state; + tool->last_pointer_coords = *coords; + tool->last_pointer_time = time - g_get_monotonic_time () / 1000; + tool->last_pointer_state = state; + if (gimp_tool_control_get_wants_click (tool->control)) { tool->in_click_distance = TRUE; @@ -789,6 +802,8 @@ gimp_tool_button_release (GimpTool *tool, g_object_ref (tool); + tool->last_pointer_state = 0; + my_coords = *coords; if (state & GDK_BUTTON3_MASK) @@ -855,6 +870,10 @@ gimp_tool_motion (GimpTool *tool, tool->got_motion_event = TRUE; + tool->last_pointer_coords = *coords; + tool->last_pointer_time = time - g_get_monotonic_time () / 1000; + tool->last_pointer_state = state; + GIMP_TOOL_GET_CLASS (tool)->motion (tool, coords, time, state, display); } @@ -1476,3 +1495,18 @@ gimp_tool_clear_status (GimpTool *tool) while (tool->status_displays) gimp_tool_pop_status (tool, tool->status_displays->data); } + +static void +gimp_tool_release (GimpTool *tool) +{ + if (tool->last_pointer_state && + gimp_tool_control_is_active (tool->control)) + { + gimp_tool_button_release ( + tool, + &tool->last_pointer_coords, + tool->last_pointer_time + g_get_monotonic_time () / 1000, + tool->last_pointer_state, + tool->display); + } +} diff --git a/app/tools/gimptool.h b/app/tools/gimptool.h index f013637745..c7943fd905 100644 --- a/app/tools/gimptool.h +++ b/app/tools/gimptool.h @@ -60,6 +60,12 @@ struct _GimpTool GdkModifierType button_press_state; GdkModifierType active_modifier_state; + /* private state for synthesizing button_release() events + */ + GimpCoords last_pointer_coords; + guint32 last_pointer_time; + GdkModifierType last_pointer_state; + /* private state for click detection */ gboolean in_click_distance;