soc.2009.webkitmessageview: b7d6654d: webkit: Scroll to end when appending htm...

masca at cpw.pidgin.im masca at cpw.pidgin.im
Sat Feb 6 17:26:24 EST 2010


-----------------------------------------------------------------
Revision: b7d6654d1d021c7532b71594ebcd325ee7b14456
Ancestor: bb76fe6ad2d9f7f8803db3d7bd34444111107caa
Author: masca at cpw.pidgin.im
Date: 2010-02-06T22:18:05
Branch: im.pidgin.soc.2009.webkitmessageview
URL: http://d.pidgin.im/viewmtn/revision/info/b7d6654d1d021c7532b71594ebcd325ee7b14456

Modified files:
        pidgin/gtkconv.c pidgin/gtkwebview.c pidgin/gtkwebview.h

ChangeLog: 


webkit: Scroll to end when appending html.

Most of the code was taken from imhtml.

-------------- next part --------------
============================================================
--- pidgin/gtkconv.c	1bbb2ffbe149b9c0824d354e70029702f4046a33
+++ pidgin/gtkconv.c	ce21c33ba93a87f354c433c07274f4f923609f5e
@@ -4915,6 +4915,8 @@ setup_common_pane(PidginConversation *gt
         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);
============================================================
--- pidgin/gtkwebview.c	bfedf0416858968394db3ae3083643f37fda14e1
+++ pidgin/gtkwebview.c	65d96c09c04829a05e1b4838e57a3aa90466f2f8
@@ -48,6 +48,9 @@ struct GtkWebViewPriv {
 	/* 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 @@ char *gtk_webview_quote_js_string(const 
 	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 @@ gtk_webview_append_html (GtkWebView* vie
 	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 @@ gboolean gtk_webview_is_empty (GtkWebVie
 	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;
============================================================
--- pidgin/gtkwebview.h	916745054254d00d1da0d77f4d7ce6a18a551cb3
+++ pidgin/gtkwebview.h	e78dca4f64edf567173dd5421ba60614bd6edd39
@@ -73,6 +73,14 @@ GtkWidget* gtk_webview_new (void);
 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* 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_ */


More information about the Commits mailing list