smzht / fakeymacs

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

not_emacs_target アプリのメニューやダイアログでの有効化方法について #26

Closed k9i closed 1 year ago

k9i commented 1 year ago

not_emacs_target 指定をするとそのアプリ全体が無効になり、(Windows標準の?)プルダウンメニューやダイアログボックスの中も emacs キーバインドが使えなくなってしまうようです。 アプリ本体(?)では emacs キーを無効にしつつ、Windows 標準UI部品のようなものでは emacs キーを有効にする方法はありますでしょうか?

fakeymacs の version は下記になります。 fakeymacs_version = "20230606_01"

smzht commented 1 year ago

プルダウンメニューやダイアログボックスのクラスが emacs キーバインドを無効にしたい箇所と異なるウィンドウのクラスをもっているのであれば、fc.emacs_target_class 変数を指定することで、fc.not_emacs_target 変数の設定より優先させることができます。デフォルトでは Edit クラスが指定されています。クラスは、Keyhac のメニューから「内部ログをON」を指定すると、Keyhac コンソールで確認できます。

k9i commented 1 year ago

ご回答ありがとうございます。 Keyhac コンソールで調べてみたところ、プルダウンメニューとアプリ本体(emacs キーバインドを無効にしたい箇所)は同じクラスでした。 (例えば、TeraTerm4 のプルダウンメニューと本体コンソール部分のクラス名は同じ「VTWin32」)

何か違いはないか ahk で調べてみたところ、ahk の場合、下記でプルダウンメニューと本体を区別できることが分かりました。

; ahk でのプルダウンメニューの識別
  try { ; WinGetClass がエラーとなる場合があるため try で囲む
    If (WinGetClass("ahk_class #32768") == "#32768") {  ; メニューの場合
      Return True  ; emacs キーバインド対象(True)
    }
  }

fc.emacs_target_class = ["Edit", "#32768" ] と設定してみたのですが、プルダウンメニューで emacs は有効になりませんでした(TeraTerm4)

ググったところ、#32768 は「メニューのクラス」のようでした。 https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-window-classes

Keyhac で #32768 を区別する方法が分からず試せずにいます。。

smzht commented 1 year ago

次で判定することができるようです。

Window.find("#32768", None)

ただし、キーの入力毎に判定する必要があるので、処理の作り込みは少し面倒になると思います。

smzht commented 1 year ago

拡張機能を一つ作成し、対応しました。config_personal.py の最後の部分に拡張機能を有効にする if 文がありますので、if 1: にしてご利用ください。

k9i commented 1 year ago

ありがとうございます! TeraTerm のメニューが emacs キーバインドになっていました。素晴らしいです。 問題ないようですのでクローズさせていただきます。ありがとうございました。

smzht commented 1 year ago

一点コメントとして、記録に残しておきます。

今回作成したコードでは、メニューが表示されているかの判定を Window.find という関数を使って行っています。ただし、この関数はフォーカスがあるウィンドウ以外も含め、ウィンドウ全体の検索を行うもののようです。

メニューがフォーカスのあるウィンドウ以外で開いている状態は無いと想定し、今回のコードとしているのですが、もしその状態があるのであれば、is_menu 関数を以下のようにした方が良いかもしれません。(一応、これでも動くことは確認しています。)

def is_menu():
    window =  Window.find("#32768", None)
    if window and window.getOwner() == keymap.getWindow():
        return True
    else:
        return False

今回は性能を優先し、Window.find 関数の結果のみによる簡易な判定としていますが、もし不都合が発生する場合があれば、このコメントを思い出していただければと思います。

以上、よろしくお願いします。

k9i commented 1 year ago

ご丁寧にありがとうございます。留意しておきます。