Issue #1824 - Crash on 2.10.4 using tablet
In GimpTool, track the last-seen pointer coordinates, modifier
state, and event time, during button_press() and motion() events
and use those to synthesize a button_release() event when
comitting/halting the tool, if the tool is still active, and a
matching button_release() event has not been received.
The paint tools (as well as other tools) require each
button_press() event to be matched by a button_release() event in
order to properly finish their operation, but one isn't organically
generated when switching tools due to a device change.
(cherry picked from commit 9b25611857)
This commit is contained in:
parent
0a22773a17
commit
a16d06a40a
2 changed files with 40 additions and 0 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue