How a window manager with tiling layouts makes a 1024x600 resolution livable.
I spend a lot of time in front of a screen, and for the past year I have used only my netbook. No desktops, no laptops. Just a cheap $200 computer that is nearly a kid's toy. The most challenging thing about this is dealing with the 1024x600 screen resolution. When I moved to this screen from something with many more pixels, it at first seemed very cramped.
After a year, I think that the most important part of coping with the small screen is the flexability and customizability of layouts provided by the Xmonad window manager. In this post I will explain a few layouts I have developed for fitting specific tasks onto the netbook screen.
(I assume that you know maybe 0.1% of Haskell (about what I do), and can read Haskell code without having a brain aneurysm.)
It's important that the web browser have as few toolbars and other cruft as possible, as horizontal space is especially at a premium. I've configured both Epiphany and Firefox to put everything in one tool bar. But now I use Chromium, which comes pre-configured that way.
What the netbook is designed for. You just want a web browser, taking up
the full screen, and with its own tabs. So far, so easy: that's Xmonad's
But, you sometimes want to see two websites side-by-side. This layout
accomplishes that, allowing the sizes to be adjusted as needed. It also
Magnifier to zoom the smaller window when it's focused,
which is useful if you briefly need to see more of a web site.
mySplit = magnifiercz' 1.4 $ Tall nmaster delta ratio where -- The default number of windows in the master pane nmaster = 1 -- Percent of screen to increment by when resizing panes delta = 3/100 -- Default proportion of screen occupied by master pane ratio = 60/100
If you're doing web development, you'll want probably one big web browser
window, but also with a nice wide terminal on the same screen, in order to
see web server logs. A simple way to do this is to mirror Xmonad's
layout by 90 degrees.
myWide = Mirror $ Tall nmaster delta ratio where -- The default number of windows in the master pane nmaster = 1 -- Percent of screen to increment by when resizing panes delta = 3/100 -- Default proportion of screen occupied by master pane ratio = 80/100
myWide layout uses the full screen width for a single terminal,
and splits the width when there are more. This is sufficient for viewing logs
and doing minor things at the shell prompt, in between testing the result in
the web browser. Of course a terminal can be temporarily moved to the master
area by pressing
mod-return, if you need it to be larger.
Tips on configuring Pidgin for a netbook: Set it up to use vertical tabs to save horizontal space. Configure the input area to only 1 line tall, and turn off as much other cruft as you can. The menu bars, sadly, cannot be disabled, nor can the excessively large borders. In my screenshots, you can see that stuff wasting space that could be used to show four more lines of text.
For chat, you want to put the buddy list on the side of the
screen, and use the rest for conversation windows. Xmonad's
takes care of allocating a sidebar on the screen for the buddy window. The
rest of the screen can be occupied by any layout you choose.
I like to have the conversation windows be as wide as possible, and
typically only want to see two conversations at a time. But sometimes I
might have a dozen visible. A good layout to cope with those needs is
myChat' l = withIM size roster l where -- Ratio of screen roster will occupy size = 1%5 -- Match roster window roster = Title "Buddy List" myChat = myChat' Grid
withIM layout puts the buddy list on the left; I prefer it on the right
for some reason, so I tweaked my layout to do that. All it took was
reflectHoriz layout modifier to get a mirror image of
the layout. Then I reflect the inner layout back to its normal orientation.
Being able to throw in a few function calls and mutate a layout like that
is where Xmonad shines.
myChat' l = reflectHoriz $ withIM size roster $ reflectHoriz $ l
Ever notice that
tail -f wastes the last line of the terminal? On a netbook
lets the last line be used.
I have a dedidated workspace that I use to tail logs, and as a place to
send long-running tasks (such as compiles). The layout for this needs to
keep windows wide, to see whole logged lines, but they need only be five
or so lines tall. And it's convenient to have one bigger window with the
small ones below. Xmonad has a perfect layout for this, called
because it's sorta like a stack of plates.
myDish = limitWindows 5 $ Dishes nmaster ratio where -- The default number of windows in the master pane nmaster = 1 -- Default proportion of screen occupied by other panes ratio = 1/5
In the second screenshot above, I have 6 windows open, but only 5 are
limitWindows 5 accomplishes this. It's handy mostly because
gnome-terminal has a bad habit of crashing when resized to 0x0.
(That's gotta be a bug in something!)
Notice that the screenshots above also have Procmeter in a sidebar on
the right. I (ab)used the
withIM layout to do that:
myLogs' l = reflectHoriz $ withIM procmeterSize procmeter $ reflectHoriz $ l where -- Ratio of screen procmeter will occupy procmeterSize = 1%7 -- Match procmeter procmeter = ClassName "ProcMeter3" myLogs = myLogs' myDish
Everything above was easy. Doing coding (or writing) on a small screen is where it gets hard. When I'm coding I want to have one window that is exactly 80 columns wide, and as tall as possible, where I do the main development. Then I need a minimum of two other windows also visible: one action window for running tests and the like, and one to view references (emails, man pages, other files, etc). I may need to view any of these windows fullscreen at any time, of course.
As an example of the three window rule:
While I'm writing this post, I have a reference window open
.xmonad/xmonad.hs, and an action window open where I am
Often, deep into something, I will accumulate many other reference and action
windows. But three seems to be the magic, minimum number for me;
screen or anything else doesn't reduce it; if I can't see all
three at once, I will waste time and concentration flipping back and forth.
The Xmonad layout I've developed to handle this is based on the handy
FixedColumn layout, which automatically keeps the master window 80
columns wide. I modify this by adding the
Magnifier, so that my action
and reference windows "pop out" over the master window when focused.
myCode = limitWindows 3 $ magnifiercz' 1.4 $ FixedColumn 1 20 80 10
The 1.4 was carefully tuned, to magnify a window to be big enough to be
usable for editing, reading, or command-line, while not obscuring too much
of the other two windows. And again I use
limitWindows, to only show
three windows, in order to keep them all as big as possible. Other windows
are hidden offscreen, but I can rotate to them with alt-tab as needed.
When I'm reading an ebook, I want to have the reader in the middle of the screen. But a widescreen netbook like mine is too wide to comfortably read text all the way across, so it's nice to have margins. (In the margins, I put terminals, or notes.)
ThreeColumns module has a layout that does just that.
myBook = ThreeColMid nmaster delta ratio where nmaster = 1 -- Percent of screen to increment by when resizing panes delta = 3/100 -- Default proportion of screen occupied by master pane ratio = 2/3
I join all my layouts together, so Xmonad will allow switching between them. These three combinations all have the same layouts, only ordered differently, so that different workspaces can have different default layouts.
codeFirst = myCode ||| myWide ||| myGrid ||| myDish dishFirst = myDish ||| myCode ||| myWide ||| myGrid gridFirst = myGrid ||| myDish ||| myCode ||| myWide
Xmonad layouts can be decorated with things like title bars. To save horizontal space, I leave off the title bars on layouts where they are not needed to disambiguate windows. Two helper functions can be applied to add or remove titles (and also cause the layout to avoid the Gnome panel.)
withTitles l = noFrillsDeco shrinkText myTheme (desktopLayoutModifiers l) noTitles l = desktopLayoutModifiers l
I have semi-dedicated workspaces; one for each of the above activities.
To assign a layout to a workspace, I use the
Notice that the "web" workspace has only two available layouts.
Meanwhile, the "book" workspace always uses the specialized
layout; I don't use that layout elsewhere.
perWS = onWorkspace "logs" (withTitles $ myLogs' dishFirst) $ onWorkspace "web" (noTitles $ (mySplit ||| myWide)) $ onWorkspace "chat" (noTitles $ myChat' gridFirst) $ onWorkspace "book" (noTitles $ myBook) $ (withTitles $ codeFirst)
Finally, I allow toggling between the currently selected layout and
fullscreen mode, and use
smartBorders to avoid displaying borders when
there is only one window onscreen.
myLayout = smartBorders $ toggleLayouts Full perWS
Xmonad layout optimised for the small screen of a netbook: Done! (For now...)
PS: Thanks to
#xmonad regulars for always having the answer
I need up their sleeves.