読者です 読者をやめる 読者になる 読者になる

2014 年やったこと - Mozc 編

いつもどおりコードが公開されている範囲で.

実は 2013 年にやっていたこと

OSS Mozc のアップデートタイミングの関係上,2013年やったこと - Mozc 編 - NyaRuRuが地球にいたころ に載っていなかった内容です.概ね 2013 年末休暇シーズンに余暇としてやっていました.

Windows 版での候補ウィンドウのカラー絵文字対応

Mozc チームを離れる直前,休暇シーズンということもあって久しぶりに自分の書きたいコードでも書くかと言うことでやってみたのがこのカラー絵文字対応です.
f:id:NyaRuRu:20150211174200p:plain
作業のほとんどは mozc_renderer (独立したプロセスとして動く,候補ウィンドウ表示用プロセス) 内の文字表示処理を DirectWrite に対応させることでした.カラー絵文字専用に追加したコードは数行です.
r192 にてリリース.
変更の大半は renderer/win32/text_renderer.cc にまとまっています.

候補ウィンドウの DirectWrite 対応

思い起こせば 2009 年,Mozc の候補ウィンドウ表示を別プロセス化したころから DirectWrite を使うというアイディア自体はありました.緊急性と重要性の高いタスクは他にいくらでもあったことからこのアイディアは長らく放置されていたのですが,カラー絵文字表示の副産物として 4 年越しの実現となります.Windows 8 以前の OS でも,高 DPI 環境ではそれなりにメリットがあるかもしれません.
r192 にてリリース.

ITfFnReconversion::GetReconversion 対応

tsf-mozc が ITfFnReconversion::GetReconversion をサポートしていなかったので実装してみた,というものです.ITfFnReconversion::GetReconversion を使用する一部アプリケーション以外でユーザーの目に見える変化はありません.

一番わかりやすいのは Microsoft Word で,文字を選択したあと右クリックすると,コンテキストメニュー内に再変換候補が表示されるようになります.
f:id:NyaRuRu:20150211163902p:plain:h600
Mozc 内部のプロトコル的に再変換は対応済みだったので,あとは単純に実装するだけという内容でした.

2014 年にやったこと

2013 年 12 月末をもって所属的には Mozc チームを離れたこともあり,休日・休暇に作業できる内容であることというのを特に重視していた 2014 年でした.そんなわけで注目してみたのが,OSS 版周りの自主オープンソース活動でした.OSS としてみた Mozc プロジェクトは,特に対外的な締め切りもなく,本当に時間的に余裕があるときだけ作業するのに適しています.また,OSS 化後のソースコードについては個人の PC 環境で作業できるので,喫茶店や旅行先でコードを見たり変更したりしながらあれこれ試せるのも嬉しいポイントでした.

OSS Mozc を選んだもうひとつの理由としては,最近モバイル OS 向けに OSS Mozc をベースにした IME を作っていただけるケースが増えていて,少し応援してみたくなったというのもあります.数字的にも合計数百万インストールという規模で,OSS としてはまずまずの成果.間接的にモバイル IME 開発の活発化に貢献できるのであれば,休日の使い方としてはまずまず Mobile First かなと思った次第.

さて,2014 年のテーマとして個人的に興味があったのは,社内リポジトリから OSS リポジトリへに変更を移動するとき,そのコミット粒度を小さくするのは可能か,というものでした.

これまで OSS Mozc といえば,いわゆる "code drop" 方式でリリースされていました.開発自体は社内のリポジトリで行い,しかるべきタイミングに (たいていはプロプライタリな製品として社外にリリースされたあと),開発されたソースコードを OSS として公開する,というものです.このとき問題になるのがコミットログで,OSS Mozc は様々な理由から変更は 1 つの SVN コミットにまとめられ,数千行から多いときは数万行の変更になることもありました.この巨大なコミットに含まれる変更点全てを把握するは開発者自身にとっても難しく,コミットログやリリースノートを書くときに苦労したのを憶えています.

そこで試してみることにしたのが,OSS 化して問題ない変更については,確認の上,個別のコミットとして OSS リポジトリに適宜反映させていくというものでした.作業自体は休日等の空き時間を利用して行っています.2014年5月24日から12月25日の間に,222 個のコミットを行いました (うち 81 コミットは 2014年12月6日から12月31日までの間,有給消化の年末休暇中に行っています).

残念ながら r467 だけは従来通りの巨大コミットになってしまいましたが,これは Android 向け新機能が多数含まれるため分けきれなかったというのが理由です.それ以前の 218 個のコミットはコミットメッセージと変更が (概ね) 対応した通常のコミットに見えるようになっています.変更の粒度を下げたことで,最後の巨大コミットを待つことなく,27 個のバグを閉じることができました.

この作業,個人的に何が新鮮に感じたかというと,それがある種の <コミット後レビュー> だったことです (このあたりの話,コードレビューいろいろ - steps to phantasien を先に読むことをおすすめ).会社に入って以来,<コミット前レビュー> は 6 年ぐらいやってきたものの,<コミット後レビュー> を継続的にやったのはこれが初めてでした.
感想 1.既にコミット済みのコードに対するレビューなので,気になるところを修正するとそれが別コミットになってしまう.
感想 2.ある程度の期間のコミットの差分をまとめて見たことで,無駄なコードが増えたのに気付きやすくなる.以下典型的なケース.

  1. ある問題に,A という方法で対処する
  2. A という方法では完全に問題が解決できないことが分かり B という方法に切り替える

複数のコミットが数日から数週間の間に加えられていたとき.あとで全体の差分を見てみると不要な変更が残ってしまっているケースを数件発見.これは確かに <コミット前レビュー> で見つけにくいパターンかも.

まあそんなわけで新鮮でもあった細切れ OSS 化作業ですが,休日の時間を結構吸い取られる作業であったのも確かで,今後どうするかはまだ決めていません.

一方,OSS 版リポジトリを活用し,実際にバグを直したり技術的負債を返済したりといったことも行っていました.以下は,そんな休日自主オープンソース活動についてです.

TF_E_NOLAYOUT 問題

Mozilla Japan の中野さんから報告していただいた問題です.調査の結果,以下のような OS 側の問題であることが分かりました.

  1. TSF で書かれた IME (TIP) が ITfContextView::GetTextExt() を呼び出す.
  2. TSF ランタイムがアプリケーションの実装する ITextStoreACP::GetTextExt() を呼び出す
  3. アプリケーションが ITextStoreACP::GetTextExt() に対して TS_E_NOLAYOUT を返す
  4. TSF ランタイムが戻り値を E_FAIL に書き換える
  5. TSF で書かれた IME (TIP) が ITfContextView::GetTextExt() の結果として E_FAIL を受け取る

開発元のサポートに相談したところ,ITfContextView::GetACPFromPoint() と ITfContextView:: GetRangeFromPoint() にはこの問題がないことが分かり,TS_E_NOLAYOUT が返されているかどうかの判定をこれらの API で行うという回避策をおすすめされました.その方針で tsf-mozc 側にて対処してみた,というのが一連の流れとなります.
r192 にてリリース.コード的には以下となります.
https://code.google.com/p/mozc/source/browse/trunk/src/win32/tip/tip_range_util.cc?r=192#231

HRESULT TipRangeUtil::GetTextExt(ITfContextView *context_view,
                                 TfEditCookie read_cookie,
                                 ITfRange *range,
                                 RECT *rect,
                                 bool *clipped) {
  BOOL clipped_result = FALSE;
  HRESULT hr = context_view->GetTextExt(
      read_cookie, range, rect, &clipped_result);
  if (clipped != nullptr) {
    *clipped = (clipped_result != FALSE);
  }
  // Due to a bug of TSF subsystem, as of Windows 8.1 and prior,
  // ITfContextView::GetTextExt never returns TF_E_NOLAYOUT even when an
  // application returns TS_E_NOLAYOUT in ITextStoreACP::GetTextExt. Since this
  // bug is specific to ITfContextView::GetTextExt, a possible workaround is
  // to also see the returned value of ITfContextView::GetRangeFromPoint.
  // If the attached application implements ITextStoreACP::GetACPFromPoint
  // consistently with ITfContextView::GetTextExt,, we can suspect if E_FAIL
  // returned from ITfContextView::GetTextExt comes from TF_E_NOLAYOUT.
  if (hr == E_FAIL) {
    // Depending on the internal design of an application, the implementation of
    // ITextStoreACP::GetACPFromPoint can easily be computationally expensive.
    // This is why we should carefully choose parameters passed to
    // ITfContextView::GetRangeFromPoint here.
    const POINT dummy_point = {
       numeric_limits<LONG>::min(), numeric_limits<LONG>::min()
    };
    CComPtr<ITfRange> dummy_range;
    const HRESULT next_hr = context_view->GetRangeFromPoint(
         read_cookie, &dummy_point, 0, &dummy_range);
    if (next_hr == TF_E_NOLAYOUT) {
      hr = TF_E_NOLAYOUT;
    }
  }
  return hr;
}

