smzht / fakeymacs

Emacs-like key bindings for Keyhac
MIT License
111 stars 49 forks source link

CapsLock キーをレジストリの設定をせずにそのままの状態で Ctrl キーとして使えるようにしたい #42

Closed smzht closed 1 month ago

smzht commented 2 months ago

日本語 Windwos で CapsLock キーを使う場合、Up イベントが発行されない場合があるため、Keyhac では CapsLock キーを Ctrl キーに置き換えることができません。一般には レジストリでキーを置き換える方法で対処していますが、この方法は PC の管理権限がないと対応できない方法と思われます。

職場などでは PC の管理権限が与えられないこともあるため、レジストリの設定をせずとも Ctrl キーとして使えるようにする方法がないか、検討します。

smzht commented 2 months ago

まず、OSの設定がUSキーボードになっている場合の設定例です。

define_key(keymap_global, "CapsLock", lambda: None)
keymap.defineModifier("CapsLock", "User2")

define_key(keymap_emacs, "U2-b", getKeyCommand(keymap_emacs, "C-b"))
define_key(keymap_emacs, "U2-f", getKeyCommand(keymap_emacs, "C-f"))
define_key(keymap_emacs, "U2-p", getKeyCommand(keymap_emacs, "C-p"))
define_key(keymap_emacs, "U2-n", getKeyCommand(keymap_emacs, "C-n"))
define_key(keymap_emacs, "U2-a", getKeyCommand(keymap_emacs, "C-a"))
define_key(keymap_emacs, "U2-e", getKeyCommand(keymap_emacs, "C-e"))
define_key(keymap_emacs, "U2-k", getKeyCommand(keymap_emacs, "C-k"))

OSの設定がUSキーボードの場合、CapsLockキーのUPイベントが返ってくるので、CapsLockキーを無効にする設定を追加する程度で動作します。

smzht commented 2 months ago

次に、OSの設定が日本語キーボードになっている場合の設定例です。

OSの設定が日本語キーボードの場合、CapsLockキーを押すと (240) のキーが押されたことになり、キーを離したときにキーのUPイベントが返ってきません。これが、日本語キーボードでCapsLockキーが使えないと言われている理由です。

ただし、CapsLockキーを押したときに、Shiftキーも押したことにすると、CapsLockキーのUPイベントが返ってきます。

以下のコードで試すことができます。

keymap.replaceKey("(240)", "CapsLock")
define_key(keymap_global, "CapsLock", self_insert_command("D-Shift"))
define_key(keymap_global, "U-CapsLock", self_insert_command("U-Shift"))

上記は一行目のキーの置き換えだけではUPイベントが返ってきませんので、二行目と三行目の対策が必要となります。

smzht commented 2 months ago

上記の日本語キーボードの設定では、CapsLockを押している間はShiftキーが押されている状態になりますので、CapsLockキーをモディファイアキーとして設定して、そのCapsLockキーを使ったキーの発行によりコマンドを実行する際には、そのコマンドの前後でShiftキーをUpしてまたDownする処理が必要となります。

これらを対策して、USキーボードでも日本語キーボードでも動作するようにしたコードが以下となります。

def shift_down():
    self_insert_command("D-Shift")()

def shift_up():
    self_insert_command("U-Shift")()

if os_keyboard_type == "JP":
    keymap.replaceKey("(240)", "CapsLock")
    define_key(keymap_global, "CapsLock", shift_down)
    define_key(keymap_global, "U-CapsLock", shift_up)
else:
    define_key(keymap_global, "CapsLock", lambda: None)

keymap.defineModifier("CapsLock", "User2")

def shift_command(func):
    if os_keyboard_type == "JP" and callable(func):
        def _func():
            shift_up()
            func()
            shift_down()
        return _func
    else:
        return func

define_key(keymap_emacs, "U2-b", shift_command(getKeyCommand(keymap_emacs, "C-b")))
define_key(keymap_emacs, "U2-f", shift_command(getKeyCommand(keymap_emacs, "C-f")))
define_key(keymap_emacs, "U2-p", shift_command(getKeyCommand(keymap_emacs, "C-p")))
define_key(keymap_emacs, "U2-n", shift_command(getKeyCommand(keymap_emacs, "C-n")))
define_key(keymap_emacs, "U2-a", shift_command(getKeyCommand(keymap_emacs, "C-a")))
define_key(keymap_emacs, "U2-e", shift_command(getKeyCommand(keymap_emacs, "C-e")))
define_key(keymap_emacs, "U2-k", shift_command(getKeyCommand(keymap_emacs, "C-k")))
smzht commented 2 months ago

