Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

OSX productivity tips: advanced shortcuts and windows manager

I’ve been a long time OSX user. The saying goes: “Once you go Mac, you never go back!” And while I absolutely love what Apple has done with the operating system, there are always some customization and productivity tricks that can make the entire experience even more awesome.

Today I would like to share a couple of customizations with you. I use these whenever I get my hands on a new Mac. I am somewhat of a shortcut junkie and I try to avoid using the mouse as much as possible. This blog post is heavily centered around that and adding new global keyboard shortcuts to OSX.

Remapping keys

If I could name one single thing that bothers me the most about modern keyboards, it has to be the ⇪ (Caps Lock) key. Honestly, when was the last time you actually used it? For a key which is so conveniently located right next to letter “a” on the home row, it gets depressingly little use. While some people, especially vim users, like to map it to the “Escape” key, I personally feel that this a waste. Instead, I map it to the combination of pressing all four modifiers on the Mac keyboard – ⌘ (Command) + ⌥ (Option) + ⌃ (Ctrl) + ⇧ (Shift).

This opens up the possibility to use ⇪, Caps Lock, as a hyper modifier key — so you could use shortcuts with ⇪ and other key combinations. The original inspiration for this hyper key came from this relatively old blog post.

In order to remap Caps Lock, you first need to download Seil. Seil is a small application that allows you to map the Caps Lock key to some other key code. However, it only allows you to map it to a single key code (not a combination of them as we would like). What we will do is map the Caps Lock in Seil to a key code which does not exist on the physical keyboard. I usually use F19 with the keycode 80.

seil-preferences

Note that Seil also asks you to disable the default Caps Lock behavior in System Preferences. Let’s go ahead and do that now.

To achieve the functionality that we want, we need to use a second application named Karabiner. Karabiner is a powerful keyboard customizer, which we will use to map our hyper Caps Lock, now producing keycode 80 on a click, to a combination of all four modifiers: ⌘ + ⌥ + ⌃ + ⇧.

This can be done by opening Karabiner > Misc & Uninstall and “Open private.xml”.

karabiner-misc-window

From here, enter the following XML configuration:

<?xml version="1.0"?>
<root>
	<item>
		<name>F19 to Hyper</name>
		<appendix>(F19 to Hyper (Ctrl+Shift+Cmd+Option))</appendix>
		<identifier>private.f19</identifier>
		<autogen>
			--KeyOverlaidModifier--
			KeyCode::F19,
			KeyCode::COMMAND_L,
			ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L
		</autogen>
	</item>
</root>

After doing this, make sure that you see “F19 to Hyper” in the “Change Key” tab in Karabiner and that it is enabled. You may need to click the Reload XML button first to see this result.

karabiner-enable-hyper

Congratulations, you have now successfully changed the “Caps Lock” key to the combination of all 4 modifiers ⌘ + ⌥ + ⌃ + ⇧. You can now start using this in your own custom shortcuts.

Try it out now in your favorite application or under System Preferences > Keyboard > Shortcuts.

Now that Caps Lock is mapped to the combination of all OSX modifier keys, what can we do with it? By default, the combination of “all modifier keys”+key is rarely used for global or application-specific shortcuts. It is therefore safe to create new, custom shortcuts with it. And since most applications already have application-specific shortcuts that use one or two modifier keys, I prefer using this new combination of four modifiers and a key for new global shortcuts. This avoids conflicts with any application-specific shortcuts.

Moving and resizing any application window

Spectacle is my favorite application for moving and resizing windows. This comes in handy when you want to lay out application windows on a whim. And as this is something I find myself doing from time to time, I map these operations to the new global “hyper”+left/right/up/down/space shortcuts instead of the default ones, which often conflict with application-specific shortcuts. Hey, IntelliJ IDEA, I am looking at you ;). Here are my shortcuts for Spectacle. Note that I only use Full screen and left/right/top/bottom half — your mileage may vary.

spectacle-shortcuts

Now try arranging the windows you have open. See how natural the remapped Caps Lock works for us here. Now you won’t need to bother with clicking the window control dot buttons ever again.

Quick access shortcuts for applications