ちなみにこの問題,現在ベータテスト中の Windows 10 では OS 側で無事修正されている模様です.


TSF を有効にした Firefox がフォーカスを失ったとき候補ウィンドウが表示されたままになる

tsf-mozc と TSF-aware Firefox の組み合わせで,文字入力中に別アプリケーションにフォーカスを移すと,Mozc の候補ウィンドウが表示されたままになるという問題です.
tsf-mozc 側で ITfThreadFocusSink::OnSetThreadFocus() と ITfThreadFocusSink::OnKillThreadFocus() を処理していなかったのが問題でした.
r192 にてリリース.

Issue 206: 特定ロケールの Windows 環境で prediction/dictionary_predictor.cc をビルドすると C2065 エラーで失敗する

https://code.google.com/p/mozc/issues/detail?id=206
Mozcの C++ で書かれたソースコードは基本的に BOM なし UTF-8 で統一されているのですが,過去何度もVisual C++ が C2065 エラーでコンパイルに失敗するというトラブルに見舞われて来ました.そこで発明された対処法が,とりあえず non-ASCII 文字は "" で囲む,というものです.
OSS Mozc の方に C2065 の報告が来たわけですが,今回も "" で囲って対処となりました.
r192 にてリリース.

Issue 215: mozc::Encryptor 実装のポータブル化

https://code.google.com/p/mozc/issues/detail?id=215
mozc::Encryptor というクラスの実装から,プラットフォーム別の処理を極力取り除いたというものです.
Mozc は,確定履歴などいくつかのローカルファイルを保存時に AES256 CBC モードで暗号化します (Design Doc 参照)
当時この実装はプラットフォームごとに異なっていて, Mac 版, NaCl 版,および Linux デスクトップ版 Mozc では OpenSSL が,Windows 版では Win32 Crypto APIが,そしてAndroid 版では javax.crypto.Cipher クラスが使われていました.
さて,話は 2014 年 2月22日にさかのぼります.当日 Mozilla Japan 東京オフィスで開かれていた FxOS コードリーディングミートアップ #4 にふらりと参加した筆者は,Mozc を Emscripten でビルドできないものかとあれこれ試し始めました.Mozc のビルドは概ね「近寄るべきではない程度に大変」の部類に属しますが,そうはいってもクロスコンパイルの必要な Android 対応と NaCl 対応は既にできているわけです.数時間もあれば最初の一歩ぐらいはなんとかなるだろうと軽い気持ちで始めたものの,結果的に最初の一歩すら踏み出せずに敗退することとなります.

