A personal journal about bits & pieces of technology.

Location-aware Functional Keys

The problem

The problem with the Apple Media Keys is that they hide the standard function keys. This is great for media consumption, as I can adjust the display brightness or sound volume with just one hand.
However in Eclipse, the current IDE I spend most of my working hours in, the F-keys are mapped to often used actions, such as debug stepping and running code. This is great, as I can debug my code step by step with just a few keys with my eyes staying on the display.

The solution

OS X provides a setting for either one of the two modes directly accessible without touching the Fn key, but this is tedious doing it everytime I switch from home to work or vice versa.

Enter ControlPlane. This app lets you do Actions based on your Context. For instance, most of my Contexts are activated, when my MacBook is connected to a certain monitor or sees a certain WiFi network, but other Evidence Sources are also possible.

The missing link between the automatically detected environment (work or home) and the correct setting (media keys or function keys) is the often neglected, because miserably documented, AppleScript.

I found a script for toggling the setting in a forum post. I took it and created two separate scripts, one for activating the setting (at work) and one for deactivating (at home).

Next I created a Shell Execution Action for each of the scripts (osascript path/to/script), one when entering the work Context, and one when leaving.

But wait! We are not done yet.

Mavericks introduced fine-granular settings for Accessibility. Each Accessibility feature has to be enabled for specific apps, when Apps request those features. But ControlPlane does not request the feature to script UI elements, so it does not get added to the list, thus our AppleScript execution fails. Giving the AppleScript Editor the rights is not enough, because when ControlPlane is executing the script the AppleScript Editor is no longer the executing app.

So, how to get the some executing app listed there?

The trick is to wrap both scripts in an Automator app; and so I wrapped both scripts and told ControlPlane to execute both apps and hide them (just to be sure I do not see them executing).

I put the code and the basic instructions into a gist: