Android VNC Serverのつづき。エミュレータ上で起動しても、期待通りタッチイベントが反映できるようにしたいので、誰か同じくエミュレータによる動作報告した人を探しました。
いました。ちょうど、Issue 14: Pressing left mouse button and moving the mouse without releasing it generates touch events badly.という報告があり、都合よく対応パッチが添付されていました。
このパッチを試してみたくて、Android NDK Release4をセットアップし、Android VNC ServerのソースをSubversionリポジトリから取得しました。
NDKのセットアップは特別難しいことはありませんでした。作業環境がWindowsなので、Cygwin 1.7.5をインストールする必要がありました。気をつける点としては、忘れずにGNU make 3.81をインストールすることぐらいです。
問題は、Android VNC Serverのソースコードをビルドするところです(NDK Release4からネイティブコードのビルド方法が変更になっているので注意が必要)。VNCサーバには、jpeglib(ヘッダファイルと静的ライブラリ)とzlib(ヘッダファイルのみ)が必要で、Froyo(Android 2.2)のGitリポジトリからそれぞれのソースコードを取得し、jpeglibに関しては、ローカルな静的ライブラリ(libjpeg.a)としてビルドしなければなりません。しかし、NDKでは、静的ライブラリのみをビルドすることができません。
そこで、ビルドに必要なjpeglibとzlibのソースコードをAndroid VNC ServerのAndroid.mkの内容にあわせて配置した後、Android.mkを編集して、次の処理ができるようにします(実際のAndroid.mkの内容は割愛します)。
/cygdrive/c/android-ndk/apps/androidvncserver/jni にAndroid VNC Serverのソースコード一式を配置したものとすると、次のようなコマンドでビルドします。
% ndk-build -C /cygdrive/c/android-ndk/apps/androidvncserver/
無事にビルドできたら、次に fbvncserver.c に例のパッチを適用します。
% patch -p2 < patch.fbvncserver
VNCサーバをリビルドして得られた実行形式androidvncserverをエミュレータにプッシュして実行してみたところ…期待通りの結果が得られませんでした。printfをソースコードに埋めてデバッグしてみたところ、fbvncserver.c の init_touch()内の
ioctl(touchfd, EVIOCGABS(ABS_X), &info)
ioctl(touchfd, EVIOCGABS(ABS_Y), &info)
の呼び出しがエラーにならないものの、変数infoに適切な値が設定されず、得られる値はすべて0。このため、VNCクライアントからタッチイベントが送信されると呼び出されるinjectTouchEvent(int down, int x, int y)で、タッチイベントの発生した位置を計算する次の行の計算結果が0になってしまうので、必ずタッチパネルの(x, y)=(0, 0)をタップしたことになってしまいます。
// Calculate the final x and y
x = xmin + (x * (xmax - xmin)) / (scrinfo.xres);
y = ymin + (y * (ymax - ymin)) / (scrinfo.yres);
この2行をコメントアウトして、VNCサーバをリビルドしたところ、ちゃんとVNCクライアントからのタッチイベントがエミュレータに反映されました。実機では試していませんので、実機でVNCサーバを実行する場合には、このような作業は必要ないかもしれません。
とりあえず…私、頑張りました。
いました。ちょうど、Issue 14: Pressing left mouse button and moving the mouse without releasing it generates touch events badly.という報告があり、都合よく対応パッチが添付されていました。
このパッチを試してみたくて、Android NDK Release4をセットアップし、Android VNC ServerのソースをSubversionリポジトリから取得しました。
NDKのセットアップは特別難しいことはありませんでした。作業環境がWindowsなので、Cygwin 1.7.5をインストールする必要がありました。気をつける点としては、忘れずにGNU make 3.81をインストールすることぐらいです。
問題は、Android VNC Serverのソースコードをビルドするところです(NDK Release4からネイティブコードのビルド方法が変更になっているので注意が必要)。VNCサーバには、jpeglib(ヘッダファイルと静的ライブラリ)とzlib(ヘッダファイルのみ)が必要で、Froyo(Android 2.2)のGitリポジトリからそれぞれのソースコードを取得し、jpeglibに関しては、ローカルな静的ライブラリ(libjpeg.a)としてビルドしなければなりません。しかし、NDKでは、静的ライブラリのみをビルドすることができません。
そこで、ビルドに必要なjpeglibとzlibのソースコードをAndroid VNC ServerのAndroid.mkの内容にあわせて配置した後、Android.mkを編集して、次の処理ができるようにします(実際のAndroid.mkの内容は割愛します)。
- 最初にlibjpeg.aをビルドする。
- VNCサーバをビルドするとき、zlibはNDKで提供される共有ライブラリをリンクし、jpeglibは最初にビルドした静的ライブラリをリンクする。
/cygdrive/c/android-ndk/apps/androidvncserver/jni にAndroid VNC Serverのソースコード一式を配置したものとすると、次のようなコマンドでビルドします。
% ndk-build -C /cygdrive/c/android-ndk/apps/androidvncserver/
無事にビルドできたら、次に fbvncserver.c に例のパッチを適用します。
% patch -p2 < patch.fbvncserver
VNCサーバをリビルドして得られた実行形式androidvncserverをエミュレータにプッシュして実行してみたところ…期待通りの結果が得られませんでした。printfをソースコードに埋めてデバッグしてみたところ、fbvncserver.c の init_touch()内の
ioctl(touchfd, EVIOCGABS(ABS_X), &info)
ioctl(touchfd, EVIOCGABS(ABS_Y), &info)
の呼び出しがエラーにならないものの、変数infoに適切な値が設定されず、得られる値はすべて0。このため、VNCクライアントからタッチイベントが送信されると呼び出されるinjectTouchEvent(int down, int x, int y)で、タッチイベントの発生した位置を計算する次の行の計算結果が0になってしまうので、必ずタッチパネルの(x, y)=(0, 0)をタップしたことになってしまいます。
// Calculate the final x and y
x = xmin + (x * (xmax - xmin)) / (scrinfo.xres);
y = ymin + (y * (ymax - ymin)) / (scrinfo.yres);
この2行をコメントアウトして、VNCサーバをリビルドしたところ、ちゃんとVNCクライアントからのタッチイベントがエミュレータに反映されました。実機では試していませんので、実機でVNCサーバを実行する場合には、このような作業は必要ないかもしれません。
とりあえず…私、頑張りました。