tmux and mouse mode

UPDATE 17 March 2013: I am placing this post into the public domain so people are free to incorporate it into their existing files which may be in the public domain already.


As I commented in my last post about tmux, tmux mouse mode left some things to be desired. Namely, there are two problems.

First, it completely takes over the mouse. Meaning that you can no longer do a simple “mark text and copy” operation on the native OS. There are patches over this problem, like reattach-to-user-namespace, but that is only helpful if you are running tmux on your Mac. I practically never do that, because most of the usefulness of tmux for me is in leaving active sessions to remote servers. I work on remote servers over ssh connections, detach from tmux, and stick my laptop in its bag. I come back to the session later. That would not be possible if tmux were running on my Mac, so I am almost always running it remotely on a Linux server.

Second, there is the pane problem. If you turn mouse mode off, and try to copy text in a pane that has another pane to its side, the terminal will just copy across the boundary. iTerm has no idea that the pane boundary exists; it’s just another character printed in the terminal window.

These days, I have mouse mode turned on by default in .tmux.conf. It’s just too useful to not have it on. If my hand is already on the trackpad, switching between windows or panes, or doing pane resizes, is very handy with the pointer. It’s also usually much faster to do a mark/copy operation within tmux by using the pointer.

1
2
3
4
set -g mode-mouse on
set -g mouse-resize-pane on
set -g mouse-select-pane on
set -g mouse-select-window on

But I do often want to do an OS-native mark and copy. So, I have defined two hotkeys to make it easy to turn mouse mode on and off.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Toggle mouse on with ^B m
bind m \
  set -g mode-mouse on \;\
  set -g mouse-resize-pane on \;\
  set -g mouse-select-pane on \;\
  set -g mouse-select-window on \;\
  display 'Mouse: ON'

# Toggle mouse off with ^B M
bind M \
  set -g mode-mouse off \;\
  set -g mouse-resize-pane off \;\
  set -g mouse-select-pane off \;\
  set -g mouse-select-window off \;\
  display 'Mouse: OFF'

UPDATE 20 July 2012: @aristidesfl points out that you don’t need to bind anything for mouse mode disable in iTerm2, simply hold option down and iTerm2 turns it off temporarily.

That makes it easy to switch between the two states (mouse mode on or off). But there is still one nagging situation: I want to do OS-native copy and paste, but it’s in a pane. Even with mouse mode off, things break because the terminal does not know what a tmux pane is. Once again, key bindings come to the rescue.

1
2
3
4
5
6
7
8
9
10
11
unbind +
bind + \
  new-window -d -n tmux-zoom 'clear && echo TMUX ZOOM && read' \;\
  swap-pane -s tmux-zoom.0 \;\
  select-window -t tmux-zoom
    
unbind -
bind - \
  last-window \;\
  swap-pane -s tmux-zoom.0 \;\
  kill-window -t tmux-zoom

These bindings (^B + and ^B -) are a “zoom” feature. Focused on a given pane, ^B + will promote the pane to be its own window. Then you can do OS-native mark and copy all you want, no panes to worry about. When you’re done, just use ^B - to turn the window back into a pane, right where it was before.

I’ve chosen to keep these two things separate, but with a little tinkering, you can create a binding that does both operations together: zoom a window, turn mouse mode off, and another binding to do the inverse.

As always you can find my current .tmux.conf file on GitHub.