上記のコードをdefine_key関数の中に組み込み、Ctrlを利用したキー設定が入ってきた場合はUser2を使う設定もするようにすれば、CapsLockキーをCtrlキーとして使えるようになるのではないかと思っています。

ただ、正常に動作しないパターンがあることも確認しており、もう少しテストが必要な状況となっています。

smzht commented 1 month ago

とりあえず develop branch に初版を登録しました。

config_parameter.py で fc.use_capslock_as_ctrl 変数を True に設定すると利用できます。

OS のキーボード設定は、日本語でも US でも使えますが、US キーボードにした場合、CapsLock と 他のモディファイアキーを組み合わせたキーを発行すると、まだ正常に動作しません。現時点では、日本語キーボードにした場合の方がうまく動くと思います。

smzht commented 1 month ago

X-Window サーバ VcXsrv で動かすと、カーソル移動が少し遅くなるようです。WSLg では遅くなりません。

smzht commented 1 month ago

本設定を利用して、CapsLock の状態やモディファイアキーの押下の状態がおかしくなった場合には、一度 Keyhac のリロードし、フックを OFF にして状態を正常化させた後に、再び フックを ON にしてください。

smzht commented 1 month ago

少なくとも OS の設定が日本語キーボードになっている場合は、CapsLock キーを Ctrl キーとしてマウスと一緒に使うことはできません。マウスを Ctrl キーと連携して使いたい場合は、本来の Ctrl キーを使う必要があります。

smzht commented 1 month ago

先にも書きましたが、OS の設定が US キーボードの場合、CapsLock+Alt+l のようなキーバインドが C-A-l として正しく動作しません。日本語キーボード設定の場合は対策済みです。この問題については、現在鋭意対応中です。

smzht commented 1 month ago

当然ですが、fc.transparent_target や fc.game_app_list に指定したアプリには本機能は適用されません。これらのアプリでは、本来の Ctrl キーを使う必要があります。

smzht commented 1 month ago

Ctrl+マウスクリック が使えないのが地味に不便かもしれません。本来の Ctrl キーを使うように慣れればいいのかもしれませんが。一応、対策がないかは検討してみます。master branch に merge するのは、もう少し先になりそうです。

smzht commented 1 month ago

develop branch の最新で、OS 設定が US キーボードの場合でも、日本語キーボードの場合と同様に動作するようになりました。

smzht commented 1 month ago

OS 設定が US キーボードの場合のみに発生している問題ですが、CapsLock+Alt+l と入力した場合、Alt -> CapsLock -> l の順番で入力すると Alt+l と認識されてしまうようです。CapsLock -> Alt -> l の順番で入力すると、正しく C-A-l と認識します。対策可能か調査しています。それ以外については、マウスと連携できないなどいくつかの制約事項はありますが、概ね問題なく動作するようになったのではないかと思います。

smzht commented 1 month ago

OS 設定が US キーボードの場合のみに発生している問題ですが、CapsLock+Alt+l と入力した場合、Alt -> CapsLock -> l の順番で入力すると Alt+l と認識されてしまうようです。CapsLock -> Alt -> l の順番で入力すると、正しく C-A-l と認識します。対策可能か調査しています。それ以外については、マウスと連携できないなどいくつかの制約事項はありますが、概ね問題なく動作するようになったのではないかと思います。

次のコミットで対策できたようです。概ね問題なく動作するようになってきたので、もう少しテストして問題なければ master branch に merge したいと思います。

smzht commented 1 month ago

マウスと連携できない以外に、もう一つ利用上の制限事項を見つけました。

OS 設定を日本語キーボードにして使う場合、CapsLock キーを押している間は Shift キーを Down している状態を作っています。これは CapsLock キーを離した際に Up イベントを発生させるためなのですが、この対応をしているため、CapsLock キーを使ったキーからコマンドを実行する際には、コマンドの前後に Shift キーの Up と Down を行う処理を入れ、Shift キーの押下の状態を一時的に解除しています。しかし、コマンドの中にはコマンド内の処理を遅延実行するものがあり、その処理の中でキーの発行をしている場合には、 Shift キーの Up と Down の間をすり抜けて処理が実行されてしまう場合があります(この場合、Shift キーが押された状態で処理が実行されてしまいます)。例としては、マクロの再生コマンドなどがあります。恐らくこれの対策をするのは難しく、これも制約事項として管理したいと思います。

