rcmdnk's blog

20250105_toggleapp_200_200

やりたいことは特定のアプリをどこからでもショートカットキーで呼び出せるようにし、 かつ、同じボタンでそのアプリを隠すことが出来るようにすることです。

Windows + AutoHotkey

Windowsでは AutoHotkey を使います。

基本的には [AutoHotkey v2]https://ahkscript.github.io/ja/docs/v2/)( であることを前提に書いています。

ChromeをToggleするHotkey設定としてはこんな感じ。

toggle.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#HotIf WinActive("ahk_exe chrome.exe")
^!c::
{
    Send("!{Tab}")
    Send("{Alt Up}")
}

#HotIf WinExist("ahk_exe chrome.exe")
^!c::
{
    WinActivate("ahk_exe chrome.exe")
}

#HotIf
^!c::
{
    Run(A_ProgramFiles "\Google\Chrome\Application\chrome.exe")
    WinWait("ahk_exe chrome.exe")
    WinActivate("ahk_exe chrome.exe")
}

Ctrl-Alt-CでChromeをトグル表示するHotkeyを書いています。

現状アクティブになっている場合にはAlt-Tabで1つ前のアプリに戻るようにしています。 これ何度も連続で使うとちょっと不安定にAlt-Tabの表示が残ってしまうこともありますが、 一回であればスムーズに動作してくれるので取り敢えずこれで。

WinMinimizeという最小化する関数もあるのでもし最小化のほうが良ければそれで。 WinCloseで閉じてしまう事もできますがWindowsだと最後のWindowの場合アプリ自体が終了してしまって次の起動が遅くなるので注意。

アクティブでない場合でウィンドウがあればWinActivateで前面に出すようにしています。 これだと複数同じアプリのウィンドウがある場合は最後にアクティブだったものが前面に出ますが、 もし必要であればahk_exe chrome.exeを全体的にタイトル名に変えるなどで特定のウィンドウを指定することもできます。

アクティブでもなくてウィンドウもない場合にはRunでアプリを立ち上げます。 立ち上げるだけだとアクティブにならないのでWinActivateしてやる必要がありますが、 即行うとアプリが立ち上がる前で認識できないのでWinWaitで待ってからWinActivateしています。

この例ではChromeで、立ち上げるアプリがA_ProgramFiles (\C:\Program Files (x86) or \C:\Program Files)の下にありますが、 Obsidianなどは通常ユーザーディレクトリの中のAppData\Localの中にあります。

AutoHotkeyにはA_AppDataという変数が定義されていますが、これは AppData\Roamingのパスを返すのでLocalを見たいときには上のようにA_UserNameを使って書くしかありません。(多分)

Chromeなどは\C:\Program Files (x86)の下にありますが、 Obsidianなどはユーザーディレクトリの中のAppData\Localの中にあるのでそれぞれ場所を指定しています。

"C:\Users\" A_UserName "\AppData\Local\obsidian\Obsidian.exe"

こんな感じのPathになります。AutohHotkeyにはA_AppDataという変数が定義されていますが、これは AppData\Roamingのパスを返すのでLocalを見たいときには上のようにA_UserNameを使って書くしかありません。(多分)

このようにしてトグル表示を実現できますが、 複数のアプリでも同じ様なことをする場合には関数化しておくと便利です。

以下のようにしてAuto execute sectionでまとめて書くことが出来ます。

toggle.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
LaunchApp(winName, appPath) {
    Run(appPath)
    WinWait(winName)
    WinActivate(winName)
}

prevApp() {
    Send("!{Tab}")
    Send("{Alt Up}")
}

ToggleApp(key, winName, appPath) {
    HotIfWinActive(winName)
    Hotkey(key, (*) => prevApp())
    HotIfWinExist(winName)
    Hotkey(key, (*) => WinActivate(winName))
    HotIf
    Hotkey(key, (*) => LaunchApp(winName, appPath))
    HotIf
}

