現在の仮想デスクトップにFinderの新規ウィンドウをワンクリックで開けるようにしてみた

# TL;DR
現在のデスクトップにFinderのウィンドウが開いていればそのウィンドウを最前面にする、開いていなければFinderの新規ウィンドウを作成するAppleScriptを作成した。

# Motivation
OS X(macOS)の仕様で私が一番改善してほしいと思っていることの一つに、「複数の仮想デスクトップ（これは正確にはWindowsでの呼び方？で、OS Xでは[Spaces](https://support.apple.com/ja-jp/guide/mac-help/mh14112/mac) という）を利用しているときに、現在のデスクトップ（Spaceとも言うが、以下これはデスクトップで統一する）で“新規ウィンドウで開く"ための機能がないこと」が挙げられる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/78923835-aab3-e095-5af1-890819f26585.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/fda9d8f1-b466-5d64-7ac4-050b383c3af9.png)


### 現状
アプリのウィンドウがすでに他のデスクトップで開いてある場合（あるいはアプリの開くデスクトップの割り当てが設定されている場合）は、Dockのアプリアイコンをクリックしたら、現在のデスクトップからアプリのウィンドウが開いてある（または設定されている）デスクトップに移動させられるか、開いてあるアプリのウィンドウが元のデスクトップから消えて現在のデスクトップに移動する。`現在使っているデスクトップで新規ウィンドウを開くには、Dockのアプリアイコンを右クリックして“新規ウィンドウで開く"に相当する項目をクリックする必要がある。`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/b4bc7c84-7e8e-31c7-9359-087dca889b09.png)


### やったこと
ブラウザだったら何個もウィンドウを開いても問題ないが、FinderとかTerminalだと、何個も開いていたら煩わしいので、毎回新規ウィンドウを開くのはやめたい。
そこで、Finderにおいて、`現在のデスクトップに所望のアプリのウィンドウが開いていればそのウィンドウを最前面にする、開いていなければ新規ウィンドウを作成する`AppleScriptを作成した。Automatorでアプリケーションにし、ショートカットキーを割り当てれば、ワンクリックで、「現在のデスクトップにFinderのウィンドウが開いていればそのウィンドウを最前面にし、開いていなければFinderの新規ウィンドウを作成する」ことができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/2dd2f748-9312-6b17-bcda-b5996cbae0ed.png)



# Source

大まかな流れは、
(i) Finderが起動していない場合
&nbsp;&nbsp;起動して現在のデスクトップに新しいウィンドウを作る
(ii) Finderが起動している場合  
&nbsp;&nbsp;(a) Finderのウィンドウが現在のデスクトップで開かれている場合
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;activateにして最前面に持ってくる
&nbsp;&nbsp;(b) Finderのウィンドウが現在のデスクトップで開かれていない場合
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;現在のデスクトップに新しいウィンドウを作る

Finderが起動していない場合、起動して現在のデスクトップに新しいウィンドウを作るコードは以下
```
if application "Finder" is not running then
	tell application "Finder"
		launch
		make new Finder window to "Macintosh HD:Users:kt:Downloads"
		set bounds of window 1 to {670, 300, 1500, 810} 
		set frontmost to true
	end tell
```
`activate`で起動させる。
`make new Finder window to "Macintosh HD:Users:kt:Downloads"` これはFinderのダウンロード（Users/kt/Downloads）を開く。
`set bounds of window 1 to {670, 300, 1500, 810} ` {左上X座標,左上Y座標,右下X座標,右下Y座標}にウィンドウをつくる。
`set frontmost to true` で最前面に持ってくる。

現在の仮想デスクトップにFinderのウィンドウが開かれている場合のコードが以下。
```
tell application "System Events"
	get (the name of every application process whose class of windows contains window)
	repeat with process_name in the result
		if ((process_name) as string is equal to "Finder") then
			tell application "Finder"
				activate 
			end tell
		end if
	end repeat
    略
end tell
```
`get (the name of every application process whose class of windows contains window)` これで、現在のデスクトップで開かれているウィンドウのアプリ一覧を取得する。
`if ((process_name) as string is equal to "Finder") then` その中にFinderがあれば
`tell application "Finder" activate end tell` activateにする。

現在の仮想デスクトップにFinderのウィンドウが開かれていないがアプリ自体は起動している場合は以下
```
get (the name of every application process whose background only is false and class of windows does not contain window)
repeat with process_name in the result
    if ((process_name) as string is equal to "Finder") then 
        tell application "Finder"
            make new Finder window to "Macintosh HD:Users:kt:Downloads"
            set bounds of window 1 to {670, 300, 1500, 810} 
            activate
        end tell
    end if
end repeat
```
`get (the name of every application process whose background only is false and class of windows does not contain window)` で、現在のデスクトップにはウィンドウがないが、起動はしている状態のアプリ一覧を取得している。


