tsutsuiの作業記録置き場

NetBSDとかPC-6001とかの作業記録のうち、Twitterの140字では収まらない内容や記事としてまとめるべき内容をとりあえず置いてみる予定

mikutter GTK3対応(4) 〜そして 5.0リリースへ〜

次回のエントリでは、この debian ruby-gtk2 パッケージのツイートを発端とした「mikutter GTK3対応の最終ステージ」について書いてみたいと思います。なんとか 12/25 の mikutter 5.0 リリースに間に合わせたい

mikutter GTK3対応(3) 〜miracle painter〜 - tsutsuiの作業記録置き場

mikutter.hatenablog.com

f:id:tsutsuii:20211225133011p:plain

というわけで無事にておくれてしまいましたが、まだ慌てるような時間じゃない、ということで前回の続きを書いてみたいと思います。

ruby-gnome GTK2廃止対応

前回のエントリで記載したとおり、 2021/4/22 リリースの ruby-gnome 3.4.4 で gtk2 のサポートは廃止され、当然ながら rubygems.org での gtk2 gem 更新も 3.4.3 までとなりました。

mikutter GTK3対応の前段階として、私が担当している pkgsrc の mikutter とそのための ruby gtk2 パッケージ の対応についてメモしておきたいと思います。

Farewell ruby-gtk2

Twitterその他をご覧の方はご存知と思いますが、私自身がメンテナとなっている mikutterおよび依存パッケージを含め、自分自身が必要な pkgsrc の各パッケージの検証を兼ねて NetBSD/amd64,i386 9.2 ておくれLive Image というものを NetBSD本体のリリースや pkgsrc の4半期毎リリースに合わせて更新するようにしています。

その関係で IFTTT で自分担当の各パッケージのリリース情報を見ていたため、 ruby-gnome 3.4.4 のリリースとその中の GTK2削除についてはその日のうちに気づいていました。

ただ、 mikutter本体の GTK3対応作業がしばらく止まっていたこと、 pkgsrc的に mikutter 以外で ruby-gnome を使っているのは ruby-gnomeメンテナご本人によるプレゼンツール rabbit くらいだったこと、さらに私自身が pkgsrc ruby-gnome パッケージの担当だったこともあり、「当面は現状の ruby-gnome 3.4.2 のままにするか」と、いったん様子見とすることにしました。

NetBSD 9.2 リリースにあわせて作った 20210521版の Live Image でも、「ruby-gnome をどうすべか」と思いつつ、リリースアナウンスや変更履歴では特に触れていませんでした。

更新プレッシャー

2021年7月の pkgsrc-2021Q2 リリース後の Live Image更新については Firefox ビルドのための rust のビルドが NetBSD/i386 では失敗する問題のためにしばらく保留していました。

8月に入ったところでこの問題が解決して Firefoxもビルドできるようになり、 Live Image更新作業を始めたところで「そろそろ ruby-gnome 対応を真面目に考えるか」と、いったん GitHub issue でメモすることにしました。

方針としては以下のような感じです。

ruby-gnome では 3.4.3 → 3.4.4 の更新で ruby-gtk2 が削除された。
mikutter は未だ gtk2 対応のみで gtk3 対応は道半ばなので
pkgsrc として対応を考える必要がある。

  • pkgsrc/x11/ruby-gtk2 は 3.4.3 のまま残す
  • pkgsrc/meta-pkgs/ruby-gnome から ruby-gtk2 を外して、 ruby-gtk2 側でバージョンや依存関係を個別定義する
  • もし 3.4.4 以降から現状の 3.4.9 までに API 変更がある場合は ruby-gtk2 のソースパッチで対応できるか検証する
ruby-gtk2 削除対応 · Issue #38 · tsutsui/netbsd-teokureliveimage · GitHub

単純に GTK2 gem を古いままにして GLIB2 その他の gem を新しくしてしまうと以下のような懸念がありました。

ただ、悩んだところで他に手はなく、検討のために ruby-gnome 3.4.4 から 3.4.9 までの変更をざっと確認したところでは virtual functionサポート追加以外のあからさまな API/ABI変更は無さそうで、とりあえず試したところ GTK2版 mikutter は動くようでした。

このため、  ruby-gnome 3.4.9 への更新と合わせて上記の変更を pkgsrc にコミットしました。これが 2021年8月29日です。

パッケージ更新問題

