It's time for web developers to break out the champagne

It is somewhat amusing to realize that Google is not playing the same game as the other browser vendors. Its incentives are very different, and that makes all the difference. Google is not directly interested in increasing adoption of Chrome; it actually benefits from increased use of the web on any browser. Sundar Pichai, the Google VP in charge of Chrome, has said as much:

"We were all very clear that if the outcome was that somehow Mozilla [Firefox] lost share to Google [Chrome], and everything else remained the same, internally, we would have been seen as having failed," Mr. Pichai says.

So, journalists who are fixated on market share, like JR Raphael of PC World (not to pick on him), are missing the point:

Can Chrome Shake Up the Browser Market? ... As it stands now, Chrome holds about 3 percent of the global browsing market ... Google's hope ... is to double that share by next September—then triple it by 2011.

Chrome has already shaken up the browser market. In the year that Chrome has been out, speed has become one of the primary selling points for every major browser. The performance of every browser (and hence, every web app) has improved dramatically, and more improvements are in the pipeline. That fact—not Chrome's who-even-cares percentage market share—is the story of this year.

And the folks at Google are probably pretty happy with that. If people use a fast browser and load more web pages and use more Google products and see more advertisements, who cares if it says "Firefox" or "Chrome" in the title bar? Google doesn't.

Hell, who cares if it says "Internet Explorer"? Google doesn't. Which brings me to Chrome Frame, a plugin that runs a Chrome renderer in IE:

I wept tears of joy when I first saw this. For comparison, see IE8's native rendering of Acid3.

The Chrome renderer is activated on an opt-in basis from web developers, using a special META tag.

It remains to be seen how all this will pan out, but this is a very clever move on Google's part. It changes the economics both for IT departments and for developers:

  • Many if not most IE users are unwilling or unable to change their browser for legacy/lockdown reasons; I suspect that is the most important reason why Firefox, after all these years, is only at around 23% market share. It's not that IT departments are inherently against installing new software. They'd love to be able to deploy spiffy HTML5 apps too. But their hands are tied because they must make sure existing apps keep working. Now that they can use HTML5 apps without breaking any legacy apps, they may be a lot more open to deploying Chrome Frame than to changing browsers entirely.
  • Installing a plugin is a lot easier for end users than installing a new browser. In fact, it's a routine enough operation that I suspect many web developers will soon choose to take the Chrome Frame route rather than continue to expend time, money, blood, sweat, and tears working on hacks for native IE support. When users are presented with a dialog saying "In order to use This App You Really Want you must install the mumble mumble plugin," most of them will do it. (Flash has upwards of 90% market penetration!)

Because it was willing to sneak in the side door, ship as a plugin, and strip the chrome from Chrome, Google may be the first to have a real shot at bringing fast and standards-compliant browsing to a majority of web users.

New external Thinkpad keyboard

I ordered one of the new external Thinkpad keyboards and have been using it for a few days now.

Specs in brief: USB, no touchpad, no numpad, feels exactly like a Thinkpad T400s keyboard, and the price is right ($60).

