カラクリサイクル

『輝かしい青春』なんて失かった人の雑記

最強の端末環境を整えるべく、 #mlterm にマウススクロール機能を足すパッチを書いた

というお話。


最近、僕は コミュニティ系 Web サービスの開発、 という目標を諦めた関係で、 割とこう、日常的に開発したいネタが尽きてしまい、手持ち無沙汰になったため、

んー、開発環境の再開発でもするか

という感じで、最強な端末環境作るべく、色々作業をしていました。

それで、 OSX のターミナルエミュレーターの再選定とかしていて、

Terminal.app は Sixel とか表示できないし、かといって iTerm2 は設定する所が結構複雑だし、 もっとこう、シンプルでいて、かつ痒いところに手が届きやすいターミナルエミュレーターは無いものか。

と思っていたところ、

そう言えば、前に Macbook Air mid 2011 に Archlinux を突っ込んでいた時、 mlterm 使ってたよなー

と思い出したため、

を OSX で使えないか、と調べたところ、なんと OSX の Cocoa 向けなビルドが可能じゃないですかーやだー、 と判ったため、mlterm を使ってみるべく、自前でコンパイルとかしていました。

が、しかし。

実際に mlterm を OSX の Cocoa 向けのビルドを行って判った事なんですが、 なんか、マウス (正確にはトラックパッド) でのスクロールが出来ない、なんでや! という感じで、一時は mlterm 使うのは諦めるかなーどうしようかなーと考えてたんですが、

とか見てて、色々調べた結果、

あれ、これ、もしかして、マウススクロール機能、自分でも実装出来るんじゃね?

と思いに至り。

自分で実装しますた!!1


というのが長い前フリなんですが、出来上がったパッチは下記になります。

$NetBSD$

--- xwindow/quartz/cocoa.m.orig   2016-05-08 06:47:04.000000000 +0000
+++ xwindow/quartz/cocoa.m
@@ -954,6 +954,47 @@ get_current_window(
    x_window_receive_event( xwindow , (XEvent*)&mev) ;
 }
 
+- (void)scrollWheel:(NSEvent *)event
+{
+   NSPoint loc = [event locationInWindow] ;
+   XButtonEvent bevPress;
+   XButtonEvent bevRelease;
+
+   bevPress.type   = X_BUTTON_PRESS ;
+   bevRelease.type = X_BUTTON_RELEASE ;
+
+   bevPress.time   = event.timestamp * 1000;
+   bevRelease.time = (event.timestamp * 1000) + 1;
+
+   bevPress.x    = loc.x - self.frame.origin.x;
+   bevRelease.x  = loc.x - self.frame.origin.x;
+
+   bevPress.y    = ACTUAL_HEIGHT(xwindow->parent) - loc.y - /* self.frame.origin.y - */ 1 ;
+   bevRelease.y  = ACTUAL_HEIGHT(xwindow->parent) - loc.y - /* self.frame.origin.y - */ 1 ;
+
+   bevPress.state    = event.modifierFlags &
+       (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask) ;
+   bevRelease.state  = event.modifierFlags &
+       (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask) ;
+
+   bevPress.click_count = 1;
+
+   if ( event.deltaY > 1 ) {
+       bevPress.button = 4;
+       bevRelease.button = 4;
+   }
+
+   if ( event.deltaY < -1 ) {
+       bevPress.button = 5;
+       bevRelease.button = 5;
+   }
+
+   if ( event.deltaY < -1 || event.deltaY > 1 ) {
+       x_window_receive_event( xwindow , (XEvent*)&bevPress );
+       x_window_receive_event( xwindow , (XEvent*)&bevRelease );
+   }
+}
+
 - (void)keyDown:(NSEvent *)event
 {
    if( [event type] == NSFlagsChanged)

また、このパッチのファイルは

でもアクセス出来ます。

なお、このパッチの注意点は幾つか注意点があり、まず第一に、僕が pkgsrc + pkgin を使っている関係で、 それらを利用して作ったパッチなため、Homebrew とかでも取り込めるかどうかが良く判っていません。

また、このパッチではスクロールイベントの移動幅 (?) を取るために使っているプロパティが最新の OSX (正確には Lion 以降) では deprecated で、 代りに新しい API を使った方が良いのですが、 mlterm の Cocoa 向け GUI が、どの バージョンの OSX までサポートするのかが良く判らなかったため、 古い OSX でも動くように、 deprecated な プロパティをそのまま使っています。

そのため、きちんと丁寧にこの辺りを実装したパッチを作成するのならば、 その辺り、 OSX のバージョンを見て、処理を分岐させた方が良い、と言えるかと思います。

あと、その他にも定数使った方が良いだとか、あるいは、Lion 以降のナチュラルスクロールへ対応とか、 それと、そもそもこの実装、結構イベント発生させる辺りが強引じゃね? とかそういう問題も有るため、

これをそのまま本家にパッチとして投げるのはちょっとなー

と思っている関係で、本家というか開発者の方にパッチを投げるとか、 そういうのは今のところ僕の方では考えていません。

ただ、このパッチが有ることによって、

mlterm の Cocoa 向けビルドへマウススクロールを実装する

という事への叩き台にはなるかなぁと思うし、あと、もし実装への叩き台にするのであれば、 Objective-C とかサッパリな自分が権利持ってても仕方がないし、と考えているので、 このパッチについては、

という扱いでお願いします。


という事で以上です。

まあ、

最強の端末環境

は、まだ出来上ってなかったりしますが、とりあえず、その過程で出来た成果物を公開した、というお話しでした。

という事で以上です。終わります。はい。