ToggleApp("^!c", "ahk_exe chrome.exe", A_ProgramFiles "\Google\Chrome\Application\chrome.exe")
ToggleApp("^!s", "ahk_exe slack.exe", A_ProgramFiles "\Slack\Slack.exe")
ToggleApp("^!t", "ahk_exe Hyper.exe", "C:\Users\" A_UserName "\AppData\Local\Programs\Hyper.exe")
ToggleApp("^!q", "ahk_exe Obsidian.exe", "C:\Users\" A_UserName "\AppData\Local\obsidian\Obsidian.exe")

Return

; Other hotkeys

...

こんな感じで、ToggleAppという関数を使ってアプリをトグル表示するHotkeyをAuto execute sectionの中で書いています。

keyにはHotkeyのキーを指定します。 winNameはWindow Spyで見つけらるclassやexe, titleなどを指定しますが、基本的にはahk_exeを指定しておくのが無難です。 appPathはアプリのパスを指定します。わからない場合はスタートメニューから該当のアプリの右クリックでファイルの場所を開くを開いて探して見てください。通常はそのファイルがさらにショートカットになっていることが多いので、それをまた右クリックしてファイルの場所を開くを開くと大元の位置が分かることが多いです。

Mac + Karabiner-Elements

macOSでは Karabiner-Elements を使います。

以下で使うfrontmost_application_history_indexがv15.3.6から導入されたもので、 これは現状ベータ版のみになっているので使う場合はベータ版にアップグレードする必要があります。 (現行のstableバージョンは15.3.0。)

ChromeをToggleするHotkey設定としてはこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    {
      "description": "Toggle Chrome",
      "extra_descriptions": [
        "Cmd-Ctrl-c to toggle Chrome."
      ],
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "c",
            "modifiers": {
              "mandatory": [
                "control",
                "command"
              ]
            }
          },
          "to": [
            {
              "software_function": {
                "open_application": {
                  "bundle_identifier": "com.google.Chrome"
                }
              }
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "^com\\.google\\.Chrome$"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "c",
            "modifiers": {
              "mandatory": [
                "control",
                "command"
              ]
            }
          },
          "to": [
            {
              "software_function": {
                "open_application": {
                  "frontmost_application_history_index": 1
                }
              }
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_if",
              "bundle_identifiers": [
                "^com\\.google\\.Chrome$"
              ]
            }
          ]
        }
      ]
    }

Windows同様に Ctrl-Alt-CでChromeをトグル表示するHotkeyを書いています。

アプリに対応するbundle_identifieropen_application のヘルプの Investigate the bundle identifier and file pathを参考にKarabiner-EventViewerを使って調べられます。

conditionsの方で使うbundle_identifiersには正規表現で指定する必要があるので 1 ^com\\.google\\.Chrome$のように正規表現で指定します。

software_function.open_applicationを使ってアプリを開くことができます。 すでにアプリが開いていればそれを前面に出すだけになるのでアプリが開いているかどうかを確認せずに 最前面がそのアプリでなければopen_applicationでアプリを開くようにしています2

アプリが前面にある際には”fromtmost_application_history_index": 1で1つ前に最前面にあったアプリを前面に出すようにしています。

Windows版と違って直接直前のアプリを持ってこれるのでかなりスムーズな感じでToggle表示ができます。

同様に別のアプリも作っていくことが出来ます。

自分の設定は pqrs-org/KE-complex_modifications をforkした rcmdnk/KE-complex_modifications で作っていますが、 scripts/erb2json.rb の中に toggle_app という関数を作って、 src/json/personal_rcmdnk.json.erb の中に

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    {
      "description": "Toggle Chrome",
      "extra_descriptions": [
        "Cmd-Ctrl-c to toggle Chrome."
      ],
      "manipulators": <%= toggle_app("com.google.Chrome", "c", ["control", "command"]) %>
    },
    {
      "description": "Toggle Slack",
      "extra_descriptions": [
        "Cmd-Ctrl-s to toggle Slack."
      ],
      "manipulators": <%= toggle_app("com.tinyspeck.slackmacgap", "s", ["control", "command"]) %>
    },
    {
      "description": "Toggle iTerm2",
      "extra_descriptions": [
        "Cmd-Ctrl-t to toggle iTerm2."
      ],
      "manipulators": <%= toggle_app("com.googlecode.iterm2", "t", ["control", "command"]) %>
    },
    {
      "description": "Toggle Obsidian",
      "extra_descriptions": [
        "Cmd-Ctrl-q to toggle Obsidian."
      ],
      "manipulators": <%= toggle_app("md.obsidian", "q", ["control", "command"]) %>
    },

こんな感じで書いてあります。

かなり前にForkしたままあとは自分で変更しただけで本家を追ってないので 現状の本家とはスクリプト等も結構違うかもしれませんが参考までに。

Sponsored Links
  1. frontmost_application_if, frontmost_application_unless Karabiner-Elements

  2. アプリが開いているかどうか、を確認する方法は今のところない? 自動スプリクト的なものでvariableにいれるとかで無理やり出来るかも?

Sponsored Links

« miseを使って仮想環境自動認識(主にPython, uv, プロンプト表示についても) WindowsでのCtrl-Alt-Shift-WinなるショートカットキーとAutoHotkeyでの対処 »

}