Skip to main content

Shifting window focus via their spacial relationship

Posted by kohsuke on November 25, 2009 at 7:27 AM PST

At work, I have two monitors hooked up to my workstation, which gives me about 4300x1600 combined screen real estate (one of them had to come out of my own pocket, but that's a separate story.) When I switched from a single monitor set up, my behavior changed a bit.

It used to be that I have most of the applications maximized, and used Alt+Tab to switch between them, most of the time. The screen wasn't big enough to run two apps side by side.

With multiple monitors, this is no longer the case. At least two, more often three applications are visible. Say a maximized IDE on the primary monitor, Gnome terminal on the left hand side of the second monitor, and Thunderbird on the right hand side of the second monitor. This arrangement lets me work on code while loking at the stack trace of an exception in a terminal, or a bug report in the e-mail, etc.

One of the pains I've been feeling is the lack of efficient way to switch window focus to different applications. And when I say "efficient", I mean by using keyboard, without reaching out to a mouse.

Let's say I'm typing an e-mail, and realized that I need to check code in IDE. For me to switch a focus, I have to first hit Alt+Tab, comprehend the list of windows that appears, then hit Alt+Tab a few more times until the right IDE window gets the focus. That's a lot of time and cognitive overhead.

So instead I developed a little script that lets me shift focus by relative directions from the current window. In the above scenario if the IDE is on the left of e-mail, I hit Win+Left, and I get the focus shifted to the left. Ditto for other arrow keys. This turns out to be much more efficient, as the spacial relationship between windows are easier to grasp and something you can see even all the time. I think this would also scale to even larger number of monitors, something which I'd love to have some time in the future.

The script uses a Ruby library that manipulates X windows underneath. It was originally developed by someone else I forgot, and I had since then started to maintain my own fork that fixes various problems. I then wrote more Ruby code that figures out which window is in the general up/down/left/right direction of the current window. This turns out to be a very interesting puzzle, as it has to cope with heuristics. In the current version, the script considers such things as visible regions of each window, their center of gravity, distance and angle from the current window, etc. Another fun part was to think about the algorithm to compute that efficiently, even though the benefit is largely theoretical and not practical, since no one opens 1000 windows. It currently takes O(N3) for the number of window N.

I think there's still some room for improvements, but I'm generally happy with the result. Beyond that, I think this library can be also used for doing all kinds of other Window manipulations that you may think of.

I use the Compiz commands plugin to kick off a script when a particular key combination is pressed. If you are using Linux/Solaris with multiple monitors, you should give it a try, too.

Related Topics >>


Eye and gesture tracking

Here is an idea for a hobby project. Set up a camera (perhaps on a pair of glasses) with some vision software to track eye or head movement and other gestures to change window focus e.g. could be a single hot key to change window focus correlated to where the eyes are currently focused. (I was wondering if one could mount some hacked Wii controllers on glasses or the head to do the same thing!)

virtual desktop

Isn't this the same principle as virtual desktops except you show more than one desktop at ones? Ronald.

Yes. The main point of this

Yes. The main point of this blog is about switching focus among windows, though. No virtual desktop have the keyboard assignment for this, AFAIK.

How do I try it?

For those of us with minimal Linux knowledge, could you give some installation instructions, or a pointer on where to look? Thanks, Curt

You need to run 'make' to

You need to run 'make' to compile the C program. Then you can run the ruby script.

Ideally I should create a package, but I'm being lazy :-)