[gimp] Bug 791689 - On-Canvas GUI broken with extended input device
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 791689 - On-Canvas GUI broken with extended input device
- Date: Thu, 4 Jan 2018 11:12:45 +0000 (UTC)
commit fa180443927763fbdcc928fdfabc4489a40636d4
Author: Ell <ell_se yahoo com>
Date: Thu Jan 4 06:02:53 2018 -0500
Bug 791689 - On-Canvas GUI broken with extended input device
Something about the unqueueing and requeueing of the entire event
queue during motion compression fries GTK's brain w.r.t. extended
input events. Instead, have gimp_display_shell_compress_motion()
return the first non-compressed event to the caller, making it
responsible for dispatching it after handling the motion event.
app/display/gimpdisplayshell-tool-events.c | 484 +++++++++++++++-------------
1 files changed, 253 insertions(+), 231 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index 262a9e7..12f93da 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -71,62 +71,68 @@
/* local function prototypes */
+static gboolean gimp_display_shell_canvas_tool_events_internal (GtkWidget *canvas,
+ GdkEvent *event,
+ GimpDisplayShell *shell,
+ GdkEvent **next_event);
+
static GdkModifierType
- gimp_display_shell_key_to_state (gint key);
+ gimp_display_shell_key_to_state (gint key);
static GdkModifierType
- gimp_display_shell_button_to_state (gint button);
-
-static void gimp_display_shell_proximity_in (GimpDisplayShell *shell);
-static void gimp_display_shell_proximity_out (GimpDisplayShell *shell);
-
-static void gimp_display_shell_check_device_cursor (GimpDisplayShell *shell);
-
-static void gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
- const GdkEvent *event,
- GdkModifierType state,
- gint x,
- gint y);
-static void gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
- const GdkEvent *event);
-static void gimp_display_shell_handle_scrolling (GimpDisplayShell *shell,
- GdkModifierType state,
- gint x,
- gint y);
-
-static void gimp_display_shell_space_pressed (GimpDisplayShell *shell,
- const GdkEvent *event);
-static void gimp_display_shell_space_released (GimpDisplayShell *shell,
- const GdkEvent *event,
- const GimpCoords *image_coords);
-
-static gboolean gimp_display_shell_tab_pressed (GimpDisplayShell *shell,
- const GdkEventKey *event);
-
-static void gimp_display_shell_update_focus (GimpDisplayShell *shell,
- gboolean focus_in,
- const GimpCoords *image_coords,
- GdkModifierType state);
-static void gimp_display_shell_update_cursor (GimpDisplayShell *shell,
- const GimpCoords *display_coords,
- const GimpCoords *image_coords,
- GdkModifierType state,
- gboolean update_software_cursor);
-
-static gboolean gimp_display_shell_initialize_tool (GimpDisplayShell *shell,
- const GimpCoords *image_coords,
- GdkModifierType state);
-
-static void gimp_display_shell_get_event_coords (GimpDisplayShell *shell,
- const GdkEvent *event,
- GimpCoords *display_coords,
- GdkModifierType *state,
- guint32 *time);
-static void gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell,
- const GimpCoords *display_coords,
- GimpCoords *image_coords,
- gboolean *update_software_cursor);
-
-static GdkEvent * gimp_display_shell_compress_motion (GdkEvent *initial_event);
+ gimp_display_shell_button_to_state (gint button);
+
+static void gimp_display_shell_proximity_in (GimpDisplayShell *shell);
+static void gimp_display_shell_proximity_out (GimpDisplayShell *shell);
+
+static void gimp_display_shell_check_device_cursor (GimpDisplayShell *shell);
+
+static void gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
+ const GdkEvent *event,
+ GdkModifierType state,
+ gint x,
+ gint y);
+static void gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
+ const GdkEvent *event);
+static void gimp_display_shell_handle_scrolling (GimpDisplayShell *shell,
+ GdkModifierType state,
+ gint x,
+ gint y);
+
+static void gimp_display_shell_space_pressed (GimpDisplayShell *shell,
+ const GdkEvent *event);
+static void gimp_display_shell_space_released (GimpDisplayShell *shell,
+ const GdkEvent *event,
+ const GimpCoords *image_coords);
+
+static gboolean gimp_display_shell_tab_pressed (GimpDisplayShell *shell,
+ const GdkEventKey *event);
+
+static void gimp_display_shell_update_focus (GimpDisplayShell *shell,
+ gboolean focus_in,
+ const GimpCoords *image_coords,
+ GdkModifierType state);
+static void gimp_display_shell_update_cursor (GimpDisplayShell *shell,
+ const GimpCoords *display_coords,
+ const GimpCoords *image_coords,
+ GdkModifierType state,
+ gboolean
update_software_cursor);
+
+static gboolean gimp_display_shell_initialize_tool (GimpDisplayShell *shell,
+ const GimpCoords *image_coords,
+ GdkModifierType state);
+
+static void gimp_display_shell_get_event_coords (GimpDisplayShell *shell,
+ const GdkEvent *event,
+ GimpCoords *display_coords,
+ GdkModifierType *state,
+ guint32 *time);
+static void gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell,
+ const GimpCoords *display_coords,
+ GimpCoords *image_coords,
+ gboolean
*update_software_cursor);
+
+static GdkEvent * gimp_display_shell_compress_motion (GdkEvent *initial_event,
+ GdkEvent **next_event);
/* public functions */
@@ -307,6 +313,184 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
GdkEvent *event,
GimpDisplayShell *shell)
{
+ GdkEvent *next_event = NULL;
+ gboolean return_val;
+
+ g_return_val_if_fail (gtk_widget_get_realized (canvas), FALSE);
+
+ return_val = gimp_display_shell_canvas_tool_events_internal (canvas,
+ event, shell,
+ &next_event);
+
+ if (next_event)
+ {
+ gtk_main_do_event (next_event);
+
+ gdk_event_free (next_event);
+ }
+
+ return return_val;
+}
+
+void
+gimp_display_shell_canvas_grab_notify (GtkWidget *canvas,
+ gboolean was_grabbed,
+ GimpDisplayShell *shell)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ Gimp *gimp;
+
+ /* are we in destruction? */
+ if (! shell->display || ! gimp_display_get_shell (shell->display))
+ return;
+
+ display = shell->display;
+ gimp = gimp_display_get_gimp (display);
+ image = gimp_display_get_image (display);
+
+ if (! image)
+ return;
+
+ GIMP_LOG (TOOL_EVENTS, "grab_notify (display %p): was_grabbed = %s",
+ display, was_grabbed ? "TRUE" : "FALSE");
+
+ if (! was_grabbed)
+ {
+ if (! gimp_image_is_empty (image))
+ {
+ GimpTool *active_tool = tool_manager_get_active (gimp);
+
+ if (active_tool && active_tool->focus_display == display)
+ {
+ tool_manager_modifier_state_active (gimp, 0, display);
+ }
+ }
+ }
+}
+
+void
+gimp_display_shell_buffer_stroke (GimpMotionBuffer *buffer,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpDisplayShell *shell)
+{
+ GimpDisplay *display = shell->display;
+ Gimp *gimp = gimp_display_get_gimp (display);
+ GimpTool *active_tool;
+
+ active_tool = tool_manager_get_active (gimp);
+
+ if (active_tool &&
+ gimp_tool_control_is_active (active_tool->control))
+ {
+ tool_manager_motion_active (gimp,
+ coords, time, state,
+ display);
+ }
+}
+
+void
+gimp_display_shell_buffer_hover (GimpMotionBuffer *buffer,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity,
+ GimpDisplayShell *shell)
+{
+ GimpDisplay *display = shell->display;
+ Gimp *gimp = gimp_display_get_gimp (display);
+ GimpTool *active_tool;
+
+ active_tool = tool_manager_get_active (gimp);
+
+ if (active_tool &&
+ ! gimp_tool_control_is_active (active_tool->control))
+ {
+ tool_manager_oper_update_active (gimp,
+ coords, state, proximity,
+ display);
+ }
+}
+
+static gboolean
+gimp_display_shell_ruler_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ GimpDisplayShell *shell,
+ GimpOrientationType orientation)
+{
+ GimpDisplay *display = shell->display;
+
+ if (display->gimp->busy)
+ return TRUE;
+
+ if (! gimp_display_get_image (display))
+ return TRUE;
+
+ if (event->type == GDK_BUTTON_PRESS && event->button == 1)
+ {
+ GimpTool *active_tool = tool_manager_get_active (display->gimp);
+
+ if (active_tool)
+ {
+ gimp_display_shell_update_focus (shell, TRUE,
+ NULL, event->state);
+
+ if (gimp_display_shell_pointer_grab (shell, NULL, 0))
+ {
+ if (gimp_display_shell_keyboard_grab (shell,
+ (GdkEvent *) event))
+ {
+ if (event->state & gimp_get_toggle_behavior_mask ())
+ {
+ gimp_sample_point_tool_start_new (active_tool, display);
+ }
+ else
+ {
+ gimp_guide_tool_start_new (active_tool, display,
+ orientation);
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ gimp_display_shell_pointer_ungrab (shell, NULL);
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+gboolean
+gimp_display_shell_hruler_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ GimpDisplayShell *shell)
+{
+ return gimp_display_shell_ruler_button_press (widget, event, shell,
+ GIMP_ORIENTATION_HORIZONTAL);
+}
+
+gboolean
+gimp_display_shell_vruler_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ GimpDisplayShell *shell)
+{
+ return gimp_display_shell_ruler_button_press (widget, event, shell,
+ GIMP_ORIENTATION_VERTICAL);
+}
+
+
+/* private functions */
+
+static gboolean
+gimp_display_shell_canvas_tool_events_internal (GtkWidget *canvas,
+ GdkEvent *event,
+ GimpDisplayShell *shell,
+ GdkEvent **next_event)
+{
GimpDisplay *display;
GimpImage *image;
Gimp *gimp;
@@ -318,7 +502,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
gboolean return_val = FALSE;
gboolean update_sw_cursor = FALSE;
- g_return_val_if_fail (gtk_widget_get_realized (canvas), FALSE);
+ *next_event = NULL;
/* are we in destruction? */
if (! shell->display || ! gimp_display_get_shell (shell->display))
@@ -851,7 +1035,8 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
if (shell->scrolling ||
motion_mode == GIMP_MOTION_MODE_COMPRESS)
{
- compressed_motion = gimp_display_shell_compress_motion (event);
+ compressed_motion = gimp_display_shell_compress_motion (event,
+ next_event);
if (compressed_motion && ! shell->scrolling)
{
@@ -1240,159 +1425,6 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
return return_val;
}
-void
-gimp_display_shell_canvas_grab_notify (GtkWidget *canvas,
- gboolean was_grabbed,
- GimpDisplayShell *shell)
-{
- GimpDisplay *display;
- GimpImage *image;
- Gimp *gimp;
-
- /* are we in destruction? */
- if (! shell->display || ! gimp_display_get_shell (shell->display))
- return;
-
- display = shell->display;
- gimp = gimp_display_get_gimp (display);
- image = gimp_display_get_image (display);
-
- if (! image)
- return;
-
- GIMP_LOG (TOOL_EVENTS, "grab_notify (display %p): was_grabbed = %s",
- display, was_grabbed ? "TRUE" : "FALSE");
-
- if (! was_grabbed)
- {
- if (! gimp_image_is_empty (image))
- {
- GimpTool *active_tool = tool_manager_get_active (gimp);
-
- if (active_tool && active_tool->focus_display == display)
- {
- tool_manager_modifier_state_active (gimp, 0, display);
- }
- }
- }
-}
-
-void
-gimp_display_shell_buffer_stroke (GimpMotionBuffer *buffer,
- const GimpCoords *coords,
- guint32 time,
- GdkModifierType state,
- GimpDisplayShell *shell)
-{
- GimpDisplay *display = shell->display;
- Gimp *gimp = gimp_display_get_gimp (display);
- GimpTool *active_tool;
-
- active_tool = tool_manager_get_active (gimp);
-
- if (active_tool &&
- gimp_tool_control_is_active (active_tool->control))
- {
- tool_manager_motion_active (gimp,
- coords, time, state,
- display);
- }
-}
-
-void
-gimp_display_shell_buffer_hover (GimpMotionBuffer *buffer,
- const GimpCoords *coords,
- GdkModifierType state,
- gboolean proximity,
- GimpDisplayShell *shell)
-{
- GimpDisplay *display = shell->display;
- Gimp *gimp = gimp_display_get_gimp (display);
- GimpTool *active_tool;
-
- active_tool = tool_manager_get_active (gimp);
-
- if (active_tool &&
- ! gimp_tool_control_is_active (active_tool->control))
- {
- tool_manager_oper_update_active (gimp,
- coords, state, proximity,
- display);
- }
-}
-
-static gboolean
-gimp_display_shell_ruler_button_press (GtkWidget *widget,
- GdkEventButton *event,
- GimpDisplayShell *shell,
- GimpOrientationType orientation)
-{
- GimpDisplay *display = shell->display;
-
- if (display->gimp->busy)
- return TRUE;
-
- if (! gimp_display_get_image (display))
- return TRUE;
-
- if (event->type == GDK_BUTTON_PRESS && event->button == 1)
- {
- GimpTool *active_tool = tool_manager_get_active (display->gimp);
-
- if (active_tool)
- {
- gimp_display_shell_update_focus (shell, TRUE,
- NULL, event->state);
-
- if (gimp_display_shell_pointer_grab (shell, NULL, 0))
- {
- if (gimp_display_shell_keyboard_grab (shell,
- (GdkEvent *) event))
- {
- if (event->state & gimp_get_toggle_behavior_mask ())
- {
- gimp_sample_point_tool_start_new (active_tool, display);
- }
- else
- {
- gimp_guide_tool_start_new (active_tool, display,
- orientation);
- }
-
- return TRUE;
- }
- else
- {
- gimp_display_shell_pointer_ungrab (shell, NULL);
- }
- }
- }
- }
-
- return FALSE;
-}
-
-gboolean
-gimp_display_shell_hruler_button_press (GtkWidget *widget,
- GdkEventButton *event,
- GimpDisplayShell *shell)
-{
- return gimp_display_shell_ruler_button_press (widget, event, shell,
- GIMP_ORIENTATION_HORIZONTAL);
-}
-
-gboolean
-gimp_display_shell_vruler_button_press (GtkWidget *widget,
- GdkEventButton *event,
- GimpDisplayShell *shell)
-{
- return gimp_display_shell_ruler_button_press (widget, event, shell,
- GIMP_ORIENTATION_VERTICAL);
-}
-
-
-/* private functions */
-
static GdkModifierType
gimp_display_shell_key_to_state (gint key)
{
@@ -1952,15 +1984,21 @@ gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell,
* remove them from the queue, and return the most recent motion event.
* Otherwise it will return NULL.
*
+ * If `next_event` is non-NULL upon return, the caller must dispatch and
+ * free this event after handling the motion event.
+ *
* The gimp_display_shell_compress_motion function source may be re-used under
* the XFree86-style license. <adam gimp org>
*/
static GdkEvent *
-gimp_display_shell_compress_motion (GdkEvent *initial_event)
+gimp_display_shell_compress_motion (GdkEvent *initial_event,
+ GdkEvent **next_event)
{
GdkEvent *last_motion = NULL;
GtkWidget *widget;
+ *next_event = NULL;
+
if (initial_event->any.type != GDK_MOTION_NOTIFY)
return NULL;
@@ -1973,12 +2011,15 @@ gimp_display_shell_compress_motion (GdkEvent *initial_event)
if (!event)
{
/* Do nothing */
+ break;
}
else if ((gtk_get_event_widget (event) == widget) &&
(event->any.type == GDK_MOTION_NOTIFY) &&
+ (event->any.window == initial_event->any.window) &&
(event->motion.state == initial_event->motion.state) &&
(event->motion.device == initial_event->motion.device))
{
+ /* Discard previous motion event */
if (last_motion)
gdk_event_free (last_motion);
@@ -1986,27 +2027,8 @@ gimp_display_shell_compress_motion (GdkEvent *initial_event)
}
else
{
- GSList *remaining_events = NULL;
-
- /* Put the event back at the front of the queue... the hard way :P */
- remaining_events = g_slist_prepend (remaining_events, event);
-
- while (gdk_events_pending ())
- if ((event = gdk_event_get ()))
- remaining_events = g_slist_prepend (remaining_events, event);
-
- remaining_events = g_slist_reverse (remaining_events);
-
- while (remaining_events)
- {
- event = remaining_events->data;
-
- gdk_event_put (event);
- gdk_event_free (event);
-
- remaining_events = g_slist_delete_link (remaining_events,
- remaining_events);
- }
+ /* Let the caller dispatch the event */
+ *next_event = event;
break;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]