モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

窓使いの憂鬱でバグっぽい現象に遭遇の憂鬱

この記事はfc2から引っ越した記事です

%sLinux版窓使いの憂鬱、0.12-1にてバグっぽい現象を見つけてしまいました。

↑以前、どこから拾ってきたのかわからなくなってしまったのですが、検索していてgithubに乗っている事を知ったのでとりあえずリンクしておきます。

以下のように左ウィンドウズキーをMod0のTrue Modifierとして定義しています。そして、Mod0との組み合わせでカーソルキーを定義し、vim風に移動できるようにしています。

mod Windows -= LWin
mod Mod0 = !LWin

# 略

key M0-*H=*Left
key M0-*J=*Down
key M0-*K=*Up
key M0-*L=*Right
key M0-*Semicolon = *Home
Key M0-*Quote = *End



この状況下で、Mod0とのコンビネーションを組み合わせたキー、たとえばhをキーリピートしつつ、後からMod0を押し、そしてhを離すと…

Mod0を押している限り、以前押していたhがリピートされます。

geditなどのテキストエディタ上での同現象を、文字列で再現しますと

mayu動作下の場合:

(h押しっぱなし)hhhhhhhhhhhhhhhh(この辺から左win=mod0押しっぱなし)hhhh(この辺でh離す)hhhhhhhhh←アルェ?

mayuが動作していない場合:

(h押しっぱなし)hhhhhhhhhhhhhhhh(この辺から左win押しっぱなし) ←hを押していても、キーコードは出なくなる


