Using Mac gestures in Emacs

| categories: emacs | tags:

I recently got a MacBook Air, and I have been exploring what you can do with it and Emacs. The Mac trackpad has some interesting gestures that are useful in Emacs. For example, you can scroll the buffer by moving two fingers up or down the trackpad. Or tap the trackpad with two fingers to get the equivalent of a right click. I was curious what other gestures could be used effectively in Emacs. Emacs does not capture all of the trackpad gestures, but it does capture the two finger swipe left and right as a triple-wheel-left or right key. We can use that to switch buffers. Normally one uses C-x leftarrow or right arrow to do that, but with the trackpack we can use a gesture!

The gesture triggers a triple-wheel key, which we can bind to an function. This code does that.

(global-set-key [triple-wheel-left] 'previous-buffer)
(global-set-key [triple-wheel-right] 'next-buffer)
next-buffer

This scrolls through buffers blazingly fast! Almost unusably fast. If you move very slow, you can get some control and switch one buffer at a time. Interestingly, I see these messages while gesturing slowly:

<wheel-left> is undefined
<double-wheel-left> is undefined
<wheel-right> is undefined
<double-wheel-right> is undefined
<wheel-right> is undefined [2 times]
<double-wheel-right> is undefined

We need a custom function that has some kind of delay to slow down the buffer switching. Here is an idea. We will store a value in a global variable, and only switch buffers when it is true. After we switch the buffer we set the variable to nil, and activate a timer to reset the variable to t after a short delay. say one second. Here it is.

(defvar *my-previous-buffer* t
  "can we switch?")

(defun my-previous-buffer ()
  (interactive)
  (message "custom prev: *my-previous-buffer*=%s" *my-previous-buffer*)
  (when *my-previous-buffer*
    (previous-buffer)
    (setq *my-previous-buffer* nil)
    (run-at-time "1 sec" nil (lambda ()
                               (setq *my-previous-buffer* t)))))

(defvar *my-next-buffer* t
  "can we switch?")

(defun my-next-buffer ()
  (interactive)
  (message "custom prev: *my-next-buffer*=%s" *my-next-buffer*)
  (when *my-next-buffer*
    (next-buffer)
    (setq *my-next-buffer* nil)
    (run-at-time "1 sec" nil (lambda ()
                               (setq *my-next-buffer* t)))))

(global-set-key [triple-wheel-right] 'my-previous-buffer)
(global-set-key [triple-wheel-left] 'my-next-buffer)
my-next-buffer

Note I reversed the left/right order. It seems that swiping left triggers the triple-wheel-right key. Go figure. Anyway, this makes the gesture actually usable, as it only changes one buffer at a time, with a short delay before you can change the buffer again. It is not a groundbreaking addition to Emacs, but it satisfied a curiousity itch for the day for me.

Copyright (C) 2014 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.7c

Discuss on Twitter