[evince] view: avoid getting pointer position from vertical scroll callback
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince] view: avoid getting pointer position from vertical scroll callback
- Date: Fri, 27 Apr 2018 15:20:58 +0000 (UTC)
commit b9059582a83c9b9ec180d2ec55898d23d9c0c2d6
Author: Cosimo Cecchi <cosimo endlessm com>
Date: Thu Apr 26 18:10:57 2018 -0700
view: avoid getting pointer position from vertical scroll callback
When an EvView is embedded in a ClutterGTK stage, such as when it's used
in sushi, calling into gdk_window_get_device_position() can result in an
infinite loop, as it will force an allocation cycle inside Clutter,
which results in a forced immediate draw event being delivered to the
scrolled window while it's processing the scroll event.
There may be more general issues with the ClutterGTK implementation, but
in the meantime it's easy to avoid the issue from Evince:
- if the adjustment changed value directly because of a scroll event, we
can get the mouse pointer coordinates directly from the event
- otherwise (e.g. scrollbar, or keynav), we can defer the update of the
cursor to an idle handler, which avoids the deadlock
https://bugzilla.gnome.org/show_bug.cgi?id=793401
libview/ev-view-private.h | 2 +
libview/ev-view.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 47 insertions(+), 3 deletions(-)
---
diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h
index 7bf9adc..2a387d0 100644
--- a/libview/ev-view-private.h
+++ b/libview/ev-view-private.h
@@ -168,6 +168,8 @@ struct _EvView {
gint scroll_x;
gint scroll_y;
+ guint update_cursor_idle_id;
+
/* Delta sum for emulating normal scrolling */
gdouble total_delta;
PendingScroll pending_scroll;
diff --git a/libview/ev-view.c b/libview/ev-view.c
index d44ad81..f4a28f1 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -6969,6 +6969,11 @@ ev_view_dispose (GObject *object)
ev_view_window_children_free (view);
+ if (view->update_cursor_idle_id) {
+ g_source_remove (view->update_cursor_idle_id);
+ view->update_cursor_idle_id = 0;
+ }
+
if (view->selection_scroll_id) {
g_source_remove (view->selection_scroll_id);
view->selection_scroll_id = 0;
@@ -7887,15 +7892,40 @@ ev_view_page_changed_cb (EvDocumentModel *model,
}
}
+static gboolean
+cursor_scroll_update (gpointer data)
+{
+ EvView *view = data;
+ gint x, y;
+
+ view->update_cursor_idle_id = 0;
+ ev_document_misc_get_pointer_position (GTK_WIDGET (view), &x, &y);
+ ev_view_handle_cursor_over_xy (view, x, y);
+
+ return FALSE;
+}
+
+static void
+schedule_scroll_cursor_update (EvView *view)
+{
+ if (view->update_cursor_idle_id)
+ return;
+
+ view->update_cursor_idle_id =
+ g_idle_add (cursor_scroll_update, view);
+}
+
static void
on_adjustment_value_changed (GtkAdjustment *adjustment,
EvView *view)
{
GtkWidget *widget = GTK_WIDGET (view);
int dx = 0, dy = 0;
- gint x, y;
+ gdouble x, y;
gint value;
GList *l;
+ GdkEvent *event;
+ gboolean cursor_updated;
if (!gtk_widget_get_realized (widget))
return;
@@ -7939,8 +7969,20 @@ on_adjustment_value_changed (GtkAdjustment *adjustment,
gdk_window_scroll (gtk_widget_get_window (widget), dx, dy);
}
- ev_document_misc_get_pointer_position (widget, &x, &y);
- ev_view_handle_cursor_over_xy (view, x, y);
+ cursor_updated = FALSE;
+ event = gtk_get_current_event ();
+ if (event) {
+ if (event->type == GDK_SCROLL &&
+ gdk_event_get_window (event) == gtk_widget_get_window (widget)) {
+ gdk_event_get_coords (event, &x, &y);
+ ev_view_handle_cursor_over_xy (view, (gint) x, (gint) y);
+ cursor_updated = TRUE;
+ }
+ gdk_event_free (event);
+ }
+
+ if (!cursor_updated)
+ schedule_scroll_cursor_update (view);
if (view->document)
view_update_range_and_current_page (view);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]