‘The half minute which we daily devote to the winding-up of our watches is an exertion of labour almost insensible; yet, by the aid of a few wheels, its effect is spread over the whole twenty-four hours.’

Group-agnostic previous-focussed-window memory in StumpWM

Benjamin Slade

I’ve started using StumpWM’s groups (like “workspaces” in other window managers) more extensively, but this broke a behaviour I like: the ability to easily switch back to the last focussed window, because StumpWM’s “last focussed” is group-specific. So I wasn’t easily about to switch quickly back and forth between two windows that were inb different groups, which turns out to be something I frequently want to do (e.g. switch back and forth between an emacsclient frame in my “emacs” group and a Firefox instance in my “web” group).

Here’s my fix:

;; Global 'last focussed window'
(setf *global-earlier-focussed-window* 'nil)
(setf *global-prev-focussed-window* 'nil)
(setf *global-cur-focussed-window* 'nil)

(defun panrecord-of-last-focussed-window (currwin lastwin)
  "Record last visited windows and their group."
  (unless (or (search "*EQUAKE*[" (window-name currwin))
               (equal (cons (current-window) (current-group)) *global-cur-focussed-window*))
    (when (find-window-globally
           (car *global-prev-focussed-window*) (screen-groups (current-screen)))
      (setf *global-earlier-focussed-window* *global-prev-focussed-window*))
    (when (find-window-globally
           (car *global-cur-focussed-window*) (screen-groups (current-screen)))
      (setf *global-prev-focussed-window* *global-cur-focussed-window*))
    (setf *global-cur-focussed-window* (cons currwin (current-group)))))

(defun find-window-globally (window group-list)
  "Check for presence of window in all groups."
    (if (equal (car group-list) 'nil)
        'nil
        (if (member window (group-windows (car group-list)))
            window
            (find-window-globally window (cdr group-list)))))

(defcommand switch-to-last-focussed-window () ()
  "Switch to last focussed window, irrespective of which group it is in and
what group we're currently in."
  (let ((switch-to-win
          (or
           (find-window-globally
            (car *global-prev-focussed-window*) (screen-groups (current-screen)))
           (find-window-globally
            (car *global-earlier-focussed-window*) (screen-groups (current-screen))))))
    (if switch-to-win
        (progn
          (switch-to-group (cdr *global-prev-focussed-window*))
          (focus-window (car *global-prev-focussed-window*) t))
        (message "No window to switch to."))))

(stumpwm:add-hook stumpwm:*focus-window-hook* 'panrecord-of-last-focussed-window)

(define-key *root-map* (kbd "s-f") "switch-to-last-focussed-window")

The unless statement in panrecord-of-last-focussed-window prevents my drop-down terminal Equake “window” from “counting” for history tracking purposes.

switch-to-last-focussed-window essentially just switches to the last focussed window, after making sure it still exists. (If not, the window which was focussed before that one, or else don’t switch and display message to user.)

(define-key *root-map* (kbd "s-f") "switch-to-last-focussed-window") means that I can double tap s-f to switch to the last focussed window, no matter which group it belongs to.

I continue to really enjoy the power that StumpWM’s Common Lisp underpinnings provides the user!