As I said initially, I use shortcuts a lot. Naturally, I would like to use those to move between the applications I use most. Instead of alt-tabbing between all of my open applications, I would like to have shortcuts to open specific applications. For example, I use ⇪ + E for Google Chrome, ⇪ + I for IntelliJ IDEA, ⇪ + S for Sublime Text or ⇪ + L for Slack. Unfortunately, OSX does not allow you to map global shortcuts to launching or switching to applications by default so this takes an external app to configure right.

Enter Slate, a powerful window management application which you can customize to do really cool stuff. The original author does not contribute to the project anymore and it is rather unstable with recent OSX versions, but thanks to the open source community, this fork sees more active development and has been much more stable.

One of the best things about Slate is that it has a very powerful JavaScript API. This can be used to do all kinds of stuff, one of which just so happens to be what we want — mapping keyboard shortcuts to specific applications.

To do that, we first need to create the JavaScript configuration file at ~/.slate.js. Then we use the slate.bind function to bind a key combination in the form of key:modifier1,modifier2,…,modifierN to a shell operation to call ‘/usr/bin/open /path/to/application.app’ using slate.shell. This might sound like mumbo-jumbo at first, so here’s an example.

The naive application of the above to open the Sublime editor would be:

slate.bind("s:ctrl,alt,cmd,shift", 
  function() { 
    slate.shell("/usr/bin/open \"/Applications/Sublime Text.app\"");
  }
);

After updating the Slate configuration file, reload the configuration by clicking Relaunch and Load Config in the context menu:

launch-slate-on-login

A more complete example (with my own key bindings, which also supports focusing the previously focused application by clicking the same key combination) can be found in my GitHub repository. Remember, I am not a JavaScript developer. Feel free to make fun of my code, but do send pull requests when you do!

Automatic layout of application windows when the display configuration changes

At work, I use a laptop with 2 external monitors attached. Since it is a laptop, I do actually want to take it home or to a meeting from time to time. Something that has always bothered me is the way OSX handles changes to the display configuration.

Some applications either remain offscreen when I unplug my monitors, or my applications do not get rearranged as they were when I come back and plug them in. Even worse, I re-plug the monitors in the wrong order because both of my HDMI cables are black! Or it gets the window sizes wrong… Or any combination of the above!

Luckily, Slate can once again come to the rescue, as it can also listen to changes in your display configuration.

First of all, you have to order your screens with the following slate.config call:

slate.config("orderScreensLeftToRight", true);

Next, Slate can be made to watch display configurations with the slate.default function. The function takes an array of layout configurations and the name of a slate.layout. In my case, I can have 3 potential configurations — just the 2560x1600px retina display on my laptop or either 1 or 2 of my 1920×1200 external monitors plugged in. My configuration looks like the following (note that the retina display should actually be entered as 1280×800):

slate.def(["1280x800"], "1monitors");
slate.def(["1280x800","1920x1200"], "2monitors");
slate.def(["1280x800","1920x1200","1920x1200"], "3monitors");

Slate will monitor the display configuration and when it sees a change event — and the new configuration matches one of the above — it will update the application layout based on the layout rule specified in the slate.layout with the given name (discussed in a bit).

Before we get into the slate.layout, we have to define the operations that will be done on our applications when the layout changes. The operation is a slate.operation object, which can be rather complex and support different kinds of transitions and actions. In my case, the operation is just a simple “move to the specific screen and maximize”. For example:

var moveToScreen = function (n) {
  return slate.operation("move", {
    "screen": n, //NB! note that this is 0-index based!
    "x": "screenOriginX",
    "y": "screenOriginY",
    "width": "screenSizeX",
    "height": "screenSizeY"
  });
}

The slate.layout then takes a name and the application layout configuration as its arguments and uses the “moveToScreen(n)” operation that we defined above to move applications to specific screens. In my case, the layout for 3 monitors is the following:

slate.layout("3monitors", {
  "Google Chrome": {
    "operations": [moveToScreen(1)],
    "repeat": true
  },
  "Sublime Text": {
    "operations": [moveToScreen(2)],
    "repeat": true
  },
  "IntelliJ IDEA CE": {
    "operations": [moveToScreen(2)],
    "repeat": true
  }
});

