[Xfce4-commits] <midori:master> Implement drag (finger) and kinetic scrolling with KatzeScrolled
Christian Dywan
noreply at xfce.org
Mon Sep 28 22:16:03 CEST 2009
Updating branch refs/heads/master
to 96093d906754a986ef9b6dae5eae0ba8411653d4 (commit)
from 7259066e20d982d98a554caf19c7c1134f4658eb (commit)
commit 96093d906754a986ef9b6dae5eae0ba8411653d4
Author: Christian Dywan <christian at twotoasts.de>
Date: Sun Sep 27 23:48:08 2009 +0200
Implement drag (finger) and kinetic scrolling with KatzeScrolled
The feature is primarily interesting for mobile devices and
by default enabled with gtk-touchscreen-mode.
katze/katze-scrolled.c | 1086 +++++++++++++++++++++++++++++++++++++++++++
katze/katze-scrolled.h | 59 +++
katze/katze.h | 1 +
midori/midori-browser.c | 3 -
midori/midori-preferences.c | 17 +-
midori/midori-view.c | 24 +-
midori/midori-websettings.c | 25 +
7 files changed, 1203 insertions(+), 12 deletions(-)
diff --git a/katze/katze-scrolled.c b/katze/katze-scrolled.c
new file mode 100644
index 0000000..b7596f5
--- /dev/null
+++ b/katze/katze-scrolled.c
@@ -0,0 +1,1086 @@
+/*
+ Copyright (C) 2007 Henrik Hedberg <hhedberg at innologies.fi>
+ Copyright (C) 2009 Nadav Wiener <nadavwr at yahoo.com>
+ Copyright (C) 2009 Christian Dywan <christian at twotoasts.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See the file COPYING for the full license text.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "katze-scrolled.h"
+
+#define DEFAULT_INTERVAL 50
+#define DEFAULT_DECELERATION 0.7
+#define DEFAULT_DRAGGING_STOPPED_DELAY 100
+
+/**
+ * SECTION:katze-scrolled
+ * @short_description: Implements drag scrolling and kinetic scrolling
+ * @see_also: #GtkScrolledWindow
+ *
+ * A scrolled window derived from #GtkScrolledWindow that implements
+ * drag scrolling and kinetic scrolling. Can be used as a drop-in replacement
+ * for the existing #GtkScrolledWindow.
+ *
+ * If a direct child of the #KatzeScrolled has its own window
+ * (InputOnly is enough for events), it is automatically activated when added
+ * as a child. All motion events in that area will be used to scroll.
+ *
+ * If some descendant widgets capture button press, button release and/ or
+ * motion nofity events, the user can not scroll the area by pressing those
+ * widgets (unless the widget is activated). #GtkButton is a typical example
+ * of that. Usually that is the desired behaviour.
+ *
+ * Any widget can be registered to provide pointer events for the
+ * #KatzeScrolled by using the
+ * #katze_scrolled_activate_scrolling function.
+ *
+ **/
+
+G_DEFINE_TYPE (KatzeScrolled, katze_scrolled, GTK_TYPE_SCROLLED_WINDOW);
+
+enum
+{
+ PROP_0,
+
+ PROP_DRAG_SCROLLING,
+ PROP_KINETIC_SCROLLING
+};
+
+static void
+katze_scrolled_set_property (GObject* object,
+ guint prop_id,
+ const GValue* value,
+ GParamSpec* pspec);
+
+static void
+katze_scrolled_get_property (GObject* object,
+ guint prop_id,
+ GValue* value,
+ GParamSpec* pspec);
+
+static void
+katze_scrolled_dispose (GObject* object);
+
+static void
+katze_scrolled_activate_scrolling (KatzeScrolled* scrolled,
+ GtkWidget* widget);
+
+static void
+katze_scrolled_set_drag_scrolling (KatzeScrolled* scrolled,
+ gboolean drag_scrolling);
+
+struct _KatzeScrolledPrivate
+{
+ /* Settings */
+ guint interval;
+ gdouble deceleration;
+ gboolean drag_scrolling;
+ gboolean kinetic_scrolling;
+ guint32 dragging_stopped_delay;
+ gboolean scrolling_hints;
+
+ /* Temporary variables */
+ gboolean dragged;
+ gboolean press_received;
+ GdkWindow* synthetic_crossing_event_window;
+
+ /* Disabling twice happening scrolling adjustment */
+ GtkAdjustment* hadjustment;
+ GtkWidget* viewport;
+
+ /* Motion scrolling */
+ gint start_x;
+ gint start_y;
+ gint previous_x;
+ gint previous_y;
+ gint farest_x;
+ gint farest_y;
+ guint32 start_time;
+ guint32 previous_time;
+ guint32 farest_time;
+ gboolean going_right;
+ gboolean going_down;
+
+ /* Kinetic scrolling */
+ guint scrolling_timeout_id;
+ gdouble horizontal_speed;
+ gdouble vertical_speed;
+ gdouble horizontal_deceleration;
+ gdouble vertical_deceleration;
+
+ /* Internal scrollbars */
+ GdkWindow* vertical_scrollbar_window;
+ GdkWindow* horizontal_scrollbar_window;
+ gint vertical_scrollbar_size;
+ gint horizontal_scrollbar_size;
+ guint hide_scrollbars_timeout_id;
+ GdkGC* hilight_gc;
+ GdkGC* shadow_gc;
+};
+
+typedef struct _KatzeScrolledState KatzeScrolledState;
+typedef gboolean (*KatzeScrolledEventHandler)(GdkEvent* event,
+ KatzeScrolledState* state,
+ gpointer user_data);
+
+typedef struct
+{
+ KatzeScrolledEventHandler event_handler;
+ gpointer user_data;
+} EventHandlerData;
+
+struct _KatzeScrolledState
+{
+ GList* current_event_handler;
+};
+
+static GList* event_handlers = NULL;
+
+static void
+katze_scrolled_event_handler_func (GdkEvent* event,
+ gpointer data);
+
+static void
+katze_scrolled_event_handler_append (KatzeScrolledEventHandler event_handler,
+ gpointer user_data)
+{
+ EventHandlerData* data;
+
+ data = g_new0 (EventHandlerData, 1);
+ data->event_handler = event_handler;
+ data->user_data = user_data;
+ event_handlers = g_list_append (event_handlers, data);
+
+ gdk_event_handler_set ((GdkEventFunc)katze_scrolled_event_handler_func, NULL, NULL);
+}
+
+static void
+katze_scrolled_event_handler_next (GdkEvent* event,
+ KatzeScrolledState* state)
+{
+ EventHandlerData* data;
+ gboolean stop_propagating;
+
+ state->current_event_handler = g_list_next (state->current_event_handler);
+ if (state->current_event_handler)
+ {
+ data = (EventHandlerData*)state->current_event_handler->data;
+ stop_propagating = data->event_handler (event, state, data->user_data);
+ if (!stop_propagating && state->current_event_handler)
+ g_critical ("%s: handler returned FALSE without calling %s first",
+ G_STRFUNC, G_STRFUNC);
+ }
+ else
+ gtk_main_do_event (event);
+}
+
+static void
+katze_scrolled_event_handler_func (GdkEvent* event,
+ gpointer user_data)
+{
+ KatzeScrolledState* state;
+ EventHandlerData* data;
+ gboolean stop_propagating;
+
+ state = g_new0 (KatzeScrolledState, 1);
+ state->current_event_handler = g_list_first (event_handlers);
+ if (state->current_event_handler)
+ {
+ data = (EventHandlerData*)state->current_event_handler->data;
+ stop_propagating = data->event_handler (event, state, data->user_data);
+ if (!stop_propagating && state->current_event_handler)
+ g_critical ("%s: handler returned FALSE without calling %s first",
+ G_STRFUNC, "katze_scrolled_event_handler_next");
+ }
+ else
+ gtk_main_do_event (event);
+
+ g_free (state);
+}
+
+static GdkWindow* current_gdk_window;
+static KatzeScrolled* current_scrolled_window;
+static GtkWidget* current_widget;
+static gboolean synthetized_crossing_event;
+
+static GTree* activated_widgets;
+
+static gint
+compare_pointers (gconstpointer a,
+ gconstpointer b)
+{
+ return a - b;
+}
+
+static void
+disable_hadjustment (KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ GtkAdjustment* hadjustment;
+ GtkWidget* viewport;
+
+ if ((hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled)))
+ && priv->hadjustment != hadjustment)
+ {
+ priv->hadjustment = hadjustment;
+ priv->viewport = NULL;
+ viewport = GTK_WIDGET (scrolled);
+ while (GTK_IS_BIN (viewport))
+ {
+ viewport = gtk_bin_get_child (GTK_BIN (viewport));
+ if (GTK_IS_VIEWPORT (viewport))
+ {
+ priv->viewport = viewport;
+ break;
+ }
+ }
+ }
+ g_signal_handlers_block_matched (priv->hadjustment, G_SIGNAL_MATCH_DATA,
+ 0, 0, 0, 0, priv->viewport);
+}
+
+static void
+enable_hadjustment (KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+
+ g_signal_handlers_unblock_matched (priv->hadjustment, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, priv->viewport);
+}
+
+static gboolean
+on_expose_event (GtkWidget* widget,
+ GdkEventExpose* event,
+ KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ gboolean ret = FALSE;
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ if (event->window == priv->horizontal_scrollbar_window)
+ {
+ if (priv->horizontal_scrollbar_size)
+ {
+ gdk_draw_line (event->window, priv->hilight_gc, 0, 0, priv->horizontal_scrollbar_size - 1, 0);
+ gdk_draw_line (event->window, priv->hilight_gc, 0, 1, 0, 9);
+ gdk_draw_line (event->window, priv->shadow_gc, priv->horizontal_scrollbar_size - 1, 1, priv->horizontal_scrollbar_size - 1, 9);
+ gdk_draw_line (event->window, priv->shadow_gc, 0, 9, priv->horizontal_scrollbar_size - 1, 9);
+ }
+
+ ret = TRUE;
+ }
+ else if (event->window == priv->vertical_scrollbar_window)
+ {
+ if (priv->vertical_scrollbar_size)
+ {
+ gdk_draw_line (event->window, priv->hilight_gc, 0, 0, 9, 0);
+ gdk_draw_line (event->window, priv->hilight_gc, 0, 1, 0, priv->vertical_scrollbar_size - 1);
+ gdk_draw_line (event->window, priv->shadow_gc, 9, 1, 9, priv->vertical_scrollbar_size - 1);
+ gdk_draw_line (event->window, priv->shadow_gc, 0, priv->vertical_scrollbar_size - 1, 9, priv->vertical_scrollbar_size - 1);
+ }
+
+ ret = TRUE;
+ }
+ }
+
+ return ret;
+}
+
+static gboolean
+adjust_scrollbar (KatzeScrolled* scrolled,
+ GdkWindow* scrollbar_window,
+ GtkAdjustment* adjustment,
+ gint* previous_size,
+ gboolean horizontal)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ GtkWidget* widget = GTK_WIDGET (scrolled);
+ gint x, y;
+ gint size;
+ double position;
+ GtkWidget* window;
+
+ if (adjustment->page_size >= adjustment->upper - adjustment->lower)
+ {
+ *previous_size = 0;
+ return FALSE;
+ }
+
+ size = ((double)adjustment->page_size) / (adjustment->upper - adjustment->lower) * (horizontal
+ ? widget->allocation.height : widget->allocation.width);
+ if (size != *previous_size)
+ {
+ *previous_size = size;
+ if (horizontal)
+ {
+ gdk_window_resize (scrollbar_window, 10, size);
+ gdk_window_clear (scrollbar_window);
+ gdk_draw_line (scrollbar_window, priv->hilight_gc, 0, 0, 9, 0);
+ gdk_draw_line (scrollbar_window, priv->hilight_gc, 0, 1, 0, size - 1);
+ gdk_draw_line (scrollbar_window, priv->shadow_gc, 9, 1, 9, size - 1);
+ gdk_draw_line (scrollbar_window, priv->shadow_gc, 0, size - 1, 9, size - 1);
+ }
+ else
+ {
+ gdk_window_resize (scrollbar_window, size, 10);
+ gdk_window_clear (scrollbar_window);
+ gdk_draw_line (scrollbar_window, priv->hilight_gc, 0, 0, size - 1, 0);
+ gdk_draw_line (scrollbar_window, priv->hilight_gc, 0, 1, 0, 9);
+ gdk_draw_line (scrollbar_window, priv->shadow_gc, size - 1, 1, size - 1, 9);
+ gdk_draw_line (scrollbar_window, priv->shadow_gc, 0, 9, size - 1, 9);
+ }
+ }
+
+ position = (adjustment->value - adjustment->lower) / (adjustment->upper - adjustment->lower);
+ window = gtk_widget_get_toplevel (widget);
+ if (horizontal)
+ {
+ gtk_widget_translate_coordinates (widget, window,
+ widget->allocation.width - 20, position * widget->allocation.height, &x, &y);
+ gdk_window_move (scrollbar_window, x, y);
+ }
+ else
+ {
+ gtk_widget_translate_coordinates (widget, window,
+ position * widget->allocation.width, widget->allocation.height - 20, &x, &y);
+ gdk_window_move (scrollbar_window, x, y);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+hide_scrollbars_timeout (gpointer data)
+{
+ KatzeScrolled* scrolled = KATZE_SCROLLED (data);
+ KatzeScrolledPrivate* priv = scrolled->priv;
+
+ gdk_threads_enter ();
+ gdk_window_hide (priv->vertical_scrollbar_window);
+ gdk_window_hide (priv->horizontal_scrollbar_window);
+
+ priv->hide_scrollbars_timeout_id = 0;
+ gdk_threads_leave ();
+
+ return FALSE;
+}
+
+static gdouble
+calculate_timeout_scroll_values (gdouble old_value,
+ gdouble upper_limit,
+ gdouble* scrolling_speed_pointer,
+ gdouble deceleration,
+ gdouble* other_deceleration,
+ gdouble normal_deceleration)
+{
+ gdouble new_value = old_value;
+
+ if (*scrolling_speed_pointer > deceleration ||
+ *scrolling_speed_pointer < -deceleration)
+ {
+ if (old_value + *scrolling_speed_pointer <= 0.0)
+ {
+ new_value = -1.0;
+ *scrolling_speed_pointer = 0.0;
+ *other_deceleration = normal_deceleration;
+ }
+ else if (old_value + *scrolling_speed_pointer >= upper_limit)
+ {
+ new_value = upper_limit;
+ *scrolling_speed_pointer = 0.0;
+ *other_deceleration = normal_deceleration;
+ }
+ else
+ new_value = old_value + *scrolling_speed_pointer;
+ if (*scrolling_speed_pointer > deceleration)
+ *scrolling_speed_pointer -= deceleration;
+ else if (*scrolling_speed_pointer < -deceleration)
+ *scrolling_speed_pointer += deceleration;
+ }
+
+ return new_value;
+}
+
+static void
+do_timeout_scroll (KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ GtkScrolledWindow* gtk_scrolled = GTK_SCROLLED_WINDOW (scrolled);
+ GtkAdjustment* hadjustment;
+ GtkAdjustment* vadjustment;
+ gdouble hvalue;
+ gdouble vvalue;
+
+ hadjustment = gtk_scrolled_window_get_hadjustment (gtk_scrolled);
+ vadjustment = gtk_scrolled_window_get_vadjustment (gtk_scrolled);
+ hvalue = calculate_timeout_scroll_values (hadjustment->value,
+ hadjustment->upper - hadjustment->page_size,
+ &priv->horizontal_speed,
+ priv->horizontal_deceleration,
+ &priv->vertical_deceleration,
+ priv->deceleration);
+ vvalue = calculate_timeout_scroll_values (vadjustment->value,
+ vadjustment->upper - vadjustment->page_size,
+ &priv->vertical_speed,
+ priv->vertical_deceleration,
+ &priv->horizontal_deceleration,
+ priv->deceleration);
+ if (vvalue != vadjustment->value)
+ {
+ if (hvalue != hadjustment->value)
+ {
+ disable_hadjustment (scrolled);
+ gtk_adjustment_set_value (hadjustment, hvalue);
+ enable_hadjustment (scrolled);
+ }
+ gtk_adjustment_set_value (vadjustment, vvalue);
+ }
+ else if (hvalue != hadjustment->value)
+ gtk_adjustment_set_value (hadjustment, hvalue);
+
+ adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window,
+ gtk_scrolled_window_get_hadjustment (gtk_scrolled),
+ &priv->horizontal_scrollbar_size, FALSE);
+ adjust_scrollbar (scrolled, priv->vertical_scrollbar_window,
+ gtk_scrolled_window_get_vadjustment (gtk_scrolled),
+ &priv->vertical_scrollbar_size, TRUE);
+}
+
+static gboolean
+timeout_scroll (gpointer data)
+{
+ gboolean ret = TRUE;
+ KatzeScrolled* scrolled = KATZE_SCROLLED (data);
+ KatzeScrolledPrivate* priv = scrolled->priv;
+
+ gdk_threads_enter ();
+ do_timeout_scroll (scrolled);
+
+ if (priv->vertical_speed < priv->deceleration &&
+ priv->vertical_speed > -priv->deceleration &&
+ priv->horizontal_speed < priv->deceleration &&
+ priv->horizontal_speed > -priv->deceleration)
+ {
+ priv->scrolling_timeout_id = 0;
+ if (!priv->hide_scrollbars_timeout_id)
+ priv->hide_scrollbars_timeout_id = g_timeout_add (500,
+ hide_scrollbars_timeout, scrolled);
+
+ ret = FALSE;
+ }
+ gdk_threads_leave ();
+
+ return ret;
+}
+
+static gdouble
+calculate_motion_scroll_values (gdouble old_value,
+ gdouble upper_limit,
+ gint current_coordinate,
+ gint previous_coordinate)
+{
+ gdouble new_value = old_value;
+ gint movement;
+
+ movement = current_coordinate - previous_coordinate;
+
+ if (old_value - movement < upper_limit)
+ new_value = old_value - movement;
+ else
+ new_value = upper_limit;
+
+ return new_value;
+}
+
+static void
+do_motion_scroll (KatzeScrolled* scrolled,
+ GtkWidget* widget,
+ gint x,
+ gint y,
+ guint32 timestamp)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ GtkAdjustment* hadjustment;
+ GtkAdjustment* vadjustment;
+ gdouble hvalue;
+ gdouble vvalue;
+
+ if (priv->dragged || gtk_drag_check_threshold (widget, priv->start_x, priv->start_y, x, y))
+ {
+ if (timestamp - priv->previous_time > priv->dragging_stopped_delay || !priv->dragged)
+ {
+ priv->dragged = TRUE;
+ priv->going_right = priv->start_x < x;
+ priv->going_down = priv->start_y < y;
+ priv->start_x = priv->farest_x = x;
+ priv->start_y = priv->farest_y = y;
+ priv->start_time = priv->farest_time = timestamp;
+ }
+ else
+ {
+ if ((priv->going_right && x > priv->farest_x)
+ || (!priv->going_right && x < priv->farest_x))
+ {
+ priv->farest_x = x;
+ priv->farest_time = timestamp;
+ }
+ if ((priv->going_down && y > priv->farest_y)
+ || (!priv->going_down && y < priv->farest_y))
+ {
+ priv->farest_y = y;
+ priv->farest_time = timestamp;
+ }
+ if (gtk_drag_check_threshold (widget, priv->farest_x, priv->farest_y, x, y))
+ {
+ priv->start_x = priv->farest_x;
+ priv->farest_x = x;
+ priv->start_y = priv->farest_y;
+ priv->farest_y = y;
+ priv->start_time = priv->farest_time;
+ priv->farest_time = timestamp;
+ priv->going_right = priv->start_x < x;
+ priv->going_down = priv->start_y < y;
+ }
+ }
+
+ hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled));
+ vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled));
+ hvalue = calculate_motion_scroll_values (hadjustment->value,
+ hadjustment->upper - hadjustment->page_size, x, priv->previous_x);
+ vvalue = calculate_motion_scroll_values (vadjustment->value,
+ vadjustment->upper - vadjustment->page_size, y, priv->previous_y);
+ if (vvalue != vadjustment->value)
+ {
+ if (hvalue != hadjustment->value)
+ {
+ disable_hadjustment (scrolled);
+ gtk_adjustment_set_value (hadjustment, hvalue);
+ enable_hadjustment (scrolled);
+ }
+ gtk_adjustment_set_value (vadjustment, vvalue);
+ }
+ else if (hvalue != hadjustment->value)
+ gtk_adjustment_set_value (hadjustment, hvalue);
+ }
+
+ priv->previous_y = y;
+ priv->previous_x = x;
+ priv->previous_time = timestamp;
+
+ adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window,
+ gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled)),
+ &priv->horizontal_scrollbar_size, FALSE);
+ adjust_scrollbar (scrolled, priv->vertical_scrollbar_window,
+ gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled)),
+ &priv->vertical_scrollbar_size, TRUE);
+}
+
+static gboolean
+button_press_event (GtkWidget* widget,
+ GdkEventButton* event,
+ KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ gint x;
+ gint y;
+ GdkModifierType mask;
+
+ if (!priv->drag_scrolling)
+ return FALSE;
+
+ if (event->button != 1)
+ return FALSE;
+
+ priv->press_received = TRUE;
+
+ if (event->time - priv->previous_time < priv->dragging_stopped_delay &&
+ gtk_drag_check_threshold (widget, priv->previous_x, priv->previous_y, x, y))
+ {
+ if (priv->scrolling_timeout_id)
+ {
+ g_source_remove (priv->scrolling_timeout_id);
+ priv->scrolling_timeout_id = 0;
+ }
+ gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask);
+ /* do_motion_scroll (scrolled, widget, x, y, event->time); */
+ }
+ else
+ {
+ if (priv->scrolling_timeout_id)
+ {
+ g_source_remove (priv->scrolling_timeout_id);
+ priv->scrolling_timeout_id = 0;
+ priv->previous_time = 0;
+ }
+ else
+ {
+ priv->dragged = FALSE;
+ priv->previous_time = event->time;
+ }
+ gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask);
+ priv->start_x = priv->previous_x = priv->farest_x = x;
+ priv->start_y = priv->previous_y = priv->farest_y = y;
+ priv->start_time = event->time;
+ }
+
+ if (priv->scrolling_hints && !GTK_SCROLLED_WINDOW (scrolled)->hscrollbar_visible &&
+ adjust_scrollbar (scrolled, priv->horizontal_scrollbar_window,
+ gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled)),
+ &priv->horizontal_scrollbar_size, FALSE))
+ {
+ gdk_window_raise (priv->horizontal_scrollbar_window);
+ gdk_window_show (priv->horizontal_scrollbar_window);
+ }
+ if (priv->scrolling_hints && !GTK_SCROLLED_WINDOW (scrolled)->vscrollbar_visible &&
+ adjust_scrollbar (scrolled, priv->vertical_scrollbar_window,
+ gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled)),
+ &priv->vertical_scrollbar_size, TRUE))
+ {
+ gdk_window_raise (priv->vertical_scrollbar_window);
+ gdk_window_show (priv->vertical_scrollbar_window);
+ }
+ if (priv->hide_scrollbars_timeout_id)
+ {
+ g_source_remove (priv->hide_scrollbars_timeout_id);
+ priv->hide_scrollbars_timeout_id = 0;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+button_release_event (GtkWidget* widget,
+ GdkEventButton* event,
+ KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ gint x;
+ gint y;
+ GdkModifierType mask;
+
+ gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask);
+ if (priv->press_received &&
+ gtk_drag_check_threshold (widget, priv->start_x, priv->start_y, x, y)) {
+ priv->dragged = TRUE;
+ }
+
+ if (priv->press_received && priv->kinetic_scrolling &&
+ event->time - priv->previous_time < priv->dragging_stopped_delay) {
+ priv->vertical_speed = (gdouble)(priv->start_y - y) / (event->time - priv->start_time) * priv->interval;
+ priv->horizontal_speed = (gdouble)(priv->start_x - x) / (event->time - priv->start_time) * priv->interval;
+ if (ABS (priv->vertical_speed) > ABS (priv->horizontal_speed)) {
+ priv->vertical_deceleration = priv->deceleration;
+ priv->horizontal_deceleration = priv->deceleration * ABS (priv->horizontal_speed / priv->vertical_speed);
+ } else {
+ priv->horizontal_deceleration = priv->deceleration;
+ priv->vertical_deceleration = priv->deceleration * ABS (priv->vertical_speed / priv->horizontal_speed);
+ }
+ priv->scrolling_timeout_id = g_timeout_add (priv->interval, timeout_scroll, scrolled);
+
+ do_timeout_scroll (scrolled);
+ }
+ else if (!priv->hide_scrollbars_timeout_id) {
+ priv->hide_scrollbars_timeout_id = g_timeout_add (500, hide_scrollbars_timeout, scrolled);
+ }
+ priv->previous_x = x;
+ priv->previous_y = y;
+ priv->previous_time = event->time;
+
+ priv->press_received = FALSE;
+
+ return FALSE;
+}
+
+static gboolean
+motion_notify_event (GtkWidget* widget,
+ GdkEventMotion* event,
+ KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ gint x;
+ gint y;
+ GdkModifierType mask;
+
+ if (priv->press_received)
+ {
+ gdk_window_get_pointer (GTK_WIDGET (scrolled)->window, &x, &y, &mask);
+ do_motion_scroll (scrolled, widget, x, y, event->time);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+katze_scrolled_event_handler (GdkEvent* event,
+ KatzeScrolledState* state,
+ gpointer user_data)
+{
+ gboolean stop_propagating;
+ GdkEventCrossing crossing;
+
+ stop_propagating = FALSE;
+
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ gdk_window_get_user_data (event->button.window, (gpointer)¤t_widget);
+
+ if ((current_scrolled_window = g_tree_lookup (activated_widgets, current_widget)))
+ {
+ current_gdk_window = event->button.window;
+ stop_propagating = button_press_event (current_widget, &event->button, current_scrolled_window);
+ }
+ else
+ current_gdk_window = NULL;
+ }
+ else if (event->any.window == current_gdk_window)
+ {
+ if (event->type == GDK_MOTION_NOTIFY)
+ {
+ if (current_scrolled_window->priv->dragged)
+ stop_propagating = motion_notify_event (current_widget, &event->motion, current_scrolled_window);
+ else
+ {
+ stop_propagating = motion_notify_event (current_widget, &event->motion, current_scrolled_window);
+ if (current_scrolled_window->priv->dragged)
+ {
+ crossing.type = GDK_LEAVE_NOTIFY;
+ crossing.window = event->motion.window;
+ crossing.send_event = event->motion.send_event;
+ crossing.subwindow = GTK_WIDGET (current_scrolled_window)->window;
+ crossing.time = event->motion.time;
+ crossing.x = event->motion.x;
+ crossing.y = event->motion.y;
+ crossing.x_root = event->motion.x_root;
+ crossing.y_root = event->motion.y_root;
+ crossing.mode = GDK_CROSSING_GRAB;
+ crossing.detail = GDK_NOTIFY_ANCESTOR;
+ crossing.focus = TRUE;
+ crossing.state = event->motion.state;
+
+ gtk_main_do_event ((GdkEvent*)&crossing);
+ synthetized_crossing_event = TRUE;
+ }
+ }
+ }
+ else if ((event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) &&
+ synthetized_crossing_event)
+ stop_propagating = TRUE;
+ else if (event->type == GDK_BUTTON_RELEASE)
+ stop_propagating = button_release_event (current_widget, &event->button, current_scrolled_window);
+ }
+
+
+ if (!stop_propagating)
+ katze_scrolled_event_handler_next (event, state);
+
+ if (event->type == GDK_BUTTON_RELEASE && event->button.window == current_gdk_window)
+ {
+ crossing.type = GDK_ENTER_NOTIFY;
+ crossing.window = event->button.window;
+ crossing.send_event = event->button.send_event;
+ crossing.subwindow = GTK_WIDGET (current_scrolled_window)->window;
+ crossing.time = event->button.time;
+ crossing.x = event->button.x;
+ crossing.y = event->button.y;
+ crossing.x_root = event->button.x_root;
+ crossing.y_root = event->button.y_root;
+ crossing.mode = GDK_CROSSING_UNGRAB;
+ crossing.detail = GDK_NOTIFY_ANCESTOR;
+ crossing.focus = TRUE;
+ crossing.state = event->button.state;
+
+ gtk_main_do_event ((GdkEvent*)&crossing);
+ synthetized_crossing_event = FALSE;
+ }
+
+ return stop_propagating;
+}
+
+static void
+katze_scrolled_add (GtkContainer* container,
+ GtkWidget* widget)
+{
+ katze_scrolled_activate_scrolling (KATZE_SCROLLED (container), widget);
+
+ (*GTK_CONTAINER_CLASS (katze_scrolled_parent_class)->add) (container, widget);
+}
+
+static void
+katze_scrolled_realize (GtkWidget* widget)
+{
+ KatzeScrolled* scrolled = KATZE_SCROLLED (widget);
+ KatzeScrolledPrivate* priv = scrolled->priv;
+ gboolean drag_scrolling;
+ GtkSettings* settings = gtk_widget_get_settings (widget);
+ GtkPolicyType policy;
+ GdkWindowAttr attr;
+ GdkColor color;
+
+ (*GTK_WIDGET_CLASS (katze_scrolled_parent_class)->realize) (widget);
+
+ g_object_get (settings, "gtk-touchscreen-mode", &drag_scrolling, NULL);
+ policy = drag_scrolling ? GTK_POLICY_NEVER : GTK_POLICY_AUTOMATIC;
+ g_object_set (scrolled, "drag-scrolling", drag_scrolling,
+ "hscrollbar-policy", policy, "vscrollbar-policy", policy, NULL);
+
+ widget->window = g_object_ref (gtk_widget_get_parent_window (widget));
+
+ attr.height = attr.width = 10;
+ attr.event_mask = GDK_EXPOSURE_MASK;
+ attr.wclass = GDK_INPUT_OUTPUT;
+ attr.window_type = GDK_WINDOW_CHILD;
+ attr.override_redirect = TRUE;
+ priv->vertical_scrollbar_window = gdk_window_new (widget->window, &attr, 0);
+ priv->horizontal_scrollbar_window = gdk_window_new (widget->window, &attr, 0);
+
+ gdk_window_set_user_data (priv->vertical_scrollbar_window, widget);
+ gdk_window_set_user_data (priv->horizontal_scrollbar_window, widget);
+ g_signal_connect (widget, "expose-event",
+ G_CALLBACK (on_expose_event), scrolled);
+
+ color.red = color.green = color.blue = 0x9999;
+ gdk_rgb_find_color (gdk_colormap_get_system (), &color);
+ gdk_window_set_background (priv->vertical_scrollbar_window, &color);
+ gdk_window_set_background (priv->horizontal_scrollbar_window, &color);
+
+ priv->hilight_gc = gdk_gc_new (widget->window);
+ color.red = color.green = color.blue = 0xcccc;
+ gdk_gc_set_rgb_fg_color (priv->hilight_gc, &color);
+ priv->shadow_gc = gdk_gc_new (widget->window);
+ color.red = color.green = color.blue = 0x6666;
+ gdk_gc_set_rgb_fg_color (priv->shadow_gc, &color);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+}
+
+static void
+katze_scrolled_dispose (GObject* object)
+{
+ KatzeScrolled* scrolled = KATZE_SCROLLED (object);
+ KatzeScrolledPrivate* priv = scrolled->priv;
+
+ if (priv->scrolling_timeout_id)
+ {
+ g_source_remove (priv->scrolling_timeout_id);
+ priv->scrolling_timeout_id = 0;
+ }
+ if (priv->hide_scrollbars_timeout_id)
+ {
+ g_source_remove (priv->hide_scrollbars_timeout_id);
+ priv->hide_scrollbars_timeout_id = 0;
+ }
+
+ (*G_OBJECT_CLASS (katze_scrolled_parent_class)->dispose) (object);
+}
+
+static void
+katze_scrolled_class_init (KatzeScrolledClass* class)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (class);
+ GtkContainerClass* container_class = GTK_CONTAINER_CLASS (class);
+ GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
+
+ gobject_class->set_property = katze_scrolled_set_property;
+ gobject_class->get_property = katze_scrolled_get_property;
+ gobject_class->dispose = katze_scrolled_dispose;
+
+ widget_class->realize = katze_scrolled_realize;
+
+ container_class->add = katze_scrolled_add;
+
+ /**
+ * KatzeScrolled:drag-scrolling:
+ *
+ * Whether the widget can be scrolled by dragging its contents.
+ *
+ * If "gtk-touchscreen-mode" is enabled, drag scrolling is
+ * automatically enabled.
+ *
+ * Since: 0.2.0
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_DRAG_SCROLLING,
+ g_param_spec_boolean (
+ "drag-scrolling",
+ "Drag Scrolling",
+ "Whether the widget can be scrolled by dragging its contents",
+ FALSE,
+ flags));
+
+ /**
+ * KatzeScrolled:kinetic-scrolling:
+ *
+ * Whether drag scrolling is kinetic, that is releasing the
+ * pointer keeps the contents scrolling further relative to
+ * the speed with which they were dragged.
+ *
+ * Since: 0.2.0
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_KINETIC_SCROLLING,
+ g_param_spec_boolean (
+ "kinetic-scrolling",
+ "Kinetic Scrolling",
+ "Whether drag scrolling is kinetic",
+ TRUE,
+ flags));
+
+ activated_widgets = g_tree_new ((GCompareFunc)compare_pointers);
+ current_gdk_window = NULL;
+
+ katze_scrolled_event_handler_append (katze_scrolled_event_handler, NULL);
+
+ g_type_class_add_private (class, sizeof (KatzeScrolledPrivate));
+}
+
+static void
+katze_scrolled_init (KatzeScrolled* scrolled)
+{
+ KatzeScrolledPrivate* priv;
+
+ scrolled->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE ((scrolled),
+ KATZE_TYPE_SCROLLED, KatzeScrolledPrivate);
+
+ priv->interval = DEFAULT_INTERVAL;
+ priv->deceleration = DEFAULT_DECELERATION;
+ priv->drag_scrolling = FALSE;
+ priv->kinetic_scrolling = TRUE;
+ priv->dragging_stopped_delay = DEFAULT_DRAGGING_STOPPED_DELAY;
+}
+
+static void
+katze_scrolled_set_property (GObject* object,
+ guint prop_id,
+ const GValue* value,
+ GParamSpec* pspec)
+{
+ KatzeScrolled* scrolled = KATZE_SCROLLED (object);
+
+ switch (prop_id)
+ {
+ case PROP_DRAG_SCROLLING:
+ katze_scrolled_set_drag_scrolling (scrolled, g_value_get_boolean (value));
+ break;
+ case PROP_KINETIC_SCROLLING:
+ scrolled->priv->kinetic_scrolling = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+katze_scrolled_get_property (GObject* object,
+ guint prop_id,
+ GValue* value,
+ GParamSpec* pspec)
+{
+ KatzeScrolled* scrolled = KATZE_SCROLLED (object);
+
+ switch (prop_id)
+ {
+ case PROP_DRAG_SCROLLING:
+ g_value_set_boolean (value, scrolled->priv->drag_scrolling);
+ break;
+ case PROP_KINETIC_SCROLLING:
+ g_value_set_boolean (value, scrolled->priv->kinetic_scrolling);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * katze_scrolled_new:
+ * @hadjustment: a horizontal #GtkAdjustment, or %NULL
+ * @vadjustment: a vertical #GtkAdjustment, or %NULL
+ *
+ * Creates a new #KatzeScrolled.
+ *
+ * Since: 0.2.0
+ **/
+
+GtkWidget*
+katze_scrolled_new (GtkAdjustment* hadjustment,
+ GtkAdjustment* vadjustment)
+{
+ if (hadjustment)
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), NULL);
+ if (vadjustment)
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), NULL);
+
+ return gtk_widget_new (KATZE_TYPE_SCROLLED,
+ "hadjustment", hadjustment,
+ "vadjustment", vadjustment, NULL);
+}
+
+/**
+ * katze_scrolled_activate_scrolling:
+ * @scrolled: a #KatzeScrolled
+ * @widget: a #GtkWidget of which area is made active event source for
+ * drag and kinetic scrolling.
+ *
+ * Activates the widget so that pointer motion events inside the widget are
+ * used to scroll the #KatzeScrolled. The widget can be a child of the
+ * #KatzeScrolled or even a separate widget ("touchpad" style).
+ *
+ * The direct child of the #KatzeScrolled (typically #GtkViewport) is
+ * activated automatically when added. This function has to be used if indirect
+ * descendant widgets are stopping propagation of the button press and release
+ * as well as motion events (for example GtkButton is doing so) but scrolling
+ * should be possible inside their area too.
+ *
+ * This function adds #GDK_BUTTON_PRESS_MASK, #GDK_BUTTON_RELEASE_MASK,
+ * #GDK_POINTER_MOTION_MASK, and #GDK_MOTION_HINT_MAKS into the widgets event mask.
+ */
+
+static void
+katze_scrolled_activate_scrolling (KatzeScrolled* scrolled,
+ GtkWidget* widget)
+{
+ gtk_widget_add_events (widget,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+ | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
+ g_tree_insert (activated_widgets, widget, scrolled);
+}
+
+static void
+katze_scrolled_set_drag_scrolling (KatzeScrolled* scrolled,
+ gboolean drag_scrolling)
+{
+ KatzeScrolledPrivate* priv = scrolled->priv;
+
+ if (priv->drag_scrolling && !drag_scrolling)
+ {
+ if (priv->scrolling_timeout_id)
+ {
+ g_source_remove (priv->scrolling_timeout_id);
+ priv->scrolling_timeout_id = 0;
+ priv->previous_time = 0;
+ }
+
+ gdk_window_hide (priv->vertical_scrollbar_window);
+ gdk_window_hide (priv->horizontal_scrollbar_window);
+ if (priv->hide_scrollbars_timeout_id)
+ {
+ g_source_remove (priv->hide_scrollbars_timeout_id);
+ priv->hide_scrollbars_timeout_id = 0;
+ }
+
+ priv->press_received = FALSE;
+ }
+
+ priv->drag_scrolling = drag_scrolling;
+}
diff --git a/katze/katze-scrolled.h b/katze/katze-scrolled.h
new file mode 100644
index 0000000..e8787f1
--- /dev/null
+++ b/katze/katze-scrolled.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2007 Henrik Hedberg <hhedberg at innologies.fi>
+ Copyright (C) 2009 Nadav Wiener <nadavwr at yahoo.com>
+ Copyright (C) 2009 Christian Dywan <christian at twotoasts.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See the file COPYING for the full license text.
+ */
+
+#ifndef KATZE_SCROLLED_H
+#define KATZE_SCROLLED_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define KATZE_TYPE_SCROLLED (katze_scrolled_get_type())
+#define KATZE_SCROLLED(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KATZE_TYPE_SCROLLED, KatzeScrolled))
+#define KATZE_SCROLLED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KATZE_TYPE_SCROLLED, KatzeScrolledClass))
+#define KATZE_IS_SCROLLED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KATZE_TYPE_SCROLLED))
+#define KATZE_IS_SCROLLED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KATZE_TYPE_SCROLLED))
+#define KATZE_SCROLLED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KATZE_TYPE_SCROLLED, KatzeScrolledClass))
+
+typedef struct _KatzeScrolled KatzeScrolled;
+typedef struct _KatzeScrolledClass KatzeScrolledClass;
+typedef struct _KatzeScrolledPrivate KatzeScrolledPrivate;
+
+struct _KatzeScrolled
+{
+ GtkScrolledWindow parent;
+
+ KatzeScrolledPrivate* priv;
+};
+
+struct _KatzeScrolledClass
+{
+ GtkScrolledWindowClass parent;
+
+ /* Padding for future expansion */
+ void (*_katze_reserved1) (void);
+ void (*_katze_reserved2) (void);
+ void (*_katze_reserved3) (void);
+ void (*_katze_reserved4) (void);
+};
+
+GType
+katze_scrolled_get_type (void);
+
+GtkWidget*
+katze_scrolled_new (GtkAdjustment* hadjustment,
+ GtkAdjustment* vadjustment);
+
+G_END_DECLS
+
+#endif /* __KATZE_SCROLLED_H__ */
diff --git a/katze/katze.h b/katze/katze.h
index 8dd286b..ab85d27 100644
--- a/katze/katze.h
+++ b/katze/katze.h
@@ -21,5 +21,6 @@
#include "katze-arrayaction.h"
#include "katze-separatoraction.h"
#include "katze-net.h"
+#include "katze-scrolled.h"
#endif /* __KATZE_H__ */
diff --git a/midori/midori-browser.c b/midori/midori-browser.c
index 1b7bc76..4e7b6b8 100644
--- a/midori/midori-browser.c
+++ b/midori/midori-browser.c
@@ -1554,9 +1554,6 @@ _midori_browser_add_tab (MidoriBrowser* browser,
KatzeItem* item;
guint n;
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view),
GTK_SHADOW_ETCHED_IN);
diff --git a/midori/midori-preferences.c b/midori/midori-preferences.c
index 34bfa79..82c19c4 100644
--- a/midori/midori-preferences.c
+++ b/midori/midori-preferences.c
@@ -315,6 +315,9 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
GtkWidget* header;
GtkWindow* parent;
const gchar* icon_name;
+ #if WEBKIT_CHECK_VERSION (1, 1, 15)
+ GtkSettings* gtk_settings;
+ #endif
GtkSizeGroup* sizegroup;
GtkWidget* toolbar;
GtkWidget* toolbutton;
@@ -341,6 +344,9 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
gtk_window_get_title (GTK_WINDOW (preferences)))))
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox),
header, FALSE, FALSE, 0);
+ #if WEBKIT_CHECK_VERSION (1, 1, 15)
+ gtk_settings = parent ? gtk_widget_get_settings (GTK_WIDGET (parent)) : NULL;
+ #endif
preferences->notebook = gtk_notebook_new ();
gtk_container_set_border_width (GTK_CONTAINER (preferences->notebook), 6);
@@ -487,9 +493,14 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
gtk_widget_set_tooltip_text (button, _("Load and display images automatically"));
INDENTED_ADD (button, 0, 1, 0, 1);
#if WEBKIT_CHECK_VERSION (1, 1, 15)
- button = katze_property_proxy (settings, "auto-shrink-images", NULL);
- gtk_button_set_label (GTK_BUTTON (button), _("Shrink images automatically"));
- gtk_widget_set_tooltip_text (button, _("Automatically shrink standalone images to fit"));
+ if (katze_object_get_boolean (gtk_settings, "gtk-touchscreen-mode"))
+ button = katze_property_proxy (settings, "kinetic-scrolling", NULL);
+ else
+ {
+ button = katze_property_proxy (settings, "auto-shrink-images", NULL);
+ gtk_button_set_label (GTK_BUTTON (button), _("Shrink images automatically"));
+ gtk_widget_set_tooltip_text (button, _("Automatically shrink standalone images to fit"));
+ }
#else
button = katze_property_proxy (settings, "middle-click-opens-selection", NULL);
#endif
diff --git a/midori/midori-view.c b/midori/midori-view.c
index 942f9d7..f3c17ba 100644
--- a/midori/midori-view.c
+++ b/midori/midori-view.c
@@ -59,7 +59,7 @@ midori_view_item_meta_data_changed (KatzeItem* item,
struct _MidoriView
{
- GtkScrolledWindow parent_instance;
+ KatzeScrolled parent_instance;
gchar* uri;
gchar* title;
@@ -104,10 +104,10 @@ struct _MidoriView
struct _MidoriViewClass
{
- GtkScrolledWindowClass parent_class;
+ KatzeScrolledClass parent_class;
};
-G_DEFINE_TYPE (MidoriView, midori_view, GTK_TYPE_SCROLLED_WINDOW)
+G_DEFINE_TYPE (MidoriView, midori_view, KATZE_TYPE_SCROLLED);
GType
midori_load_status_get_type (void)
@@ -1525,6 +1525,9 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
katze_object_assign (view->hit_test,
webkit_web_view_get_hit_test_result (web_view, &event));
context = katze_object_get_int (view->hit_test, "context");
+ /* Ensure view->link_uri is correct. */
+ katze_assign (view->link_uri,
+ katze_object_get_string (view->hit_test, "link-uri"));
has_selection = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;
/* Ensure view->selected_text */
midori_view_has_selection (view);
@@ -1533,6 +1536,8 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
is_media = context & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
is_document = !view->link_uri && !has_selection && !is_image && !is_media;
#else
+ /* There is no guarantee view->link_uri is correct in case
+ gtk-touchscreen-mode is enabled, nothing we can do. */
has_selection = midori_view_has_selection (view);
is_document = !view->link_uri && !has_selection;
@@ -2329,13 +2334,14 @@ midori_view_new (KatzeNet* net)
static void
_midori_view_update_settings (MidoriView* view)
{
- gboolean zoom_text_and_images;
+ gboolean zoom_text_and_images, kinetic_scrolling;
g_object_get (view->settings,
"speed-dial-in-new-tabs", &view->speed_dial_in_new_tabs,
"download-manager", &view->download_manager,
"news-aggregator", &view->news_aggregator,
"zoom-text-and-images", &zoom_text_and_images,
+ "kinetic-scrolling", &kinetic_scrolling,
"close-buttons-on-tabs", &view->close_buttons_on_tabs,
"open-new-pages-in", &view->open_new_pages_in,
"ask-for-destination-folder", &view->ask_for_destination_folder,
@@ -2345,8 +2351,9 @@ _midori_view_update_settings (MidoriView* view)
NULL);
if (view->web_view)
- g_object_set (view->web_view, "full-content-zoom",
- zoom_text_and_images, NULL);
+ g_object_set (view->web_view,
+ "full-content-zoom", zoom_text_and_images, NULL);
+ g_object_set (view, "kinetic-scrolling", kinetic_scrolling, NULL);
}
static void
@@ -2379,6 +2386,11 @@ midori_view_settings_notify_cb (MidoriWebSettings* settings,
g_object_set (view->web_view, "full-content-zoom",
g_value_get_boolean (&value), NULL);
}
+ else if (name == g_intern_string ("kinetic-scrolling"))
+ {
+ g_object_set (view, "kinetic-scrolling",
+ g_value_get_boolean (&value), NULL);
+ }
else if (name == g_intern_string ("close-buttons-on-tabs"))
{
view->close_buttons_on_tabs = g_value_get_boolean (&value);
diff --git a/midori/midori-websettings.c b/midori/midori-websettings.c
index 9ef8b40..336a14f 100644
--- a/midori/midori-websettings.c
+++ b/midori/midori-websettings.c
@@ -75,6 +75,7 @@ struct _MidoriWebSettings
gboolean zoom_text_and_images;
gboolean find_while_typing;
+ gboolean kinetic_scrolling;
MidoriAcceptCookies accept_cookies;
gboolean original_cookies_only;
gint maximum_cookie_age;
@@ -151,6 +152,7 @@ enum
PROP_ZOOM_TEXT_AND_IMAGES,
PROP_FIND_WHILE_TYPING,
+ PROP_KINETIC_SCROLLING,
PROP_ACCEPT_COOKIES,
PROP_ORIGINAL_COOKIES_ONLY,
PROP_MAXIMUM_COOKIE_AGE,
@@ -833,6 +835,22 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
FALSE,
flags));
+ /**
+ * MidoriWebSettings:kinetic-scrolling:
+ *
+ * Whether scrolling should kinetically move according to speed.
+ *
+ * Since: 0.2.0
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_KINETIC_SCROLLING,
+ g_param_spec_boolean (
+ "kinetic-scrolling",
+ _("Kinetic scrolling"),
+ _("Whether scrolling should kinetically move according to speed"),
+ TRUE,
+ flags));
+
g_object_class_install_property (gobject_class,
PROP_ACCEPT_COOKIES,
g_param_spec_enum (
@@ -1025,6 +1043,7 @@ midori_web_settings_init (MidoriWebSettings* web_settings)
web_settings->open_popups_in_tabs = TRUE;
web_settings->remember_last_form_inputs = TRUE;
web_settings->remember_last_downloaded_files = TRUE;
+ web_settings->kinetic_scrolling = TRUE;
web_settings->auto_detect_proxy = TRUE;
g_signal_connect (web_settings, "notify::default-encoding",
@@ -1303,6 +1322,9 @@ midori_web_settings_set_property (GObject* object,
case PROP_FIND_WHILE_TYPING:
web_settings->find_while_typing = g_value_get_boolean (value);
break;
+ case PROP_KINETIC_SCROLLING:
+ web_settings->kinetic_scrolling = g_value_get_boolean (value);
+ break;
case PROP_ACCEPT_COOKIES:
web_settings->accept_cookies = g_value_get_enum (value);
break;
@@ -1506,6 +1528,9 @@ midori_web_settings_get_property (GObject* object,
case PROP_FIND_WHILE_TYPING:
g_value_set_boolean (value, web_settings->find_while_typing);
break;
+ case PROP_KINETIC_SCROLLING:
+ g_value_set_boolean (value, web_settings->kinetic_scrolling);
+ break;
case PROP_ACCEPT_COOKIES:
g_value_set_enum (value, web_settings->accept_cookies);
break;
More information about the Xfce4-commits
mailing list