という具合いに「どうしたものか」と考えた中で流れてきたのが、前回も紹介した以下のツイートです。

同じパッケージ管理者として debian ではどうなっていくのだろうか、ということでこれ幸いといろいろお話を聞いてみることに。

pkgsrc では ruby-gnome の各パッケージを独立した gem から生成するように変更していましたが、 debian では単一の ruby-gnome の GitHub リポジトリを親として各パッケージを生成しているそうです。このため、 ruby-gtk2 のみを古いまま新たなパッケージとして追加することは難しいのではないか、ということでした。

やはりておくれる運命のmikutter

GTK3再始動

この私の勝手な決意表明(?)のツイートを見て立ち上がってくれたのが、人気Android Twitter/MastodonクライアントYukari の作者で mikutterのコミッタでもある shibafu528氏です。

ネクロマンシーは、死体による占い全般を指す通俗的な呼称で、未来や過去を知るために死者を呼び出し、また情報を得るために一時的な生命を与えることを含む。

ネクロマンシー - Wikipedia

2021年5月の ruby-gnome 3.4.5 で virtual function サポートが入ったものの、 mikutter GTK3作業をしていた yuntan_t氏は多忙となったため作業は止まっていた状態でした。まずはこの virtual function 対応を確認するところからだったようです。

というわけで、 9月7日 22:27の決意表明ツイートからわずか 2時間ほどで shibafu528さんがジェバンニしてくれたのでした。

ここから mikutter GTK3対応が再始動していくことになります。なんでも書いてみるものです

ruby-gnome側課題

まず ruby-gnome 3.4.5 での virtual function に問題があったようです。これは、 shibafu528氏により pull request が出され、すぐにマージされることとなりました。

github.com

このスーパークラスの virtual function の問題のほかに、 ruby-gnome 側の問題としてもう一つあったのが mikutter GTK3対応(1) のエントリでも記載した pango gem のモージュル名変更の問題です。

この問題については、12月頭の上記のブログエントリを見た shibafu528さんがサクッと mikutter側にモンキーパッチを用意してくれました。

  1. https://github.com/ruby-gnome/ruby-gnome/pull/1433 をモンキーパッチで適用
  2. ruby-gnome 3.5.0 では PangoCairo 配下にある定数群が ruby-gnome 3.4.9以下では Pango 配下にあるので、エイリアスを張った
提案 #1551: gtk3: ruby-gnome 3.4.9でも動くようにする - mikutter - やること

mikutter 5.0.0 リリースの今日 2021年12月25日まで ruby-gnome 3.5.0 のリリースは行われなかったため、現時点ではこの暫定対応がそのまま採用されている状態となっています。

mikutter GTK3 cleanup

9月10日以降、主に shibafu528氏が中心となって GTK3版の実用を目指したデバッグが始まりました。詳細は mikutter Redmine の活動ページを見ていただくとして、大枠は以下のGTK3チケットにある項目の対応です。

各チケットの件名を見ればだいたい雰囲気はわかるかと思いますが、 miracle painter というフレームワーク対応が概ね終わり、実用するための修正がメインになっていることはわかるかと思います。

9月終わりになると toshi_aさんも加わって GTK3版 miracle painter 詳細実装の修正も進んでいきます。

GTK3作業参戦

shibafu528氏と toshi_aさんが GTK3版の修正に取り掛かっていた9月後半、私自身は NetBSD/luna68k キーボードシリアルドライバの修正などというマイナー作業を2週間ほど続けていました。

10月に入り pkgsrc-2021Q3リリースに対応した Live Imageの更新版作成作業に取り掛かったところで、例の ruby-gnome 対応 GitHub issue を思い出し、「そろそろやるか」と自分でも手を出してみることにしました。

前述の PangoCairoモジュール名問題や pqueue gem 問題等々を対処しつつもちょくちょくクラッシュが発生してちょっと心を折られかけたのですが、ここでもアシストしてくれたのは shibafu528氏です。私が作っているておくれ Live Imageを使って NetBSDでの動作検証をしてくれました。

とりあえず NetBSD+pkgsrc 環境固有の問題はないということはわかったので、むりやりで ruby-gnome パッケージ関連のファイルを GitHub HEADのファイルで上書きして作業をすることにしました。その上で、各種 Twitterプラグインを持ってきて mikutter GTK3対応(1)のエントリ記載の通り適当に GTK3対処を入れると、とりあえずタイムラインは出るようになりました。

