GNOME Bugzilla – Bug 307963
GtkSpinButton clamps value with the wrong maximum.
Last modified: 2011-01-04 02:52:47 UTC
Please describe the problem: The GtkSpinButton doesn't ignore the page_size field of the GtkAdjustment on the line 1815 in gtkspinbutton.c. Steps to reproduce: 1. Set a GtkSpinButton with an GtkAdjustment with a page_size not zero. 2. set the value of the GtkSpinButton to the max value 3. change the range with a smaller maximum Actual results: The GtkSpinButton is clamped to the maximum minus the page_size ==> this is wrong Expected results: The GtkSpinButton should be clamped to the maximum. Does this happen every time? yes Other information: the documentation mentions that the page_size value should be zero for GtkSpinButton.
Where does the documentation mention that ? I did not see it. But if it does, there should be no problem, because upper - 0 == upper...
I don't think we should change the code here. If anything the documentation may need clarification.
In the GtkAdjustment doc at the "page-size" property: The page size of the adjustment. Note that the page-size is irrelevant and should be set to zero if the adjustment is used for a simple scalar value, e.g. in a GtkSpinButton. so the recommandation is mandatory for a fonctionnal GtkSpinButton :-) but in the code, I don't find any reason for this subtraction to occur.
Think a scrollbar ... if a document is of length N, and has a page size P, the valid values of the scrollbar position are 0 ... N - P.
But this behavior in the function 'gtk_spin_button_set_range' is inconsistent with others functions. The page_size property is not honored for by example the 'gtk_spin_button_set_value'. In my program I generate my code from glade and when I instanciate a GtkSpinButton, glade defaults the page_size property to 10. Every thing nice until I change the range with a value in GtkSpinButton set to the max, the value is now set to the new max minus 10 => very disturbing, and not easy to find.
Sounds as gtk_spin_button_set_value() in fact behaves inconsistent here. If we can't change it for compatibility reasons, we should document that it ignores page_size, and also add a little discussion of page_size to the spin button docs. The glade bhaviour sounds just buggy. It should normally set page_size to 0 for a spinbutton.
I agree that glade is bugged here, but in fact I think it's the gtk_spin_button_set_range() function which is inconsistent and it is the easiest to correct. Moreover, I don't think it's incompatible since the actual result is very weird.
I've just run into this "bug" today, and tends to agree with Guillaume. My understanding of the page property for spin button is just a setting that allows bigger jump when clicking with button 2 (and that's how it is described in the documentation of gtk_spin_button_set_increments () function). By the way, during user interaction, value in spin button doesn't stop at max_value - page_size, but at max_value. For example, if max_value is set to 100, step to 1 and page to 10, if you have 91 in spin button, if you click with button 2, the new value is 100. Currently, gtk_spin_button_set_range() is inconsistent with user interaction. A fix is to change the following line in gtk_spin_button_set_range: value = CLAMP (spin_button->adjustment->value, spin_button->adjustment->lower, (spin_button->adjustment->upper - spin_button->adjustment->page_size)); by: value = CLAMP (spin_button->adjustment->value, spin_button->adjustment->lower, spin_button->adjustment->upper); The current behaviour is really weird, especially when you have for example spin button value set to 90 with max_value set to 100, and you change max_value to 90 : value is changed to 80 :( . Why would value be modified, since its a perfectly valid value ?
Oh, sorry, I have confused page_size and page_increment. But anyway, if page_size is ignored during user interaction, why would gtk_spin_button_set_range take this property into account ?
It is not only gtk_spin_button_set_value() that ignores page_size when computing the maximum value for the spin buttons value. It is done all over the place in gtkspinbutton.c (for example, in gtk_spin_button_get_range()), which seems reasonable since ignoring the page_size is the documented behaviour. Seems to me that it really is gtk_spin_button_set_range() that is wrong here.
*** Bug 478889 has been marked as a duplicate of this bug. ***
Created attachment 115756 [details] [review] Disregard adj->page_size when clamping Simple patch that fixes problem.
You can't dereference the spinbutton before the g_return_if_fail().
I vote that we raise the priority on this. It's been around for 4 years with a known fix. I just wasted a bunch of time trying to debug why the go-to-line dialog of the Medit text editor would never let me go within the last 10 lines of any file. Because the GtkAdjustment for it's GtkSpinButton had a page_size of 10! Event the Gtk documentation example code makes the mistake of setting a non-zero page_size on the GtkAdjustment! See "Example 17. Using a GtkSpinButton to get an integer" here: http://library.gnome.org/devel/gtk/unstable/GtkSpinButton.html Intuitively page_size does not apply to a GtkSpinButton. So surely Gtk should be smart enough to ignore it. Here's a runnable version of the example given in the Gtk documentation: -------------- Makefile ---------------------------------- gtk_spinbutton_bug: gtk_spinbutton_bug.c gcc `pkg-config --cflags --libs gtk+-2.0` gtk_spinbutton_bug.c -o gtk_spinbutton_bug -------------- gtk_spinbutton_bug.c ---------------------- #include<gtk/gtk.h> //following function is from: http://library.gnome.org/devel/gtk/unstable/GtkSpinButton.html void create_integer_spin_button (void) { GtkWidget *window, *spinner; GtkAdjustment *spinner_adj; spinner_adj = (GtkAdjustment *) gtk_adjustment_new (50.0, 0.0, 100.0, 1.0, 5.0, 5.0); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_container_set_border_width (GTK_CONTAINER (window), 5); /* creates the spinner, with no decimal places */ spinner = gtk_spin_button_new (spinner_adj, 1.0, 0); gtk_container_add (GTK_CONTAINER (window), spinner); gtk_widget_show_all (window); return; } int main(int argc, char* argv[]) { gtk_init (&argc, &argv); create_integer_spin_button(); gtk_main(); return 0; }