After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 674098 - Enable GDK_SMOOTH_SCROLL events for document view
Enable GDK_SMOOTH_SCROLL events for document view
Status: RESOLVED FIXED
Product: evince
Classification: Core
Component: general
git master
Other Linux
: Normal normal
: ---
Assigned To: Evince Maintainers
Evince Maintainers
: 567033 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2012-04-14 09:11 UTC by Chow Loong Jin
Modified: 2017-10-03 17:05 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch to enable GDK_SMOOTH_SCROLL events (6.78 KB, patch)
2012-04-14 09:12 UTC, Chow Loong Jin
none Details | Review
Amended patch to enable GDK_SMOOTH_SCROLL events (6.68 KB, patch)
2012-04-16 17:37 UTC, Chow Loong Jin
none Details | Review
Amended patch to enable GDK_SMOOTH_SCROLL events (6.68 KB, patch)
2012-04-16 23:27 UTC, Chow Loong Jin
none Details | Review
Patch to enable GDK_SMOOTH_SCROLL events (6.75 KB, patch)
2012-04-24 00:58 UTC, Chow Loong Jin
needs-work Details | Review
Updated patch to enable GDK_SMOOTH_SCROLL events (6.35 KB, patch)
2012-07-14 16:29 UTC, Chow Loong Jin
reviewed Details | Review
Smooth scroll test case (853 bytes, text/plain)
2012-08-07 18:49 UTC, Chow Loong Jin
  Details
Refreshed patch for latest git sources (3.79 KB, patch)
2012-10-11 19:00 UTC, Andrew Gunnerson
none Details | Review
libview: Enable GDK_SMOOTH_SCROLL events for view (3.79 KB, patch)
2013-04-16 19:39 UTC, David King
committed Details | Review
libview: Allow zooming to the limits of the scale (3.05 KB, patch)
2013-04-16 19:39 UTC, David King
none Details | Review

Description Chow Loong Jin 2012-04-14 09:11:08 UTC
Gtk+ 3.3.18 introduces GDK_SMOOTH_SCROLL events which brings kinetic scrolling to touch devices. However, the document view in Evince does not enable these events, and therefore GtkScrolledWindow falls back to the traditional scrolling.

The attached patch enables this event, and handles smooth scroll events for ctrl+scroll, shift+scroll, and non-continuous scrolling as well.
Comment 1 Chow Loong Jin 2012-04-14 09:12:06 UTC
Created attachment 212041 [details] [review]
Patch to enable GDK_SMOOTH_SCROLL events
Comment 2 Christian Persch 2012-04-14 10:55:01 UTC
If we really want to add these as public functions, they need to have docs comments, including Since: annotation, and an entry in the docs' sections.txt file.
Comment 3 Chow Loong Jin 2012-04-14 11:00:39 UTC
Would it be better to have them as public functions or static functions?
Comment 4 Christian Persch 2012-04-16 16:03:37 UTC
Unless you foresee a need to call these directly from outside ev-view, they should be private. (We can always make them public later!)
Comment 5 Chow Loong Jin 2012-04-16 17:37:47 UTC
Created attachment 212160 [details] [review]
Amended patch to enable GDK_SMOOTH_SCROLL events

Alright, here's an amended patch that has the two functions as static functions instead.
Comment 6 José Aliste 2012-04-16 18:06:21 UTC
Review of attachment 212160 [details] [review]:

::: libview/ev-view.c
@@ +3304,3 @@
+			gdouble factor = pow (delta < 0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR, fabs (delta));
+
+			if (ev_view_can_zoom (view, factor)) {

Why Can't  you just use ev_view_can_zoom_in &&  ev_view_can_zoom_out ?

@@ +3361,3 @@
+			        decrement = view->total_delta_x < 0 ? -1.0 : 1.0;
+			        for (; fabs (view->total_delta_x) >= 1.0; view->total_delta_x -= decrement)
+				        if (decrement < 0)

you should add braces at least to the for statements... these for statements without the init part also look weird (but no opinion on this)

@@ +5478,2 @@
 }
 

I don't see the need for this method. (see above). Otherwise, I would just do 
return ev_view_can_zoom_in && ev_view_can_zoom_out

@@ +5495,1 @@
 }

Why are you changing the behaviour of this func? unless I am missing something, you should not change the behaviour of this func.

@@ +5501,2 @@
 }
 