このとき最初の一歩として立ちふさがったのが,この OpenSSL 依存でした.以下に,当時私が参考にしようとしていた nacl-mozc の OpenSSL 依存部分を示します.
https://code.google.com/p/mozc/source/browse/trunk/src/base/base.gyp?r=185#508

    ['target_platform=="NaCl"', {
      'targets': [
        {
          'target_name': 'pepper_file_system_mock',
          'type': 'static_library',
          'sources': [
            'pepper_file_system_mock.cc',
          ],
          'dependencies': [
            'base.gyp:base',
          ],
        },
        {
          'target_name': 'openssl_crypto_aes',
          'type': 'static_library',
          'variables': {
            'openssl_dir%': '<(DEPTH)/third_party/openssl/openssl',
          },
          'direct_dependent_settings': {
            'defines': [
              'HAVE_OPENSSL=1',
            ],
            'include_dirs': [
              '<(gen_out_dir)/openssl/include',
              '<(openssl_dir)/include',
            ],
          },
          'cflags': [
            # Suppresses warnings in third_party codes.
            '-Wno-unused-value',
          ],
          'include_dirs': [
            '<(gen_out_dir)/openssl/include',
            '<(openssl_dir)',
            '<(openssl_dir)/crypto',
            '<(openssl_dir)/include',
          ],
          'hard_dependency': 1,
          'sources': [
            # The following files are the minumum set for 'encryptor.cc'
            '<(openssl_dir)/crypto/aes/aes_cbc.c',
            '<(openssl_dir)/crypto/aes/aes_core.c',
            '<(openssl_dir)/crypto/aes/aes_misc.c',
            '<(openssl_dir)/crypto/mem_clr.c',
            '<(openssl_dir)/crypto/modes/cbc128.c',
            '<(openssl_dir)/crypto/sha/sha1dgst.c',
            '<(openssl_dir)/crypto/sha/sha1_one.c',
            '<(openssl_dir)/crypto/sha/sha256.c',
            '<(openssl_dir)/crypto/sha/sha512.c',
            '<(openssl_dir)/crypto/sha/sha_dgst.c',
            '<(openssl_dir)/crypto/sha/sha_one.c',
          ],
          'dependencies': [
            'openssl_config',
          ],
          'export_dependent_settings': [
            'openssl_config',
          ],
        },
        {
          'target_name': 'openssl_config',
          'type': 'none',
          'actions': [
            {
              'action_name': 'openssl_config',
              'inputs': [
                'openssl_config.sh',
              ],
              'outputs': [
                '<(gen_out_dir)/openssl/include/openssl/opensslconf.h',
              ],
              'action': [
                'bash', 'openssl_config.sh', '<(gen_out_dir)', '$(abspath ./)',
              ],
            },
          ],
        },
      ]},
    ],
  ],
}

ここでやっているのは,OpenSSL のソースコードがダウンロード済みと仮定して,configure スクリプトを走らせ,ターゲットの toolchain でビルドする,というものです.asm.js 版 Mozc を作るにあたって,これとほぼ同様の作業を行う必要がありました.一方 Android 版も, JNI を使って javax.crypto.Cipher クラスの一部を C++ に公開するという,処理的にもビルド設定的にも非常に複雑な実装になっていることが分かりました.
実は Mozc がローカルにファイルを保存するときの暗号化処理は,"カジュアルな" 情報漏洩対策という何とも微妙な目的で導入されたという過去があります.デスクトップ版のみであった最初期は,この機能による複雑さの増加もまだ許容できたのかもしれませんが, Android 版や NaCl 版開発時に「がんばって移植すべき機能」のひとつになってしまったのは不幸でした.これらの環境では,システムの OpenSSL を単純に呼び出すといった方法が使えなかったため,ビルド時に OpenSSL 自体をビルドしたり,JNI コードを追加したりといった方法で対処されることとなりました.このがんばりは,予定されたスケジュールまでに製品をリリースするという点では有効でしたが,残ることになった複雑さはまさに技術的負債でした.
さて,よくよく処理内容を調べてみると,SHA1 と AES256 CBC の計算で,きちんと認証を受けた OS 固有実装を利用しようとした結果,物事が複雑化しまっていることがわかります.しかしながら,もともと "カジュアルな" 情報漏洩対策でしかない暗号化処理で,FIPS 認定にこだわるというのも変な話です.だったら自前で SHA1 と AES256 CBC を実装してしまえば,大幅にビルドが単純になるだろう,と始めてみたのがこの Issue 215 となります.
基本実装は r192 に含まれていますが,この時点では旧実装も残されていました.その後,r208r209r497 として旧実装は削除されています.
規格を読みながら有名アルゴリズムを実装するのは楽しい体験でした.計算結果の比較のために見ていた Chromium の SHA1 実装にバグを見つけるというおまけもありました (Chromium Issue 348333) .4 月に OpenSSL の Heartbleed が盛り上がったのも,面白い偶然の一致です.
まとめると,以下のようなメリットがあったものと考えています.

  • 実行時に依存するライブラリが少なくなる
  • ビルドが単純化される
  • プラットフォーム共通コードが増える
  • (OSS Mozc に GPL コードを組み合わせたい人にとっての),潜在的なライセンス非互換問題のリスクが減る