For my own purposes, the design decisions that Lenovo made here are pretty much spot-on. This thing is fantastic; in particular:

  • TrackPoint scrolling on my desktop machine! No exaggeration, this alone is worth the price. Scrolling any other way is just… uncivilized. I look forward to using the mouse a lot less.
  • I was at first skeptical of Lenovo's decision to make a small keyboard, but I think it really turned out well:
    1. It significantly reduces the distance I have to reach to press keys like PgUp, PgDn, and the arrow keys. Alas, there are still a bunch of apps that have the poor sense to bind commonly used commands to keys like Ctrl+PgDn. I'm looking at you, web browsers. (If you wish, read more ranting about poorly chosen keyboard shortcuts.)
    2. I don't use the numpad often enough to justify having one.
    3. I like having the free desk space. And not having to reach as far for the mouse when I want to use it.
  • I like how thin the keyboard is (it's sort of wedge-shaped, and only about half an inch thick at the home row). At first I didn't think this would matter, but I definitely end up contorting my wrists much less than with my old keyboard.

And, to boot, it looks very classy— the picture above doesn't really do it justice.

Thinkpad keyboards do have some quirks (e.g. Fn key placement). I don't mind these anymore, but I know some people do. So perhaps the most useful thing that I can say in this review is that there are no surprises, as far as I can tell. If you've used a Thinkpad, you probably already know whether you want one of these Thinkpad keyboards.

The only reservation I have is that the keys seem to be spaced a little further apart than I'm used to (having become acclimated to the X series keyboards). I'm presuming that this is something I'll get used to over time, so I'm not worrying yet.

Kudos to David Hill and his team for a job well done.

ThinkPad Keyboard at the Lenovo Store

Additional notes on GNU/Linux support:

  • All the special keys (that I tried, anyway— volume, mute, and media player control) work out of the box on Ubuntu GNU/Linux 9.04.
  • TrackPoint scrolling works, too. Follow the instructions here, except in mouse-wheel.fdi, use "Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint" instead of "TPPS/2 IBM TrackPoint". (In general, it looks like you can figure out the right info.product string to use by running xinput list and finding the right device from the list.)

Getting more "flow" from your window manager

Working on a Thinkpad keyboard is pure bliss. The Trackpoint lets me point (and scroll!) without moving my wrists; within Emacs/screen, even it is superfluous. Being able to immediately act on one's intentions is an important factor in attaining a state of flow, and there is a huge psychological difference between being able to do something "now" and "wait, hang on for 500ms so I can reach the touchpad." When I'm really in the zone, I can actually notice my concentration dissipating if I need to reach for the arrow keys, or worse, the mouse or touchpad (this is hard to explain to people who don't use Emacs or Vim!).

But window managers are still awful

Yet, even if I'm using Emacs and/or a web browser 90% of the time, and even supposing they left nothing to be desired, there's another program I have to interact with near 100% of the time: the window manager.

It's a shame, but few of the usability lessons we learned over the years made it to any of the common window managers— Windows, Mac, or Metacity. The window manager acts an intermediary sitting between the user and every single app, but WM functions are often marginalized and too hard to activate. This is especially unfortunate, because now that huge monitors are commonplace, we actually need better WMs to help us effectively use that screen space— maximize and minimize alone don't cut it anymore! (Jeff Atwood pointed this out all the way back in 2007.)

How can we do better? Well, what does "better" even mean? Here are the assumptions I'm operating under, about what kinds of operations are easy or hard to perform:

  • "Reaching is hard": reaching touch-typeable keys is easier than reaching the function keys (F1 … F12), the arrow keys, or the numpad.
  • "Pointing is hard": typing a small number of keystrokes is easier than using the mouse (or any other pointing device).
  • "Fitts's law": pointing at a large target with the mouse (e.g. a window) is easier than pointing at a small target (e.g. an icon, menu, button, border, or title bar).

You may be able to see where the problems are. Windows and Metacity map a bunch of window management functions to far-away placed keys like Alt+F4 and Alt+F10. Mac OS has better bindings for some functions, but doesn't map Maximize at all by default, instead providing access via itty-bitty buttons on each window. On both Windows and Mac OS, the fastest way to move (or resize) a window is by dragging it by its title bar (or resize handle). It doesn't get any worse than that.

Dragging resize handles… seriously? Fitts's law, anyone? This is nonsense.

This is the main reason that I can only use Windows or Mac OS for about 30 seconds before my blood pressure starts to go up. They are not usable. Having to fish around with the pointer every time you want to do something is also a great way to develop RSI.

Building a better WM

I've played around with a few scattered ideas with the goal of making a better WM for myself. I've implemented these in my Openbox config, although any reasonably configurable WM will do.

But, I would like to stress here, the details are unimportant. If you can find the parts of your workflow that are unnecessarily slow, and eliminate them, more power to you.

1. Manage windows and workspaces with shortcuts that don't require function keys or arrow keys. For example, Alt+F10 (maximize a window) and Ctrl+Alt+LeftArrow (switch workspaces) are out. In my setup they are replaced by Win+1 and Win+j, respectively.

2. Move and resize windows with alt-dragging (actually, Win-key dragging). When you want to move or resize the window, the entire window is your drag target. No need to aim for the title bar, or the resize handle, or the window border. Fitts's law, suckers.

To move windows: point at the window, hold down Win, and drag with the left mouse button. To resize windows: point at the window anywhere near the corner you want to move, hold down Win, and drag with the right mouse button.

Kudos to Metacity (and most other X WMs) for shipping with something similar by default.

3. Arrange windows using the keyboard.

It took me the longest time to realize that this was something that would actually be useful.

Most people only have a couple of common ways they like to arrange windows on the screen— for example, one window filling the entire screen, or two half-width windows side by side. What this means is that in the common case, you are really not asking for windows to be placed at specific pixel positions on your screen. Hence, the mouse isn't actually needed.

I use a couple of different window management "idioms," which are probably best illustrated by example:

  • Win+s i j k RET, for example expands the current window until it meets the nearest edge to the north, west, and south. Before and after:

    Win+s activates window-expanding and i, j, k, and l indicate north, west, south, and east, respectively.

  • Win+s Win+s means "expand the current window as much as possible without covering anything else," which seems like a common thing to want. Before and after:

    Openbox's smart window placement policy attempts to place a second window within the space left by the first one. So a quick Win+s Win+s makes a second window neatly fill up all the space left unused by the first one!

    For more complex arrangements, it's very fast to drag a window to an approximate location (see alt-dragging, above), then use Win+s Win+s to make it neatly fill the available space.

  • Win+w is analagous to Win+s except that it moves a window to the nearest edge to the north/west/south/east instead of resizing it.

An alternative strategy is to bind keys to move windows to a small number of fixed "slots," such as the two halves of a screen. Jeff Atwood mentions this strategy and its implementation in WinSplit Revolution.

4. Configure single-key shortcuts for launching common apps. For example, Win+b for a web browser. Not always a window-manager responsibility, but it can really streamline one's work.

Conclusion

Although I am still experimenting with some aspects of this setup, I am fairly happy with it. For better or for worse it does feel a lot like a "normal" window manager, just one that is highly streamlined (and doesn't give me hypertension). I'd be curious to see what additional improvements can be gained by giving up some of the associated flexibility and moving to a more restrictive model (e.g. something like a tiling WM).

For the curious, I've posted Openbox configuration recipes for tips 2 and 3 here.

AUCTeX and preview-latex

AUCTeX is a TeX mode for Emacs that adds various conveniences for editing LaTeX (and other macro packages). One of its killer features is inline previews of math and graphics, using preview-latex:

With AUCTeX and preview-latex, you can properly edit your document and equations in their high-level (TeX source) representation, while getting near-instant confirmation that your equations will turn out the way you want. It's pretty much the best of both worlds.

AUCTeX is easy to set up on Ubuntu, although it takes slightly more work than the usual apt-get invocation. Here is a HOWTO for my future reference (and yours). This has been tested on Ubuntu 9.04 with a post-v23-release emacs-snapshot:

Install AUCTeX.

$ sudo aptitude install auctex

Add the following init code to your .emacs file.

(load "auctex.el" nil t t)
(load "preview-latex.el" nil t t)

Open a LaTeX file in Emacs and press C-c C-p C-b (M-x preview-buffer) to generate math/graphics previews for the entire buffer. After you update an equation, press C-c C-p C-p (M-x preview-at-point) to refresh the preview.

Further reading: AUCTeX, AUCTeX manual

Zeya 0.1

Zeya is a streaming music server that supports an HTML 5 (draft standard) based player.


Motto: bring your music anywhere

I'm pleased to announce the first numbered release of Zeya, version 0.1.

Notable new features:

  • Support for the directory backend, which scans a directory recursively and serves up all the music in it. Invoke with
      zeya.py --backend=dir --path=/path/to/music
  • Experimental support for Google Chrome clients. Zeya plays music in Chrome. Latency is still poor and advance-to-next-track is broken for the time being. Read the README for the gory details.
  • Keyboard shortcuts for play controls: j, k, and SPC.

Visit http://web.psung.name/zeya/ for more information, and read the previous blog post on Zeya for a bit more context.

Google Web Toolkit and Java/JS translation

I've been using Google Web Toolkit for some projects at work, and I've been quite impressed with it. I think that for many classes of web apps, GWT (or something with the same general model) is really the "right" way to build your app.

(Disclosure: these were the first nontrivial web apps I've written since before the term "AJAX" came into common parlance, so I've not been totally in the loop for some time with respect to web programming or any of the major JS libraries.)

For the uninitiated: GWT is a free software development stack that lets web developers write apps entirely in Java. GWT provides various UI and utility libraries, as well as a compiler that compiles your Java code to a combination of Java servlets and client-side Javascript— including the XMLHttpRequest serialization/deserialization code needed at the client/server boundary.

I don't have anything against Javascript or dynamic languages. But I think that for certain web apps it can make sense to trade away some of the flexibility of Javascript. In many web apps today, the app is just the frontend to some database, and the client's responsibility is mainly just to manipulate the DOM and shuttle data around. Not a whole lot of business logic— although, to be fair, JS apps will likely become more and more sophisticated in the future. I suspect many of these apps might be better served by a strongly typed language. The GWT Java compiler prevents entire classes of errors right off the bat, including the most common type in JS apps in my experience: typos. (Yeah, unit tests and tools will also mitigate these problems a bit.)

However, I think the most important idea at the core of GWT is that of a language-to-language translator. The problem with pure Javascript is that the code you want to be writing and maintaining does not look at all like the code you want the browser to be executing. The idea of an intermediate translation step is not new: people have been using Javascript minifiers/obfuscators for years to speed up loading and execution. But GWT takes this further: in addition to shortening identifiers, it aggressively inlines code and eliminates dead code (unused variables, fields, methods, classes, ...). Now you're free to introduce indirection in your code to make it more readable and testable (for example, refactoring to the model-view-presenter pattern) without feeling guilty that you are making your app slower. (Testability! Hooray!) This eliminates some of the usual tension between speed and maintainability.

Actually, GWT takes its translation process even further: it compiles multiple browser-specific versions of your app— something that few, if any, humans would bother to do— so that no client ever has to load or execute switch-on-browser logic and each client gets a variant optimized for its platform.

When all these optimizations are considered, Google claims that GWT-generated code is "often ... faster than equivalent handwritten Javascript." That shouldn't be surprising: code that is to be maintained has to meet some minimum standard of readability, but code that is to be executed has no such requirement. This really drives home the importance, and the power, of having a source-to-source translation process in the pipeline.

(There are a number of other compelling reasons to use GWT that I haven't mentioned here. The GWT page gives a pretty good overview of them.)

Emacs 23

Emacs 23 has been released. You can download it from GNU's FTP server.

The most notable new features or changes that I noticed or have been using:

  • A single Emacs process can generate frames on any number of TTYs and on X simultaneously. Run M-x server-start and then emacsclient -t or emacsclient -c to create a new TTY or X frame, respectively.
  • C-p and C-n now move by screen/visual lines instead of by logical lines. While this makes Emacs more consistent with most modern apps, it has the potential to break keyboard macros. If you use macros frequently, consider setting (setq line-move-visual nil) to disable this behavior.
  • Transient Mark mode is enabled by default. I find t-m-m is occasionally really handy, especially after the mark-* commands, and for restricting the region for query-replace. However, I think t-m-m highlights a little too aggressively. To disable t-m-m except after the mark-* commands, I use the following:
  • (transient-mark-mode 0)
    
    ;; Activate t-m-m only after mark-* commands (you can also enable it manually
    ;; at any time with C-u C-x C-x).
    (require 'cl)
    (macrolet
        ((advise (&rest commands)
                 `(progn
                    ,@(mapcar (lambda (command)
                                `(defadvice ,command (after transient-mark activate)
                                   "Activate Transient Mark mode temporarily."
                                   (setq transient-mark-mode '(only))))
                              commands))))
      (advise mark-sexp
              mark-word
              mark-paragraph
              mark-defun
              mark-end-of-sentence
              mark-page
              mark-whole-buffer
              LaTeX-mark-environment
              LaTeX-mark-section))
  • C-l is bound to recenter-top-bottom, which moves the viewable area so that the current line is at the center, top, or bottom on successive presses. Useful for surveying the area around point.
  • DocView mode, new, is a PDF/PostScript/DVI viewer.
  • Emacs is smarter about splitting windows (e.g. after C-x 4 C-f), splitting vertically if your frame is sufficiently wide.
  • Beautiful anti-aliased fonts.

There are many, many, more changes. See etc/NEWS for the gory details.

On emacs-devel, I recently got a pointer to Richard Stallman's 1981 paper on the design of Emacs, presented at the ACM Conference on Text Processing:

Extensibility means that the user can add new editing commands or change old ones to fit his editing needs, while he is editing. EMACS is written in a modular fashion, composed of many separate and independent functions. The user extends EMACS by adding or replacing functions, writing their definitions in the same language that was used to write the original EMACS system. We will explain below why this is the only method of extension which is practical in use: others are theoretically equally good but discourage use, or discourage nontrivial use.

Extensibility makes EMACS more flexible than any other editor. Users are not limited by the decisions made by the EMACS implementors. What we decide is not worth while to add, the user can provide for himself. He can just as easily provide his own alternative to a feature if he does not like the way it works in the standard system.

It is striking how so little software today, even "professional" software that users are apt to use 8 hours a day, is actually designed to facilitate extensibility and automation by users.