ditto
Comment 7 Chow Loong Jin 2012-04-16 18:21:10 UTC
(In reply to comment #6)
> Review of attachment 212160 [details] [review]:
> 
> ::: libview/ev-view.c
> @@ +3304,3 @@
> +            gdouble factor = pow (delta < 0 ? ZOOM_IN_FACTOR :
> ZOOM_OUT_FACTOR, fabs (delta));
> +
> +            if (ev_view_can_zoom (view, factor)) {
> 
> Why Can't  you just use ev_view_can_zoom_in &&  ev_view_can_zoom_out ?

Because scrolling now happens in sub-tick increments (I'm not sure what to call it, but by "tick", I mean Button[4-7] events or GDK_SCROLL_{UP,DOWN,LEFT,RIGHT} events). `delta' is a fractional value indicating how much of a scroll has happened. For example, if under the old mechanism it takes you 1cm of movement on a touchpad per scroll tick, you move by 1.5cm on the touchpad, delta will be equal to 1.5.

In other words, this particular hunk makes it possible to zoom in/out using ctrl+scroll smoothly on hardware that supports it.

ev_view_can_zoom_{in,out} calculate the possibility of zooming with a constant factor (1.2, and 1/1.2), resulting in discrete zooming even on GDK_SCROLL_SMOOTH supported hardware.

Likewise for ev_view_zoom{in,out}.
 
> @@ +3361,3 @@
> +                    decrement = view->total_delta_x < 0 ? -1.0 : 1.0;
> +                    for (; fabs (view->total_delta_x) >= 1.0;
> view->total_delta_x -= decrement)
> +                        if (decrement < 0)
> 
> you should add braces at least to the for statements... these for statements
> without the init part also look weird (but no opinion on this)
> 
> @@ +5478,2 @@
>  }
> 
> 
> I don't see the need for this method. (see above). Otherwise, I would just do 
> return ev_view_can_zoom_in && ev_view_can_zoom_out

I think you're misunderstanding the purpose of this function. Perhaps it should be renamed to ev_view_can_zoom_for_factor()? This function does not check that both zooming in and out are possible, but tests that zooming for a specifically given factor is possible (note the extra gdouble factor argument).

> 
> @@ +5495,1 @@
>  }
> 
> Why are you changing the behaviour of this func? unless I am missing something,
> you should not change the behaviour of this func.

I didn't. The behaviour is exactly the same as before. The code that's in ev_view_[can_]zoom was duplicated and more or less identical in both ev_view_[can_]_zoom_{in,out} before (with the exception of the ZOOM_{IN,OUT}_FACTOR).



> 
> @@ +5501,2 @@
>  }
> 
> 
> ditto
Comment 8 José Aliste 2012-04-16 18:33:05 UTC
(In reply to comment #7)
> (In reply to comment #6)
> > Review of attachment 212160 [details] [review] [details]:
> > 
> > ::: libview/ev-view.c
> > @@ +3304,3 @@
> > +            gdouble factor = pow (delta < 0 ? ZOOM_IN_FACTOR :
> > ZOOM_OUT_FACTOR, fabs (delta));
> > +
> > +            if (ev_view_can_zoom (view, factor)) {
> > 
> > Why Can't  you just use ev_view_can_zoom_in &&  ev_view_can_zoom_out ?
> 
> Because scrolling now happens in sub-tick increments (I'm not sure what to call
> it, but by "tick", I mean Button[4-7] events or GDK_SCROLL_{UP,DOWN,LEFT,RIGHT}
> events). `delta' is a fractional value indicating how much of a scroll has
> happened. For example, if under the old mechanism it takes you 1cm of movement
> on a touchpad per scroll tick, you move by 1.5cm on the touchpad, delta will be
> equal to 1.5.
> 
> In other words, this particular hunk makes it possible to zoom in/out using
> ctrl+scroll smoothly on hardware that supports it.
> 
> ev_view_can_zoom_{in,out} calculate the possibility of zooming with a constant
> factor (1.2, and 1/1.2), resulting in discrete zooming even on
> GDK_SCROLL_SMOOTH supported hardware.
> 
> Likewise for ev_view_zoom{in,out}.
> 

Indeed, totally missed that :)


> > @@ +3361,3 @@
> > +                    decrement = view->total_delta_x < 0 ? -1.0 : 1.0;
> > +                    for (; fabs (view->total_delta_x) >= 1.0;
> > view->total_delta_x -= decrement)
> > +                        if (decrement < 0)
> > 
> > you should add braces at least to the for statements... these for statements
> > without the init part also look weird (but no opinion on this)
> > 
> > @@ +5478,2 @@
> >  }
> > 
> > 
> > I don't see the need for this method. (see above). Otherwise, I would just do 
> > return ev_view_can_zoom_in && ev_view_can_zoom_out
> 
> I think you're misunderstanding the purpose of this function. Perhaps it should
> be renamed to ev_view_can_zoom_for_factor()? This function does not check that
> both zooming in and out are possible, but tests that zooming for a specifically
> given factor is possible (note the extra gdouble factor argument).

Sure, I misunderstood. 


> 
> > 
> > @@ +5495,1 @@
> >  }
> > 
> > Why are you changing the behaviour of this func? unless I am missing something,
> > you should not change the behaviour of this func.
> 
> I didn't. The behaviour is exactly the same as before. The code that's in
> ev_view_[can_]zoom was duplicated and more or less identical in both
> ev_view_[can_]_zoom_{in,out} before (with the exception of the
> ZOOM_{IN,OUT}_FACTOR).


My point is still valid. In zoom_in and zoom_out funcs you only check for one condition, while in zoom func you check for both conditions (for max and min scale). I could imagine a situation where these two comparisons give different results. 

> 
> 
> 
> > 
> > @@ +5501,2 @@
> >  }
> > 
> > 
> > ditto
Comment 9 Chow Loong Jin 2012-04-16 23:16:51 UTC
(In reply to comment #8)
> [...]
> > > @@ +5495,1 @@
> > >  }
> > > 
> > > Why are you changing the behaviour of this func? unless I am missing something,
> > > you should not change the behaviour of this func.
> > 
> > I didn't. The behaviour is exactly the same as before. The code that's in
> > ev_view_[can_]zoom was duplicated and more or less identical in both
> > ev_view_[can_]_zoom_{in,out} before (with the exception of the
> > ZOOM_{IN,OUT}_FACTOR).
> 
> 
> My point is still valid. In zoom_in and zoom_out funcs you only check for one
> condition, while in zoom func you check for both conditions (for max and min
> scale). I could imagine a situation where these two comparisons give different
> results. 

I see. I think I understand what you mean. Basically if the current zoom level is greater than the maximum zoom level, we still want to be able to zoom out, and vice versa?
Comment 10 Chow Loong Jin 2012-04-16 23:27:58 UTC
Created attachment 212176 [details] [review]
Amended patch to enable GDK_SMOOTH_SCROLL events

Here's an amended patch that fixes the use-case mentioned in #8.
Comment 11 Chow Loong Jin 2012-04-24 00:58:59 UTC
Created attachment 212657 [details] [review]
Patch to enable GDK_SMOOTH_SCROLL events

It looks like I forgot to commit my changes before running format-patch. Here's the real amended patch.
Comment 12 Thomas Andersen 2012-05-15 11:17:06 UTC
Is there any chance that this might make it into a 3.4.x release? Smooth scrolling makes reading documents much nicer when using a trackpad (and I imagine even more on a tablet)
Comment 13 Carlos Garnacho 2012-05-19 10:47:41 UTC
Review of attachment 212657 [details] [review]:

The patch looks and works mostly ok to me, although the handling of best_fit && !continuous acts a bit weird, as diagonal scrolling may trigger page switches back and forth, even cancelling out each other. I would recommend tying together both delta_x/y, and having it tick when that combination reaches a threshold, something like:

view->total_delta_x += event->delta_x;
view->total_delta_y += event->delta_y;

if (pow (view->total_delta_x, 2) + pow (view->total_delta_y, 2) > 1)
  {
    /* handle moving to previous/next page based on overall direction */
    ...
    view->total-delta_x = view->total_delta_y = 0;
  }
Comment 14 Chow Loong Jin 2012-07-14 05:13:00 UTC
I noticed that Nautilus appears to completely ignore horizontal smooth scrolling in its thumbnail mode, and vertical smooth scrolling in its compact mode. Perhaps to be consistent with Nautilus, Evince should ignore horizontal smooth scrolling (delta_x) in the case of best_fit && !continuous?
Comment 15 Chow Loong Jin 2012-07-14 16:29:17 UTC
Created attachment 218823 [details] [review]
Updated patch to enable GDK_SMOOTH_SCROLL events

Alright, here's a patch that combines total_delta_x and total_delta_y into a single variable, total_delta.

Instead of doing a pythagoras calculation of the hypotenuse when scrolling diagonally, this has the effect of letting the two deltas add up.

So basically what we have is this:
 - scroll left or scroll up, go to previous page
 - scroll right or scroll down, go to next page

And if the user scrolls diagonally, it's more stable now that we don't keep flipping to and fro between two pages erratically:
 - if the user scrolls diagonally upwards towards the left, then we treat it as scrolling up, twice as fast.
 - if the user scrolls diagonally upwards towards the right, then we treat it as scrolling up, twice as slow.

The angle matters, of course, depending on how much physical distance you have to move to get the same scroll delta. I believe this mimics the previous (non-smooth-scrolling) behaviour for diagonal scrolls perfectly.

I have kept the loop in place, so that if the user scrolls really quickly and manages to get in total_delta > 2.0 in a single event, then we can flip pages faster as well, instead of rate-limiting it to 1 page per event.
Comment 16 Carlos Garcia Campos 2012-08-07 17:42:48 UTC
Review of attachment 218823 [details] [review]:

I've split the patch and pushed the zoom methods refactoring. I've tried the patch and it doesn't seem to work in some cases for me. If I open a document in best fit non continuous mode, the first time I move the scroll wheel, it doesn't change the page because it seems total_delta is 0.
Comment 17 Chow Loong Jin 2012-08-07 18:49:15 UTC
Created attachment 220592 [details]
Smooth scroll test case

I see it too. It looks like a Gtk/Gdk bug though. Using the attached test case, I got the following output:
------
GDK_SCROLL_SMOOTH 0, 0
GDK_SCROLL_DOWN
GDK_SCROLL_SMOOTH 0, 0
GDK_SCROLL_UP
------

It seems that the first scroll event using a normal mouse after focusing on the window yields a delta_x and delta_y of 0.
Comment 18 Andrew Gunnerson 2012-10-11 19:00:21 UTC
Created attachment 226288 [details] [review]
Refreshed patch for latest git sources

Here is the patch refreshed for the latest git sources.
Comment 19 Jean-François Fortin Tam 2012-10-16 00:29:33 UTC
*** Bug 567033 has been marked as a duplicate of this bug. ***
Comment 20 David King 2013-04-16 19:39:14 UTC
Created attachment 241682 [details] [review]
libview: Enable GDK_SMOOTH_SCROLL events for view

This enables the smooth/kinetic scrolling support found in GTK+ 3.3.18
with the document view, and handles them for the Ctrl+scroll,
Shift+scroll, and non-continuous best-fit mode scrolling cases.
Comment 21 David King 2013-04-16 19:39:20 UTC
Created attachment 241683 [details] [review]
libview: Allow zooming to the limits of the scale

If the current zoom level was within one zoom factor of the limit, it
was not possible to scroll towards the limit. This made smooth scrolling
near the limit awkward, as unless the scroll event had a large delta it
was impossible to reach the zoom limit. Non-smooth scrolling was also
affected, but it was just much more difficult to trigger.

Fix this by allowing zooming while the current zoom level is within one
zoom factor of the limit. Add a new ev_view_can_zoom() function to make
zooming by a factor (as with smooth scrolling) more convenient.
Comment 22 Carlos Garcia Campos 2013-05-28 12:32:55 UTC
Comment on attachment 241682 [details] [review]
libview: Enable GDK_SMOOTH_SCROLL events for view

Thanks!, I've just pushed it to git master with some minor cosmetic changes.
Comment 23 Carlos Garcia Campos 2013-05-28 12:54:49 UTC
(In reply to comment #21)
> Created an attachment (id=241683) [details] [review]
> libview: Allow zooming to the limits of the scale
> 
> If the current zoom level was within one zoom factor of the limit, it
> was not possible to scroll towards the limit. This made smooth scrolling
> near the limit awkward, as unless the scroll event had a large delta it
> was impossible to reach the zoom limit. Non-smooth scrolling was also
> affected, but it was just much more difficult to trigger.
> 
> Fix this by allowing zooming while the current zoom level is within one
> zoom factor of the limit. Add a new ev_view_can_zoom() function to make
> zooming by a factor (as with smooth scrolling) more convenient.

Thanks for the patch, but I'm not sure I understand it, we need to check the scale after applying the zoom to check if it's possible to zoom in/out, no?. In any case, this bug is about enabling smooth scroll events, could you please open a new bug report for this patch so that we can discuss it there?
Comment 24 Germán Poo-Caamaño 2014-05-04 05:19:29 UTC
What is missing to close this bug?
Comment 25 Carlos Garcia Campos 2014-05-04 08:45:30 UTC
Nothing, the pending patch is unrelated to this bug. David, feel free to open a new bug report for the other patch.
Comment 26 Germán Poo-Caamaño 2017-10-03 17:05:52 UTC
I rebased David's patch and attached to a new bug (Bug 788480)