最近更新: 2010-10-27

JavaScript 與 Desktop - WebKit

繼《JavaScript 與 Desktop - DBus 》,本文將說明 gjs/seed 如何結合 GTK 和 WebKit 設計 GUI。由於本系列文章的重點,放在將 Web UI 的開發經驗延續到桌面軟體的開發上,因此在 GTK 方面僅著墨於如何開啟一個視窗,並加入一個 WebKit 元件;換一個較易理解的說法是,建立一個桌面視窗,並嵌入一個 Web 瀏覽器呈現網頁內容。

gjs/seed 藉由 GNOME GObject Introspection 機制結合既有的 glib bindings ,包括 GTK, WebKit 在內。這使得它們的開發團隊不需要額外維護與擴充自己的函數庫。在 gjs/seed 中使用 GTK, WebKit 等函數庫的方式,和其他程式語言環境相差無幾。對於曾經使用過 GTK, WebKit 的使用者而言,可以延續以往的使用經驗,不需重新學習。當然對於不曾接觸過 GTK 和 WebKit 的使用者而言,還是要學一些東西。

GTK and WebKit

想要開發一個桌面 GUI 軟體,第一件要做的事,就是建立一個視窗。視窗建立之後,我們才有一個容器,可以讓我們擺放其他的視覺化元件,例如選單、面板、按鍵、表單等等。

在 Linux 桌面環境中,有許多 GUI 函數庫,最被廣泛使用的是 GTK 和 Qt 。由於 GTK 和 GNOME Library 的整合度最高,因此基於 GNOME Library 的開發工具通常也採用 GTK 開發 GUI 軟體。gjs/seed 自然也如此。

Debian/Ubuntu 的使用者需要安裝以下套件: gir1.0-gtk-2.0, gir1.0-webkit-1.0, gir1.0-soup-2.4 。 gir 是 GObject Introspection Repository 之意。與其綁定的函數庫,可以被其他支援 gir 的程式語言載入。gjs/seed 就是透過這個途徑,使用 GTK, WebKit 等函數庫。

我們來看看我們的第一個範例程式: gtk.js 。它的工作很簡單,調用 GTK 建立一個視窗,再往上面擺一個 WebKit 元件。至於視窗上的畫面內容,就全部使用 HTML+CSS 設計,交給 WebKit 元件呈現。

var GLib = imports.gi.GLib;
var Gtk = imports.gi.Gtk;
var WebKit = imports.gi.WebKit;
// apt-get install git1.0-gtk-2.0 gir1.0-webkit-1.0, gir1.0-soup-2.4


GLib.set_prgname('hello');
Gtk.init(0, null);

var w = new Gtk.Window();

//GTK event: destroy

if ('signal' in w) // Seed implementation

    w.signal.hide.connect(Gtk.main_quit);
else
    w.connect("destroy", Gtk.main_quit);

var view = new WebKit.WebView();
w.add(view);

view.load_html_string('<p>hello <em>world</em>. ' +
    '<a href="http://www.google.com">Google</a></p>',
    "file://null"); //base url


/*
typedef enum
{
  GTK_WIN_POS_NONE,
  GTK_WIN_POS_CENTER,
  GTK_WIN_POS_MOUSE,
  GTK_WIN_POS_CENTER_ALWAYS,
  GTK_WIN_POS_CENTER_ON_PARENT
} GtkWindowPosition;
*/
w.set_position(1); //GTK_WIN_POS_CENTER

w.show_all();

print("Working...")
Gtk.main(); // gtk loop, quit by main_quit().

print("Goodbye");

執行它,就會在畫面中間看到一個我們建立的視窗以及用 HTML 描述的內容。

$ gjs gtk.js
Working...
Goodbye

