GNOME Bugzilla – Bug 600535
GtkScale::value-change receives values beyond its GtkAdjustment:upper bound
Last modified: 2018-05-02 14:51:20 UTC
Created attachment 146810 [details] sample program The callback function of value-change will receive an out-of-range value if I drag the scrollbar to the rightest. The sample program will create a HScale with the range [0,100]. cb_scroll_change() prints the value it got when it is aroused by "value-change". The returned value will be larger than 100 while I dragged the scrollbar to the rightest. Reproduce Steps: 1. Open a terminal and compile the sample program with gcc `pkg-config gtk+-2.0 --libs --cflags` scale.c -o scale 2. Execute scale 3. Drag the scroll bar to the rightest and observe the number printed in the terminal
The problem is that the value increases according to an imaginable scale that extends outside of the window. My guess is, either CSW changed how it works, or it doesn't properly detect whether the mouse is above the window at all.
Created attachment 152269 [details] [review] gsynaptics-bnc550335-bgo600535-horizscroll.patch We had this patch for this bug in Moblin in openSUSE.
still present in both 2.24 and 3.22
Actually, this isn't much of a a bug. If you connect to Range::change-value, it's documented that you are responsible for deciding whether or not the new value is valid, and updating it accordingly. If you want values clamped between lower and upper, then connect to Scale::value-changed, which handles that for you. That said, since the bit in GtkRange that calculates what the value *would* be _does_ clamp at lower, it should probably clamp at upper too; I'm not sure there's any benefit to being asymmetrical there.
Created attachment 361199 [details] test case with Scale::value-changed added, showing it clamps correctly
Created attachment 361200 [details] [review] Range: Make coord_to_value clamp at both min & max Dragging the slider beyond the upper bound of the Range resulted in emissions of ::change-value above that bound, but the same was not true for the lower bound, which was clamped. Be symmetrical and clamp both. -- This makes the upper bound behave the same as the lower already does: you keep getting ::change-value, but the value remains at the bound despite how far past the trough you drag the slider. I don’t know if somehow the previous behaviour could have been useful; I can’t see how, but I’d prefer to get a review on this before doing anything with it.
Matthias pointed out that the out-of-range values may possible be use(d|ful) for e.g. triggering loading of additional content in a scrolling view. However, it looks like the correct way to do that is ScrolledWindow::edge-overshot, which already works even at the lower bound, despite that already being clamped by GtkRange. So it may be that we don't need to worry about leaving the upper bound unclamped here. Besides, Range::change-value keeps emitting even if the value is clamped (i.e. as the lower bound is already), so it seems that a user wanting to load more content in something not using a ScrolledWindow could listen for consecutive emissions with the same value. Also, Timm pointed out that it's better to load more content *before* hitting the edge anyway. That indeed is more user friendly; you don't want your user sitting there, not realising they have to push at the edge by some arbitrary amount to get more content. (...whereas at least loading when you get some arbitrary amount near the end is more likely to kick in without requiring discovery) So, unless there's a use-case where knowing about the overshoot and its precise magnitude in Range::change-value is needed (and at the upper bound only), maybe this patch is fine.
Created attachment 361355 [details] [review] Range: Make coord_to_value clamp at both min & max coord_to_value() clamps to the lower bound if a drag would otherwise result in a value below the lower bound. However, it did not do the same for the upper bound, so ::change-value would be emitted with values over the upper bound, proportional to how far off the trough you had dragged. Be symmetrical: change MAX(0, frac) to CLAMP(frac, 0, 1). We still emit ::change-value as we drag, but the received value is within both bounds. -- fixed whitespace alignment and elaborated on commit message
Any thoughts here?
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gtk/issues/328.