Full Sourceは以下。
```
--もしFinderが起動していない場合、起動して現在の仮想デスクトップに新しいウィンドウを作る
--もし現在の仮想デスクトップにFinderのウィンドウが開かれている場合、activateにして最前面に持ってくる
--もし現在の仮想デスクトップにFinderのウィンドウが開かれていないがアプリ自体は起動している場合、現在の仮想デスクトップに新しいウィンドウを作る
--もし非表示の場合、現在の仮想デスクトップに新しいウィンドウを作る
if application "Finder" is not running then --もしFinderが起動していない場合、起動して現在の仮想デスクトップに新しいウィンドウを作る
	tell application "Finder"
		launch --ここactivateにしたら、以前開いていたデスクトップにかってに移動してしまう。
		make new Finder window to "Macintosh HD:Users:kt:Downloads"
		set bounds of window 1 to {670, 300, 1500, 810} --set bounds of window 1 of application "'アプリケーション名'" to {左上X座標,左上Y座標,右下X座標,右下Y座標}
		set frontmost to true --activateしているのになぜか最前面に来ないのでこの行を追加している。activeでも良いはず
	end tell
else
	tell application "System Events"
		get (the name of every application process whose class of windows contains window)
		repeat with process_name in the result
			if ((process_name) as string is equal to "Finder") then --もし現在の仮想デスクトップにFinderのウィンドウが開かれている場合、activateにして最前面に持ってくる
				tell application "Finder"
					activate --activateコマンドはアプリが起動していなければ起動し（ただしそのままだと最前面には表示せずにbackground状態、隠した状態になる）、起動していればアプリのウィンドウを最前面に表示する。「アプリケーションが起動しており、なおかつ、ウインドウが背面に表示されている状態」だと上手く前面に表示されるが、「アプリケーションは起動していてもウインドウが閉じられている状態」だとメニューバーはactiveになるがウインドウが表示されない。）
				end tell
			end if
		end repeat
		get (the name of every application process whose background only is false and class of windows does not contain window)
		repeat with process_name in the result
			if ((process_name) as string is equal to "Finder") then --もし現在の仮想デスクトップにFinderのウィンドウが開かれていないがアプリ自体は起動している場合、現在の仮想デスクトップに新しいウィンドウを作る
				tell application "Finder"
					make new Finder window to "Macintosh HD:Users:kt:Downloads"
					set bounds of window 1 to {670, 300, 1500, 810} --set bounds of window 1 of application "'アプリケーション名'" to {左上X座標,左上Y座標,右下X座標,右下Y座標}
					activate
				end tell
			end if
		end repeat
		get (the name of every application process whose background only is false and visible is false)
		repeat with process_name in the result
			if ((process_name) as string is equal to "Finder") then --もし非表示の場合、現在の仮想デスクトップに新しいウィンドウを作る		
				tell application "Finder"
					activate
					make new Finder window to "Macintosh HD:Users:kt:Downloads"
					set bounds of window 1 to {670, 300, 1500, 810} --set bounds of window 1 of application "'アプリケーション名'" to {左上X座標,左上Y座標,右下X座標,右下Y座標}
					activate
				end tell
			end if
		end repeat
	end tell
end if
```

# 導入
Automator>新規>アプリケーション>AppleScriptを実行>ソースをコピペ>保存

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/e6a1d6db-6991-035b-d298-d60753e632eb.png)


# 最後に
当初は、Terminalでやろうと思っていた。
```
defaults read com.apple.spaces | plutil -convert json - -o - | jq '.SpacesDisplayConfiguration'
```
これで仮想デスクトップの情報を取得でき、仮想デスクトップの数などの情報は正しそうだった。しかし`Current Space`がなぜかどこのSpaceでこのコマンドを実行しても変わらず、よくわからなかった。[同じ状況の人がいた。](https://ianyh.com/blog/identifying-spaces-in-mac-os-x/)

現在のデスクトップで開いているウィンドウを取得するのが大変だったが、AppleScriptでなんとかできた。これがあれば、私が最も改善してほしい[「再起動したら一つのデスクトップにウィンドウが集中してしまう」問題](https://discussionsjapan.apple.com/thread/251071989)を回避できるかもしれない。これは（勝手に）全人類の悩みだと思っているのでなんとか解決方法を考えたい。


Terminal

```
if application "Terminal" is not running then
	tell application "Terminal"
		launch --ここactivateにしたら、以前開いていたデスクトップにかってに移動してしまう。
		do script ""
		set bounds of window 1 to {250, 550, 840, 940}
		activate
	end tell
else
	tell application "System Events"
		tell application "Terminal"
			do script ""
			set bounds of window 1 to {250, 550, 840, 940}
			activate
		end tell
	end tell
end if
```

iTerm 

```

if application "iTerm" is not running then
	tell application "iTerm"
		activate application "iTerm"
		delay 1
		set bounds of window 1 to {250, 550, 840, 940}
	end tell
else
	tell application "System Events"
		tell application "iTerm"
			create window with default profile
			set bounds of window 1 to {250, 550, 840, 940}
			activate
		end tell
	end tell
end if

```