由於 gjs/seed 都是載入同一個 GNOME GTK Library ,所以兩者的 GTK 使用方式基本相同。但是對於 GTK Signal 的處理方式有所差異。gjs 使用 Widget::connect() 方法指派 GTK Signal 的傾聽者;seed 則是使用 Widget::signal.???.connect()。本文基本上以 gjs 為主要工具,故以下範例若無特別說明,皆只適用 gjs 。

GTK 視窗 API 的參考文件,請見 GTK+ Reference Manual。WebKitGtk+ API 的參考文件,請見 WebKitGTK+ Reference Manual 。只是這兩份文件都是 C 語言 API 的文件,不具 C 語言基礎者閱讀時要多花點功夫。

將既有的 Web 軟體搬到桌面軟體中

為了展示 HTML5 向桌面軟體開發領域延伸的企圖,我曾經用 HTML5 結合 XULRunner 寫了一篇文章,即《Hello HTML5 and XULRunner》。由於 HTML5 是一種與開發環境無關的 UI 描述語言,它所描述的 UI 內容,不只可以被 XULRunner 使用,也可以用於 WebKit。本節將直接使用《Hello HTML5 and XULRunner》所使用的 html,css 等內容於 WebKit 中。我們只需要讓 WebKit 載入我們的首頁。

XULRunner 和 WebKit 一樣,都是 HTTP client + HTML/CSS render + JavaScript DOM host。所以它們都可以呈現 HTML/CSS 的內容,並提供我們一個以 JavaScript 控制 DOM (W3C Document Object Model) 的環境。

執行本節的範例程式(gtk-webkit.js)需要下列文件。那些文件都是《Hello HTML5 and XULRunner》用過的,請參考該文,本文不在列出它們的內容。

  • index.html
  • site.js
  • jquery-1.4.2.min.js
  • Big_Buck_Bunny_small.ogv
  • butterfly.svg

上列文件內容,我仍然保留著,都存在 /home/rock/hello_xulrunner/chrome/context 的目錄下。我接下來要做的事,就是用 WebKitView::load_uri() 方法,讓 WebKit 載入我放在那個目錄下的 index.html 。

var GLib = imports.gi.GLib;
var Gtk = imports.gi.Gtk;
var WebKit = imports.gi.WebKit;
// apt-get install git1.0-gtk-2.0 gir1.0-webkit-1.0, gir1.0-soup-2.4


GLib.set_prgname('hello webkit');
Gtk.init(0, null);

var w = new Gtk.Window();

//GTK event: destroy

w.connect("destroy", Gtk.main_quit);

var view = new WebKit.WebView();
w.add(view);

// WebKit: for security reason, you must give absolute path.

view.load_uri("file:///home/rock/hello_xulrunner/chrome/content/index.html");

w.set_position(1); //GTK_WIN_POS_CENTER

w.show_all();

Gtk.main(); // gtk loop, quit by main_quit().

print("Goodbye");

gjs gtk-webkit.js

基於安全理由,WebKit 不允許使用相對路徑指向本地文件。所以呼叫 load_uri() 時,必須給它絕對路徑。而在 index.html 中所使用的其他外部資源,只要以相對路徑描述者,皆使用 load_uri() 載入之文件的目錄路徑,作為基礎路徑 (base url)。

小結

本節的兩個範例,只是示範如何使用 gjs/seed 建立桌面視窗軟體,並透過 WebKit 使用 HTML+CSS 處理 UI。但還只是讓 WebKit 與網路上的資源互動,就像是普通的 Web 軟體一樣。我接下來還會寫一篇文章,說明如何讓 WebKit 中的程式與桌面環境互動,例如調用 D-Bus 。

我曾經使用 PHP, Ruby 甚至 Python ,結合 Glade 設計 GUI 軟體,例如《以 PHP-GTK + Glade 設計桌面應用程式 - 混合 Web 應用程式的 MVC 架構途徑 》。不過結合 WebKit 還是頭一遭。我也還在摸索 WebKit 的使用技巧,歡迎各位提供意見。

相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/14282187.html