mikutter関連作業をするときは関係者が多い都合上 Mastodonメインになるのですが、とりあえず「ruby-gnome 3.5.0 出ないかなー」ということで Twitterにもそれっぽく告知したのがこのタイミング。

Twitterプラグイン GTK3対応

Twitter プラグインのうち、ホームタイムライン表示関連のプラグインはとりあえず動いていたのですが、いくつかのプラグインはそもそもロードされない、ロードされても動きがおかしい、という状況でした。

GTK3対応の中心となっていた shibafu528氏や toshi_aさんは Twitter プラグインのサポートにあまり前向きではないというのは察せられていました。これは自分でなんとかするしかないか、と ruby の勉強も兼ねて Twitter関連プラグインの GTK3対応作業に本腰を入れてみることにしました。

個別の作業を書き出すといくらページがあっても足りないので適当に端折りますが、やはりというかなんというか ruby や miracle painter 以前に GTK2→GTK3の移行作業の勘所を掴むというところが一番苦労しました。

GTK3対応の作業としては、大きく以下に分けられるかと思います。

  • GTK2→GTK3 における API変更
  • GTK2 と GTK3 の同一ウィジェットのデフォルトの振る舞いの変更
  • ruby-gnome の gtk2 gem と gtk3 gem の非互換性
  • mikutter GTK3版本体の変更に伴うプラグイン側の変更
GTK2→GTK3 における API変更

まず、すぐに気づくのが Gtk::Hbox, Gtk::Vbox が deprecated という警告。

ただの警告なので無視してもよいのですが、結構大量に出るのでこれを消さないと本題のデバッグがはかどらないという問題が。まあ、これらは警告メッセージ通り Gtk::Box(:horizontal)gtk::Box(:vertical)機械的に置き換えれば済むのでまだ楽な部類です。

次に :draw シグナルの廃止。

これは最初見様見真似で :expose_event に置き換えたのですが、実は GTK本家のドキュメントにも記載があるとのことでした。まあ読んでも中身の本質はわからないんですけど

あと、数は少ないものの困ったのが色関係の指定。

GTK2では #FFFFFF 形式の 24ビット表記だったものが、 GTK3では各色 0.0〜1.0 の数値を指定する CSS方式に変更になっているようです。これが機械的に 1:1 で置き換える作業では対応できないようで、この問題に当たった user_detail_view プラグインでは mikutter 本体の gtk_postbox での修正内容を適当に真似る、という雑対処で済ませています。

他にも細かい修正があったような気はしますが、これらは地道に対処していく類の作業になります。

GTK2 と GTK3 の同一ウィジェットのデフォルトの振る舞いの変更

一番手を焼いたのがこれです。エラーも警告も出ずに表示だけがおかしいので、どう修正すればよいか見当がつかない、検索しようにも良いキーワードが思いつかない、できることは試行錯誤だけ、という状況に陥りがち。しかも何度も起動するには mikutterさんが重い

まず Gtk::ScrolledWindow の幅指定。

画像投稿プラグインの mikutter-uwm-hommage で謎の表示になったのがこれ。 GTK2環境ではうまいこと(?)親のウィジェット幅に収まっていたものが、謎のデフォルト値 200pxくらいの幅になってしまうようでした。最初は width_request = 500 を指定したりしたのですが、結局 propagate_natural_width = true を指定するとそれっぽくなるようでした。

次に、かなりの時間を費やしたのが Gtk::BoxGtk::Scrollbar の組み合わせ挙動。

GTK2環境ではこの組み合わせで Box表示が表示領域より大きくなるとスクロールバーが表示されていたが、 GTK3ではスクロールバーが表示されるだけで機能しないようでした。それだけではなく、「表示領域のサイズが収まるようにアプリケーションのウインドウサイズが無限に拡大していく」という動作を引き起こし、当該操作のあるタブを表示してしまうと mikutterさんがあっという間にフルスクリーンサイズに張り付いてしまい、アプリごと落とすしか無いという状況に陥っていました。

何日かトライアンドエラーを繰り返して、「Gtk::Scrollbar を捨てて Gtk::ScrolledWindow を使えばよい」という結論に。

他に目についたのは以下の Gtk::ImaegMenuItem の挙動ですが、詳細はそれぞれ Redmine チケットを参照してください。

