comparison pidgin/gtkwebview.c @ 32581:24c8a98a6acc

webkit: Scroll to end when appending html. Most of the code was taken from imhtml.
author masca@cpw.pidgin.im
date Sat, 06 Feb 2010 22:18:05 +0000
parents 1cebf9aa291a
children 1795afae76f2
comparison
equal deleted inserted replaced
32580:23b16f51e15a 32581:24c8a98a6acc
46 gboolean empty; /**< whether anything has been appended **/ 46 gboolean empty; /**< whether anything has been appended **/
47 47
48 /* JS execute queue */ 48 /* JS execute queue */
49 GQueue *js_queue; 49 GQueue *js_queue;
50 gboolean is_loading; 50 gboolean is_loading;
51 GtkAdjustment *vadj;
52 guint scroll_src;
53 GTimer *scroll_time;
51 }; 54 };
52 55
53 GtkWidget* gtk_webview_new (void) 56 GtkWidget* gtk_webview_new (void)
54 { 57 {
55 GtkWebView* ret = GTK_WEBVIEW (g_object_new(gtk_webview_get_type(), NULL)); 58 GtkWebView* ret = GTK_WEBVIEW (g_object_new(gtk_webview_get_type(), NULL));
288 } 291 }
289 g_string_append_c (str, '"'); 292 g_string_append_c (str, '"');
290 return g_string_free (str, FALSE); 293 return g_string_free (str, FALSE);
291 } 294 }
292 295
296 void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj)
297 {
298 webview->priv->vadj = vadj;
299 }
293 300
294 /* this is a "hack", my plan is to eventually handle this 301 /* this is a "hack", my plan is to eventually handle this
295 * correctly using a signals and a plugin: the plugin will have 302 * correctly using a signals and a plugin: the plugin will have
296 * the information as to what javascript function to call. It seems 303 * the information as to what javascript function to call. It seems
297 * wrong to hardcode that here. 304 * wrong to hardcode that here.
302 char* escaped = gtk_webview_quote_js_string (html); 309 char* escaped = gtk_webview_quote_js_string (html);
303 char* script = g_strdup_printf ("document.write(%s)", escaped); 310 char* script = g_strdup_printf ("document.write(%s)", escaped);
304 printf ("script: %s\n", script); 311 printf ("script: %s\n", script);
305 webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), script); 312 webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), script);
306 view->priv->empty = FALSE; 313 view->priv->empty = FALSE;
314 gtk_webview_scroll_to_end(view, TRUE);
307 g_free (script); 315 g_free (script);
308 g_free (escaped); 316 g_free (escaped);
309 } 317 }
310 318
311 gboolean gtk_webview_is_empty (GtkWebView *view) 319 gboolean gtk_webview_is_empty (GtkWebView *view)
312 { 320 {
313 return view->priv->empty; 321 return view->priv->empty;
322 }
323
324 #define MAX_SCROLL_TIME 0.4 /* seconds */
325 #define SCROLL_DELAY 33 /* milliseconds */
326
327 /*
328 * Smoothly scroll a WebView.
329 *
330 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom.
331 */
332 static gboolean smooth_scroll_cb(gpointer data)
333 {
334 struct GtkWebViewPriv *priv = data;
335 GtkAdjustment *adj = priv->vadj;
336 gdouble max_val = adj->upper - adj->page_size;
337 gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3);
338
339 g_return_val_if_fail(priv->scroll_time != NULL, FALSE);
340
341 if (g_timer_elapsed(priv->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) {
342 /* time's up. jump to the end and kill the timer */
343 gtk_adjustment_set_value(adj, max_val);
344 g_timer_destroy(priv->scroll_time);
345 priv->scroll_time = NULL;
346 g_source_remove(priv->scroll_src);
347 priv->scroll_src = 0;
348 return FALSE;
349 }
350
351 /* scroll by 1/3rd the remaining distance */
352 gtk_adjustment_set_value(adj, scroll_val);
353 return TRUE;
354 }
355
356 static gboolean scroll_idle_cb(gpointer data)
357 {
358 struct GtkWebViewPriv *priv = data;
359 GtkAdjustment *adj = priv->vadj;
360 if(adj) {
361 gtk_adjustment_set_value(adj, adj->upper - adj->page_size);
362 }
363 priv->scroll_src = 0;
364 return FALSE;
365 }
366
367 void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth)
368 {
369 struct GtkWebViewPriv *priv = webview->priv;
370 if (priv->scroll_time)
371 g_timer_destroy(priv->scroll_time);
372 if (priv->scroll_src)
373 g_source_remove(priv->scroll_src);
374 if(smooth) {
375 priv->scroll_time = g_timer_new();
376 priv->scroll_src = g_timeout_add_full(G_PRIORITY_LOW, SCROLL_DELAY, smooth_scroll_cb, priv, NULL);
377 } else {
378 priv->scroll_time = NULL;
379 priv->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, priv, NULL);
380 }
314 } 381 }
315 382
316 GType gtk_webview_get_type (void) 383 GType gtk_webview_get_type (void)
317 { 384 {
318 static GType mview_type = 0; 385 static GType mview_type = 0;