Issue 211: 2 段階ビルドを廃止

https://code.google.com/p/mozc/issues/detail?id=211
従来,たとえば Android 版 Mozc の APK をビルドするときには,以下のようにコマンドを 3 回実行する必要がありました.

python build_mozc.py gyp --target_platform=Android
python build_mozc.py build_tools -c Release
python build_mozc.py build -c Debug_Android android/android.gyp:apk

これが,以下のようにコマンド 2 回でビルドできるようになった,というものです.

python build_mozc.py gyp --target_platform=Android
python build_mozc.py build -c Debug android/android.gyp:apk

Mozc のビルドが build_tools というコマンドと build の 2 段階に分けられたのは,実に 2010 年,Mozc を OSS 化するにあたってビルドシステムを GYP に移行するさなかのことでした.当初の動機は,時間のかかるバイナリ辞書圧縮処理を開発中何度も実行したくないという理由でした.状況が変わったのは,Android 版や NaCl 版の必要がでてきてからです.これらのプラットフォームはクロスコンパイルを必要とし,そのための基盤として 2 段階ビルドが「利用」されました.ビルドの複雑さは一時制御不能な規模までふくれあがり,一見正しく見える変更が,なぜか Android ビルドだけを壊すという問題が多発しました.記憶が確かなら 2011 年から 2012 年頃が最も酷かったように思います.
このひどい状況は,2013 年末,Android 版ビルドが GYP の Android.mk ジェネレータから一般的な make ジェネレータに切り替えられることで大幅に改善され,今回 FxOS コードリーディングミートアップ #4 に参加したのを切っ掛けに取り払ってみた感じです.
ちなみに 2010 年ごろ懸念されたビルド時間の問題も,今時のワークステーションで作業する分には概ね問題になりません.
基本実装は r192 にて.その後,r211およびr214にて有効化されました.
2 段階ビルドに使用されたコードはその後 r371 および r507 として完全に削除されます.

Issue 224: enable_gtk_renderer=0 指定時にビルドが失敗する

https://code.google.com/p/mozc/issues/detail?id=224
Linux 版 Mozc で, mozc_renderer を無効にした状態でビルドしようとするとコンパイルエラーになるという問題.単純なミスだったので即修正となりました.
r215 にて修正.

Unicode 絵文字変換を NaCl 環境および Linux デスクトップ環境でもデフォルト有効化

今までは特定環境のみ Unicode 絵文字をデフォルト有効化というロジックだったのですが,コードがだいぶ複雑になってしまっていたので,逆に特定環境のみデフォルト無効化というロジックに変更しました.このときの簡略化の一環で, NaCl 環境および Linux デスクトップ環境でも Unicode 絵文字変換はデフォルト有効化となりました.
r229r230r231 の 3 つのコミットにより有効化.

Issue 226: ibus-mozc の周辺文字列取得コードが正しく動作していなかった

https://code.google.com/p/mozc/issues/detail?id=226
ibus-mozc の周辺文字列の取得コードにバグがあって,UTF-8 文字列のバイトオフセットを使って部分文字列を切り出すべきところに,間違って文字数を使って部分文字列を切り出していたというもの.結果的に,ibus-mozc で周辺文字列を考慮した変換が意図しない形で動作してしまっていました.
r232 および r233 にて修正.

Issue 227: IBus 1.5 環境下で確定取り消しが動作しない

https://code.google.com/p/mozc/issues/detail?id=227
Issue 201 修正の副作用で,ibus-mozc を IBus 1.5 環境下で使用しているとき,確定取り消し (MS-IME キー設定で言うところの Ctrl+BS) が動作しなくなっていた,という問題の修正です.
r234 にて修正.

Issue 233: ibus-mozc 使用時,MozcTool に対応するテキストラベルが存在しない

