Work with XMonad in OS X

Over the years, I’ve developed a small set of tools that I cannot live without when coding. Usually this means a Linux environment with XMonad as my windows manager. At work I ran a Linux VM on top of Windows 7 just so that I can stay within my comfort zone.

Recently my main computer at home, an Acer Aspire One netbook, was giving me a lot of trouble including corrupted filesystem, dead disk (which is actually an SD card), and so on. It made me consider switching to the iMac desktop, a 4 year old machine that was mostly collecting dust at home. For various reasons, wiping it out with a fresh Linux distro is not an option, so I decide to look for ways of getting back to my usual setup – afterall, OS X is Unix.

It turns out that having XMonad on OS X is a reasonably well documented practice. Nevertheless, there are still differences in my case that I feel like to write down.

Macports and Xcode

I only have OS X 10.5.8 (Leopard) on the iMac, and although Apple still pushes updates from time to time, some software on it is no longer current, including Xcode.

To get a proper X11 and an reasonably up-to-date Unix environment on OS X, one has to use systems such as Macports or Fink. I had Macports on this machine before, so I decide to continue using it. The only problem, however, is that my version of Xcode was still 3.0, which is too old to please Macports. In fact Macports refused to upgrade (stuck at the libtiff package) and recommended Xcode 3.1.4, which is the last 3.* version for Leopard. All later versions would require Snow Leopard (OS X 10.6).

There are two options for me:

  1. Follow the documentation of Macports to download and install Xcode 3.1.4 (around 900M), which requires ADC (Apple Developer Connection) membership.

  2. My wife has a 13" Macbook Pro from 2010, whose installation disk was Leopard and had Xcode 3.1.2 on it (Apple sent us a Snow Leopard DVD shortly after we bought this machine).

I took the 2nd approach, and it works out fine. Note that when I logged onto ADC’s main site and searched for Xcode in developer tools, its link to version 3.1.4 was actually broken. So the only method would be to follow the above link from the Macports site, which re-directs to ADC’s download page of Xcode 3.1.4.

After updating Xcode, I update Macports, which is pretty easy:

sudo port selfupdate
sudo port upgrade outdated

It took quite a while to get everything in place. I also installed firefox and git as follows:

sudo port install firefox-x11
sudo port install git-core

I wasn’t successful in getting firefox 4.0 (which is under the name firefox-x11-devel) to work, but firefox 3.6 isn’t bad either.

X11 and Meta Key

Although there is an X11 app in OS X, it is not as up-to-date as XQuartz, which also has versions for both Leopard and Snow Leopard. Make sure you install (or re-install) it after updating Xcode.

Setting up X11 for Leopard also took a few tries, and here is what I eventually do in its preference menu:

  1. In the Input section, only check Option keys send ALT_L and ALT_R;
  2. In the Output section, check Fullscreen as well as Auto-show menu bar;
  3. In $HOME/.Xmodmap, put the following:

    clear mod1
    clear mod2
    add mod1 = Meta_L Meta_R
    add mod2 = Alt_L Alt_R

This setting will turn the Apple Command keys into Mod1 under X11, which is crucial in operating XMonad. The step 3 above can be omitted if you would like to keep Mod1 mapped to the Alt keys instead of Command.

GHC and XMonad

Official Haskell Platform no longer supports Leopard, so I have to use GHC, but unfortunately the latest GHC doesn’t provide binary packages for Leopard either. I had GHC 6.10.2 on the machine before, and it still works fine to build XMonad, so I didn’t bother to change. Otherwise, I could have gotten an older GHC version from GHC website, or even from Macports, which at the moment provides GHC 6.10.4.

I also need the latest Cabal (Haskell’s package manager) in order to compile XMonad. I download cabal-install-0.8.2 and run sh, which supposely should have taken care of everything, well, not in my case. For some reason, it complained about missing a later version of the time package, which I then tried to get from HackageDB but only to be met with broken compilation under GHC 6.10.2. So I had to download the slightly older time-1.1.4, which then installed fine, and the installation of Cabal eventually went through.

After getting Cabal in place, I install XMonad (and xmobar):

export PATH=$HOME/.cabal/bin:$PATH
cabal update
cabal install xmonad
cabal install xmonad-contrib
cabal install xmobar

I usually don’t run the vanilla XMonad, so here is how I customize it:

cd ~
mkdir .xmonad
cp .cabal/share/xmonad-0.9.2/man/xmonad.hs .xmonad/
cd .xmonad
patch -p1 < xmonad-0.9.2.hs.patch

The patch file I used can be downloaded here: xmonad-0.9.2.hs.patch, which makes xmonad spawn xmobar on starting up, and uses the in-built XPConfig instead of dmenu.

Chinese Language

Because Apple’s international language input doesn’t work under X11, I need to seek a native X11 solution. Unfortunately Macports has yet to have any reasonable support in this respect, no SCIM, no fcitx, no nothing. I have to seek elsewhere and compile myself.

Because I only use PinYin for Chinese input, I found a nice XIM compatible solution called sunpinyin, which also supports Windows as well as native OS X. With a little tweak, I made it work under Leopard’s X11, with both xterm and firefox. Here is how:

sudo port install scons
git clone git://
cd sunpinyin
git apply ../sunpinyin.git.patch
scons --prefix=/opt/local
sudo scons install
cd wrapper/xim
scons --prefix=/opt/local
sudo scons install

The git apply step requires a patch file that I made: sunpinyin.git.patch. This patch does two things: setting the install name of sunpinyin-3.0.dylib to be under /opt/local/lib (otherwise dynamically linked executables do not know where to find this dylib), and fixing the compilation flag of the XIM frontend xsunpinyin.

On the display side, xterm is perfectly happy to handle UTF-8 text when it is given proper font to run. The actual setting is also pretty simple, just put the following in ~/.Xdefaults:

xterm*faceName:             Bitstream Vera Sans Mono
xterm*faceNameDoublesize:   Hei
xterm*faceSize:             10
xterm*utf8:                 true

I find Vera Sans Mono a tad nicer than the Monaco font used in Apple’s Terminal app.

Putting It Together

Finally, I put everything together and run them. Here is my ~/.profile:

export PATH=$HOME/.cabal/bin:/opt/local/bin:$PATH
export USERWM=`which xmonad`

And my ~/.xinitrc:

cd $HOME
source .profile
export XMODIFIERS=@im=xsunpinyin
export XIM=xsunpinyin
export XIM_ARGS=-d
export XIM_PROGRAM=/opt/local/bin/xsunpinyin
export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim
export LC_CTYPE=zh_CN.UTF-8
exec $USERWM

Basically it runs xsunpinyin in the background, and starts xmonad as the window manager for X11. Success!

In retrospect, it didn’t go smoothly all the way for me. In particular I ran into a bad Macports upgrade problem, where I used -n option by mistake. It screwed up quite a number of dependencies, and I had to fix them by hand.

Comments powered by Disqus