[goocanvas] Fix stuck grab bug #711709
- From: Damon Chaplin <damon src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goocanvas] Fix stuck grab bug #711709
- Date: Thu, 31 Aug 2017 07:30:41 +0000 (UTC)
commit cd1ad0f66ded84901f77519434191ae108dadace
Author: Damon Chaplin <Damon A Chaplin gmail com>
Date: Thu Aug 31 08:18:14 2017 +0100
Fix stuck grab bug #711709
2017-08-30 Damon Chaplin <damon gnome org>
* src/goocanvas.c: If we receive a LEAVE_NOTIFY event with a mode of
GDK_CROSSING_GRAB or GDK_CROSSING_GTK_GRAB we finish any passive grab
we have underway. Hopefully fixes #711709
* demo/mv-simple-demo.c (on_rect_button_press):
* demo/simple-demo.c (on_rect_button_press): show a dialog to test
the grab bug fix above.
.gitignore | 1 +
ChangeLog | 10 +++++++
demo/mv-simple-demo.c | 17 +++++++++--
demo/simple-demo.c | 17 +++++++++--
src/Makefile.am | 7 +++++
src/goocanvas.c | 73 +++++++++++++++++++++++++++++-------------------
6 files changed, 90 insertions(+), 35 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index b5916a8..fd25ad2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,6 +45,7 @@ Makefile.in
/install-sh
/libtool
/ltmain.sh
+/m4
/missing
/mkinstalldirs
/py-compile
diff --git a/ChangeLog b/ChangeLog
index 9a8d576..0a022af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2017-08-30 Damon Chaplin <damon gnome org>
+
+ * src/goocanvas.c: If we receive a LEAVE_NOTIFY event with a mode of
+ GDK_CROSSING_GRAB or GDK_CROSSING_GTK_GRAB we finish any passive grab
+ we have underway. Hopefully fixes #711709
+
+ * demo/mv-simple-demo.c (on_rect_button_press):
+ * demo/simple-demo.c (on_rect_button_press): show a dialog to test
+ the grab bug fix above.
+
2017-08-29 Damon Chaplin <damon gnome org>
* src/goocanvas.c:
diff --git a/demo/mv-simple-demo.c b/demo/mv-simple-demo.c
index 9ec41eb..1026518 100644
--- a/demo/mv-simple-demo.c
+++ b/demo/mv-simple-demo.c
@@ -72,15 +72,26 @@ main ()
}
-/* This handles button presses in item views. We simply output a message to
- the console. */
+/* The signal handler for the rectangle item. We show a dialog here. */
static gboolean
on_rect_button_press (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event,
gpointer data)
{
- g_print ("rect item received button press event\n");
+ GooCanvas *canvas;
+ GtkWidget *window, *dialog;
+
+ canvas = goo_canvas_item_get_canvas (item);
+ window = gtk_widget_get_toplevel (GTK_WIDGET (canvas));
+ dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "rect item received button press event");
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
return TRUE;
}
diff --git a/demo/simple-demo.c b/demo/simple-demo.c
index 9a3358f..7e7bdcd 100644
--- a/demo/simple-demo.c
+++ b/demo/simple-demo.c
@@ -68,15 +68,26 @@ main ()
}
-/* This handles button presses in item views. We simply output a message to
- the console. */
+/* The signal handler for the rectangle item. We show a dialog here. */
static gboolean
on_rect_button_press (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event,
gpointer data)
{
- g_print ("rect item received button press event\n");
+ GooCanvas *canvas;
+ GtkWidget *window, *dialog;
+
+ canvas = goo_canvas_item_get_canvas (item);
+ window = gtk_widget_get_toplevel (GTK_WIDGET (canvas));
+ dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "rect item received button press event");
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
return TRUE;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f31008..2f7d4f3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -146,6 +146,13 @@ BUILT_SOURCES = $(libgoocanvas_built_headers) $(libgoocanvas_built_sources)
MAINTAINERCLEANFILES = $(BUILT_SOURCES) $(stamp_files)
EXTRA_DIST = $(BUILT_SOURCES) $(libgoocanvas_extra_sources)
+# if srcdir!=builddir, clean out maintainer-clean files from builddir
+# this allows dist to pass.
+distclean-local:
+ if test $(srcdir) != .; then \
+ rm -f $(MAINTAINERCLEANFILES); \
+ fi
+
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
diff --git a/src/goocanvas.c b/src/goocanvas.c
index 77d20e6..5641f45 100644
--- a/src/goocanvas.c
+++ b/src/goocanvas.c
@@ -122,6 +122,7 @@ struct _GooCanvasPrivate {
gint static_window_x, static_window_y;
GdkRGBA background_color;
guint background_color_set : 1;
+ guint pointer_grab_is_implicit : 1;
};
@@ -3159,17 +3160,51 @@ update_pointer_item (GooCanvas *canvas,
}
+static void
+goo_canvas_finish_pointer_grab (GooCanvas *canvas,
+ GdkEvent *event)
+{
+ /* We set the pointer item back to the item it was in before the
+ grab, so we'll synthesize enter/leave notify events as appropriate. */
+ if (canvas->pointer_grab_initial_item
+ && ITEM_IS_VALID (canvas->pointer_grab_initial_item))
+ set_item_pointer (&canvas->pointer_item,
+ canvas->pointer_grab_initial_item);
+ else
+ set_item_pointer (&canvas->pointer_item, NULL);
+
+ set_item_pointer (&canvas->pointer_grab_item, NULL);
+ set_item_pointer (&canvas->pointer_grab_initial_item, NULL);
+
+ update_pointer_item (canvas, event);
+}
+
+
static gboolean
goo_canvas_crossing (GtkWidget *widget,
GdkEventCrossing *event)
{
GooCanvas *canvas = GOO_CANVAS (widget);
+ GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
if (event->window != canvas->canvas_window)
return FALSE;
- /* This will result in synthesizing focus_in/out events as appropriate. */
- update_pointer_item (canvas, (GdkEvent*) event);
+ /* If the pointer has left the canvas window due to a grab, then finish any
+ implicit pointer grab we have underway. */
+ if (event->type == GDK_LEAVE_NOTIFY
+ && (event->mode == GDK_CROSSING_GRAB
+ || event->mode == GDK_CROSSING_GTK_GRAB)
+ && canvas->pointer_grab_item
+ && priv->pointer_grab_is_implicit)
+ {
+ goo_canvas_finish_pointer_grab (canvas, (GdkEvent*) event);
+ }
+ else
+ {
+ /* This will result in synthesizing focus_in/out events as appropriate. */
+ update_pointer_item (canvas, (GdkEvent*) event);
+ }
return FALSE;
}
@@ -3201,6 +3236,7 @@ goo_canvas_button_press (GtkWidget *widget,
GdkEventButton *event)
{
GooCanvas *canvas = GOO_CANVAS (widget);
+ GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
GdkDevice *device = gdk_event_get_device ((GdkEvent*) event);
GdkDisplay *display;
@@ -3220,6 +3256,7 @@ goo_canvas_button_press (GtkWidget *widget,
set_item_pointer (&canvas->pointer_grab_item,
canvas->pointer_item);
canvas->pointer_grab_button = event->button;
+ priv->pointer_grab_is_implicit = TRUE;
}
return emit_pointer_event (canvas, "button_press_event", (GdkEvent*) event);
@@ -3249,19 +3286,7 @@ goo_canvas_button_release (GtkWidget *widget,
&& event->button == canvas->pointer_grab_button
&& !gdk_display_device_is_grabbed (display, device))
{
- /* We set the pointer item back to the item it was in before the
- grab, so we'll synthesize enter/leave notify events as appropriate. */
- if (canvas->pointer_grab_initial_item
- && ITEM_IS_VALID (canvas->pointer_grab_initial_item))
- set_item_pointer (&canvas->pointer_item,
- canvas->pointer_grab_initial_item);
- else
- set_item_pointer (&canvas->pointer_item, NULL);
-
- set_item_pointer (&canvas->pointer_grab_item, NULL);
- set_item_pointer (&canvas->pointer_grab_initial_item, NULL);
-
- update_pointer_item (canvas, (GdkEvent*) event);
+ goo_canvas_finish_pointer_grab (canvas, (GdkEvent*) event);
}
return retval;
@@ -3484,6 +3509,7 @@ goo_canvas_pointer_grab (GooCanvas *canvas,
GdkCursor *cursor,
guint32 time)
{
+ GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
GdkGrabStatus status = GDK_GRAB_SUCCESS;
GdkDisplay *display;
@@ -3520,6 +3546,7 @@ goo_canvas_pointer_grab (GooCanvas *canvas,
canvas->pointer_item);
set_item_pointer (&canvas->pointer_grab_item,
item);
+ priv->pointer_grab_is_implicit = FALSE;
}
return status;
@@ -3560,20 +3587,8 @@ goo_canvas_pointer_ungrab (GooCanvas *canvas,
gdk_display_pointer_ungrab (display, time);
#endif
- /* We set the pointer item back to the item it was in before the
- grab, so we'll synthesize enter/leave notify events as appropriate. */
- if (canvas->pointer_grab_initial_item
- && ITEM_IS_VALID (canvas->pointer_grab_initial_item))
- set_item_pointer (&canvas->pointer_item,
- canvas->pointer_grab_initial_item);
- else
- set_item_pointer (&canvas->pointer_item, NULL);
-
- set_item_pointer (&canvas->pointer_grab_item, NULL);
- set_item_pointer (&canvas->pointer_grab_initial_item, NULL);
-
- update_pointer_item (canvas, NULL);
- }
+ goo_canvas_finish_pointer_grab (canvas, NULL);
+}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]