Add press and hold support to set zoom scroll mode

Triggering zoom scroll mode by Shift click was too much
of an easter egg. It also requires using keyboard and
mouse together, which is hard to do for many users.

Instead, we now trigger zoom scroll mode by click-and-hold
(or touch-and-hold).

https://bugzilla.gnome.org/show_bug.cgi?id=704703
This commit is contained in:
William Jon McCann 2013-07-18 17:35:42 -04:00 committed by Matthias Clasen
parent 46302c522b
commit c3e172e546

View File

@ -36,6 +36,7 @@
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkorientableprivate.h"
#include "gtkpressandholdprivate.h"
#include "gtkprivate.h"
#include "gtkscale.h"
#include "gtkscrollbar.h"
@ -62,6 +63,7 @@
#define UPDATE_DELAY 300 /* Delay for queued update */
#define TIMEOUT_INITIAL 500
#define TIMEOUT_REPEAT 50
#define ZOOM_HOLD_TIME 500
typedef struct _GtkRangeStepTimer GtkRangeStepTimer;
@ -142,6 +144,8 @@ struct _GtkRangePrivate
/* Whether we're doing fine adjustment */
guint zoom : 1;
guint zoom_set : 1;
GtkPressAndHold *press_and_hold;
/* Fill level */
guint show_fill_level : 1;
@ -1499,6 +1503,8 @@ gtk_range_destroy (GtkWidget *widget)
gtk_range_remove_step_timer (range);
g_clear_object (&priv->press_and_hold);
if (priv->adjustment)
{
g_signal_handlers_disconnect_by_func (priv->adjustment,
@ -2346,6 +2352,33 @@ range_grab_add (GtkRange *range,
gtk_widget_queue_draw (GTK_WIDGET (range));
}
static void
update_zoom_state (GtkRange *range,
gboolean enabled)
{
GtkStyleContext *context;
context = gtk_widget_get_style_context (GTK_WIDGET (range));
if (enabled)
gtk_style_context_add_class (context, "fine-tune");
else
gtk_style_context_remove_class (context, "fine-tune");
gtk_widget_queue_draw (GTK_WIDGET (range));
range->priv->zoom = enabled;
}
static void
update_zoom_set (GtkRange *range,
gboolean zoom_set)
{
if (zoom_set)
g_clear_object (&range->priv->press_and_hold);
range->priv->zoom_set = zoom_set;
}
static void
range_grab_remove (GtkRange *range)
{
@ -2368,7 +2401,8 @@ range_grab_remove (GtkRange *range)
location != MOUSE_OUTSIDE)
gtk_widget_queue_draw (GTK_WIDGET (range));
priv->zoom = FALSE;
update_zoom_state (range, FALSE);
update_zoom_set (range, FALSE);
}
static GtkScrollType
@ -2511,6 +2545,16 @@ gtk_range_key_press (GtkWidget *widget,
return GTK_WIDGET_CLASS (gtk_range_parent_class)->key_press_event (widget, event);
}
static void
hold_action (GtkPressAndHold *pah,
gint x,
gint y,
GtkRange *range)
{
update_zoom_state (range, TRUE);
update_zoom_set (range, TRUE);
}
static gint
gtk_range_button_press (GtkWidget *widget,
GdkEventButton *event)
@ -2657,7 +2701,32 @@ gtk_range_button_press (GtkWidget *widget,
{
/* Shift-click in the slider = fine adjustment */
if (event->state & GDK_SHIFT_MASK)
priv->zoom = TRUE;
{
update_zoom_state (range, TRUE);
update_zoom_set (range, TRUE);
}
else
{
if (!priv->press_and_hold)
{
gint drag_threshold;
g_object_get (gtk_widget_get_settings (widget),
"gtk-dnd-drag-threshold", &drag_threshold,
NULL);
priv->press_and_hold = gtk_press_and_hold_new ();
g_object_set (priv->press_and_hold,
"drag-threshold", drag_threshold,
"hold-time", ZOOM_HOLD_TIME,
NULL);
g_signal_connect (priv->press_and_hold, "hold",
G_CALLBACK (hold_action), range);
}
gtk_press_and_hold_process_event (priv->press_and_hold, (GdkEvent *)event);
}
}
if (priv->orientation == GTK_ORIENTATION_VERTICAL)
@ -2803,7 +2872,11 @@ gtk_range_button_release (GtkWidget *widget,
priv->grab_button == event->button)
{
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);
if (priv->press_and_hold)
gtk_press_and_hold_process_event (priv->press_and_hold, (GdkEvent *)event);
}
stop_scrolling (range);
@ -2905,7 +2978,12 @@ gtk_range_motion_notify (GtkWidget *widget,
gtk_widget_queue_draw (widget);
if (priv->grab_location == MOUSE_SLIDER)
update_slider_position (range, event->x, event->y);
{
if (!priv->zoom_set && priv->press_and_hold != NULL)
gtk_press_and_hold_process_event (priv->press_and_hold, (GdkEvent *)event);
update_slider_position (range, event->x, event->y);
}
/* We handled the event if the mouse was in the range_rect */
return priv->mouse_location != MOUSE_OUTSIDE;