https://code.google.com/p/mozc/issues/detail?id=233
MozcTool に対応するテキストラベルが存在せず,空白のエントリが表示されるというものです. IBus 1.4 環境までは言語バー的な UI が標準で表示されていたため問題になりませんでしたが,IBus 1.5 環境で言語バー的な UI が廃止されたためこの問題が表面化する可能性が高くなりました.
f:id:NyaRuRu:20150211174258p:plain
ちょうど社内のワークステーションが Ubuntu 14.04 に切り替わるタイミングだったので,同僚から言われる前に IBus 1.5 関係のやり残しタスクの一環で直してみた感じです.
r251 にて修正.

Issue 236: Windows 8.1 update1 環境で Explorer がクラッシュすることがある

https://code.google.com/p/mozc/issues/detail?id=236
安定性の確認もかねて,家でときどき tsf-mozc を使っていたところ,Windows 8.1 update1 環境で Explorer がクラッシュする確実な手順を発見したので,デバッグ・対処してみたというものです.再現率 100% なので, Visual Studio で簡単にデバッグできるかと思いきや,windbg で WinRT の内部まで潜る必要があって大変でした.Ntdebugging Blog の記事を見つけられなければデバッグは無理だったように思います.WinRT で言語共通の実行時例外がどのように実装されているか興味がある人には,この記事面白いかもしれません.
r252 にて対処.

Issue 222: Linux デスクトップ, NaCl, および Android ビルドで Ninja を使用する

https://code.google.com/p/mozc/issues/detail?id=222
2012年他にやったこと - Mozc 編 - NyaRuRuが地球にいたころ で書いたように,2012 年末から Windows 版 Mozc は Ninja でビルドされるようになっていたのですが,これを Linux デスクトップ, NaCl, および Android ビルドでも使うようにしたというものです.
やってみて分かったのですが,どうも GYP の Ninja ジェネレータとmake_global_settings という GYP の設定の組み合わせで Android 向けクロスビルドを行ったのは Mozc が最初らしく,結局自分で GYP 側も直す必要がありました.以下のようにせっせと GYP 側にパッチを送っていたりします.たまに役立つ GYP コミット権.

Mozc 側では,r265, r266, r267, r268 の 4 回に分けて有効化されました.

Issue 240: Linux デスクトップ, NaCl, および Android ビルド環境構築のための Dockerfile の提供開始

https://code.google.com/p/mozc/issues/detail?id=240
OSS Mozc の公式ビルド環境を Docker で定義してみよう,と Docker の勉強がてらやってみました.特に Android 版 Mozcのビルド環境を Docker 化できたおかげで,その後のビルドの検証がだいぶ楽になりました.
r271 にて Ubuntu 12.04 ベースのコンテナを提供開始.
r330 にて Ubuntu 14.04 ベースのコンテナの試験提供を開始しました.
なお, r486 で Ubuntu 12.04 ベースのコンテナは役目を終了し,以後は Ubuntu 14.04 に一本化しています.

Ninja の Console Pool 機能を有効化

https://code.google.com/p/mozc/source/detail?r=314
Ninja 1.5 の新機能に Console Pool というのがあって,これが Mozc の Android ビルドのときに使えるかなと試してみたものです.
r314 にて有効化.

Issue 246: Linux, NaCl, および Android 環境で,'Set input mode to X' コマンドが直接入力モードで動作しない

https://code.google.com/p/mozc/issues/detail?id=246
https://bugzilla.redhat.com/show_bug.cgi?id=1119048
Red Hat Bugzilla で ibus-mozc 向けに報告されていた問題で,キーマップエディタで直接入力モード時に「ひらがなモードに切り替え」というコマンドを設定したとしても,実際には動作しないという問題です.
Windows では問題なく動作するのですが,動作するプラットフォームが実はホワイトリスト方式になっていて,Windows 以外では意図的に受け付けないようになっていました.実際には Mac 以外で許可することに問題はないので,そのように対処した,というものです.
r315 にて修正.

Issue 244: Visual C++ 2013 対応

https://code.google.com/p/mozc/issues/detail?id=244
OSS Mozc を Visual Studio 2013 でビルドできるようにしてみた,というものです.
r311 以降で対応.
ちなみにこの後 Visual Studio Community がリリースされたおかげで,無償版の Visual Studio を利用して OSS Mozc Windows 版をビルドできるようになっています.
なお, r509 以降では Visual Studio 2013 にサポートするコンパイラを一本化しています.

About ダイアログ上の Copyright 表記の更新

