follow me on Twitter

    Blog has moved to, see February, 2005 on new site

    Blog entries for February, 2005

    This post moved to

    Jeff, the thing to remember about terminal performance is that you can trade off update rate with throughput to your heart's content. That is, to make a really fast terminal, never update the screen until the child process stops outputting. To make a really slow terminal, update the screen every time the child process outputs a single byte. To make a reasonable terminal, pick some spot in the middle, or try to come up with a fancy algorithm for when to repaint.

    To compare the paint speed or parsing speed of two terminals you probably have to somehow get those two terminals to follow the same rules on updating, and you may also want to configure them feature-equivalent in terms of font rendering and i18n.

    Moral of the story is that when optimizing a terminal you can't just make it as fast as possible, you first have to define the behavior/features you consider acceptable, and then stay "within spec" as you optimize. Anyone can write a fast terminal if "cheating" is allowed but it isn't clear what constitutes "cheating."

    I'm not trying to say anything good or bad about VTE or the performance patches for it, since I haven't looked at those, just making a general observation.

    This post moved to

    One of the more annoying properties of the Internet is that no matter what you post to your blog (or mailing list, or chat) people add comments like: "that isn't new, the Amiga had it in 1987" or "that isn't new, we did that with punch cards in 1953" or "Longhorn has that already" or whatever. These comments are especially popular in places like osnews and slashdot.

    I usually add a disclaimer to my posts specifically to head this off, but it never helps. (Shocking!)

    Why post ideas? It's not to get credit for originality. It's because in this specific context, at this specific time, we should discuss and possibly implement those ideas.

    Side point: there's much to be gained by simply doing something better than it's been done in the past. Apple's new Pages app,, there are countless examples. They aren't really "new ideas" per se, they are well-done and tasteful composites of many old ideas. And they were finished, and made available. Not a trivial thing in the modern software industry.

    This post moved to

    Two simpler approaches to the theme thing:

    • Like OS X, just scrap the idea of themes and hardcode an application-specific design into each app.
    • Limit the problem to layout. So have a layout widget that looks up the layout of an entire window from resource files, and allow themes to intercept the lookup to modify the layout.
    This post moved to

    What an exhausting week; XDevConf last weekend, LWE, then FUDCon. Really enjoyed FUDCon today, I thought it went really well. Big thanks to the organizers. We also had a very productive meeting yesterday with some of the major external contributors and some Red Hat people; decisions were reached and action items assigned on a variety of issues.

    Since I suck at displays of enthusiasm Seth is picking up the slack explaining some of the Red Hat team's work. We also presented some of this stuff at XDevConf and FUDCon this week.

    I think some people didn't catch on to how Sabayon works and what it does; this thing is not a control panel. It's a sort of live summarizer of changes you've made to a prototype user account, and lets you choose the changes to be included in a user profile. The idea is to take care of any needed hacks as well, for example stripping out user home directories hardcoded in settings. As far as we can tell this automates what most admins already do by hand today. Any cruise through list archives reveals that admins have a lot of trouble figuring out which files to extract and what to do with them after they set up a prototype user the way they want. Even the strongest mind can be crushed by the GConf and tag team.

    Colin has been doing a ton of work to create GObject bindings for D-BUS; looking nice so far, see the list archives.

    I want to elaborate a bit on one aspect of "next generation rendering" that we haven't really worked on yet. Everyone is working on the ability to do OS X or Enlightenment style effects; essentially, enabling the window manager to use OpenGL and enabling the toolkit to use Cairo. This gives us drop shadows and minimize animations, and kills off a bunch of flicker/tearing artifacts. Very good stuff.

    However, it doesn't address one huge limitation: themes can only be designed piecemeal (button, scrollbar, etc.). Graphical elements can't span multiple widgets. An especially hard case to solve is that graphical elements can't cover both the window manager frame and inside the application window.

    To make the desktop look really nice, you want the ability to theme a window (or sub-component thereof) as a whole. This could mean graphics that span multiple widgets, it could mean moving widgets around, it could mean changing the spacing between widgets, etc.

    To address this, I believe we'd need to rework GTK+ a fair bit. I have a bunch of vague thoughts on how to do so.

    First, if you look at most widget implementations they effectively hardcode their layout and graphics in two places: the expose handler (painting the widget) and the events-that-have-coordinates (button/motion) handlers. So to allow more free-form theming of single widgets, an approach would be to have a set of GnomeCanvas-style primitives (lines, rectangles, etc.) and assemble widgets from those. Rather than hit-testing in the widget code, event handlers would be connected to "the rectangle" or "the line" and the theme could move around said rectangle or line.

    Second, you need to derive these drawing primitives and their layout from the theme rather than hardcoding them. The obvious approach here is something like libglade (resource files), where the theme provides or modifies the resources.

    There are some special "drawing primitives" we could support to handle some back compat cases. One primitive could be a "custom-rendered area" and would be the equivalent of an X window (or in web terms, an image map). A compositing manager treats an app window as this kind of primitive. GtkWidget could be wrapped in this kind of primitive.

    Another special primitive would be the equivalent of an input-only X window: an invisible event receiver. So e.g. a button could have one of these and the button code would refer to it. The theme would set the location and size of this thing. The point is to allow receiving events without hardcoding any visible graphics primitives. Alternative or additional approach: something like GnomeCanvasGroup. So the button itself would be a group object, and could say "a click anywhere on this group counts as a button press" (equivalent to saying "clicking any object the theme provides")

    Third, something I've often thought is that the need for a "canvas widget" comes from having a limited widget system in the first place. "Canvas items" are just widgets that are lightweight, don't have to be rectangular, have Z-order controls, etc. So if we say that we want to build widgets from drawing primitives, a logical extension is that widgets and drawing primitives are the same thing; and we can build widgets from other widgets in the same way we build them from drawing primitives. "Composite widgets" are a sort of wacky special-case in GTK+ today but all widgets become composite if you count lines and other primitives as widgets.

    Thus there's a pretty straightforward way to introduce a more powerful widget system into GTK+: a canvas widget. Think of the canvas widget specifically as a new widget system. Support placing an old-style GtkWidget on a canvas by treating it as a raster image. Make CanvasItem an interface, and a single GtkWidget could even implement both the old GtkWidget stuff and support the new features of an improved widget system. An unmodified GtkButton looks to the new canvas like an X Window, but when support for the new interfaces gets added to GtkButton the new canvas can see the lines and other sub-components inside the button and those things can be themed, etc.

    Fourth, Seth suggested an interesting idea which is to make resource files primary. In other words, to create a widget you first make a resource file (think of it as an HTML page) and then you specify some code to go with the resource file (think of JavaScript, though the idea is that you could also specify some C code). The widget "is" the collection of sub-widgets (remember that now lines and so forth are widgets also) specified by the resource file.

    In the resource file, some sub-widgets would be essential or mandatory, and others would really be a "default theme." For a button widget, it might be required that the resource file have an "input-only window" widget and a "text string" widget. The code for the button would refer to those to get events and display the button text, respectively. However, everything else in the resource file might be purely cosmetic (not used by the code). So for example there might be a beveled rectangle widget and themes could remove it or change its properties.

    You see where this is going: the theme is just an alternate resource file, or a resource file transformation. There are some tough complexities, because you want to bind the graphics in the theme to certain widget states or events. You can imagine doing this with full-blown scripting, but it may be possible to do it with some relatively simple approach. For example in the metacity theme file you have to specify the resources and their properties for each possible state. Another option would be some kind of extremely limited "scripting", maybe only allow relating attributes to each other like this:

     when button.STATE = PRESSED, bevel.STYLE = IN
    If you had attributes for the major widget states, widget visibility, etc. you could do a lot there. Add simple math as in metacity themes and you could do even more. So e.g.:
     line.X1 = button.X1 + 2
    These simple constructs may well be good enough to do all kinds of great themes.

    The important thing here is that entire application windows are themselves just widgets, and the layout of a window is just the default "theme" for that window. So say you have a control panel, you could recurse down into it:

     ControlPanel -> Frame -> Button -> Rectangle -> Line
    A GUI builder is a widget editor, which can edit everything from the lines inside a GtkButton, to the entire toplevel window. To do a new theme, graphic designers would just load up the original resource file in the GUI builder and start changing around the "inessential" aspects of the widget tree while leaving the "mandatory" widgets/attributes unmodified.

    Some of the more complex widgets essentially have to be primitives ("atoms") rather than composed. We know from long experience that a tree widget can't be defined as a bunch of tree item subwidgets and still perform adequately. However, some of the visuals (such as column headers) are GtkWidgets today and could be composed widgets in this new system.

    Fifth, and this is maybe true whether or not we do all this blue-sky stuff, the GTK+ layout system is showing its age. It's pretty unpleasant to use with Glade as it is, but if you start to think about changing the layout of a window in a theme for that window, it seems pretty clear that we can do better. In a next-generation widget system, the layout would almost always be in the "inessential" properties of a widget, rather than the "essential" properties. i.e. we would not expect the layout to be referenced from inside the code.

    Summarizing so far: the idea here is to define a widget as a primitive widget (such as a line or input-only region) or a recursive group of sub-widgets. To create a new app window, you just design a new widget in the GUI builder. The resulting widget tree has "essential" nodes and "inessential" nodes, where "inessential" nodes can be replaced by alternate "inessential" nodes. The inessential nodes are the "theme."

    Themes are suddenly able to do far more than they do today: 1) they can rearrange the internals of a button, because the basic layout isn't hardcoded in the expose or coordinate event handlers 2) they can rearrange buttons with respect to one another, because the widget containing the buttons is just another widget which is themeable as a whole. A control panel widget is to button widgets as button widgets are to line and rectangle widgets. And of course themes can insert new widgets (of the drawing primitive variety) anywhere in the widget tree.

    (I freely admit to handwaving a bunch of details here.)

    Sixth, we still have the problem that we can't have graphical elements that span the window manager frame and the client contents. A hugely hard solution is to somehow have a global widget tree (the widget tree for each app is visible to the compositing manager as a subtree of the WM frame). I think some simpler hack would turn out to be better, though in a resource-file-based widget system pushing the widgets to the display server could be fundamentally saner than it would be today. I'm not sure it would be saner, but it seems plausible that you could do some clever things.

    To make this seem less far-fetched, imagine that most widgets still had an X window associated with them; now imagine that some hints were set on those X windows about the kind of widget and how to render it; the compositing manager could then be aware of the entire global widget tree, and render graphical elements mixed in with the widgets inside an app.

    Anyway, that's what I've been thinking on this topic. To me this would be a really interesting line of thought to prototype in the context of a canvas widget. By doing a new widget system inside a canvas widget, you could let GTK+ provide all the basics and just worry about the new ideas. You could also allow apps to try out the new stuff in limited contexts without porting to a wacky new widget system.

    I know people will send me mail about HTML, XUL, and Longhorn and how they already do much of this - to answer the question, I don't disagree. There are several analogies I've had in my head here, including HTML/CSS/DOM; scene graphs (and 2D "scene graphs"); and GnomeCanvas.

    I tried sketching out what the "resource file" and code would contain for GtkButton and GtkEntry; it gets complicated fast and there are unquestionably some issues to think about. In the worst case these basic widgets would have to be relatively hardcoded: they could have numerous "essential" aspects and assumptions about the visual details in the code portion of the widgets. However, even if these basic widgets are largely hardcoded, their complexities look specific to basic widgets. Higher-level widgets such as entire application windows are a lot easier in some ways (especially if we avoid the container-widgets approach to layout).