いずれ、 CapsLock キーを Ctrl キーとして使うことは、キーの配置をレジストリで変更できない場合の「次善の策」として考えていただければと思います。ほとんどのキーボードでは、左下に正式な Ctrl キーがあるので回避する方法はあり、問題とはならないと考えています。

smzht commented 1 month ago

master branch に merge しました。

smzht commented 1 month ago

マウスと連携できない以外に、もう一つ利用上の制限事項を見つけました。

OS 設定を日本語キーボードにして使う場合、CapsLock キーを押している間は Shift キーを Down している状態を作っています。これは CapsLock キーを離した際に Up イベントを発生させるためなのですが、この対応をしているため、CapsLock キーを使ったキーからコマンドを実行する際には、コマンドの前後に Shift キーの Up と Down を行う処理を入れ、Shift キーの押下の状態を一時的に解除しています。しかし、コマンドの中にはコマンド内の処理を遅延実行するものがあり、その処理の中でキーの発行をしている場合には、 Shift キーの Up と Down の間をすり抜けて処理が実行されてしまう場合があります(この場合、Shift キーが押された状態で処理が実行されてしまいます)。例としては、マクロの再生コマンドなどがあります。恐らくこれの対策をするのは難しく、これも制約事項として管理したいと思います。

この問題を解決できたかもしれません。develop branch側で継続開発中です。一日テストして問題なければ、master branchにmergeします。

smzht commented 1 month ago

master branch に merge しました。

README の説明文も更新しています。

smzht commented 1 month ago

fc.side_of_ctrl_keyを"R"にした場合、正常に動作していませんでした。対策中です。

smzht commented 1 month ago

fc.side_of_ctrl_keyを"R"にした場合、正常に動作していませんでした。対策中です。

対策しました。バグでした。

smzht commented 1 month ago

まだ操作は特定できていませんが、何かしらの操作をしたときに CapsLock が ON になる場合があります。この状態を元に戻せるように CapsLock の切り替えを行うキーバインド C-CapsLock をサポートしました。これで、CapsLock を切り替えるためにKeyhacのフックをOFFにする必要がなくなりました。

smzht commented 1 month ago

Ctl-x C-c のようなキーバインドで、後半の Ctrl キーが CapsLock キーで利用できな不具合がありました。次のコミットで対応しています。

smzht commented 1 month ago

マルチストロークキーの対策を行いました。

smzht commented 1 month ago

C-u などで数引数を指定したときの不具合の対策を行いました。この対策で、リピート回数の最大値が 1024 から 128 に変更となっています。

smzht commented 1 month ago

fc.emacs_exclusion_key に指定したキーを CapsLock キーとしても認識するように対策しました。

smzht commented 1 month ago

リモートデスクトップを利用した際に正常に動作しません。ウィンドウを最大化しない場合に正常に動作する方法は見つけましたが、ウィンドウを最大化した場合には接続元のキーの処理の方法が変わるため、正常に動作しなくなります。検討は継続しますが、なかなか難しそうです。 あと、キーボードマクロが正常に動作しないことも確認しました。こちらは制約事項になるかなと思っています。

smzht commented 1 month ago

リモートデスクトップを利用した際に正常に動作しません。ウィンドウを最大化しない場合に正常に動作する方法は見つけましたが、ウィンドウを最大化した場合には接続元のキーの処理の方法が変わるため、正常に動作しなくなります。検討は継続しますが、なかなか難しそうです。

ウィンドウを最大化した場合でも、接続元でキーの処理をする方法があることが分かりました。リモートデスクトップ接続のオプションのローカルリソース->キーボードで「このコンピューター」を選択する方法です。

この選択をする場合、接続先での一部のキーバインドが変更となります。

まだテスト中ですが、次のコミットで対策してみました。

smzht commented 1 month ago

リモートデスクトップ接続先でもかなりまともに動作するようになりました。

接続元、接続先に同じバージョンの Fakeymacs をインストールし、上記に記載しているローカルリソースの設定を行って、接続してください。

smzht commented 1 month ago

ほぼ満足する動作がするようになったので、本 issue は close とします。