25 Jun 2003
(updated 25 Jun 2003 at 16:02 UTC) »
I did a fun little configuration-hack today. It makes the CD-player next/prev buttons on my Inspiron laptop cycle me between my regular desktop display and the full-screen displays of some VMware machines I run. The main desktop runs in one Sawfish "workspace" (using a 3x3 grid of Viewports), and each VMware runs in its own workspace (also with 9 viewports, but using only one). (Little details make it ugly to run full-screen VMwares just in viewports.)
If you want to do this fun and pointless hack too, there are two steps: binding the buttons as keys, and some Sawfish tweaking.
The CD-player buttons on the Inspiron are nothing special - just keys that generate unmapped keycodes. To bind them to keys in Sawfish, you just need to associate their Keycodes (found in xev) with Keysyms. I browsed through <X11/keysymdef.h> and found a couple of rather appropriate-looking keysyms to add to my .Xmodmap:
keycode 132 = Next_Virtual_Screen
keycode 131 = Prev_Virtual_Screen
Then these can be bound to "Next Workspace" and "Previous Workspace".
That's most of it done. The only problem is, when you switch workspaces you keep the viewport (position) of the one you jumped from. So when I jump to a VMware workspace, I won't necessarily land in the viewport where VMware is running. This problem is solved by a little sawfish configuration hack:
;; When I leave a workspace and then come back to it, I want to end up
;; in the same viewport as when I left. I don't know if Sawfish
;; supports this behaviour by pure configuration, so..
(defun remember-workspace-viewport (workspace)
"Remember which viewport WORKSPACE is looking at."
(put (workspace-symbol workspace) 'viewport (screen-viewport)))
(defun restore-workspace-viewport (workspace)
"Go back to the viewport that we remember WORKSPACE was looking at."
(let ((viewport (get (workspace-symbol workspace) 'viewport)))
(set-screen-viewport (car viewport) (cdr viewport)))))
(defun workspace-symbol (workspace)
"Return a symbol to represent WORKSPACE.
A different symbol is returned for each workspace."
(intern (format nil "workspace-%S" workspace)))
(add-hook 'leave-workspace-hook remember-workspace-viewport)
(add-hook 'enter-workspace-hook restore-workspace-viewport)