# HG changeset patch # User masca@cpw.pidgin.im # Date 1265494685 0 # Node ID 24c8a98a6acc8feae22305c4229c1d6aceced132 # Parent 23b16f51e15a247289591c7306a8975b4d10fe9b webkit: Scroll to end when appending html. Most of the code was taken from imhtml. diff -r 23b16f51e15a -r 24c8a98a6acc pidgin/gtkconv.c --- a/pidgin/gtkconv.c Sat Feb 06 22:08:41 2010 +0000 +++ b/pidgin/gtkconv.c Sat Feb 06 22:18:05 2010 +0000 @@ -4915,6 +4915,8 @@ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (webview_sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtkconv->webview = gtk_webview_new (); + gtk_webview_set_vadjustment(GTK_WEBVIEW(gtkconv->webview), + gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(webview_sw))); gtk_container_add (GTK_CONTAINER (webview_sw), gtkconv->webview); gtk_widget_set_size_request(gtkconv->webview, -1, 0); diff -r 23b16f51e15a -r 24c8a98a6acc pidgin/gtkwebview.c --- a/pidgin/gtkwebview.c Sat Feb 06 22:08:41 2010 +0000 +++ b/pidgin/gtkwebview.c Sat Feb 06 22:18:05 2010 +0000 @@ -48,6 +48,9 @@ /* JS execute queue */ GQueue *js_queue; gboolean is_loading; + GtkAdjustment *vadj; + guint scroll_src; + GTimer *scroll_time; }; GtkWidget* gtk_webview_new (void) @@ -290,6 +293,10 @@ return g_string_free (str, FALSE); } +void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj) +{ + webview->priv->vadj = vadj; +} /* this is a "hack", my plan is to eventually handle this * correctly using a signals and a plugin: the plugin will have @@ -304,6 +311,7 @@ printf ("script: %s\n", script); webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), script); view->priv->empty = FALSE; + gtk_webview_scroll_to_end(view, TRUE); g_free (script); g_free (escaped); } @@ -313,6 +321,65 @@ return view->priv->empty; } +#define MAX_SCROLL_TIME 0.4 /* seconds */ +#define SCROLL_DELAY 33 /* milliseconds */ + +/* + * Smoothly scroll a WebView. + * + * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. + */ +static gboolean smooth_scroll_cb(gpointer data) +{ + struct GtkWebViewPriv *priv = data; + GtkAdjustment *adj = priv->vadj; + gdouble max_val = adj->upper - adj->page_size; + gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3); + + g_return_val_if_fail(priv->scroll_time != NULL, FALSE); + + if (g_timer_elapsed(priv->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) { + /* time's up. jump to the end and kill the timer */ + gtk_adjustment_set_value(adj, max_val); + g_timer_destroy(priv->scroll_time); + priv->scroll_time = NULL; + g_source_remove(priv->scroll_src); + priv->scroll_src = 0; + return FALSE; + } + + /* scroll by 1/3rd the remaining distance */ + gtk_adjustment_set_value(adj, scroll_val); + return TRUE; +} + +static gboolean scroll_idle_cb(gpointer data) +{ + struct GtkWebViewPriv *priv = data; + GtkAdjustment *adj = priv->vadj; + if(adj) { + gtk_adjustment_set_value(adj, adj->upper - adj->page_size); + } + priv->scroll_src = 0; + return FALSE; +} + +void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth) +{ + struct GtkWebViewPriv *priv = webview->priv; + if (priv->scroll_time) + g_timer_destroy(priv->scroll_time); + if (priv->scroll_src) + g_source_remove(priv->scroll_src); + if(smooth) { + priv->scroll_time = g_timer_new(); + priv->scroll_src = g_timeout_add_full(G_PRIORITY_LOW, SCROLL_DELAY, smooth_scroll_cb, priv, NULL); + } else { + priv->scroll_time = NULL; + priv->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, priv, NULL); + } +} + GType gtk_webview_get_type (void) { static GType mview_type = 0; diff -r 23b16f51e15a -r 24c8a98a6acc pidgin/gtkwebview.h --- a/pidgin/gtkwebview.h Sat Feb 06 22:08:41 2010 +0000 +++ b/pidgin/gtkwebview.h Sat Feb 06 22:18:05 2010 +0000 @@ -73,6 +73,14 @@ GtkWidget* gtk_webview_new (void); /** + * Set the vertical adjustment for the GtkWebView. + * + * @param webview The GtkWebView. + * @param vadj The GtkAdjustment that control the webview. + */ +void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj); + +/** * A very basic routine to append html, which can be considered * equivalent to a "document.write" using JavaScript. * @@ -124,4 +132,12 @@ */ char* gtk_webview_quote_js_string (const char* str); +/** + * Scrolls the Webview to the end of its contents. + * + * @param webview The GtkWebView. + * @param smoth A boolean indicating if smooth scrolling should be used. + */ +void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth); + #endif /* _PIDGIN_WEBVIEW_H_ */