In addition to Slate listening to changes in the display configuration and laying out my applications automatically when the configuration changes, I have also specified the keyboard shortcuts to selectively move applications between screens:

slate.bind("1:ctrl,alt,cmd,shift", moveToScreen(0));
slate.bind("2:ctrl,alt,cmd,shift", moveToScreen(1));
slate.bind("3:ctrl,alt,cmd,shift", moveToScreen(2)); 

Again, my display configuration can be used as a starting point for yours. The full .slate.js configuration with the displays and bindings is also available.

Fade out applications that do not have focus

The final application that I would like to introduce is HazeOver. Differently from the utilities described above, this is a paid app. For me at the moment of writing this, costs 3.99 EUR in the AppStore. And it solves a real problem for me.

With my three displays and all the nifty application shortcuts set up, I found that I was constantly unaware of which application actually had focus. I would look at an application on any of my screens, assume it had focus and start typing — only to find out that nothing happened, as the text input went to some other application. It was even messier when I would accidentally use some application specific shortcut inside a different application, where the shortcut would do something completely different or even destructive.

HazeOver helps alleviate this problem. It slightly fades out the application windows that do not have focus while keeping the active, focused window bright in all its glory. After I started using it, I found that I did not make the mistakes anymore. I could clearly see which window has focus. Configuring it is super easy. There’s a graphical interface for that, so I won’t spend more time describing it. Here is a screenshot of my current configuration:

hazeover-configuration-screen

Configure it as you deem necessary and just enjoy it!

Bonus: mapping diacritics to ⌥+key and ⇧+⌥+key

The last trick that I teach here may be of use to some of you — users who switch between 2 or more different keyboard layouts depending on what you do. I used to constantly switch between English which is vastly more convenient for programming work and Estonian, which I used when I was chatting with somebody in Estonian. Estonian has the diacritics such as ‘õ’, ‘ä’, ‘ö’, ‘ü’ — in addition to the letters found in the English alphabet. In the default Estonian keyboard layout, these letters occupy the same locations as the ‘[‘ ‘‘’ ‘;’ ‘]’ keys on the US layout.

estonian-layout
us-layout

As you can see, the locations of some frequently used symbols can be very different between these layouts. I had to constantly keep a mental note for what layout I was using and where my ‘/’ symbol was. Not to mention switching between my IDE and a chat window, writing something and having to delete that just because I accidentally did not change the layout.

After doing this for a couple of years, I found a better way. Simply use one layout – i.e. us-english – and map the key combination of ⌥ + ], ⌥ + ’, ⌥ + ;, ⌥ + [ to õäöü respectively, as well as ⇧ + ⌥ + [key] to their uppercase variants. I noticed that I do not really use the symbols that are mapped to the ⇧ + ⌥ + [key] combinations by default — it was rather safe to overwrite those.

This can all be done by using an application named Ukelele. After downloading and running it, you can create a custom keyboard layout from the current one by selecting File > New From Current Input Source. From there you can see the layout that is currently in effect.

Holding down the different modifier keys displays the symbols that would be entered when pressing a key on the keyboard. Updating the symbol to something different is straightforward, just hold down the modifier key (in my case ⌥) and double click on the key whose symbol you would like to update. For example, here I am changing the ⌥ + ; combination to output ö instead:

ukelele-custom-layout

I would then repeat this process for the other keys as well as the uppercase letters. When you are finished, Ukelele will ask you to save the updated .bundle file when closing. I named mine us-est-alt.bundle if you are looking for inspiration. After saving, move the .bundle file to /Library/Keyboard Layouts, restart your Mac and after restart, select the new keyboard layout from System Preferences > Keyboard > Input Sources. Voila, it should work now. If you need to test it by chatting with someone in Estonian, I’m all ears @svenlaanela.

Ping me and tell me what you think of these tips. Tell me what can I improve in the configurations, and what other apps I should try to enhance my setup?


I hope the above description of my preferred OSX (soon to be macOS) setup gave you some new cool ideas of what to try out. What are the tips and tricks you use on your Mac? Do you know how to achieve something similar for a Windows or Linux installation? Please let us know in the comments below! :)


Read next: