2010/10/28

ibus 無調注音支援空白鍵作為一聲

最近都在修改 ibus 的注音輸入法,這次新增的功能是把原本空白鍵的導引鍵功能,改成支援陰平聲調(也就是注音聲調中的一聲)。之前的無調注音雖然好用,不過許多人還是習慣在輸入的時候鍵入聲調。而 ibus 注音輸入法遇到聲調目前會自動忽略,所以就算你輸入聲調也不會有什麼問題,不過令人困擾的是平常繁體中文使用者使用空白鍵作為聲調中的一聲,正巧跟 ibus 注音輸入法的導引鍵衝突。所以我花了一些時間加入空白鍵作為一聲的支援。

相同的源碼我都放在 github 上,現在要使用新增的功能都需要編譯源碼。晚點我測試的差不多後就會推到官方 ibus 的 repository 中。

新的 ibus 注音輸入法在設定的地方會多一個空白鍵功能的選項。



現在預設會使用陰平聲調,所以新的使用者不需要調整。之前有使用 ibus 注音輸入法的使用者只需要切換這個選項就可以讓空白鍵變成陰平聲調。

2010/10/20

ibus-pinyin-bopomofo 無調注音輸入法新增 enter 直接輸出第一個候選字

最近正在參與 ibus 中的無調注音輸入法 (pinyin-bopomofo) 的開發。希望能夠讓這個輸入法更好用,並且也同時考慮到對岸以及台灣使用者的使用習慣。

這次修改的是加入 enter 鍵的功能選項。原本的輸入法按下 enter 後會輸出原本的英文字串。比如說輸入 yurenju 雖然剛開始會變成好像是亂打的字如下圖:


不過當你按下 Enter 之後就會變成 yurenju。不過台灣的中文使用者有些比較習慣按下 Enter 後輸出的是第一個候選詞。所以小弟新增了一個小功能,讓使用者可以在設定裡面調整 Enter 鍵的功能。源碼在 github 上,現在要使用必須直接編譯源碼。新的版本預設會讓按下 Enter 後輸出第一個候選字,不過也可以在設定裡面調整。


另外在我 github 的版本也有把 shift + , 與 shift + . 重新 mapping 到全形的逗點跟句點了。接下來會看一些 issues 有哪些要幫忙解。

2010/10/19

[筆記] gdb C++ 小技巧

以前自己用 gdb 都是拿來 debug C 語言的程式,這次拿來對 C++ 除錯發現有些小地方要注意的。

第一個是 C++ 字串。平常印出 C 語言的字串只需要用 print str_var 就可以了,不過要印出 C++ 的字串則是要用 print str_var.c_str()。

另外一個要注意的是 breakpoint 的設定方式。breakpoint 的設定可以用行號或者是 function name,不過如果在 C++ 除錯時如果有 namespace 必須要打出完整的 name + class + method name。比如說 ibus 的 PYBopomofoEditor.cc 裡面有 BopomofoEditor::processBopomofo method,要設定中斷點就必須打


b PY::BopomofoEditor::processBopomofo(unsigned int, unsigned int, unsigned int)


我想你也會跟我一樣覺得打這串也太長了吧,不過 gdb 支援自動補齊,只要打 PY::Bo 之後按下 Tab 鍵就可以用自動補齊的方式快速的打完整串了。

2010/10/12

printf debug 大法?改用 gdb 取代 printf debug 方式

這個東西 jserv 在好久以前的演講就提過,不過今天要用又找了一會才找到,筆記與此。

很多時候在 debug 的時候只是要確定程式跑到那段時,大概有很大的機率會加入 printf 到程式碼裡面來進行這樣的 debug 動作。不過使用 printf 每次都要重新編譯源碼實在是有點麻煩,而使用 gdb print 資訊可以在不更動源碼也不會有每次都因為設定中斷點就停下來的問題。

比如說有以下程式:
switch (m_punct_mode) {
    case MODE_DISABLE:
        {
            g_assert (ch == IBUS_grave);
            ...
            update ();
        }
        break;
    case MODE_INIT:
        {
            m_text.clear ();
            ...
            m_cursor = 0;
        }
    case MODE_NORMAL:
        {
            m_text.insert (m_cursor, ch);
            ...
            update ();
        }
        break;
    default:
        g_assert_not_reached ();
    }

我們想在程式運行時知道到底跑到那個 switch case, 就可以用 gdb 來 print。其中的原理是利用中斷之後執行一小段 gdb 命令來達成。gdb 有個指令叫做 commands 可以在中斷後自動執行一小段 gdb 指令,所以如果我們使用 command 指令再配合 print 以及 continue 就可以做出類似 printf 的除錯功能。比如說第一個中斷點的設定方式則為:

b editor.cc:4
commands
print "MODE_DISABLE"
continue
end

這樣執行時就可以讓 gdb 印出資訊達到 printf 的效果,但卻不用重新編譯源碼。

2010/10/06

Linux 無調注音輸入法 - ibus-pinyin-bopomofo

前幾天,PingoooHychen 在 TOSSUG 討論最近 Ubuntu 10.04 的 ibus 輸入法有很多 issues,然後又聊到對岸的拼音輸入法比起注音輸入法少打了聲調速度好像快很多之後,我們三個就想說是不是自己來修一下 ibus 的問題,順便看有沒有可能寫出無調的注音輸入法。

無調注音輸入法的概念也很簡單,基本上跟使用新酷音用法差不多,但是不需要輸入一二三四聲,所以才稱爲無調注音。基本上拼音輸入法原本就不需要輸入聲調,理論上我們可以基於拼音輸入法把英文拼音轉換成注音這樣的基礎原理來創造無調注音輸入法。

沒想到前幾天 hychen 丟出了一個對岸同胞作出以拼音爲基礎的注音輸入法,正巧是我們想要的無調注音輸入法!

這個注音輸入法是基於 ibus-pinyin 所作的注音輸入法,雖然說目前正在研發還不是很穩定,不過基本上方向是與我們心目中的無調注音輸入法是相同的。要在 Ubuntu 10.04 安裝也是相當容易,輸入以下指令即可安裝:

sudo add-apt-repository ppa:shawn-p-huang/ppa
sudo apt-get update
sudo apt-get install ibus-gtk ibus-qt ibus-pinyin ibus-pinyin-db-open-phrase
 

這兩天試用了一下發現有些問題先筆記起來,或許有機會可以提交到原作者的『注音模式用戶交互設計方案』,這些發現是基於一個新酷音使用者的意見回饋,或許拼音輸入法的使用者有更好的使用方式,只是我只試用兩天還沒發現罷了

  1. 輸入完畢後,如果輸入法候選字都正確時,不能直接按下 enter 鍵直接輸出,需要先按空白鍵再選擇第一組正確的候選字組纔可以輸入(或者是連按兩下空白鍵)。
  2. 輸入完畢後直接按 enter 會直接出現剛剛敲過的所有按鍵,看起來像這樣:d0fux9vu;5ku;。這個似乎不是使用者預期的輸出
  3. 以上兩點如果將 enter 鍵改成直接輸出正確的候選字會比較快速。
  4. 按着 shift + , 或者 shift + . 出現的並不是全形的逗號以及句號,而是『《』以及『》』,感覺不符合使用者預期
  5. 使用 ` 鍵叫出符號表的時候,如果已經設定選字鍵爲 asdfghjkl;,但是符號表的選字鍵依然是 1234567890
  6. 輸入了一個句子後,可以用左右鍵移動到注音符號的任意位置,但不清除功能爲何。看起來似乎可以用來決定切字點,但是移到要切字的位置後按下空白選字,接下來的字會變成注音符號。例如要輸入:十全路十五號,需要切字在『十五』之間。如果移到十五中間按下空白鍵選字,整串字會變成『十全路十ㄨㄏㄠ』
  7. 按下空白鍵選字後,必須要按下 page up/down 跳頁選字。此時方向鍵之中的上下鍵並沒有功能,建議可以用來取代 page up/down
  8. 如果第一次選詞的時候沒有正確選擇,下次就算正確選詞也沒辦法更正。比如說我第一次選擇注音輸入法的時候選錯成『註音』,接下來就算我多選幾次注音也沒辦法讓註音慢慢消失。
接下來希望可以跟開發者有些聯絡,來協助改善這個無調注音輸入法 :-)

2010/09/28

[筆記] android WebView 遇到網頁重導後開新視窗的問題

塞個 WebViewClient 給他。

WebView web = (WebView)findViewById(R.id.WebPages);
web.setWebViewClient(new WebViewClient());

最近會筆記些零碎的 android 問題。

2010/09/19

吃了蘑菇的 gnome-shell




會變大~

上面這個影片主要是 demo 目前 gnome-shell 的 extension 可以控制 gnome-shell 裡面的任意元件,所以才可以做出讓 calendar 放大的外掛。有興趣可以看一下源碼

這是在 ICOS 的講題 Javascript in Linux Desktop,雖然跟 COSCUP 講的題目一樣,不過經過了一個月當然是要升級一下啦。

這次不一樣的地方還有加入了 seedkit 的部份。不過瞄準的是略有開發經驗的聽眾,所以技術細節其實並沒有提很多。這次 seedkit 的範例用了 seedkit 原本就內附的 dbus, libnotify 範例外,也加了使用 wnck, 用 javascript 控制視窗的範例。

下面這個影片依據 demo 用 dbus 控制 Ubuntu music player - rhythmbox 的上下首變更、libnotify 跳出通知訊息、以及用 wnck 取得視窗標題以及最後的操作所有視窗最小化。



而操作這些動作的全部都是使用 html 與 javascript, 範例源碼如下:
HTML 部份
<html>
    <head>
    <link rel="stylesheet" href="./ui.css" type="text/css" media="all" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script src="./ui.js"></script>

    </head>
    <body>
    <div class="demo">
        <img id="cover-art"></img>
        <div id="prev-button" class="button">Prev</div>
        <div id="next-button" class="button">Next</div>
        <div id="notify-button" class="button">notify</div>
        <div id="wins-button" class="button">get wins</div>
        <div id="min-button" class="button">minimize</div>
        <div id="file-uri"></div>
    </div>
    <ul id="windows-list"></ul>
</body>
</html>

Javascript 部份:
Seed.include("./dbus-rhythmbox.js");

function sendNotification(summary, body, timeOut) {
 var notification = new Notify.Notification({summary:summary, body:body});
 notification.set_timeout(timeOut);
 notification.show();
}

function getWindows () {
        Wnck = imports.gi.Wnck;
        Gtk = imports.gi.Gtk
        Gtk.init(Seed.argv);

        var screen = Wnck.Screen.get_default();
        while (Gtk.events_pending())
            Gtk.main_iteration();
        return screen.get_windows();
}

$(document).ready(function(){
 var shell = new RhythmboxShell();
 var player = new RhythmboxPlayer();

 Notify = imports.gi.Notify;

 $("#wins-button").click( function() {
        var wins = getWindows();
        Seed.print (wins.length);
        for (var i = 0; i < wins.length; i++) {
            Seed.print (wins[i].get_name());
            $("#windows-list").append("<li>" + wins[i].get_name() + "</li>");
        }
    });

 $("#min-button").click( function() {
        var wins = getWindows();
        for (var i = 0; i < wins.length; i++) {
            wins[i].minimize();
        }
    });
 
    Notify.init("Webview");
 $("#notify-button").click( function() {
  sendNotification("Raised from a WebView","Raised from a WebView", 500); 
  Seed.print("clicked");
 });

 //playeplayer.getVolumeRemote(function (volume) {print("oi")});
 $("#next-button").click(function(){
  player.nextRemote();
 });

 $("#prev-button").click(function(){
  player.previousRemote();
 });

 player.connect("playingUriChanged", 
         function(emitter, uri){
   //var song = shell.getSongPropertiesRemoteSync(uri);
   //print(song); 
         });

 player.connect("playingSongPropertyChanged", 
         function(emitter, title, property_name, old_value, new_value){
   if (property_name == "rb:coverArt-uri")
    $("#cover-art").attr('src', new_value);
 });
});

dbus 的操作一樣的是比較複雜,你可以參考上一篇。不過相對起來 wnck, libnotify 就簡單許多。而這整個操作,全部都可以使用 jquery 的方式操作,撰寫起桌面應用程式就跟網頁一樣。


最後是 slide。謝謝昨天大家的聆聽

2010/09/07

seedkit - 用 web technology 撰寫 desktop application

繼上次 COSCUP 講了 Javascript in linux desktop 後,最近又在看之前 penk 跟我介紹的 seedkit,還有會後 sleepnova 跟我提到一些 java 上有些 javascript implementation 的實做,去慶功宴的時候阿修又提了好幾個 javascript 寫 desktop application 的 framework,才知道這個部份已經蠻多人在做了。

不過這次會議也有另外一個感想,就是 web developer 還是比較希望維持原有的開發模式,而不僅只是使用 javascript 語言來撰寫程式。翻開 seed/gjs 寫的 javascript 源碼,開發的思維其實跟 python 差不多,幾乎都可以從 python 無痛轉換了。

而 seedkit 就是打算維持原本 web application 的開發模式而設計的工具。在 seedkit-viewer 的 example 裡面提供了一些有趣的範例。比如說 dbus-rhythmbox  這個範例,他透過 dbus 的方式控制歌曲的上、下首切換。



右邊的 seedkit-viewer 視窗裡面的 next/previous 可以操作 rhythmbox 上、下首。這個程式與 rhythmbox 是兩個獨立的程式,而不是 rhythmbox 的外掛。

這個功能可以在各種語言用 dbus 實做出來。不過在 Seedkit 的實做方式則是比較近乎 web application 的開發方式。首先我們看源碼中的 ui.html (沒錯是 HTML 檔案)。

<html>
    <head>
    <link rel="stylesheet" href="./ui.css" type="text/css" media="all" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script src="./ui.js"></script>

    </head>
    <body>
    <div class="demo">
        <img id="cover-art"></img>
        <div id="prev-button" class="button">Prev</div>
        <div id="next-button" class="button">Next</div>
        <div id="file-uri"></div>
    </div>
</body>
</html>

基本上就是使用 jquery 函式庫,並引入了 ui.js 這個 javascript。接下來是 ui.js。
Seed.include("./dbus-rhythmbox.js");

$(document).ready(function(){

var shell = new RhythmboxShell();
var player = new RhythmboxPlayer();

//playeplayer.getVolumeRemote(function (volume) {print("oi")});

$("#next-button").click(function(){
 player.nextRemote();
});

$("#prev-button").click(function(){
 player.previousRemote();
});


player.connect("playingUriChanged", 
        function(emitter, uri){
  //var song = shell.getSongPropertiesRemoteSync(uri);
  //print(song); 
        });

player.connect("playingSongPropertyChanged", 
        function(emitter, title, property_name, old_value, new_value){
  if (property_name == "rb:coverArt-uri")
   $("#cover-art").attr('src', new_value);
});

});

這段也相當簡單,就是按下 next 或 previous 之後去呼叫 player.nextRemote/previousRemote,並且使用了 jquery 的語法。至於 player 則定義於 dbus-rhythmbox.js 裡面。

另外,這個範例為了方便的操作 dbus,所以做了一個 wrapper 在 dbus-local.js,有興趣的話可以翻一下,特別是把 next mapping 到 nextRemote 可以翻一下 proxifyPrototype 這個函式。

基本上 seedkit 讓開發桌面程式的方式盡可能的接近網頁應用程式,並且還是可以使用系統的 API 去作檔案 IO、網路存取、dbus、notification 之類的系統 API,感覺起來是 GTK 裡面比較完整的解決方案。

而更棒的是 seedkit 也可以當作一個 Gtk Widget,你可以將這些程式片段嵌入在 UI 的一部分,這也保持了開發彈性,開發者還是可以選用其他的 UI 函式庫如 Clutter 或是 GTK,而不是只能使用 Web Application 的 View。

2010/08/03

[talk] Javascript in Linux Desktop

最近在這邊發了幾篇 Javascript 跟 GNOME Desktop 相關的文章,其實是為了 COSCUP 的分享『Javascript in Linux Desktop』作準備。如果你也對 Javascript 撰寫桌面應用程式有興趣,歡迎在 COSCUP 第二天 (8/15) 下午 4:00-4:30 到第二會議室來聽我的分享。(喔,我知道同一個時段也有很精彩的 Jserv 演講啦 XD)

2010/08/02

gnome-shell 擴充套件簡介

有用過 Firefox 的延伸套件嗎?那是個很好的功能擴充模式,使用者可以選用自己喜歡的延伸套件後,增強 Firefox 的功力。感覺就像洛克人拿到手部裝備一樣厲害。

有想過如果你的桌面也可以有這麼好用的延伸套件可以用嗎?gnome-shell 正在逐漸的啟用這種延伸套件模式。相信過沒多久,gnome-shell 就能全面啟動了 (笑)

基本上 gnome-shell  有幾個特點:
  1. 可變更原有的元件:跟 Firefox 一樣,你可以隨意變更已存在的元件。Firefox 使用 overlay 的概念,而 gnome-shell 你可以從 Main 或 Global 參數裡面取得原有的元件,再做修改。
  2. gnome-shell 延伸套件使用的程式語言是 Javascript!
  3. gnome-shell 的樣式是採用 CSS!
如果你寫過 Firefox 延伸套件,相信 gnome-shell 延伸套件對你來說會非常親切的。如何開始第一步呢?首先當然你要先啟用 gnome-shell,在 Ubuntu 底下你可以安裝 gnome-shell,然後在終端機輸入以下指令啟動 gnome-shell。
gnome-shell --replace &
要如何開始撰寫擴充程式的第一步呢?gnonme-shell 提供了建立一個簡易擴充套件的方式,鍵入以下指令:
gnome-shell --create-extension
接下來要輸入 Name, Description 跟 Uuid。輸入完畢之後,gnome-shell 會開啟你預設的編輯器,開啟一個由 gnome-shell 提供的樣板延伸套件。

// Sample extension code, makes clicking on the panel show a message
const St = imports.gi.St;
const Mainloop = imports.mainloop;

const Main = imports.ui.main;

function _showHello() {
    let text = new St.Label({ style_class: 'helloworld-label', text: "Hello, world!" });
    let monitor = global.get_primary_monitor();
    global.stage.add_actor(text);
    text.set_position(Math.floor (monitor.width / 2 - text.width / 2), Math.floor(monitor.height / 2 - text.height / 2));
    Mainloop.timeout_add(3000, function () { text.destroy(); });
}

// Put your extension initialization code here
function main() {
    Main.panel.actor.reactive = true;
    Main.panel.actor.connect('button-release-event', _showHello);
}

這個 javascript 放置於家目錄的 .config/gnome-shell/extensions/ 裡面。這個樣板延伸套件會讓你點擊 panel 的時候在螢幕中央出現一個 Hello world 的 label:


簡單吧?程式碼中:

  • 17-18 行:將你的 panel 設置成可互動 (reactive),然後將 panel 的 mouse click/release event 連結到 _showHello 的 callback。
  • 8-12 行:建立一個 text label,接著取得你的螢幕參數,並且把 text label 塞到螢幕的中間。最後指定 3 秒後 destroy 掉 text label。
如果還想做進一步的操作,請參考 gnome-shell 的程式碼,有相當大一部分都是使用 javascript 寫成,位置在 /usr/share/gnome-shell/js/ui。


[update]

忘記說一件事情,弄好你的延伸套件後按 alt + F2,輸入 r 按 enter 就可以重新啟動 gnome-shell 了。

2010/07/23

debian squeeze plymouth

這兩天裝了兩台 Debian Squeeze 之後,突然發現 plymouth 已經很簡單的可以使用了。如果你正巧用的是 Intel 的顯示晶片,請聽我娓娓道來…(飛踢)

首先裝 plymouth 跟一些 theme:
sudo aptitude install plymouth plymouth-themes-all plymouth-x11

plymouth-x11 我猜測應該是 plymouth 跟 gdm 接合用的一些程序。

裝好之後,請修改 /etc/default/grub,把下面這個參數加入 splash (原本應該是空的):
GRUB_CMDLINE_LINUX="splash"

接著更新 grub 參數:
sudo update-grub

因為預設的佈景主題很遜,建議你用 solar:
sudo plymouth-set-default-theme solar
sidp update-initramfs -u

做完之後重開機就完成了。雖然最後噴了一些錯誤訊息出來

2010/07/21

js-gallery: javascript desktop app 範例

這幾天用 javascript 寫了個範例,是個簡單的圖片瀏覽程式。目前行數約略 250 行,希望還是可以再精簡一點囉。




source code: http://gist.github.com/484314

GNOME javascript runtime introdution

這幾天在寫 COSCUP 議程 Javascript in Linux Desktop 的範例,對於 Seed 跟 GJS 有了些認識。先解釋一下 GNOME javascript runtime。這個時候你先要把『javascript 就是拿來寫 Web Application』的觀念先忘掉,GNOME javascript runtime 可以讓你使用 javascript 撰寫桌面應用程式,一如 pidgin, stardict, 或是 filezilla 這類的軟體(當然 js runtime 現在還沒成熟)。

這個時候問題就跟你挑瀏覽器一樣:我要用哪種 javascript engine? 目前開放源碼的 javascript 不外乎是 Mozilla Firefox 用的 Spidermonkey, Webkit 內建的 JavaScriptCore, 以及 Google Chrome 用的 V8。而 Spidermonkey 跟 JavaScriptCore 在 GNOME 裡面分別被發展成兩套 Javascript runtime: GJSSeed

或許你有點疑惑,怎麼又提 javascript engine 又提 javascript runtime?

因為有了 javascriptp engine 後,內建的函式庫並不足以開發桌面應用程序,而且在桌面應用程式也不一定有 DOM 可以使用。GNOME 為了解決這個問題,發展了一套 framework: GObject introspection (GI),他主要的用處是提供 GNOME 使用 C 語言撰寫的函式庫跟其他 runtime 如 javascript, python, ruby 的橋樑,讓這些語言都可以透過 binding 的方式來使用 GNOME 函式庫。不過 GObject introspection 發展以前,python 跟 ruby 都已經有了跟 gnome 的 binding,只是 GObject introspection 採用更全面的方式來分享這類 dynamic language 作 binding 時都需要的基礎工程。詳細的原理寫出來就太多了,略過 XD

所以基本上 GNOME 開發的函式庫都已經包含了 GIR (GObject Introspection Repository),也就是給動態語言用的 binding 資料。Runtime 如 javascript engine 就可以利用這些資料來製作對 GNOME 函式庫的 binding,所以使用 javascript runtime 也可以撰寫 GTK 程式。

以下是個 GTK hello world in javascript
#!/usr/bin/seed

Gtk = imports.gi.Gtk;
Gtk.init(Seed.argv);

var window = new Gtk.Window();
window.signal.hide.connect(Gtk.main_quit);
window.show_all();
Gtk.main();

如果你有安裝 python-gi, 那也可以透過 gir 來呼叫 gtk (而不是以現有的 python-gtk)。不過 GI 官網上是建議如果已經有了作好的 binding 就用原本的就好。畢竟 GI 的東西沒有針對每個語言 fine tune。


#!/usr/bin/env python
from gi.repository import Gtk
import sys

Gtk.init (sys.argv)

window = Gtk.Window ();
window.connect ("hide", Gtk.main_quit);
window.show_all ();
Gtk.main ();



晚點再來寫 seed 跟 gjs 真的動工時的差異。

2010/07/14

vim 一次註解多行

eclipse 有個蠻不錯的功能,就是框選多行之後,按下 ctrl + / 就可以註解所選的行。那 vim 呢?找了一下,看到有類似的功能。

首先按下 ctrl + v 區塊選取,選取你要標注最前面的一個字元。比如說

var width = aWin.document.documentElement.scrollWidth;
var height = aWin.document.documentElement.scrollHeight;
if (effect.viewCanvas == null)
   effect.viewCanvas = this.createCanvas (width, height);

就選取 v, v, i 和空白。按下大寫 I,輸入你正在寫得程式語言的註解,javascript 就是 //。最後按下 Esc 就完成了。

不過如果要像 eclipse 按一次 ctrl + / 就註解,再按一次取消註解就要寫 vim script 了。

2010/07/11

在 Ubuntu 10.04 啟用 Touchpad 雙指滾輪的功能

這幾天用 EeePC S101 的時候,發現 Ubuntu 10.04 對於 Elantech Touchpad 的雙指滾輪又改成在 Touchpad 右側滑動的滾輪了。

搜尋了一下才知道現在設定的方式都是用 xinput 的方式設定。不過上面的設定方式是針對 Synaptics Touchpad,所以要先用以下指令找出 Elantech 所用的裝置名稱:
xinput list
用完之後會有以下輸出,可以從裡面發現使用的 Touchpad 裝置名稱是 ETPS/2 Elantech Touchpad
⎡ Virtual core pointer                     id=2 [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer               id=4 [slave  pointer  (2)]
⎜   ↳ ETPS/2 Elantech Touchpad                 id=13 [slave  pointer  (2)]
⎜   ↳ Macintosh mouse button emulation         id=14 [slave  pointer  (2)]
⎣ Virtual core keyboard                    id=3 [master keyboard (2)]
    ↳ Virtual core XTEST keyboard              id=5 [slave  keyboard (3)]
    ↳ Power Button                             id=6 [slave  keyboard (3)]
    ↳ Video Bus                                id=7 [slave  keyboard (3)]
    ↳ Power Button                             id=8 [slave  keyboard (3)]
    ↳ Sleep Button                             id=9 [slave  keyboard (3)]
    ↳ USB2.0 0.3M UVC WebCam                   id=10 [slave  keyboard (3)]
    ↳ Asus EeePC extra buttons                 id=11 [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard             id=12 [slave  keyboard (3)]

所以只要用以下指令就可以設定好 Elantech Touchpad 的雙指滾輪
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Two-Finger Scrolling" 8 1
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Synaptics Two-Finger Scrolling" 8 1 1
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Synaptics Two-Finger Pressure" 32 10
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Synaptics Two-Finger Width" 32 8

不過這些設定都不會保存下來,需要在登入的時候重新設定。所以我把他放在 ~/bin/touchpad-setting.sh 底下,並且用 chmod +x touchpad-setting.sh 更改成可執行權限,然後在 [系統] → [偏好設定] → [始動應用程式] → [初始啟動程式] 裡面加入 touchpad-setting.sh。

這個時候又遇到一個奇怪的問題,我直接執行這個 script 有用,不過如果是登入的時候自動執行卻沒用。後來我猜是剛登入的時候 xinput 的 backend 可能還沒準備好,所以執行下去沒反應。最後我又加入了 sleep 5 之後,就一切正常了。
#!/bin/bash

sleep 5
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Two-Finger Scrolling" 8 1
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Synaptics Two-Finger Scrolling" 8 1 1
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Synaptics Two-Finger Pressure" 32 10
xinput set-int-prop "ETPS/2 Elantech Touchpad" "Synaptics Two-Finger Width" 32 8

2010/07/06

Firefox 之簡易觸控手勢實做

其實我不知道 Firefox 有沒有觸控手勢。不過寫了一陣子的延伸套件,依我看到的資料來說應該是還沒有。在 framework 還沒支援觸控手勢時,我們可以先用簡單的方式實做。觸控手勢跟一般滑鼠手勢不同,觸控沒有『右鍵』可以使用。所以就我的狀況而言,我需要使用拖曳的方式來實做。

比如說我有個 richlistbox 上的 item 要作往右滑的觸控手勢,首先在 XUL 加上 Drag & Drop 的事件

<richlistbox id="testList" 
                ondragstart="gesture.onDragStart (event);"
                ondragend="gesture.onDragEnd(event);">
    ...
    </richlistbox>

接下來在 javascript 中簡單計算時間跟滑動距離來決定要不要觸發 gesture。

var gesture = {
    gestureStartX: 0,
    gestureEndX: 0,
    gestureTimeStart: 0,
    gestureTimeEnd: 0,

    onDragStart: function (event) {
        event.dataTransfer.setData("text/plain", "Drag Gesture");
        gesture.gestureStartX = event.screenX;
        gesture.gestureTimeStart = (new Date()).getTime();
    },

    onDragEnd: function (event) {
        gesture.gestureEndX = event.screenX;
        gesture.gestureTimeEnd = (new Date()).getTime();
        let offsetX = gesture.gestureEndX - gesture.gestureStartX;
        let offsetTime = gesture.gestureTimeEnd - gesture.gestureTimeStart;

        if (offsetX < 500 && offsetX > 0 && offsetTime < 1000) {
            Application.console.log ("X offset: " + offsetX);
            Application.console.log ("time offset: " + offsetTime);
            Application.console.log ("Do gesture.");
        }
    },
};


不過這跟 firefox 延伸套件的滑鼠手勢差距還很大,比較好的解法是 Firefox (或是說 Fennec/Firefox Mobile) 要提供觸控手勢 framework。

2010/06/23

[筆記] vim 儲存/還原開啟的分頁

來源: http://www.cs.utah.edu/~kad/vim/vimnotes.shtml

當要儲存 vim 分頁時,輸入 :mks <filename> 即可。下次要開啟的時候,使用 vim -S <filename> 即可還原

2010/05/24

[筆記] Firefox Screenshot 整個瀏覽器

這段 code 從 UploadScreenshot.com Capture 延伸套件還有 Canvas - MDC 拼湊出來的。

function onScreenshot (event) {
    var canvas = document.createElementNS ("http://www.w3.org/1999/xhtml", "html:canvas");
    var width = document.documentElement.scrollWidth;
    var height = document.documentElement.scrollHeight;
    canvas.style.width = String (width) + "px";
    canvas.style.height= String (height) + "px";
    canvas.width = width;
    canvas.height = height;

    var ctx = canvas.getContext ("2d");
    ctx.clearRect (0, 0, width, height);
    ctx.save ();
    ctx.drawWindow (window, 0, 0, width, height, "rgb(255,255,255)");
    ctx.restore ();
    saveCanvas (canvas, "/tmp/test.png");
}

function saveCanvas(canvas, destFile) {
    // convert string filepath to an nsIFile
    var file = Components.classes["@mozilla.org/file/local;1"]
                       .createInstance(Components.interfaces.nsILocalFile);
    file.initWithPath(destFile);

    // create a data url from the canvas and then create URIs of the source and targets  
    var io = Components.classes["@mozilla.org/network/io-service;1"]
                     .getService(Components.interfaces.nsIIOService);
    var source = io.newURI(canvas.toDataURL("image/png", ""), "UTF8", null);
    var target = io.newFileURI(file)

    // prepare to save the canvas data
    var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
                          .createInstance(Components.interfaces.nsIWebBrowserPersist);

    persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
    persist.persistFlags |= Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;

    // displays a download dialog (remove these 3 lines for silent download)
    var xfer = Components.classes["@mozilla.org/transfer;1"]
                       .createInstance(Components.interfaces.nsITransfer);
    xfer.init(source, target, "", null, null, null, persist);
    persist.progressListener = xfer;

    // save the canvas data to the file
    persist.saveURI(source, null, null, null, null, file);
}

[筆記] Nexus One 的 USB tethering

Nexus One Android 2.2 版的 USB tethering 用的 driver 是 cdc_ether (Communications Device Class, Ethernet Control model)。

wikipedia: http://en.wikipedia.org/wiki/Communications_Device_Class

2010/05/21

用 eclipse 開發 Firefox/Thunderbird Extension

再次聲明,我自己是用 vim 寫 mozilla application,搞 eclipse 純粹只是自 high。

前置作業


要用 eclipse 開發 Mozilla Application,首先需要 WTP (Web Tools Platform)。一樣也是 [help] → [Install New Software], work with 填入 http://download.eclipse.org/webtools/updates,接著安裝最新的 WTP。在撰文時最新的版本是 Web Tools Platform (WTP) 3.1.2。

安裝完畢後,或許你還會有興趣安裝 XulBooster。請到 Sourceforge 下載最新版本的 XulBooster,並且在  [help] → [Install New Software] 按下 Add → Archive,選擇剛下載的 XulBooster 的 zip file 安裝。

開發延伸套件


通常會有兩個狀況:(一)你已經自己有 extension,只是想轉換開發環境為 eclipse。(二)你想要全新開發一個 extension。如果你是第二種狀況,XulBooster 有提供 XUL project 幫你建立簡單的 extension 結構。或是也可以用 Extension Wizard 建立,不過用 Extension Wizard 建立的話,要在自己建立 .project file,在你匯入專案時他才會認得你的 project,請參考 [筆記] 在 eclipse 用 git

如果你是第一種狀況的使用者,同樣的你也要建立 .project file。接下來就可以在 eclipse 開發了。

安裝延伸套件


安裝套件很麻煩。這邊我寫了兩個 script 分別處理 windows 跟 linux 的安裝。EXTENSION_NAME 請自行取代成你的 extension 名稱。使用方式都一樣:

Linux:
./install.sh trxw3c99.default

Windows:
install.bat trxw3c99.default

trxw3c99.default 請改成在你電腦上的目錄名稱。

Linux 版 (Linux 版我多處理了 vim 的暫存檔問題, 刪除 compreg.dat 等問題)
#!/bin/bash

FF_PROFILE="$HOME/.mozilla/firefox/$1"
FF_EXT="extensions/EXTENSION_NAME"

echo "copy files...."
find . -maxdepth 1 -mindepth 1 \
        ! -name '.git' ! -name '*.swp' \
        -printf "\t%f\n" -exec cp -r {} $FF_PROFILE/$FF_EXT \;

if [ -e "$FF_PROFILE/compreg.dat" ]; then
    echo "remove compreg.dat"
    rm "$FF_PROFILE/compreg.dat"
fi

echo "delete vim swap files..."
find $FF_PROFILE/$FF_EXT -name *.swp \
     -printf "\t%f\n" -exec rm {} \;

Windows 版本要有兩個檔案 exculude.txt 跟 install.bat
exclude.txt 裡面指包含一行: .git

install.bat:
xcopy * %APPDATA%\Mozilla\Firefox\Profiles\%1\extensions\EXTENSION_NAME /E /Y /EXCLUDE:exclude.txt

在 eclipse 安裝延伸套件


寫好安裝 script 之後,在 eclipse 的安裝就簡單的多。在 [Run] → [External Tools] → [External Tools Configurations] 在 Program 按右鍵選擇 New,取名為 Install。Location 按 Browse Workspace 選擇 install.bat,Working Directory 按 Browse Workspace 選擇你的 extension project。選擇完畢之後應該長這樣:


設定完畢後,按下 toolbar 上面的 選擇 install 就可以安裝了。

相同的如果你想跑 Firefox 也可以用相同的設定方式跑 Firefox :)

[筆記] 在 eclipse 用 git

我這個人還蠻無聊的。自己是用 vim 開發,不過還是想試試看用 eclipse 設置開發環境。我之前的開發環境是 vim editor 配合指令介面的 git,就這樣。設定開發環境的目標是把整個開發過程都可以在 eclipse 內完成。

首先在你的 git repository 建立一個 .project 檔案,這是 eclipse 的 project, 匯入 project 時會用到
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
    <name>entegomode</name>
    <comment></comment>
    <projects></projects>
    <buildSpec></buildSpec>
    <natures></natures>
</projectDescription>

[eclipse]
eclipse 裡面可以用 EGit 操作 git,EGit 包含了一個用 java implement git 的套件 jgit。不過簡單的說用 egit 就是了。在 eclipse 的 [help] → [Install New Software], work with 填入 http://download.eclipse.org/egit/updates ,安裝 egit 與 jgit 重新啟動即可。

重新啟動後按 file → import,選擇從 git repository 匯入,接下來的東西你用過 git 就知道該怎麼做了。不過要注意一點,如果你沒建立 .project 檔案時,到最後會沒有 project 可以匯入,切記。

還有一件事也很麻煩,就是 egit/jgit 還不支援 ssh key 。

[筆記] 使用 sed 轉換 HTML tag

貼 blog 時常用到 html/xml tag 的時候,直接貼上去 blogger 都會很聰明的當成你要使用 html tag。有個轉換小工具可以處理這件事情總是好的。

源自 http://www.html-tags-guide.com/html-xmp-tag.html

建立檔案 convert.sed:
s/&/\&amp;/g
s/"/\&quot;/g
s/</\&lt;/g
s/>/\&gt;/g

使用以下指令來轉換你的 XML/HTML
sed -f convert.sed <your-xml-file>

2010/05/17

[筆記] 關於 XUL Tree 對於拖曳移動位置的實做

最近一直在看 XUL 裡面關於 Tree 拖曳的實做。不論哪種 UI framework 裡面的 Tree 都還真的挺複雜的。

以下是自己實做 TreeView 需要 implement 的 method:
http://doxygen.db48x.net/mozilla-full/html/d1/dbc/interfacensITreeView.html

其中 canDrop () 跟 drop () 的參數 orientation 可以拿來判斷現在 drag 的 item 到底是在 target item 的正上方 (DROP_ON), 前面或後面 (DROP_BEFORE/DROP_AFTER)。所以如果你正巧要實做把 item 移動到資料夾,又需要實做 ordering item 時,就可以利用 orientation 來判斷要執行這兩種動作的那一種。

以下的程式就可以拿來印出 drag 的狀況:

_printDrop: function (aRow, aOrientation) {
    let targetFolder = mytreeview._map[aRow]._folder;
    let aDropText = null;
    if (aOrientation == -1) 
        aDropText = "DROP_BEFORE";
    else if (aOrientation == 0)
        aDropText = "DROP_ON";
    else
        aDropText = "DROP_AFTER"
    Application.console.log (aDropText + ": " + targetFolder.name);
  },

五月份 TIOBLE 程式語言排行贏家:Objective-C, Go

參見
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

由於 iPhone 程式愈來愈重要的關係,1980 年代發明的 Objective-C 突然之間就衝上了第十名,Ruby 正巧被擠出前十名。另外由 Google 開發的 Go 程式語言也是一匹黑馬,從 2009 十一月正式發布後,竟然在半年後衝上十八名。

TIOBLE 排行就跟夜市人生一樣精彩阿,不過相同的也只需要久久看一次就好,反正劇情都接得上。

2010/05/14

你愛 Javascript 的 Array 嗎?

最近開始常寫 javascript 後,發現了不少好東西 -- 尤其是 Array。有幾個新 function 不得不提。

[filter]
可以把過濾用的 function 丟給 filter 去過濾,範例:

let items = [1, 10, 20, 50, 80, 100];
function aFilter (element) {
  if (element >= 50)
    return true;
  return false;
}
let filterItems = items.filter (aFilter);

[some]
上面那篇已經提過了,如果有任何符合條件的就 return true:

let items = [1, 10, 20, 50, 80, 100];
function someGreatThan50 (element) {
  if (element > 50)
    return true;
  return false;
}

if (items.some (someGreatThan50)
  alert ("some element great than 50");
像上面這兩個例子一樣好用的 function 有 forEach, every. 詳情請查閱 MDC
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array

python 的 if item not in items 的 javascript 版本?

平常在 Python 底下 if not in 還蠻好用的。舉例:
items = [1, 2, 3, 4]
if 2 in items:
  print "in here!"
else
  print "not in here"
那 javascript 有什麼簡單的方法可以作這判斷呢?目前還沒想到,所以用以下方法。
let targetItem = something;
let items = [1, 2, 3, 4];

function containItem (item) {
  if (item == targetItem)
    return true;
  return false;
}

if (items.some (containItem))
  alert ("in here");
else
  alert ("not in here");
好多行阿,懇求 javascript 高手釋疑。

[updated]
下面的迴響提供了 array.indexOf 這個更好用的方法。感謝
items = [1, 2, 3, 4];
if (items.indexOf (2) >= 0)
  alert ("in here");
else
  alert ("not in here");

2010/05/13

了解你的 snippets.vim - javascript

今天翻了 snippets.vim 的 javascript 部份,才發現有些拿來寫 XUL/Javascript 還蠻方便的。比如說寫 Mozilla Application 常會用到 object method。其實安裝 snippets.vim 之後只要輸入

:f

按下 tab 就可以補齊成

method_name: function (attribute) {
},

很久沒更新的 Yuren's Info Area...

最近發現實在太久沒有更新了。不過也不是因為沒什麼新鮮事情,只是沒時間長篇大論的寫一些東西。作為應對方式,以後 Post 的文章會比較簡短一點。配合直接用 email 發文,希望可以提高一些更新頻率囉。

當然提高更新頻率的前提是內容要有趣啦 :P

[筆記] 擷取滑鼠座標或操作滑鼠自動測試

可以用 xdotool 這個工具。例如要用滑鼠按右鍵:

xdotool click 3

man 裡面有些範例可以看。

寫 HTML/XML 讓你很煩心嗎?你需要 zen coding

http://code.google.com/p/zen-coding/

他有 vim 外掛,裝上去後,開啟你的 XML/HTML。如果你想要以下結構
<div class="main">
  <p></p>
  <p></p>
  <p></p>
<div>

只要打
div.main>p*3
按下 Ctrl + Y,再按下逗點就可以展開成上面的語法了。

[筆記] 打開 vim 時就在多個 tab 開啟檔案

vim -p file1 file2 ...

2010/03/19

GNOME 2.30 新特性搶先看

GNOME 2.30 預計在 3/31 要釋出了。我提前先去看了一下 release notes,列些重要的改進出來。


  • Hamster 看起來增強不少

Main applet window has now input box for tags

  • 現在 double click 字型檔就可以安裝字型了。
  • GNOME 解壓縮程式 File roller 現在如果遇到不支援的壓縮格式,會透過 PackageKit 安裝適當地壓縮軟體,我猜 Ubuntu 暫時沒辦法支援這功能,看起來 Ubuntu 還沒導入 PackageKit。
  • gnome-terminal 現在支援無限捲軸!聽起來好像 RPG 裡面的某種技能,不過其實是可以無限的往前看到底下過什麼指令跟輸出。
  • Vinagre 支援 VNC over SSH,這個很不錯。
  • 檔案管理員 Nautilus 支援分割視窗模式,所以可以一次看兩個目錄內容的意思
  • 支援 iPhone 跟 iPod Touch
  • Evolution 全面移除 Bonobo,改用 dbus!可喜可賀!

2010/02/12

Linux 設定 Firefox 羅技 M505 滑鼠按鈕成上下頁



今天買了個新滑鼠 Logitech M505,插上 Linux 的機器基本上沒什麼問題。不過以前用 MX510 時滑鼠翻上一頁、下一頁不需要設定的便利卻消失了。用 xev 看了一下,發現滑鼠的按鈕已經全部都可以使用,編號是按鈕 6, 7。

所以基本上只是 Mapping 的問題。上網 Google 一下發現 Firefox 從 3.0 開始上/下一頁全部都改成按鈕 8/9。所以只要照著 Firefox 說明改成 6/7 馬上就可以使用。

  1. 打開 Firefox,在網址列輸入 about:config
  2. 鍵入過濾條件為 mousewheel.horizscroll.withnokey
  3. mousewheel.horizscroll.withnokey.action 改成 2
  4. mousewheel.horizscroll.withnokey.numlines 改成 -1
  5. mousewheel.horizscroll.withnokey.sysnumlines 改成 false   

這樣就 OK 囉。