その他、' (クォート)にEndキーなどマッピングしているのですが、moinmoinのbold記法、'''〜'''のためにクォート連打してるときにvimふうにバシっとカーソルを移動させようとすると、時折 'が増殖したりするのでおかしいな〜と思ったのです。
もしかしてリアルフォースの不良かとさえ思いましたが、mayuを使わないと発生しないのですねこれが。
そして、もしかして以前、ロジクールのマウスm560対応の為に書き換えた部分が悪さをしてるのかと思って元に戻してみたのですが、相変わらず発生するのです。

そうこうしているうちに現象の再現の方法が分かったというのが、上の「hキー押しっぱなし中にmod0押しでh連打が続く件」だったのです。


ソースコードを解読して調べた結果、以下の結論に達しました。

  • リピートしているのはmayuではなく、キーボードドライバである - mayuはほとんどが入力待ちである
  • True modifierの入力は正しく見れている
  • 他のキー、たとえばxなどならこの現象は起きない。つまりモデファイヤとモデファイヤとのコンビネーション登録キーに限った現象
  • 後からモデファイヤが押されたら、キーを一旦離したことにして、そこからモデファイヤ適用後のコードを発するようにするのが望ましい(?)



そこで頑張って、「とりあえずmayu内のキーオブジェクトを再生成して、キーが離された状況にしよう」と思い、いろいろやってみたのですが…

難しすぎて全然わかりません!

正直、基本部分だけ頂いて自分で作りなおしたほうが簡単なんじゃないかとさえ思えました…
(そういうのを作ってもワンショットモデファイヤとかのない、超簡易版でしょうけども)

条件的には普通のキーの押下が発生したのに解放がなされていない時に、True modifierが押されると起きるようですので、その辺のフラグをたてて条件の絞り込みは出来たのですが、キーオブジェクトを生成してイベントを起こす時点でSegfaultばかり…
なんか、以前のキーコードやら何やらを保存しておいて、条件は再現しているはずなのですが、全然キーを得られないのですね。それでどっかがNULLになっててsegfaultになるようです。

ちなみにこの現象が起きたときはキーがリピートしっぱなしになるので、デバッガを使うにせよコマンドラインのデバッガは使用しないほうがよさげ。というかmayuのようなタイプのプログラムはデバッグがやりづらくて困りますね。
今回はkdbgを使いました。綺麗で使いやすいなぁ〜
kdeあまり好きではないのですが、kritaも使いたいしkdeアプリもどんどん使っていくべきかもですね。

さてそれでしばらく何度もソースを読み返し、考えてみましたがどうしてもわからないので、やがて考えるのをやめた…

結局、モデファイ後のキーを改めて送出というのは諦め…

以前に押されたままの時の、「普通の」キーコードを保持しておき、「普通のキーは押されっぱなしでさらにモデファイアも押された状況」が発生したら

send_keyboard_event(prevcode, KEY_EVENT_BREAK);


と、以前のキーが離されたことにするという。
妥協かつLinuxでしか通用しない上に、副作用もわからない適当なコードを…(;´Д`)イイノカコンナンデ
本当はモデファイされたコードを出すのが筋のような気もしますが、とりあえずこれでお茶を濁すということで…

まったくいい加減なハックですが、とりあえずイラつきの元であったリピート増殖だけは収まりましたんで、しばらくこれで使ってみますです。

今回の適当ハックのdiffは以下の通り(engine.cpp)

722a723,725
>   bool prev_pressed=false;
>   bool mod_pressed=false;
>   int prevcode=0;
974a978,992
>
>       if (!mod_pressed)
>       {
>           if(prev_pressed)
>           {
>               send_keyboard_event(prevcode, KEY_EVENT_BREAK);
>               prev_pressed=false;
>           }
>           mod_pressed=true;
>       }
>       else
>       {
>       mod_pressed=false;
>       }
>
1029a1048
>       {
1030a1050,1056
>         prevcode=ievent.code;
>         prev_pressed=true;
>       }
>       else
>       {
>         prev_pressed=false;
>       }



ifの一行ケース時も{}をつけてるのは、今後拡張しなければならなくなる危険性を察知したため、あらかじめつけておきました。

さてこれでmayuの解析も進んで結構わかってきたところもあり、いよいよ「デバイス毎のマッピング切り替え」改造に挑戦してみようかなどと。
これができれば、gimpで「複雑な同時押しショートカット」を何個も定義し、そして一方でmayuにより、普段使ってない薄型キーボードに、その複雑な同時押しが一発で出るように設定すれば…
gimp操作がますますお手軽・超速になりそう!
ペンタブレットに右手を置いたまま、左手だけでコンビネーションを打つのは結構大変なのです。しかしキーボードのキーは限られている…

ワンキーで32pxのガウスぼかしを適用とか、考えただけで胸熱です。ちょっとキーレイアウト表を作って印刷して貼っとかないと(何か本末転倒している気もしますが)

まぁubuntu14.04でmayuが動くかどうか、その対応が先ですねえ。
それにしてもオープンソースというものは本当に有難いものですなぁ…

ところでこの現象、以前はまったく気づかなかったんですが、リアルフォースの反応がよすぎるせいでしょうかね?
なんだかマグネットコーティング前のガンダムを使ってるアムロの逆みたいな…w
そういやリアルフォースっていう字面もモビルフォースっぽいので、是非ガンガルの同人作品ではこのネタ(主人公がマシンの速度についていけなくてデチューン)も入れて欲しいですねw

ちなみにマグネットコーティング後のガンダムはわずか1.1秒で姿勢を180度変えられるそうです。

例の1/1ガンダムが1.1秒で180度転回した姿を想像すると…
危ないだろうwww それはwww

%sLinux版窓使いの憂鬱、0.12-1にてバグっぽい現象を見つけてしまいました。

↑以前、どこから拾ってきたのかわからなくなってしまったのですが、検索していてgithubに乗っている事を知ったのでとりあえずリンクしておきます。

以下のように左ウィンドウズキーをMod0のTrue Modifierとして定義しています。そして、Mod0との組み合わせでカーソルキーを定義し、vim風に移動できるようにしています。

mod Windows -= LWin
mod Mod0 = !LWin

# 略

key M0-*H=*Left
key M0-*J=*Down
key M0-*K=*Up
key M0-*L=*Right
key M0-*Semicolon = *Home
Key M0-*Quote = *End



この状況下で、Mod0とのコンビネーションを組み合わせたキー、たとえばhをキーリピートしつつ、後からMod0を押し、そしてhを離すと…

Mod0を押している限り、以前押していたhがリピートされます。

geditなどのテキストエディタ上での同現象を、文字列で再現しますと

mayu動作下の場合:

(h押しっぱなし)hhhhhhhhhhhhhhhh(この辺から左win=mod0押しっぱなし)hhhh(この辺でh離す)hhhhhhhhh←アルェ?

mayuが動作していない場合:

(h押しっぱなし)hhhhhhhhhhhhhhhh(この辺から左win押しっぱなし) ←hを押していても、キーコードは出なくなる


その他、' (クォート)にEndキーなどマッピングしているのですが、moinmoinのbold記法、'''〜'''のためにクォート連打してるときにvimふうにバシっとカーソルを移動させようとすると、時折 'が増殖したりするのでおかしいな〜と思ったのです。
もしかしてリアルフォースの不良かとさえ思いましたが、mayuを使わないと発生しないのですねこれが。
そして、もしかして以前、ロジクールのマウスm560対応の為に書き換えた部分が悪さをしてるのかと思って元に戻してみたのですが、相変わらず発生するのです。

そうこうしているうちに現象の再現の方法が分かったというのが、上の「hキー押しっぱなし中にmod0押しでh連打が続く件」だったのです。


ソースコードを解読して調べた結果、以下の結論に達しました。

  • リピートしているのはmayuではなく、キーボードドライバである - mayuはほとんどが入力待ちである
  • True modifierの入力は正しく見れている
  • 他のキー、たとえばxなどならこの現象は起きない。つまりモデファイヤとモデファイヤとのコンビネーション登録キーに限った現象
  • 後からモデファイヤが押されたら、キーを一旦離したことにして、そこからモデファイヤ適用後のコードを発するようにするのが望ましい(?)



そこで頑張って、「とりあえずmayu内のキーオブジェクトを再生成して、キーが離された状況にしよう」と思い、いろいろやってみたのですが…

難しすぎて全然わかりません!

正直、基本部分だけ頂いて自分で作りなおしたほうが簡単なんじゃないかとさえ思えました…
(そういうのを作ってもワンショットモデファイヤとかのない、超簡易版でしょうけども)

条件的には普通のキーの押下が発生したのに解放がなされていない時に、True modifierが押されると起きるようですので、その辺のフラグをたてて条件の絞り込みは出来たのですが、キーオブジェクトを生成してイベントを起こす時点でSegfaultばかり…
なんか、以前のキーコードやら何やらを保存しておいて、条件は再現しているはずなのですが、全然キーを得られないのですね。それでどっかがNULLになっててsegfaultになるようです。

ちなみにこの現象が起きたときはキーがリピートしっぱなしになるので、デバッガを使うにせよコマンドラインのデバッガは使用しないほうがよさげ。というかmayuのようなタイプのプログラムはデバッグがやりづらくて困りますね。
今回はkdbgを使いました。綺麗で使いやすいなぁ〜
kdeあまり好きではないのですが、kritaも使いたいしkdeアプリもどんどん使っていくべきかもですね。

さてそれでしばらく何度もソースを読み返し、考えてみましたがどうしてもわからないので、やがて考えるのをやめた…

結局、モデファイ後のキーを改めて送出というのは諦め…

以前に押されたままの時の、「普通の」キーコードを保持しておき、「普通のキーは押されっぱなしでさらにモデファイアも押された状況」が発生したら

send_keyboard_event(prevcode, KEY_EVENT_BREAK);


と、以前のキーが離されたことにするという。
妥協かつLinuxでしか通用しない上に、副作用もわからない適当なコードを…(;´Д`)イイノカコンナンデ
本当はモデファイされたコードを出すのが筋のような気もしますが、とりあえずこれでお茶を濁すということで…

まったくいい加減なハックですが、とりあえずイラつきの元であったリピート増殖だけは収まりましたんで、しばらくこれで使ってみますです。

今回の適当ハックのdiffは以下の通り(engine.cpp)

722a723,725
>   bool prev_pressed=false;
>   bool mod_pressed=false;
>   int prevcode=0;
974a978,992
>
>       if (!mod_pressed)
>       {
>           if(prev_pressed)
>           {
>               send_keyboard_event(prevcode, KEY_EVENT_BREAK);
>               prev_pressed=false;
>           }
>           mod_pressed=true;
>       }
>       else
>       {
>       mod_pressed=false;
>       }
>
1029a1048
>       {
1030a1050,1056
>         prevcode=ievent.code;
>         prev_pressed=true;
>       }
>       else
>       {
>         prev_pressed=false;
>       }



ifの一行ケース時も{}をつけてるのは、今後拡張しなければならなくなる危険性を察知したため、あらかじめつけておきました。

さてこれでmayuの解析も進んで結構わかってきたところもあり、いよいよ「デバイス毎のマッピング切り替え」改造に挑戦してみようかなどと。
これができれば、gimpで「複雑な同時押しショートカット」を何個も定義し、そして一方でmayuにより、普段使ってない薄型キーボードに、その複雑な同時押しが一発で出るように設定すれば…
gimp操作がますますお手軽・超速になりそう!
ペンタブレットに右手を置いたまま、左手だけでコンビネーションを打つのは結構大変なのです。しかしキーボードのキーは限られている…

ワンキーで32pxのガウスぼかしを適用とか、考えただけで胸熱です。ちょっとキーレイアウト表を作って印刷して貼っとかないと(何か本末転倒している気もしますが)

まぁubuntu14.04でmayuが動くかどうか、その対応が先ですねえ。
それにしてもオープンソースというものは本当に有難いものですなぁ…

ところでこの現象、以前はまったく気づかなかったんですが、リアルフォースの反応がよすぎるせいでしょうかね?
なんだかマグネットコーティング前のガンダムを使ってるアムロの逆みたいな…w
そういやリアルフォースっていう字面もモビルフォースっぽいので、是非ガンガルの同人作品ではこのネタ(主人公がマシンの速度についていけなくてデチューン)も入れて欲しいですねw

ちなみにマグネットコーティング後のガンダムはわずか1.1秒で姿勢を180度変えられるそうです。

例の1/1ガンダムが1.1秒で180度転回した姿を想像すると…
危ないだろうwww それはwww