Ctrlキーを押した時のカーソル位置の保持について

  1. お世話になります。
    Windows10 64bit 1909 / Mery3.2.6 64bit
    特殊な環境下での話で恐縮ですが、キーリマップソフト(Autohotkey)を使用して、Ctrl+IKを{Up}{Down}のカーソルキーを割り当てています。
    この環境下でMeryのカーソル位置を移動させると、Ctrl+IKキーを利用したカーソル移動の時のみ、カーソルキーの位置の保持がおかしくなります。
    具体的には以下のような感じです。

    ※「|」がカーソルキーの現在位置です。
    ---
    あああ

    あああああ|
    ---

    この状態の時にキーボードのカーソルキーの上を2回押すと

    ---
    あああ

    あああああ
    ---
    ---
    あああ|

    あああああ
    ---

    こうなり、ここからキーボードのカーソルキーの下を2回押すと

    ---
    あああ

    あああああ
    ---
    ---
    あああ

    あああああ|
    ---

    こうなります。これはカーソルキーの位置が保持された期待通りの挙動です。
    しかしながら、カーソルキーにリマップしたCtrl+IKを使用すると、以下のようになります。

    ---
    あああ

    あああああ|
    ---

    この状態の時にCtrl+I(Up)を2回押すと

    ---
    あああ

    あああああ
    ---
    ---
    |あああ

    あああああ
    ---

    こうなり、ここからCtrl+K(Down)を2回押すと

    ---
    あああ

    あああああ
    ---
    ---
    あああ

    |あああああ
    ---

    このようにカーソルキーの現在位置が保持されず、カーソル位置が行頭に戻ってしまいます。
    しかし、キーのリマップを変更して、たとえば無変換+IKにUp/Downに割り当てると、カーソル位置の保持に問題は起きません。
    また、キーリマップソフトを別のものに変更しても、やはりCtrl+IKキーに割り当てると、カーソルキーの保持がされなくなります。

    この挙動はほかのいくつかのエディタではおこらないため、できればMeryでもCtrl+IKのリマップ使用時にカーソルキーの保持が行えるようにしたいのですが、なにかMeryでの特別な制限などがあるのでしょうか?
    なにか思い当たることがありましたら教えていただきたいと思い、書きこませていただきました。
    よろしくお願いいたします。

     |  sakai  |  返信
  2. 複数の箇所でカーソルのことをカーソルキーと誤記してしまい、とても読みにくい文章になっておりました・・。
    大変失礼いたしました。

     |  sakai  |  返信
  3. 上記と同じ要因なのかはわかりませんが、もう一点カーソル位置の不可解な挙動で

    ---
    あああ
    - ああ|
    ---
    この状態の時にCtrl+IKでのカーソル上下をくり返すと、
    ---
    ああ|あ
    - ああ
    ---
    ---
    あああ
    - あ|あ
    ---
    ---
    あ|ああ
    - ああ
    ---
    ---
    あああ
    - |ああ
    ---
    と、半角文字が存在する行から半角文字がない行に移動した際に、カーソル位置が一つ前に下がってしまいます。
    なお、この問題は
    ---
    - ああ
    - ああ|
    ---
    のように半角文字が同数の場合、起こりません。
    この問題もカーソルキーを使った上下では起こらず、Ctrl+IKでのリマップ時のみ起こります。
    よろしくお願いいたします。

     |  sakai  |  返信
  4. ご報告ありがとうございます。

    AutoHotkey は使ったことがなかったもので、使い方が合ってるかどうかわかりませんが、とりあえず以下のようなスクリプトで試してみたところ現象を再現できた気がします。

    ^i::Send,{Up}
    ^k::Send,{Down}

    上記のスクリプトで Ctrl + I, K を押下すると、Up, Down キーが Mery に送信されましたが、同時に Ctrl キーも送信されてしまうことが原因のようです。

    Mery のエディター部分のソースコードを確認してみましたところ、どうやら Up, Down, PageUp, PageDown 以外のキーを押下すると、保持しているカーソル位置を破棄して、新たに現在の位置を基準にカーソル位置として記憶するという仕様になっているようです。

    今回のケースだと、Ctrl + I, K を押下するたびに Up, Down とは別に Ctrl キーが送信されるため、カーソル位置の保持が解除、現在の位置で更新されて、このような挙動になっているものと思われます。

    エディター部分は私が開発したものではないため、そのような仕様の意図はわからないのですが、なんとなく Ctrl キーなどの修飾キーは仕様の対象外にしても大丈夫そうな気もするので、調査して対策を考えてみたいと思います。

     |  Kuro  |  返信
  5. 横からすみません。
    AutoHotkeyユーザーとしてちょっぴり補足します。

    ^i::Send,{Up}

    AutoHotkeyを使うと、下記のような順序でキー押下情報が流れます。AutoHotkeyで定義しているキー押下を検知すると、AutoHotkeyでキー情報を誤魔化してOSに渡します。

    キーボード入力 → AutoHotkey → OS

    上記のようなAutoHotkeyスクリプトを使うと、OS側には以下のような順序でキー情報が送られるはずです。

    1. Ctrl Down (キーボードからの入力。AutoHotkeyはフックせずそのままOSに渡す)
    2. I Down (キーボードからの入力。AutoHotkeyのフック対象になるので、このキー情報はOSに渡さない)
    3. AutoHotkeyがフックして、以下の処理を行う
     3-1. Ctrl Up をOSに渡す (Send, {Up} をするときに Ctrl が邪魔になるため、Ctrlを一旦外したものとOSに認識させる)
     3-2. 修飾キー無しの {Up} をOSに渡す
     3-3. Ctrl Down をOSに渡す (Ctrl を押したままである物理キーボード状態の復元)

    上記3-1、3-3あたりでMeryにCtrlキー単体のDown/Up情報が送られているものと推測しています。

     |  yuko  |  返信
  6. さっそく調査いただきまして、ありがとうございます。
    再現に使用していたスクリプトは私の環境のものと同様でした。
    挙動を再現できたようでよかったです。

    なるほど、Ctrlキーの押下のタイミングでカーソル位置が更新されていたのですね。
    あらためて挙動を確認したところ、たしかに、
    ---
    あああ

    あああああ|
    ---
    ここから「カーソルキーの上」→「Ctrl」→「カーソルキーの上」の順にキーを押すと、
    ---
    あああ

    あああああ
    ---
    ---
    |あああ

    あああああ
    ---
    と、キーリマップに関係なく再現することが確認できました。

    > エディター部分は私が開発したものではないため、そのような仕様の意図はわからないのですが、なんとなく Ctrl キーなどの修飾キーは仕様の対象外にしても大丈夫そうな気もするので、調査して対策を考えてみたいと思います。

    対策をご検討いただき、ありがとうございます。
    よろしくお願いいたします。

     |  sakai  |  返信
  7. yukoさまも、Autohotkeyの詳細な流れを補足いただき、ありがとうございます。

     |  sakai  |  返信
  8. >> yuko さん

    情報ありがとうございます。

    なるほど、Ctrl はずっと押しっぱなしのはずなのに i キーを押すたびに Ctrl キーの Up/Down が飛んでくるのは不可解だったのですが、そういう仕組みでしたか。

    仕組み上、仕方がないのだと思いますが、それはなかなかやっかいですね。他にも AutoHotkey と競合してしまう部分があるかもしれません。

    >> sakai さん

    ご確認いただきありがとうございます。スクリプト、同様のものだということで安心しました。

    > なるほど、Ctrlキーの押下のタイミングでカーソル位置が更新されていたのですね。

    そうですね。その条件に加えて、yuko さんからの情報ですが、キーを押下するたびに AutoHotkey 側から Ctrl の Up/Down が送信されるという条件が重なって、今回の現象が発生しているようです。

    もう少し調査してみますね。

     |  Kuro  |  返信
  9. Kuroさん

    > 仕組み上、仕方がないのだと思いますが、それはなかなかやっかいですね。他にも AutoHotkey と競合してしまう部分があるかもしれません。

    あ、そういえば…と思うところがもう1つありました。

    AutoHotkeyでは、Alt, Winキーを使ったホットキーを定義した場合でも、Ctrlを挟み込む動きをします。

    例えば Win + I キーで {Up} を送るスクリプトを想定してみます。

    #i::Send,{Up}

    この場合、AutoHotkeyフックの部分の動き (前述の流れの項3の部分) が以下のようになります。

    3-1. Ctrl Down/Up をOSに渡す (3-2の Win Up でWindowsメニューが開いてしまうのを抑止するための処置)
    3-2. Win Up をOSに渡す
    3-3. 修飾キー無しの {Up} をOSに渡す
    3-4. Ctrl Down をOSに渡す (3-5で復元した Win Down 後、物理キーボードの Win Up によってWindowsメニューが開いてしまうのを抑止するための処置)
    3-5. Win Down をOSに渡す (Win を押したままである物理キーボード状態の復元)
    3-6. Ctrl Up をOSに渡す

    Altを使ったホットキーの場合も、上記のWinの読み替えで同じ動きをします。

    AltとWinは単体Down/Upによる操作が割当たってるため、それらをキャンセルするために上記のような泥臭い処理が発生します。

    ちなみに上記の3-1,3-4,3-6のようなWin/Altキー無害化の処理ではCtrlが使われていますが、Ctrl以外が送られるようにする設定も可能だったりします。
    https://www.autohotkey.com/docs/commands/_MenuMaskKey.htm

     |  yuko  |  返信
  10. お世話になっております。
    昨日公開されたVer3.2.7にて、AutohotkeyでCtrlと組み合わせたカーソルキーのリマップの際にもカーソル位置の保持がされるようになり、より直感的なカーソル操作が行えるようになりました。
    素早いご対応いただきまして、ありがとうございました。

     |  sakai  |  返信
スポンサーリンク