ruby-gnome の gtk2 gem と gtk3 gem の非互換性

これはとりあえず Gtk::TreeViewvisible_range1件だけでしたが、とにかくドキュメントがないため、試行錯誤のテストコードを書いて挙動を確認しながらの修正になりました。

visible_range が動かないのは gtk3 の問題なのか gem の問題なのかはよくわかりませんが。

添付 ruby-gtk3-TreeView.rb のテキトーテストプログラムを書いていろいろ調べたところ、
どうも GTK2 と GTK3 とで visible_range の返り値が異なるようです。
具体的には GTK3 では 1つ目の返り値として bool が返ってきています。
GTK2 での返り値 1つ目と2つ目 GTK3 での返り値 1つ目と2つ目

ドキュメントがないので仕様がよくわかりませんが、とりあえずブラインドで
1つ目の返り値を visible_range の有効無効判定に使い
2つ目、3つ目の返り値を従来の start_path end_path 相当で扱うように書き換えると
一応ユーザーフォロータブの表示動作(スクロールして表示されたところだけアイコンを出す)は
mikutter_gtk3-UserList-visible_range.mp4 のとおりで実現できているようです。

バグ #1514: gtk3: core/mui/gtk_userlist.rb で visible_range と :expose_event が参照されている - mikutter - やること

GIで非voidな戻り値型かつout引数を伴う関数呼出の戻り値は、関数の本来の戻り値+out引数の配列。
今回は関係ないですが、out引数が1つの場合には配列ではなくそのout引数を単体で返すといった特殊ケースも存在するようです。
(さすがにこの辺の規約はドキュメントあってほしい)

バグ #1514: gtk3: core/mui/gtk_userlist.rb で visible_range と :expose_event が参照されている - mikutter - やること
mikutter GTK3版本体の変更に伴うプラグイン側の変更

mikutter の GTK3対応においては、 GTK APIを 1:1 で置き換えたのではなく、別のウィジェットAPIに置き換えたケースが複数あります。よくハマったところとしては、ウィジェット配置が Gtk::Box から Gtk::Grid に置き換えられた部分をバンドルプラグインで参照しているようなケースです。また、置き換え作業やリファクタリングにおいて意図しない変更が入ってしまった部分もあるようでした。

これらはわかってしまえば機械的な置き換えになるのですが、前回のエントリで書いたとおり GTK3対応は yuntan_t氏が長期に渡って独力で作業していたこともあり、記録を掘り返しながらの作業になりました。

個別の内容についてはそれぞれ Redmineチケットに挙がっていますので、今後 mikutter 5.0 のバグ取りに参加しようという方はながめてみてください。

miracle painter とセットで実装されている timeline 関連の変更も大きく、挙動が異なる場合の差分確認が結構大変だったという印象です。ただ、これらの作業記録が将来の移行作業でも役に立つことを信じたいと思います。

その他、雑多なメモトゥートだけ貼っておきます。

mikutter GTK3対応 まとめ

長々とセルフまとめ状態を含めて書いてしまいましたが、ここで書いた以外にも様々な活動を経て、 GTK3版 mikutter は無事に mikutter 5.0.0 としてリリースされることになりました。

冒頭で引用した mikutter 5.0 リリースのエントリの中で、 toshi_aさん自身は以下のように書かれています。

Gtk3対応は、はっきりいって退屈なものでした。 だからこそ、貢献してくれた方々に心から敬意を表します。

mikutter 5.0.0 - mikutter blog

しかし、NetBSDカーネルC言語以外のプログラミングに手を出す機会がなかなかなかった自分としては、10月から約2か月間で得られた経験値はある意味新鮮で大きなものでした。いい歳になってしまった自分ですが「古い常識に囚われた老害にならない」ためのよい勉強をさせてもらったという気持ちです。

今までも mikutter Redmine のモデレータとしてサポートメインの立場でお手伝いをさせていただいていましたが、今後は mikutter 本体コードへの貢献量も増やせればいいな、と考えています。

最後に、 mikutter というアプリを作り上げてメンテし続けてくれている toshi_aさん、そして yuntan_t氏、 shibafu528氏、その他 mikutter 開発に関わってくれた方々に感謝の言葉を贈りたいと思います。

このエントリを読んでいただいた方も、ここまでの長文駄文にお付き合いいただきどうもありがとうございました!