X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkrange.c;h=8339e52b70c195a829185fd0ddad7217012e3d79;hb=32aa7f0582febb614c41e4130ad34ac44ef6efd2;hp=ffd45e97b44db78355218a48de92aedd610938df;hpb=b123bc41fdce1e2cbf4ab6f998b3dd372aab515f;p=~andy%2Fgtk diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index ffd45e97b..8339e52b7 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* @@ -30,16 +28,20 @@ #include #include -#include "gtkmainprivate.h" -#include "gtkmarshalers.h" -#include "gtkorientable.h" #include "gtkrange.h" + +#include "gtkadjustment.h" +#include "gtkcolorscaleprivate.h" +#include "gtkintl.h" +#include "gtkmain.h" +#include "gtkmarshalers.h" +#include "gtkorientableprivate.h" +#include "gtkprivate.h" #include "gtkscale.h" #include "gtkscrollbar.h" -#include "gtkwindow.h" -#include "gtkprivate.h" -#include "gtkintl.h" #include "gtktypebuiltins.h" +#include "gtkwindow.h" +#include "a11y/gtkrangeaccessible.h" /** * SECTION:gtkrange @@ -79,15 +81,12 @@ struct _GtkRangePrivate gint mouse_x; gint mouse_y; MouseLocation grab_location; /* "grabbed" mouse location, OUTSIDE for no grab */ - guint grab_button : 8; /* 0 if none */ GtkRangeStepTimer *timer; GtkAdjustment *adjustment; - GtkOrientation orientation; GtkSensitivityType lower_sensitivity; GtkSensitivityType upper_sensitivity; - GtkUpdateType update_policy; GdkDevice *grab_device; GdkRectangle range_rect; /* Area of entire stepper + trough assembly in widget->window coords */ @@ -103,7 +102,7 @@ struct _GtkRangePrivate GQuark slider_detail_quark; GQuark stepper_detail_quark[4]; - gboolean recalc_marks; + GtkOrientation orientation; gdouble fill_level; gdouble *marks; @@ -117,9 +116,6 @@ struct _GtkRangePrivate gint slider_start; /* Slider range along the long dimension, in widget->window coords */ gint slider_end; - guint repaint_id; - guint update_timeout_id; - /* Steppers are: < > ---- < > * a b c d */ @@ -131,31 +127,39 @@ struct _GtkRangePrivate guint flippable : 1; guint inverted : 1; guint need_recalc : 1; + guint recalc_marks : 1; guint slider_size_fixed : 1; guint trough_click_forward : 1; /* trough click was on the forward side of slider */ - guint update_pending : 1; /* need to emit value_changed */ /* Stepper sensitivity */ guint lower_sensitive : 1; guint upper_sensitive : 1; + /* The range has an origin, should be drawn differently. Used by GtkScale */ + guint has_origin : 1; + + /* Whether we're doing fine adjustment */ + guint zoom : 1; + /* Fill level */ guint show_fill_level : 1; guint restrict_to_fill_level : 1; + + guint grab_button : 8; /* 0 if none */ }; enum { PROP_0, PROP_ORIENTATION, - PROP_UPDATE_POLICY, PROP_ADJUSTMENT, PROP_INVERTED, PROP_LOWER_STEPPER_SENSITIVITY, PROP_UPPER_STEPPER_SENSITIVITY, PROP_SHOW_FILL_LEVEL, PROP_RESTRICT_TO_FILL_LEVEL, - PROP_FILL_LEVEL + PROP_FILL_LEVEL, + PROP_ROUND_DIGITS }; enum { @@ -266,14 +270,11 @@ static void gtk_range_adjustment_changed (GtkAdjustment *adjustme static void gtk_range_add_step_timer (GtkRange *range, GtkScrollType step); static void gtk_range_remove_step_timer (GtkRange *range); -static void gtk_range_reset_update_timer (GtkRange *range); -static void gtk_range_remove_update_timer (GtkRange *range); static GdkRectangle* get_area (GtkRange *range, MouseLocation location); static gboolean gtk_range_real_change_value (GtkRange *range, GtkScrollType scroll, gdouble value); -static void gtk_range_update_value (GtkRange *range); static gboolean gtk_range_key_press (GtkWidget *range, GdkEventKey *event); @@ -380,10 +381,8 @@ gtk_range_class_init (GtkRangeClass *class) * @range: the #GtkRange that received the signal * @scroll: the type of scroll action that was performed * @value: the new value resulting from the scroll action - * @returns: %TRUE to prevent other handlers from being invoked for the - * signal, %FALSE to propagate the signal further * - * The ::change-value signal is emitted when a scroll action is + * The #GtkRange::change-value signal is emitted when a scroll action is * performed on a range. It allows an application to determine the * type of scroll event that occurred and the resultant new value. * The application can handle the event itself and return %TRUE to @@ -392,12 +391,15 @@ gtk_range_class_init (GtkRangeClass *class) * reached. * * The value parameter is unrounded. An application that overrides - * the ::change-value signal is responsible for clamping the value to - * the desired number of decimal digits; the default GTK+ handler - * clamps the value based on @range->round_digits. + * the GtkRange::change-value signal is responsible for clamping the + * value to the desired number of decimal digits; the default GTK+ + * handler clamps the value based on #GtkRange:round-digits. * * It is not possible to use delayed update policies in an overridden - * ::change-value handler. + * #GtkRange::change-value handler. + * + * Returns: %TRUE to prevent other handlers from being invoked for + * the signal, %FALSE to propagate the signal further * * Since: 2.6 */ @@ -416,15 +418,6 @@ gtk_range_class_init (GtkRangeClass *class) PROP_ORIENTATION, "orientation"); - g_object_class_install_property (gobject_class, - PROP_UPDATE_POLICY, - g_param_spec_enum ("update-policy", - P_("Update policy"), - P_("How the range should be updated on the screen"), - GTK_TYPE_UPDATE_TYPE, - GTK_UPDATE_CONTINUOUS, - GTK_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_ADJUSTMENT, g_param_spec_object ("adjustment", @@ -511,6 +504,24 @@ gtk_range_class_init (GtkRangeClass *class) G_MAXDOUBLE, GTK_PARAM_READWRITE)); + /** + * GtkRange:round-digits: + * + * The number of digits to round the value to when + * it changes, or -1. See #GtkRange::change-value. + * + * Since: 2.24 + */ + g_object_class_install_property (gobject_class, + PROP_ROUND_DIGITS, + g_param_spec_int ("round-digits", + P_("Round Digits"), + P_("The number of digits to round the value to."), + -1, + G_MAXINT, + -1, + GTK_PARAM_READWRITE)); + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("slider-width", P_("Slider Width"), @@ -539,8 +550,6 @@ gtk_range_class_init (GtkRangeClass *class) * GtkRange:stepper-spacing: * * The spacing between the stepper buttons and thumb. Note that - * setting this value to anything > 0 will automatically set the - * trough-under-steppers style property to %TRUE as well. Also, * stepper-spacing won't have any effect if there are no steppers. */ gtk_widget_class_install_style_property (widget_class, @@ -572,9 +581,7 @@ gtk_range_class_init (GtkRangeClass *class) * GtkRange:trough-under-steppers: * * Whether to draw the trough across the full length of the range or - * to exclude the steppers and their spacing. Note that setting the - * #GtkRange:stepper-spacing style property to any value > 0 will - * automatically enable trough-under-steppers too. + * to exclude the steppers and their spacing. * * Since: 2.10 */ @@ -600,6 +607,8 @@ gtk_range_class_init (GtkRangeClass *class) GTK_PARAM_READABLE)); g_type_class_add_private (class, sizeof (GtkRangePrivate)); + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_RANGE_ACCESSIBLE); } static void @@ -622,11 +631,9 @@ gtk_range_set_property (GObject *object, priv->stepper_detail_quark[2] = 0; priv->stepper_detail_quark[3] = 0; + _gtk_orientable_set_style_classes (GTK_ORIENTABLE (range)); gtk_widget_queue_resize (GTK_WIDGET (range)); break; - case PROP_UPDATE_POLICY: - gtk_range_set_update_policy (range, g_value_get_enum (value)); - break; case PROP_ADJUSTMENT: gtk_range_set_adjustment (range, g_value_get_object (value)); break; @@ -648,6 +655,9 @@ gtk_range_set_property (GObject *object, case PROP_FILL_LEVEL: gtk_range_set_fill_level (range, g_value_get_double (value)); break; + case PROP_ROUND_DIGITS: + gtk_range_set_round_digits (range, g_value_get_int (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -668,9 +678,6 @@ gtk_range_get_property (GObject *object, case PROP_ORIENTATION: g_value_set_enum (value, priv->orientation); break; - case PROP_UPDATE_POLICY: - g_value_set_enum (value, priv->update_policy); - break; case PROP_ADJUSTMENT: g_value_set_object (value, priv->adjustment); break; @@ -692,6 +699,9 @@ gtk_range_get_property (GObject *object, case PROP_FILL_LEVEL: g_value_set_double (value, gtk_range_get_fill_level (range)); break; + case PROP_ROUND_DIGITS: + g_value_set_int (value, gtk_range_get_round_digits (range)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -712,7 +722,6 @@ gtk_range_init (GtkRange *range) priv->orientation = GTK_ORIENTATION_HORIZONTAL; priv->adjustment = NULL; - priv->update_policy = GTK_UPDATE_CONTINUOUS; priv->inverted = FALSE; priv->flippable = FALSE; priv->min_slider_size = 1; @@ -731,6 +740,7 @@ gtk_range_init (GtkRange *range) priv->upper_sensitivity = GTK_SENSITIVITY_AUTO; priv->lower_sensitive = TRUE; priv->upper_sensitive = TRUE; + priv->has_origin = FALSE; priv->show_fill_level = FALSE; priv->restrict_to_fill_level = TRUE; priv->fill_level = G_MAXDOUBLE; @@ -763,53 +773,6 @@ gtk_range_get_adjustment (GtkRange *range) return priv->adjustment; } -/** - * gtk_range_set_update_policy: - * @range: a #GtkRange - * @policy: update policy - * - * Sets the update policy for the range. #GTK_UPDATE_CONTINUOUS means that - * anytime the range slider is moved, the range value will change and the - * value_changed signal will be emitted. #GTK_UPDATE_DELAYED means that - * the value will be updated after a brief timeout where no slider motion - * occurs, so updates are spaced by a short time rather than - * continuous. #GTK_UPDATE_DISCONTINUOUS means that the value will only - * be updated when the user releases the button and ends the slider - * drag operation. - **/ -void -gtk_range_set_update_policy (GtkRange *range, - GtkUpdateType policy) -{ - GtkRangePrivate *priv; - - g_return_if_fail (GTK_IS_RANGE (range)); - - priv = range->priv; - - if (priv->update_policy != policy) - { - priv->update_policy = policy; - g_object_notify (G_OBJECT (range), "update-policy"); - } -} - -/** - * gtk_range_get_update_policy: - * @range: a #GtkRange - * - * Gets the update policy of @range. See gtk_range_set_update_policy(). - * - * Return value: the current update policy - **/ -GtkUpdateType -gtk_range_get_update_policy (GtkRange *range) -{ - g_return_val_if_fail (GTK_IS_RANGE (range), GTK_UPDATE_CONTINUOUS); - - return range->priv->update_policy; -} - /** * gtk_range_set_adjustment: * @range: a #GtkRange @@ -968,7 +931,7 @@ gtk_range_get_flippable (GtkRange *range) * @size_fixed: %TRUE to make the slider size constant * * Sets whether the range's slider has a fixed size, or a size that - * depends on it's adjustment's page size. + * depends on its adjustment's page size. * * This function is useful mainly for #GtkRange subclasses. * @@ -1046,7 +1009,7 @@ gtk_range_set_min_slider_size (GtkRange *range, if (gtk_widget_is_drawable (GTK_WIDGET (range))) { priv->need_recalc = TRUE; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); gtk_widget_queue_draw (GTK_WIDGET (range)); } } @@ -1075,7 +1038,7 @@ gtk_range_get_min_slider_size (GtkRange *range) /** * gtk_range_get_range_rect: * @range: a #GtkRange - * @range_rect: return location for the range rectangle + * @range_rect: (out): return location for the range rectangle * * This function returns the area that contains the range's trough * and its steppers, in widget->window coordinates. @@ -1095,7 +1058,7 @@ gtk_range_get_range_rect (GtkRange *range, priv = range->priv; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); *range_rect = priv->range_rect; } @@ -1103,8 +1066,10 @@ gtk_range_get_range_rect (GtkRange *range, /** * gtk_range_get_slider_range: * @range: a #GtkRange - * @slider_start: (allow-none): return location for the slider's start, or %NULL - * @slider_end: (allow-none): return location for the slider's end, or %NULL + * @slider_start: (out) (allow-none): return location for the slider's + * start, or %NULL + * @slider_end: (out) (allow-none): return location for the slider's + * end, or %NULL * * This function returns sliders range along the long dimension, * in widget->window coordinates. @@ -1124,7 +1089,7 @@ gtk_range_get_slider_range (GtkRange *range, priv = range->priv; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); if (slider_start) *slider_start = priv->slider_start; @@ -1158,7 +1123,7 @@ gtk_range_set_lower_stepper_sensitivity (GtkRange *range, priv->lower_sensitivity = sensitivity; priv->need_recalc = TRUE; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); gtk_widget_queue_draw (GTK_WIDGET (range)); g_object_notify (G_OBJECT (range), "lower-stepper-sensitivity"); @@ -1209,7 +1174,7 @@ gtk_range_set_upper_stepper_sensitivity (GtkRange *range, priv->upper_sensitivity = sensitivity; priv->need_recalc = TRUE; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); gtk_widget_queue_draw (GTK_WIDGET (range)); g_object_notify (G_OBJECT (range), "upper-stepper-sensitivity"); @@ -1251,16 +1216,19 @@ gtk_range_set_increments (GtkRange *range, gdouble step, gdouble page) { - GtkRangePrivate *priv; + GtkAdjustment *adjustment; g_return_if_fail (GTK_IS_RANGE (range)); - priv = range->priv; - - priv->adjustment->step_increment = step; - priv->adjustment->page_increment = page; + adjustment = range->priv->adjustment; - gtk_adjustment_changed (priv->adjustment); + gtk_adjustment_configure (adjustment, + gtk_adjustment_get_value (adjustment), + gtk_adjustment_get_lower (adjustment), + gtk_adjustment_get_upper (adjustment), + step, + page, + gtk_adjustment_get_page_size (adjustment)); } /** @@ -1279,24 +1247,27 @@ gtk_range_set_range (GtkRange *range, gdouble max) { GtkRangePrivate *priv; + GtkAdjustment *adjustment; gdouble value; g_return_if_fail (GTK_IS_RANGE (range)); g_return_if_fail (min <= max); priv = range->priv; + adjustment = priv->adjustment; - priv->adjustment->lower = min; - priv->adjustment->upper = max; - - value = priv->adjustment->value; - + value = gtk_adjustment_get_value (adjustment); if (priv->restrict_to_fill_level) - value = MIN (value, MAX (priv->adjustment->lower, + value = MIN (value, MAX (gtk_adjustment_get_lower (adjustment), priv->fill_level)); - gtk_adjustment_set_value (priv->adjustment, value); - gtk_adjustment_changed (priv->adjustment); + gtk_adjustment_configure (adjustment, + value, + min, + max, + gtk_adjustment_get_step_increment (adjustment), + gtk_adjustment_get_page_increment (adjustment), + gtk_adjustment_get_page_size (adjustment)); } /** @@ -1320,7 +1291,7 @@ gtk_range_set_value (GtkRange *range, priv = range->priv; if (priv->restrict_to_fill_level) - value = MIN (value, MAX (priv->adjustment->lower, + value = MIN (value, MAX (gtk_adjustment_get_lower (priv->adjustment), priv->fill_level)); gtk_adjustment_set_value (priv->adjustment, value); @@ -1339,7 +1310,7 @@ gtk_range_get_value (GtkRange *range) { g_return_val_if_fail (GTK_IS_RANGE (range), 0.0); - return range->priv->adjustment->value; + return gtk_adjustment_get_value (range->priv->adjustment); } /** @@ -1528,11 +1499,6 @@ gtk_range_destroy (GtkWidget *widget) GtkRangePrivate *priv = range->priv; gtk_range_remove_step_timer (range); - gtk_range_remove_update_timer (range); - - if (priv->repaint_id) - g_source_remove (priv->repaint_id); - priv->repaint_id = 0; if (priv->adjustment) { @@ -1655,7 +1621,7 @@ modify_allocation_for_window_grip (GtkWidget *widget, translated_rect = *allocation; else { - gtk_widget_translate_coordinates (gtk_widget_get_parent (widget), + gtk_widget_translate_coordinates (parent, window, allocation->x, allocation->y, &x, &y); @@ -1666,7 +1632,7 @@ modify_allocation_for_window_grip (GtkWidget *widget, } /* If the stepper button intersects the window resize grip.. */ - if (gdk_rectangle_intersect (&grip_rect, &translated_rect, NULL)) + if (gdk_rectangle_intersect (&grip_rect, &translated_rect, &grip_rect)) { if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { @@ -1698,7 +1664,7 @@ gtk_range_size_allocate (GtkWidget *widget, priv->recalc_marks = TRUE; priv->need_recalc = TRUE; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); if (gtk_widget_get_realized (widget)) gdk_window_move_resize (priv->event_window, @@ -1725,7 +1691,7 @@ gtk_range_hierarchy_changed (GtkWidget *widget, G_CALLBACK (resize_grip_visible_changed), widget); window = gtk_widget_get_toplevel (widget); - if (GTK_IS_WINDOW (window)) + if (gtk_widget_is_toplevel (window)) g_signal_connect (window, "notify::resize-grip-visible", G_CALLBACK (resize_grip_visible_changed), widget); } @@ -1740,7 +1706,7 @@ gtk_range_realize (GtkWidget *widget) GdkWindowAttr attributes; gint attributes_mask; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); gtk_widget_set_realized (widget, TRUE); @@ -1760,9 +1726,11 @@ gtk_range_realize (GtkWidget *widget) attributes.wclass = GDK_INPUT_ONLY; attributes.event_mask = gtk_widget_get_events (widget); attributes.event_mask |= (GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_SCROLL_MASK | + GDK_SMOOTH_SCROLL_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); @@ -1770,7 +1738,7 @@ gtk_range_realize (GtkWidget *widget) priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); - gdk_window_set_user_data (priv->event_window, range); + gtk_widget_register_window (widget, priv->event_window); } static void @@ -1780,9 +1748,8 @@ gtk_range_unrealize (GtkWidget *widget) GtkRangePrivate *priv = range->priv; gtk_range_remove_step_timer (range); - gtk_range_remove_update_timer (range); - gdk_window_set_user_data (priv->event_window, NULL); + gtk_widget_unregister_window (widget, priv->event_window); gdk_window_destroy (priv->event_window); priv->event_window = NULL; @@ -1880,7 +1847,6 @@ _gtk_range_update_context_for_stepper (GtkRange *range, } gtk_style_context_set_junction_sides (context, sides); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON); } static void @@ -1889,18 +1855,17 @@ draw_stepper (GtkRange *range, cairo_t *cr, GtkArrowType arrow_type, gboolean clicked, - gboolean prelighted) + gboolean prelighted, + GtkStateFlags state) { GtkRangePrivate *priv = range->priv; GtkAllocation allocation; - GtkStateFlags state = 0; GtkStyleContext *context; GtkWidget *widget = GTK_WIDGET (range); - GdkWindow *window; gfloat arrow_scaling; GdkRectangle *rect; - gint arrow_x; - gint arrow_y; + gdouble arrow_x; + gdouble arrow_y; gdouble arrow_size, angle; gboolean arrow_sensitive; @@ -1938,8 +1903,12 @@ draw_stepper (GtkRange *range, arrow_sensitive = priv->lower_sensitive; } - if (!gtk_widget_is_sensitive (GTK_WIDGET (range)) || !arrow_sensitive) - state = GTK_STATE_FLAG_INSENSITIVE; + state &= ~(GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT); + + if ((state & GTK_STATE_FLAG_INSENSITIVE) || !arrow_sensitive) + { + state |= GTK_STATE_FLAG_INSENSITIVE; + } else { if (clicked) @@ -1948,13 +1917,36 @@ draw_stepper (GtkRange *range, state |= GTK_STATE_FLAG_PRELIGHT; } - window = gtk_widget_get_window (widget); context = gtk_widget_get_style_context (widget); gtk_style_context_save (context); - _gtk_range_update_context_for_stepper (range, context, stepper); + + /* don't set juction sides on scrollbar steppers */ + if (gtk_style_context_has_class (context, GTK_STYLE_CLASS_SCROLLBAR)) + gtk_style_context_set_junction_sides (context, GTK_JUNCTION_NONE); + else + _gtk_range_update_context_for_stepper (range, context, stepper); + + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON); gtk_style_context_set_state (context, state); + switch (arrow_type) + { + case GTK_ARROW_RIGHT: + gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT); + break; + case GTK_ARROW_DOWN: + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM); + break; + case GTK_ARROW_LEFT: + gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT); + break; + case GTK_ARROW_UP: + default: + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP); + break; + } + gtk_render_background (context, cr, rect->x, rect->y, rect->width, rect->height); @@ -1975,8 +1967,8 @@ draw_stepper (GtkRange *range, gtk_range_get_props (GTK_RANGE (widget), NULL, NULL, NULL, NULL, NULL, NULL, - &arrow_displacement_x, &arrow_displacement_y); - + &arrow_displacement_x, &arrow_displacement_y); + arrow_x += arrow_displacement_x; arrow_y += arrow_displacement_y; } @@ -2007,28 +1999,32 @@ draw_stepper (GtkRange *range, } static gboolean -gtk_range_draw (GtkWidget *widget, - cairo_t *cr) +gtk_range_draw (GtkWidget *widget, + cairo_t *cr) { GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = range->priv; - gboolean sensitive; - GtkStateFlags state = 0; - GdkWindow *window; + GtkStateFlags widget_state; gint focus_line_width = 0; gint focus_padding = 0; - gboolean touchscreen; gboolean draw_trough = TRUE; + gboolean draw_slider = TRUE; GtkStyleContext *context; + GtkBorder margin; context = gtk_widget_get_style_context (widget); - g_object_get (gtk_widget_get_settings (widget), - "gtk-touchscreen-mode", &touchscreen, - NULL); if (GTK_IS_SCALE (widget) && - priv->adjustment->upper == priv->adjustment->lower) - draw_trough = FALSE; + gtk_adjustment_get_upper (priv->adjustment) == gtk_adjustment_get_lower (priv->adjustment)) + { + draw_trough = TRUE; + draw_slider = FALSE; + } + if (GTK_IS_COLOR_SCALE (widget)) + { + draw_trough = FALSE; + draw_slider = TRUE; + } if (gtk_widget_get_can_focus (GTK_WIDGET (range))) gtk_widget_style_get (GTK_WIDGET (range), @@ -2036,17 +2032,10 @@ gtk_range_draw (GtkWidget *widget, "focus-padding", &focus_padding, NULL); - window = gtk_widget_get_window (widget); - - /* we're now exposing, so there's no need to force early repaints */ - if (priv->repaint_id) - g_source_remove (priv->repaint_id); - priv->repaint_id = 0; - gtk_range_calc_marks (range); - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); - sensitive = gtk_widget_is_sensitive (widget); + widget_state = gtk_widget_get_state_flags (widget); /* Just to be confusing, we draw the trough for the whole * range rectangle, not the trough rectangle (the trough @@ -2075,14 +2064,6 @@ gtk_range_draw (GtkWidget *widget, "stepper-spacing", &stepper_spacing, NULL); - gtk_style_context_save (context); - - if (!sensitive) - gtk_style_context_set_state (context, GTK_STATE_FLAG_INSENSITIVE); - - if (stepper_spacing > 0) - trough_under_steppers = FALSE; - if (!trough_under_steppers) { gint offset = 0; @@ -2123,148 +2104,180 @@ gtk_range_draw (GtkWidget *widget, y += offset; height -= shorter; } - } + } gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); + gtk_style_context_get_margin (context, widget_state, &margin); + + x += margin.left; + y += margin.top; + width -= margin.left + margin.right; + height -= margin.top + margin.bottom; if (draw_trough) { - gint trough_change_pos_x = width; - gint trough_change_pos_y = height; - - if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) - trough_change_pos_x = (priv->slider.x + - priv->slider.width / 2 - - x); - else - trough_change_pos_y = (priv->slider.y + - priv->slider.height / 2 - - y); - - /* FIXME: was trough-upper and trough-lower really used, - * in that case, it should still be exposed somehow. - */ - gtk_render_background (context, cr, x, y, - trough_change_pos_x, - trough_change_pos_y); - - if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) - trough_change_pos_y = 0; - else - trough_change_pos_x = 0; - - gtk_render_background (context, cr, - x + trough_change_pos_x, y + trough_change_pos_y, - width - trough_change_pos_x, - height - trough_change_pos_y); - - gtk_render_frame (context, cr, - x, y, width, height); - } - else - { - gtk_render_background (context, cr, - x, y, width, height); - gtk_render_frame (context, cr, - x, y, width, height); + if (!priv->has_origin || !draw_slider) + { + gtk_render_background (context, cr, + x, y, width, height); + + gtk_render_frame (context, cr, + x, y, width, height); + } + else + { + gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; + + gint trough_change_pos_x = width; + gint trough_change_pos_y = height; + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + trough_change_pos_x = (priv->slider.x + + priv->slider.width / 2 - + x); + else + trough_change_pos_y = (priv->slider.y + + priv->slider.height / 2 - + y); + + gtk_style_context_save (context); + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT); + + if (!is_rtl) + gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT); + } + else + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP); + + gtk_render_background (context, cr, x, y, + trough_change_pos_x, + trough_change_pos_y); + + gtk_render_frame (context, cr, x, y, + trough_change_pos_x, + trough_change_pos_y); + + gtk_style_context_restore (context); + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + trough_change_pos_y = 0; + else + trough_change_pos_x = 0; + + gtk_style_context_save (context); + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT); + + if (is_rtl) + gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT); + } + else + { + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT); + } + + gtk_render_background (context, cr, + x + trough_change_pos_x, y + trough_change_pos_y, + width - trough_change_pos_x, + height - trough_change_pos_y); + + gtk_render_frame (context, cr, + x + trough_change_pos_x, y + trough_change_pos_y, + width - trough_change_pos_x, + height - trough_change_pos_y); + + gtk_style_context_restore (context); + } } gtk_style_context_restore (context); if (priv->show_fill_level && - priv->adjustment->upper - priv->adjustment->page_size - - priv->adjustment->lower != 0) - { + gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) - + gtk_adjustment_get_lower (priv->adjustment) != 0) + { gdouble fill_level = priv->fill_level; - gint fill_x = x; - gint fill_y = y; - gint fill_width = width; - gint fill_height = height; - gchar *fill_detail; + gint fill_x = x; + gint fill_y = y; + gint fill_width = width; + gint fill_height = height; gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR); - fill_level = CLAMP (fill_level, priv->adjustment->lower, - priv->adjustment->upper - - priv->adjustment->page_size); - - if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) - { - fill_x = priv->trough.x; - fill_width = (priv->slider.width + - (fill_level - priv->adjustment->lower) / - (priv->adjustment->upper - - priv->adjustment->lower - - priv->adjustment->page_size) * + fill_level = CLAMP (fill_level, gtk_adjustment_get_lower (priv->adjustment), + gtk_adjustment_get_upper (priv->adjustment) - + gtk_adjustment_get_page_size (priv->adjustment)); + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + fill_x = priv->trough.x; + fill_width = (priv->slider.width + + (fill_level - gtk_adjustment_get_lower (priv->adjustment)) / + (gtk_adjustment_get_upper (priv->adjustment) - + gtk_adjustment_get_lower (priv->adjustment) - + gtk_adjustment_get_page_size (priv->adjustment)) * (priv->trough.width - priv->slider.width)); if (should_invert (range)) fill_x += priv->trough.width - fill_width; - } - else - { - fill_y = priv->trough.y; - fill_height = (priv->slider.height + - (fill_level - priv->adjustment->lower) / - (priv->adjustment->upper - - priv->adjustment->lower - - priv->adjustment->page_size) * + } + else + { + fill_y = priv->trough.y; + fill_height = (priv->slider.height + + (fill_level - gtk_adjustment_get_lower (priv->adjustment)) / + (gtk_adjustment_get_upper (priv->adjustment) - + gtk_adjustment_get_lower (priv->adjustment) - + gtk_adjustment_get_page_size (priv->adjustment)) * (priv->trough.height - priv->slider.height)); if (should_invert (range)) fill_y += priv->trough.height - fill_height; - } - - if (fill_level < priv->adjustment->upper - priv->adjustment->page_size) - fill_detail = "trough-fill-level-full"; - else - fill_detail = "trough-fill-level"; + } gtk_render_activity (context, cr, fill_x, fill_y, fill_width, fill_height); gtk_style_context_restore (context); - } - - gtk_style_context_restore (context); + } - if (sensitive && gtk_widget_has_focus (widget)) + if (!(widget_state & GTK_STATE_FLAG_INSENSITIVE) && gtk_widget_has_visible_focus (widget)) { - gtk_style_context_save (context); - gtk_style_context_set_state (context, - gtk_widget_get_state_flags (widget)); - gtk_render_focus (context, cr, priv->range_rect.x, priv->range_rect.y, priv->range_rect.width, priv->range_rect.height); - - gtk_style_context_restore (context); } } cairo_restore (cr); - if (!sensitive) - state = GTK_STATE_FLAG_INSENSITIVE; - else if (!touchscreen && priv->mouse_location == MOUSE_SLIDER) - state = GTK_STATE_FLAG_PRELIGHT; + if (draw_slider) + { + GtkStateFlags state = widget_state; - if (priv->grab_location == MOUSE_SLIDER) - state |= GTK_STATE_FLAG_ACTIVE; + state &= ~(GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_ACTIVE); - cairo_save (cr); - gdk_cairo_rectangle (cr, &priv->slider); - cairo_clip (cr); + if (priv->mouse_location == MOUSE_SLIDER && !(state & GTK_STATE_FLAG_INSENSITIVE)) + state |= GTK_STATE_FLAG_PRELIGHT; + + if (priv->grab_location == MOUSE_SLIDER) + state |= GTK_STATE_FLAG_ACTIVE; + + cairo_save (cr); + gdk_cairo_rectangle (cr, &priv->slider); + cairo_clip (cr); - if (draw_trough) - { gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_set_state (context, state); @@ -2277,34 +2290,38 @@ gtk_range_draw (GtkWidget *widget, priv->orientation); gtk_style_context_restore (context); - } - cairo_restore (cr); + cairo_restore (cr); + } if (priv->has_stepper_a) draw_stepper (range, STEPPER_A, cr, priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_UP : GTK_ARROW_LEFT, priv->grab_location == MOUSE_STEPPER_A, - !touchscreen && priv->mouse_location == MOUSE_STEPPER_A); + priv->mouse_location == MOUSE_STEPPER_A, + widget_state); if (priv->has_stepper_b) draw_stepper (range, STEPPER_B, cr, priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT, priv->grab_location == MOUSE_STEPPER_B, - !touchscreen && priv->mouse_location == MOUSE_STEPPER_B); + priv->mouse_location == MOUSE_STEPPER_B, + widget_state); if (priv->has_stepper_c) draw_stepper (range, STEPPER_C, cr, priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_UP : GTK_ARROW_LEFT, priv->grab_location == MOUSE_STEPPER_C, - !touchscreen && priv->mouse_location == MOUSE_STEPPER_C); + priv->mouse_location == MOUSE_STEPPER_C, + widget_state); if (priv->has_stepper_d) draw_stepper (range, STEPPER_D, cr, priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT, priv->grab_location == MOUSE_STEPPER_D, - !touchscreen && priv->mouse_location == MOUSE_STEPPER_D); - + priv->mouse_location == MOUSE_STEPPER_D, + widget_state); + return FALSE; } @@ -2319,15 +2336,11 @@ range_grab_add (GtkRange *range, if (device == priv->grab_device) return; - if (priv->grab_device != NULL) - { - g_warning ("GtkRange already had a grab device, releasing device grab"); - gtk_device_grab_remove (GTK_WIDGET (range), priv->grab_device); - } - - /* we don't actually gdk_grab, since a button is down */ - gtk_device_grab_add (GTK_WIDGET (range), device, TRUE); - + /* Don't perform any GDK/GTK+ grab here. Since a button + * is down, there's an ongoing implicit grab on + * priv->event_window, which pretty much guarantees this + * is the only widget receiving the pointer events. + */ priv->grab_location = location; priv->grab_button = button; priv->grab_device = device; @@ -2344,9 +2357,10 @@ range_grab_remove (GtkRange *range) if (priv->grab_device) { - gtk_device_grab_remove (GTK_WIDGET (range), - priv->grab_device); + GdkDevice *grab_device = priv->grab_device; + priv->grab_device = NULL; + gtk_device_grab_remove (GTK_WIDGET (range), grab_device); } location = priv->grab_location; @@ -2356,6 +2370,8 @@ range_grab_remove (GtkRange *range) if (gtk_range_update_mouse_location (range) || location != MOUSE_OUTSIDE) gtk_widget_queue_draw (GTK_WIDGET (range)); + + priv->zoom = FALSE; } static GtkScrollType @@ -2372,13 +2388,13 @@ range_get_scroll_for_grab (GtkRange *range) case MOUSE_STEPPER_C: switch (priv->grab_button) { - case 1: + case GDK_BUTTON_PRIMARY: return invert ? GTK_SCROLL_STEP_FORWARD : GTK_SCROLL_STEP_BACKWARD; break; - case 2: + case GDK_BUTTON_MIDDLE: return invert ? GTK_SCROLL_PAGE_FORWARD : GTK_SCROLL_PAGE_BACKWARD; break; - case 3: + case GDK_BUTTON_SECONDARY: return invert ? GTK_SCROLL_END : GTK_SCROLL_START; break; } @@ -2389,13 +2405,13 @@ range_get_scroll_for_grab (GtkRange *range) case MOUSE_STEPPER_D: switch (priv->grab_button) { - case 1: + case GDK_BUTTON_PRIMARY: return invert ? GTK_SCROLL_STEP_BACKWARD : GTK_SCROLL_STEP_FORWARD; break; - case 2: + case GDK_BUTTON_MIDDLE: return invert ? GTK_SCROLL_PAGE_BACKWARD : GTK_SCROLL_PAGE_FORWARD; break; - case 3: + case GDK_BUTTON_SECONDARY: return invert ? GTK_SCROLL_START : GTK_SCROLL_END; break; } @@ -2422,7 +2438,7 @@ range_get_scroll_for_grab (GtkRange *range) static gdouble coord_to_value (GtkRange *range, - gint coord) + gdouble coord) { GtkRangePrivate *priv = range->priv; gdouble frac; @@ -2464,9 +2480,9 @@ coord_to_value (GtkRange *range, if (should_invert (range)) frac = 1.0 - frac; - value = priv->adjustment->lower + frac * (priv->adjustment->upper - - priv->adjustment->lower - - priv->adjustment->page_size); + value = gtk_adjustment_get_lower (priv->adjustment) + frac * (gtk_adjustment_get_upper (priv->adjustment) - + gtk_adjustment_get_lower (priv->adjustment) - + gtk_adjustment_get_page_size (priv->adjustment)); return value; } @@ -2504,7 +2520,10 @@ gtk_range_button_press (GtkWidget *widget, { GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = range->priv; - GdkDevice *device; + GdkDevice *device, *source_device; + GdkInputSource source; + gboolean primary_warps; + gint page_increment_button, warp_button; if (!gtk_widget_has_focus (widget)) gtk_widget_grab_focus (widget); @@ -2514,29 +2533,57 @@ gtk_range_button_press (GtkWidget *widget, return FALSE; device = gdk_event_get_device ((GdkEvent *) event); + source_device = gdk_event_get_source_device ((GdkEvent *) event); + source = gdk_device_get_source (source_device); + priv->mouse_x = event->x; priv->mouse_y = event->y; if (gtk_range_update_mouse_location (range)) gtk_widget_queue_draw (widget); - if (priv->mouse_location == MOUSE_TROUGH && - event->button == 1) + g_object_get (gtk_widget_get_settings (widget), + "gtk-primary-button-warps-slider", &primary_warps, + NULL); + if (primary_warps) + { + warp_button = GDK_BUTTON_PRIMARY; + page_increment_button = GDK_BUTTON_SECONDARY; + } + else + { + warp_button = GDK_BUTTON_MIDDLE; + page_increment_button = GDK_BUTTON_PRIMARY; + } + + if (priv->mouse_location == MOUSE_SLIDER && + gdk_event_triggers_context_menu ((GdkEvent *)event)) { - /* button 1 steps by page increment, as with button 2 on a stepper + gboolean handled; + + g_signal_emit_by_name (widget, "popup-menu", &handled); + + return TRUE; + } + + if (source != GDK_SOURCE_TOUCHSCREEN && + priv->mouse_location == MOUSE_TROUGH && + event->button == page_increment_button) + { + /* button 2 steps by page increment, as with button 2 on a stepper */ GtkScrollType scroll; gdouble click_value; - + click_value = coord_to_value (range, priv->orientation == GTK_ORIENTATION_VERTICAL ? event->y : event->x); - priv->trough_click_forward = click_value > priv->adjustment->value; + priv->trough_click_forward = click_value > gtk_adjustment_get_value (priv->adjustment); range_grab_add (range, device, MOUSE_TROUGH, event->button); - + scroll = range_get_scroll_for_grab (range); - + gtk_range_add_step_timer (range, scroll); return TRUE; @@ -2545,7 +2592,9 @@ gtk_range_button_press (GtkWidget *widget, priv->mouse_location == MOUSE_STEPPER_B || priv->mouse_location == MOUSE_STEPPER_C || priv->mouse_location == MOUSE_STEPPER_D) && - (event->button == 1 || event->button == 2 || event->button == 3)) + (event->button == GDK_BUTTON_PRIMARY || + event->button == GDK_BUTTON_MIDDLE || + event->button == GDK_BUTTON_SECONDARY)) { GtkAllocation allocation; GdkRectangle *stepper_area; @@ -2569,17 +2618,17 @@ gtk_range_button_press (GtkWidget *widget, return TRUE; } else if ((priv->mouse_location == MOUSE_TROUGH && - event->button == 2) || + (source == GDK_SOURCE_TOUCHSCREEN || + event->button == warp_button)) || priv->mouse_location == MOUSE_SLIDER) { gboolean need_value_update = FALSE; /* Any button can be used to drag the slider, but you can start - * dragging the slider with a trough click using button 2; - * On button 2 press, we warp the slider to mouse position, - * then begin the slider drag. + * dragging the slider with a trough click using button 1; + * we warp the slider to mouse position, then begin the slider drag. */ - if (event->button == 2) + if (priv->mouse_location != MOUSE_SLIDER) { gdouble slider_low_value, slider_high_value, new_value; @@ -2607,6 +2656,12 @@ gtk_range_button_press (GtkWidget *widget, */ need_value_update = TRUE; } + else + { + /* Shift-click in the slider = fine adjustment */ + if (event->state & GDK_SHIFT_MASK) + priv->zoom = TRUE; + } if (priv->orientation == GTK_ORIENTATION_VERTICAL) { @@ -2639,13 +2694,14 @@ update_slider_position (GtkRange *range, gint mouse_y) { GtkRangePrivate *priv = range->priv; - gint delta; - gint c; + gdouble delta; + gdouble c; gdouble new_value; gboolean handled; gdouble next_value; gdouble mark_value; gdouble mark_delta; + gdouble zoom; gint i; if (priv->orientation == GTK_ORIENTATION_VERTICAL) @@ -2653,17 +2709,31 @@ update_slider_position (GtkRange *range, else delta = mouse_x - priv->slide_initial_coordinate; - c = priv->slide_initial_slider_position + delta; + if (priv->zoom) + { + zoom = MIN(1.0, (priv->orientation == GTK_ORIENTATION_VERTICAL ? + priv->trough.height : priv->trough.width) / + (gtk_adjustment_get_upper (priv->adjustment) - + gtk_adjustment_get_lower (priv->adjustment) - + gtk_adjustment_get_page_size (priv->adjustment))); + /* the above is ineffective for scales, so just set a zoom factor */ + if (zoom == 1.0) + zoom = 0.25; + } + else + zoom = 1.0; + + c = priv->slide_initial_slider_position + zoom * delta; new_value = coord_to_value (range, c); next_value = coord_to_value (range, c + 1); - mark_delta = fabs (next_value - new_value); + mark_delta = fabs (next_value - new_value); for (i = 0; i < priv->n_marks; i++) { mark_value = priv->marks[i]; - if (fabs (priv->adjustment->value - mark_value) < 3 * mark_delta) + if (fabs (gtk_adjustment_get_value (priv->adjustment) - mark_value) < 3 * mark_delta) { if (fabs (new_value - mark_value) < (priv->slider_end - priv->slider_start) * 0.5 * mark_delta) { @@ -2671,19 +2741,17 @@ update_slider_position (GtkRange *range, break; } } - } + } g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_JUMP, new_value, &handled); } -static void +static void stop_scrolling (GtkRange *range) { range_grab_remove (range); gtk_range_remove_step_timer (range); - /* Flush any pending discontinuous/delayed updates */ - gtk_range_update_value (range); } static gboolean @@ -2700,7 +2768,7 @@ gtk_range_grab_broken (GtkWidget *widget, priv->grab_location != MOUSE_OUTSIDE) { if (priv->grab_location == MOUSE_SLIDER) - update_slider_position (range, priv->mouse_x, priv->mouse_y); + update_slider_position (range, priv->mouse_x, priv->mouse_y); stop_scrolling (range); @@ -2751,37 +2819,57 @@ gtk_range_button_release (GtkWidget *widget, /** * _gtk_range_get_wheel_delta: * @range: a #GtkRange - * @direction: A #GdkScrollDirection - * + * @event: A #GdkEventScroll + * * Returns a good step value for the mouse wheel. - * - * Return value: A good step value for the mouse wheel. - * + * + * Return value: A good step value for the mouse wheel. + * * Since: 2.4 **/ gdouble -_gtk_range_get_wheel_delta (GtkRange *range, - GdkScrollDirection direction) +_gtk_range_get_wheel_delta (GtkRange *range, + GdkEventScroll *event) { GtkRangePrivate *priv = range->priv; - GtkAdjustment *adj = priv->adjustment; + GtkAdjustment *adjustment = priv->adjustment; + gdouble dx, dy; gdouble delta; + gdouble page_size; + gdouble page_increment; + gdouble scroll_unit; + + page_size = gtk_adjustment_get_page_size (adjustment); + page_increment = gtk_adjustment_get_page_increment (adjustment); if (GTK_IS_SCROLLBAR (range)) - delta = pow (adj->page_size, 2.0 / 3.0); + scroll_unit = pow (page_size, 2.0 / 3.0); else - delta = adj->step_increment * 2; - - if (direction == GDK_SCROLL_UP || - direction == GDK_SCROLL_LEFT) - delta = - delta; - + scroll_unit = page_increment; + + if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &dx, &dy)) + { + if (dx != 0 && + gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL) + delta = dx * scroll_unit; + else + delta = dy * scroll_unit; + } + else + { + if (event->direction == GDK_SCROLL_UP || + event->direction == GDK_SCROLL_LEFT) + delta = - scroll_unit; + else + delta = scroll_unit; + } + if (priv->inverted) delta = - delta; return delta; } - + static gboolean gtk_range_scroll_event (GtkWidget *widget, GdkEventScroll *event) @@ -2791,22 +2879,14 @@ gtk_range_scroll_event (GtkWidget *widget, if (gtk_widget_get_realized (widget)) { - GtkAdjustment *adj = priv->adjustment; gdouble delta; gboolean handled; - delta = _gtk_range_get_wheel_delta (range, event->direction); + delta = _gtk_range_get_wheel_delta (range, event); g_signal_emit (range, signals[CHANGE_VALUE], 0, - GTK_SCROLL_JUMP, adj->value + delta, + GTK_SCROLL_JUMP, gtk_adjustment_get_value (priv->adjustment) + delta, &handled); - - /* Policy DELAYED makes sense with scroll events, - * but DISCONTINUOUS doesn't, so we update immediately - * for DISCONTINUOUS - */ - if (priv->update_policy == GTK_UPDATE_DISCONTINUOUS) - gtk_range_update_value (range); } return TRUE; @@ -2920,7 +3000,7 @@ gtk_range_adjustment_changed (GtkAdjustment *adjustment, priv->recalc_marks = TRUE; priv->need_recalc = TRUE; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); /* now check whether the layout changed */ if (layout_changed (priv, &priv_aux)) @@ -2935,20 +3015,6 @@ gtk_range_adjustment_changed (GtkAdjustment *adjustment, */ } -static gboolean -force_repaint (gpointer data) -{ - GtkRange *range = GTK_RANGE (data); - GtkRangePrivate *priv = range->priv; - GtkWidget *widget = GTK_WIDGET (range); - - priv->repaint_id = 0; - if (gtk_widget_is_drawable (widget)) - gdk_window_process_updates (gtk_widget_get_window (widget), FALSE); - - return FALSE; -} - static void gtk_range_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data) @@ -2958,20 +3024,15 @@ gtk_range_adjustment_value_changed (GtkAdjustment *adjustment, GtkRangePrivate priv_aux = *priv; priv->need_recalc = TRUE; - gtk_range_calc_layout (range, priv->adjustment->value); + gtk_range_calc_layout (range, gtk_adjustment_get_value (priv->adjustment)); /* now check whether the layout changed */ if (layout_changed (priv, &priv_aux) || (GTK_IS_SCALE (range) && gtk_scale_get_draw_value (GTK_SCALE (range)))) { gtk_widget_queue_draw (GTK_WIDGET (range)); - /* setup a timer to ensure the range isn't lagging too much behind the scroll position */ - if (!priv->repaint_id) - priv->repaint_id = gdk_threads_add_timeout_full (GDK_PRIORITY_EVENTS, - 181, force_repaint, - range, NULL); } - + /* Note that we don't round off to priv->round_digits here. * that's because it's really broken to change a value * in response to a change signal on that value; round_digits @@ -3022,8 +3083,8 @@ step_back (GtkRange *range) gdouble newval; gboolean handled; - newval = priv->adjustment->value - priv->adjustment->step_increment; - apply_marks (range, priv->adjustment->value, &newval); + newval = gtk_adjustment_get_value (priv->adjustment) - gtk_adjustment_get_step_increment (priv->adjustment); + apply_marks (range, gtk_adjustment_get_value (priv->adjustment), &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_STEP_BACKWARD, newval, &handled); } @@ -3035,8 +3096,8 @@ step_forward (GtkRange *range) gdouble newval; gboolean handled; - newval = priv->adjustment->value + priv->adjustment->step_increment; - apply_marks (range, priv->adjustment->value, &newval); + newval = gtk_adjustment_get_value (priv->adjustment) + gtk_adjustment_get_step_increment (priv->adjustment); + apply_marks (range, gtk_adjustment_get_value (priv->adjustment), &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_STEP_FORWARD, newval, &handled); } @@ -3049,8 +3110,8 @@ page_back (GtkRange *range) gdouble newval; gboolean handled; - newval = priv->adjustment->value - priv->adjustment->page_increment; - apply_marks (range, priv->adjustment->value, &newval); + newval = gtk_adjustment_get_value (priv->adjustment) - gtk_adjustment_get_page_increment (priv->adjustment); + apply_marks (range, gtk_adjustment_get_value (priv->adjustment), &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_PAGE_BACKWARD, newval, &handled); } @@ -3062,8 +3123,8 @@ page_forward (GtkRange *range) gdouble newval; gboolean handled; - newval = priv->adjustment->value + priv->adjustment->page_increment; - apply_marks (range, priv->adjustment->value, &newval); + newval = gtk_adjustment_get_value (priv->adjustment) + gtk_adjustment_get_page_increment (priv->adjustment); + apply_marks (range, gtk_adjustment_get_value (priv->adjustment), &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_PAGE_FORWARD, newval, &handled); } @@ -3075,7 +3136,7 @@ scroll_begin (GtkRange *range) gboolean handled; g_signal_emit (range, signals[CHANGE_VALUE], 0, - GTK_SCROLL_START, priv->adjustment->lower, + GTK_SCROLL_START, gtk_adjustment_get_lower (priv->adjustment), &handled); } @@ -3086,7 +3147,7 @@ scroll_end (GtkRange *range) gdouble newval; gboolean handled; - newval = priv->adjustment->upper - priv->adjustment->page_size; + newval = gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_END, newval, &handled); } @@ -3096,7 +3157,7 @@ gtk_range_scroll (GtkRange *range, GtkScrollType scroll) { GtkRangePrivate *priv = range->priv; - gdouble old_value = priv->adjustment->value; + gdouble old_value = gtk_adjustment_get_value (priv->adjustment); switch (scroll) { @@ -3188,7 +3249,7 @@ gtk_range_scroll (GtkRange *range, break; } - return priv->adjustment->value != old_value; + return gtk_adjustment_get_value (priv->adjustment) != old_value; } static void @@ -3234,13 +3295,6 @@ gtk_range_move_slider (GtkRange *range, if (! gtk_range_scroll (range, scroll)) gtk_widget_error_bell (GTK_WIDGET (range)); - - /* Policy DELAYED makes sense with key events, - * but DISCONTINUOUS doesn't, so we update immediately - * for DISCONTINUOUS - */ - if (priv->update_policy == GTK_UPDATE_DISCONTINUOUS) - gtk_range_update_value (range); } static void @@ -3269,9 +3323,6 @@ gtk_range_get_props (GtkRange *range, "arrow-displacement-y", &tmp_arrow_displacement_y, NULL); - if (tmp_stepper_spacing > 0) - tmp_trough_under_steppers = FALSE; - if (gtk_widget_get_can_focus (GTK_WIDGET (range))) { gint focus_line_width; @@ -3548,13 +3599,15 @@ gtk_range_calc_layout (GtkRange *range, GtkRangePrivate *priv = range->priv; gint slider_width, stepper_size, focus_width, trough_border, stepper_spacing; gint slider_length; - GtkBorder border; + GtkBorder border, trough_margin; gint n_steppers; gboolean has_steppers_ab; gboolean has_steppers_cd; gboolean trough_under_steppers; GdkRectangle range_rect; GtkWidget *widget; + GtkStyleContext *context; + GtkStateFlags state; if (!priv->need_recalc) return; @@ -3570,6 +3623,13 @@ gtk_range_calc_layout (GtkRange *range, */ widget = GTK_WIDGET (range); + context = gtk_widget_get_style_context (widget); + + state = gtk_widget_get_state_flags (widget); + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); + gtk_style_context_get_margin (context, state, &trough_margin); + gtk_style_context_restore (context); gtk_range_get_props (range, &slider_width, &stepper_size, @@ -3716,9 +3776,9 @@ gtk_range_calc_layout (GtkRange *range, * total_adjustment_range) times the trough height in pixels */ - if (priv->adjustment->upper - priv->adjustment->lower != 0) - height = ((bottom - top) * (priv->adjustment->page_size / - (priv->adjustment->upper - priv->adjustment->lower))); + if (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) != 0) + height = ((bottom - top) * (gtk_adjustment_get_page_size (priv->adjustment) / + (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment)))); else height = priv->min_slider_size; @@ -3730,9 +3790,9 @@ gtk_range_calc_layout (GtkRange *range, y = top; - if (priv->adjustment->upper - priv->adjustment->lower - priv->adjustment->page_size != 0) - y += (bottom - top - height) * ((adjustment_value - priv->adjustment->lower) / - (priv->adjustment->upper - priv->adjustment->lower - priv->adjustment->page_size)); + if (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) != 0) + y += (bottom - top - height) * ((adjustment_value - gtk_adjustment_get_lower (priv->adjustment)) / + (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment))); y = CLAMP (y, top, bottom); @@ -3838,7 +3898,6 @@ gtk_range_calc_layout (GtkRange *range, */ priv->trough.x = priv->stepper_b.x + priv->stepper_b.width + stepper_spacing * has_steppers_ab; priv->trough.y = range_rect.y; - priv->trough.width = priv->stepper_c.x - priv->trough.x - stepper_spacing * has_steppers_cd; priv->trough.height = range_rect.height; @@ -3865,9 +3924,9 @@ gtk_range_calc_layout (GtkRange *range, * total_adjustment_range) times the trough width in pixels */ - if (priv->adjustment->upper - priv->adjustment->lower != 0) - width = ((right - left) * (priv->adjustment->page_size / - (priv->adjustment->upper - priv->adjustment->lower))); + if (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) != 0) + width = ((right - left) * (gtk_adjustment_get_page_size (priv->adjustment) / + (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment)))); else width = priv->min_slider_size; @@ -3879,9 +3938,9 @@ gtk_range_calc_layout (GtkRange *range, x = left; - if (priv->adjustment->upper - priv->adjustment->lower - priv->adjustment->page_size != 0) - x += (right - left - width) * ((adjustment_value - priv->adjustment->lower) / - (priv->adjustment->upper - priv->adjustment->lower - priv->adjustment->page_size)); + if (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) != 0) + x += (right - left - width) * ((adjustment_value - gtk_adjustment_get_lower (priv->adjustment)) / + (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment))); x = CLAMP (x, left, right); @@ -3903,8 +3962,8 @@ gtk_range_calc_layout (GtkRange *range, { case GTK_SENSITIVITY_AUTO: priv->upper_sensitive = - (priv->adjustment->value < - (priv->adjustment->upper - priv->adjustment->page_size)); + (gtk_adjustment_get_value (priv->adjustment) < + (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment))); break; case GTK_SENSITIVITY_ON: @@ -3920,7 +3979,7 @@ gtk_range_calc_layout (GtkRange *range, { case GTK_SENSITIVITY_AUTO: priv->lower_sensitive = - (priv->adjustment->value > priv->adjustment->lower); + (gtk_adjustment_get_value (priv->adjustment) > gtk_adjustment_get_lower (priv->adjustment)); break; case GTK_SENSITIVITY_ON: @@ -3997,11 +4056,11 @@ gtk_range_real_change_value (GtkRange *range, g_signal_emit (range, signals[ADJUST_BOUNDS], 0, value); if (priv->restrict_to_fill_level) - value = MIN (value, MAX (priv->adjustment->lower, + value = MIN (value, MAX (gtk_adjustment_get_lower (priv->adjustment), priv->fill_level)); - value = CLAMP (value, priv->adjustment->lower, - (priv->adjustment->upper - priv->adjustment->page_size)); + value = CLAMP (value, gtk_adjustment_get_lower (priv->adjustment), + (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment))); if (priv->round_digits >= 0) { @@ -4016,49 +4075,17 @@ gtk_range_real_change_value (GtkRange *range, value = floor ((value * power) + 0.5) / power; } - if (priv->adjustment->value != value) + if (gtk_adjustment_get_value (priv->adjustment) != value) { priv->need_recalc = TRUE; gtk_widget_queue_draw (GTK_WIDGET (range)); - switch (priv->update_policy) - { - case GTK_UPDATE_CONTINUOUS: - gtk_adjustment_set_value (priv->adjustment, value); - break; - - /* Delayed means we update after a period of inactivity */ - case GTK_UPDATE_DELAYED: - gtk_range_reset_update_timer (range); - /* FALL THRU */ - - /* Discontinuous means we update on button release */ - case GTK_UPDATE_DISCONTINUOUS: - /* don't emit value_changed signal */ - priv->adjustment->value = value; - priv->update_pending = TRUE; - break; - } + gtk_adjustment_set_value (priv->adjustment, value); } return FALSE; } -static void -gtk_range_update_value (GtkRange *range) -{ - GtkRangePrivate *priv = range->priv; - - gtk_range_remove_update_timer (range); - - if (priv->update_pending) - { - gtk_adjustment_value_changed (priv->adjustment); - - priv->update_pending = FALSE; - } -} - struct _GtkRangeStepTimer { guint timeout_id; @@ -4134,41 +4161,17 @@ gtk_range_remove_step_timer (GtkRange *range) } } -static gboolean -update_timeout (gpointer data) -{ - GtkRange *range = GTK_RANGE (data); - GtkRangePrivate *priv = range->priv; - - gtk_range_update_value (range); - priv->update_timeout_id = 0; - - /* self-remove */ - return FALSE; -} - -static void -gtk_range_reset_update_timer (GtkRange *range) +void +_gtk_range_set_has_origin (GtkRange *range, + gboolean has_origin) { - GtkRangePrivate *priv = range->priv; - - gtk_range_remove_update_timer (range); - - priv->update_timeout_id = gdk_threads_add_timeout (UPDATE_DELAY, - update_timeout, - range); + range->priv->has_origin = has_origin; } -static void -gtk_range_remove_update_timer (GtkRange *range) +gboolean +_gtk_range_get_has_origin (GtkRange *range) { - GtkRangePrivate *priv = range->priv; - - if (priv->update_timeout_id != 0) - { - g_source_remove (priv->update_timeout_id); - priv->update_timeout_id = 0; - } + return range->priv->has_origin; } void @@ -4207,11 +4210,45 @@ _gtk_range_get_stop_positions (GtkRange *range, return priv->n_marks; } +/** + * gtk_range_set_round_digits: + * @range: a #GtkRange + * @round_digits: the precision in digits, or -1 + * + * Sets the number of digits to round the value to when + * it changes. See #GtkRange::change-value. + * + * Since: 2.24 + */ void -_gtk_range_set_round_digits (GtkRange *range, - gint round_digits) +gtk_range_set_round_digits (GtkRange *range, + gint round_digits) { + g_return_if_fail (GTK_IS_RANGE (range)); + g_return_if_fail (round_digits >= -1); + range->priv->round_digits = round_digits; + + g_object_notify (G_OBJECT (range), "round-digits"); +} + +/** + * gtk_range_get_round_digits: + * @range: a #GtkRange + * + * Gets the number of digits to round the value to when + * it changes. See #GtkRange::change-value. + * + * Return value: the number of digits to round to + * + * Since: 2.24 + */ +gint +gtk_range_get_round_digits (GtkRange *range) +{ + g_return_val_if_fail (GTK_IS_RANGE (range), -1); + + return range->priv->round_digits; } void