I decided to speed up a repetitive task I have been doing
lately…. Moving windows around and repositioning them.
In my current job I have a nice adequate apple
macbook pro attacked to a 27" thunderbolt screen. I appreciate the extra space but it comes at
a cost, whenever I run to a meeting with my laptop or take my laptop home all
my application windows get repositioned.
Then when I plug back into the big monitor or reboot my machine I have
to move all my windows to the positions I prefer.
Well this particular problem can be fixed with a few Applescript
scripts. And to make it even awesomer you
can add ControlPlane http://www.controlplaneapp.com/
[1] to the equation
Here is what I did to save my sanity. It’s a long read but worth it…
First things first
The first thing you need to do is give the terminal some
special permissions (to allow it to manipulate windows via a script… there is
some security risk in this if someone is able to get into your command line…
but really if someone is in your command line they can do a lot of damage anyway)
I found the following information at http://stackoverflow.com/questions/10140334/applescript-system-events-error-access-for-assistive-devices-is-disabled [2] From NSAddict
Click on the apple icon in the upper right and select
"System Preferences"
Open "Security & Privacy"
Click on Accessibility, unlock it by clicking the lock and entering your password. Then checkbox "Terminal"
Now Terminal has more permissions to have its scripts
effect other programs.
Close the window.
Terminal
First I am going to tackle moving and resizing the
terminal.
From the command line create
and edit moveWindowTerminal.scpt
> vi moveWindowTerminal.scpt
|
tell
application "Terminal"
tell window 1
set position to {3390, -2000}
set size to {850, 1414}
end tell
end
tell
|
This will set the width of my first Terminal Window to
"850" and its Height to "1414" which is the max height it can be on a
27" monitor that has a resolution of 2560x1440 (you need to account for the top bar)
My laptop sits to the left of my monitor so to get it all
the way over to the right side of the 27" I have to use 3390 pixels. Also it may seem funny that the other number
is -2000…. Well I found out that since I do line up my screens so that
technically my laptop is lower than my monitor (see image)
The position can get a little confused as it crossed the
screen boundaries. One way I solved this
was to just use a large negative number which forces it up against the bottom
of the menu bar.
Ok now to run this code from the command line.
> osascript moveWindowTerminal.scpt
|
That worked!
The terminal ends up roughly here on the 27" screen.
Moving Intellij
Moving my Intellij Windows was a little more of a chore,
but I did get it working.
From the command line create
and edit moveWindowIntellij.scpt
> vi moveWindowIntellij.scpt
|
tell
application "System Events"
tell process "idea"
repeat with x from 1 to (count windows)
set position of window x to {1680, -2000}
set size of window x to {1710, 1414}
end repeat
end tell
try
set ideaPIDs to every process whose name contains "idea"
set ideaPID to item 1 of ideaPIDs
set frontmost of ideaPID to true
end try
end
tell
|
This will move every Intellij Window and resize it. After it resizes them all it will bring the
application to the front.
Now to run this code from the command line.
> osascript moveWindowIntellij.scpt
|
If you look at the code you will see that you can't talk
directly to Intellij. It is not
applescript aware. But we can tweak a
few things, like the windows, by using the "System Events"
application.
Intellij now takes up this portion of my 27" monitor.
Skype
I am running Skype in fullscreen mode because I can take
advantage of spaces… I really do like spaces. They really help my
workflow. Unfortunately I have spent the
last several years developing on a windows machine and I missed a lot of the UI
goodness of OS X. But now I am
developing again on a Mac, so I get my spaces back… enough of the nostalgia.
At any rate I want to make my Skype full screen via a
script.
From the command line create
and edit moveWindowSkype.scpt
> vi moveWindowSkype.scpt
|
tell
application "Skype"
set isfullscreen to false
tell application "System Events" to tell process
"Skype"
set isfullscreen to value of attribute
"AXFullScreen" of window 1
end tell
if not isfullscreen then
activate
tell
application "System Events" to keystroke "f" using {
command down, control down }
end if
end
tell
|
Ok now to run this code from the command line.
> osascript moveWindowSkype.scpt
|
It goes fullscreen just fine, and it occupies its own
"Space" .
I would also like it to move itself to the first space,
but I have not figured out how to do that yet.
If you have a solution please send it my way!
… looking at this code I need to fix something. This will go full screen on the screen skype
currently is. I want to move it to my
laptop monitor first then resize it.
The following code seemed to
fixed that.
tell application
"Skype"
set isfullscreen to false
tell application "System Events"
to tell process "Skype"
set isfullscreen to value of attribute
"AXFullScreen" of window 1
end tell
tell application "System Events"
tell process "Skype"
repeat with x from 1 to (count windows)
set position of window x to {0, 0}
end repeat
end tell
end tell
if not isfullscreen then
activate
tell application "System
Events" to keystroke "f" using { command down, control down }
end if
end tell
|
Wrap it all in a simple bash script
I don't know about you but I just like s simple bash
script to run all three at once. Here is
my simple bash script.
> vi moveAllWindows.sh
|
Here is the code
#!/bin/bash
echo
'Moving all Windows to make use of the big 27" screen!'
osascript
moveWindowSkype.scpt
osascript
moveWindowTerminal.scpt
osascript
moveWindowIntellij.scpt
|
Then remember to make it executable, then run it.
> chmod u+x moveAllWindows.sh
> ./moveAllWindows.sh
|
And voila all my windows are moved into the correct position.
Extra Goodness
I used a script from this forum http://forums.macrumors.com/showthread.php?t=711954 [3] See Kainjow.
That will list all processes running on your system (their
names you must use in your applescript)
Here is the code that was posted
tell application "System Events"
repeat with p in
every process
if
background only of p is false then
display
dialog name of p as string
end if
end repeat
end tell
|
What about automating it?
Wouldn't it be nice to have this script run when I plug
the monitor in?
Looking around a little I found an open source program
called ControlPlane http://www.controlplaneapp.com/ [1]
After downloading and starting this program click on the
plane icon in the menu bar.
First things first,
Checkbox the "Start ControlPlane at login.
I found this great site that will walk you through how to
use ControlPlane.
http://mac.appstorm.net/reviews/productivity-review/controlplane-automation-cockpit-for-your-mac-2/ [5]
Here is how I set mine up to change when the monitor was
plugged in.
Click on the Contexts menu then click the + button
Give the Context a name and click OK.
Click on the Evidence Sources tab and make sure
"Attached Monitor" is check boxed
Click on Rules tab and click the + Button
Click "Add Attached Monitor Rule"
Cool, it sees my cinema display and fills out all the data
just fine!
Oh and it chose the context I created earlier …. Cool!
Click OK
Select Actions tab and press +
Select System Actions and then "Run Shell
Script"
Find your script and click Open
Select the context, on arrival and give it a delay of 2
seconds. (not sure if I need to but its
probably a good idea)
Unplugging the monitor and plugging it in again did
nothing… sigh… OK what is the problem?
Looking at the menu it looks like I can force the script
to run by forcing the context.
That gave me this error.
Doing a quick no brainer test of the script ran just fine
> ./moveAllWindows.sh
|
I found the log its under the Advanced tab, scroll down
and you can see I got a non-zero status error.
I figured it out I need to put in absolute paths in my
script.
#!/bin/bash
echo
'Moving all Windows to make use of the big 27" screen!'
osascript
/Users/patman/moveWindowSkype.scpt
osascript
/Users/patman/moveWindowTerminal.scpt
osascript
/Users/patman/moveWindowIntellij.scpt
|
This almost worked
This dialog popped up.
I need to Open my system Preferences and give Control Plane
some additional permission.
From Security & Privacy select Accessibility and
checkbox "Control Plane" To give it permission to move windows
around.
Now forcing the script works, but plugging the monitor in
and out does not.
Turns out the confidence switch was too high. It was at 75% I had to lower it to 70% to
match the Rule level
Finally its working like I want.
This is a pretty cool tool I can imagine a few more fun
things to do with this tool!
I removed the 2 second delay and it still works just
fine. It does take 2-4 seconds after
the screen is attached and working to recognize it and run the script, but that
is acceptable for my needs.
References
Visited 7/2014
[2] AppleScript - System Events
Error : Access for assistive devices is disabled (NSAddict)
Visited 7/2014
[3] Applescript -
list of running apps?
Visited 7/2014
Visited 7/2014
[5] ControlPlane:
Automation Cockpit For Your Mac
Visited 7/2014