2014 年も半分以上過ぎているのに,About Dialog 上の Copyright 表記が 2013 年のままだったので直したというものです.
r324 にて修正.

アプリケーションマニフェストに Windows 10 対応宣言を追加

Windows 版の実行ファイル全てに,Windows 10 対応という GUID をセットするというものです.
r344 にて対処.

UserHistoryStorage の 2038 年問題

Mozc の入力履歴ファイル内で使用されるタイムスタンプが 2038 年以降不正な値になるという問題です.たまたまコードを眺めていて発見したので直してみました.修正自体はほぼ Protocol Buffers で定義されたデータ型の型を uint32 から uint64 に変更するだけといえます.Protocol Buffers の特徴として,この変更に関しては互換性と保存されるデータサイズ的に影響を及ぼさないと分かっていたため,割と気軽に直すことができました.
r346 にて対処.

SafeStrToDouble/SafeStrToFloat を Android 環境で再度有効化

https://code.google.com/p/mozc/source/detail?r=370
特定バージョンの Android NDK でビルドすると,strtod に 16 進数表記の文字列を渡したときの挙動に非互換の変更があったため,Android 環境で一部のテストを無効化されていたのですが,Android NDK r10c でこの問題が修正されたためテストを再度有効化したというものです.
r370 にて対処.

Issue 249: Windows 8 以降の環境でスタート画面に統合された IME 候補表示が正しく動作しない

https://code.google.com/p/mozc/issues/detail?id=249
これも家で tsf-mozc を使っていて発見した問題です.当時実験的に tsf-mozc でITfFnSearchCandidateProvider をサポートしていたのですが,どうも実装が不完全だったため逆に問題のある挙動になってしまっていたらしく,該当機能を無効化することで対処となりました.
r329 にて修正.

Issue 248: Android 環境に物理キーボードを接続し,デッドキーを使用するとクラッシュする

https://code.google.com/p/mozc/issues/detail?id=248
OSS Mozc の Issue Tracker に寄せられた報告です.Android 環境での Mozc のデッドキーイベントの扱いに問題があり,特定キーボードレイアウトで特定キーシーケンスを入力すると必ず Mozc がクラッシュしてしまっていました.
r463 にて修正.

Issue 255: ibus-mozc を XIM プロトコルで使用すると,フォーカスロスト時にプリエディットがクリアされない

https://code.google.com/p/mozc/issues/detail?id=255
OSS Mozc の Issue Tracker に寄せられた報告です.元々は日本 IBM の人から SUSE Linux に報告が寄せられ,さらに openSUSE の Issue Tracker を経ての報告だそうです.
ibus-mozc を XIM プロトコルで使用し,gedit 上でプリエディットが残っている状態で,別アプリケーションにフォーカスを移し,再度 gedit にフォーカスを戻すと,以前のプリエディットは既に確定されているのに,ibus-mozc は以前のプリエディットの内容が残ったままであるかのように振る舞う,という問題でした.
調べてみると Mozc 1.2.809.102 より前のバージョンではこのケースでも正しく動いていたものの, Chromium OS (当時はまだ IBus を使用していた)でのフォーカス周りのバグに対処すべくあれこれ変更するうちに現在の挙動になってしまったということが分かりました.
r386 にて修正.

2015 年の話とか

今年は休日の空き時間があまり読めないので,分からないというのが正直なところです.少なくとも OSS 化作業については,Android 5.0 向けの OSS 化が一息ついたので,多少は時間が稼げたんではなかろうかと.

もし何かひとつ優先するすれば,今年こそ不要コードの削除に注力したいかなと.Windows XP 対応のために入れていたコードや,もうあまり意味の無さそうなパフォーマンスチューニング,古いコンパイラのために必要だったコードなどなど.書いた本人ならすぐに判断がつくものの,もし仮に誰かが引き継いでしまうと消していいかの判断がつかなくなりそうなものは今のうちに消してしまいたいと思う次第.

次点としては,Windows 版向けにずっとやりたかったことあれこれ,たとえば OSS 版のインストーラーを動くようにするとか per-monitor DPI-aware 対応とか.とはいえ,すべては今年の休日具合次第なんですけどね.あとどんなミートアップに参加するかも.