GtkWidgetブラウザコンポーネント比較その1

概要

最近、HTMLレンダリングエンジンを利用したプログラム作成を目論んでるので、調査してわかったことのメモです。代表的な物にXULRunnerとWebkit(以前も少し触った事がありましたが)の2種類が使えるようですが、どちらもGtkWedgetとして扱えるようです。

環境

Ubuntu-9.10-i386Athlon64-300+/512MB

ライブラリの種類と概要

% ldd /usr/lib/firefox-3.6.3/firefox-bin | grep xul
        libxul.so => not found(起動スクリプト時に参照libディレクトリを指定してるの?)
 % ldd /usr/bin/epiphany-browser | grep webkit
        libwebkit-1.0.so.2 => /usr/lib/libwebkit-1.0.so.2 
 % ldd /usr/lib/chromium-browser/chromium-browser | grep webkit
        なし

両ライブラリのAPI比較

やりたいこと/動作機能 XULRunner Webkit
インクルードヘッダ
コンパイル方法 cc -o browser browser.c `pkg-config --cflags --libs xulrunner-gtkmozembed gtk+-2.0` cc -o browser browser.c `pkg-config --cflags --libs webkit-1.0 gtk+-2.0`
GtkWidgetを作成 gtk_moz_embed_new webkit_web_view_new
指定したURLを開く gtk_moz_embed_load_url webkit_web_view_open
現在表示しているURLを取得 gtk_moz_embed_get_location webkit_web_view_get_uri
戻る gtk_moz_embed_go_back webkit_web_view_go_back
進む gtk_moz_embed_go_forward webkit_web_view_go_forward
更新(リロード) gtk_moz_embed_reload webkit_web_view_reload

両方APIの形は非常に似てます。高度なAPI操作をしなければ完全に1:1でマッピングできそうです。

ソース例

#include 
#include 
#ifdef USE_XUL
#include 
#define WEBVIEW_TYPE GtkMozEmbed*
#define WEBVIEW_FUNC_NEW() GTK_MOZ_EMBED(gtk_moz_embed_new())
#define WEBVIEW_FUNC_GETURL(n) gtk_moz_embed_get_location(n)
#define WEBVIEW_FUNC_SETURL(n, url) gtk_moz_embed_load_url(n, url)
#define WEBVIEW_FUNC_BACK(n) gtk_moz_embed_go_back(n)
#define WEBVIEW_FUNC_FORWARD(n) gtk_moz_embed_go_forward(n)
#define WEBVIEW_FUNC_RELOAD(n) gtk_moz_embed_reload(n, gtk_moz_embed_reload)
#else
#include 
#define WEBVIEW_TYPE WebKitWebView*
#define WEBVIEW_FUNC_NEW() WEBKIT_WEB_VIEW(webkit_web_view_new())
#define WEBVIEW_FUNC_GETURL(n) webkit_web_view_get_uri(n)
#define WEBVIEW_FUNC_SETURL(n, url) webkit_web_view_open(n, url)
#define WEBVIEW_FUNC_BACK(n) webkit_web_view_go_back(n)
#define WEBVIEW_FUNC_FORWARD(n) webkit_web_view_go_forward(n)
#define WEBVIEW_FUNC_RELOAD(n) webkit_web_view_reload(n)
#endif

GtkWidget* window; // メインウインドウ
WEBVIEW_TYPE web_view;

// キーイベントハンドラ関数
void my_keyevent(GtkWidget *widget, GdkEvent *event, gpointer data) {
        GdkEventKey *kevent = (GdkEventKey *) event;
        if (kevent->keyval == 0xFF1B) { // ESCボタンを押されたら終了
                g_signal_emit_by_name(window, "destroy", NULL, NULL);
        }
}

void my_destroyevent(GtkWidget *widget, GdkEvent *event, gpointer data) {
        gtk_main_quit();
}

// gtk-windowを作成する
int gtk_window_main(int argc, char *argv) {
        // GTKの初期化
        if (!g_thread_supported()) {
                g_thread_init(NULL);
                gdk_threads_init();
        }
        gtk_init_check(&argc, &argv);

        // GTKウインドウを作る
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        web_view = WEBVIEW_FUNC_NEW();

        GtkWidget* scrolled;
        scrolled = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(web_view));
        gtk_container_add(GTK_CONTAINER(window), scrolled);

        gtk_window_set_title(GTK_WINDOW(window), "WebViewGTK Demo");
        gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
        gtk_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(
                        my_keyevent), NULL);
        gtk_signal_connect(G_OBJECT(window), "destroy",
                        G_CALLBACK(my_destroyevent), NULL);

        WEBVIEW_FUNC_SETURL(web_view, "http://www.google.com");

        // 全ウィジェットを可視化しGTKメイン関数に入る
        gtk_widget_show_all(window);
        gtk_main();

        return 0;
}

// main関数
int main(int argc, char *argv) {
        // gtk_window_mainの初期化
        gtk_window_main(argc, argv);

        return 0;
}

サンプルプログラムではシングルスレッド前提として作成してるのでロック処理を実装してませんが、マルチスレッドを含む箇所から制御する場合はGTKのロック制御が必要になります。そこらへんの内容は↓のURL先を参照してください。

http://www.gnome.gr.jp/docs/gtk+faq.20040114.html

本当はJavaScriptの速度比較、起動速度の違いとかも評価してみたかったのですがそこまで出来ませんでした。今後そこらへんも比較できればいいなとおもいます。