<?xml version="1.0"?>
<rss version="2.0">
  <channel>
    <title>Advogato blog for wingo</title>
    <link>http://www.advogato.org/person/wingo/</link>
    <description>Advogato blog for wingo</description>
    <language>en-us</language>
    <generator>mod_virgule</generator>
    <pubDate>Wed, 8 Oct 2008 02:48:24 GMT</pubDate>
    <item>
      <pubDate>Fri, 26 Sep 2008 18:13:00 GMT</pubDate>
      <title>the economy, stupid</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=278</link>
      <guid>http://wingolog.org/archives/2008/09/26/the-economy-stupid</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;Modern finance tries as hard as it can to be obtuse, opaque, and unintelligible.&lt;/p&gt;&lt;p&gt;You can even hear this from establishment sources, as they cry out for "transparency in the markets". But still, without active government intervention, transparency is on the decline: nobody knows what is going on in the commodities market, in the securitized bonds market, even in the stock market. Speculators pump and dump. This is the "free market" tendency.&lt;/p&gt;&lt;p&gt;All of this seems to be irrational, an aberration from the "free market" ideals. (The quotations are to indicate that this is a marketing term, that liberty does not necessarily proceed from mercantile exchange.) This fact is a bit strange if you come from an orthodox economic training, such as that which is propagated in the newspapers or in Econ 201 classes across the US.&lt;/p&gt;&lt;p&gt;However, lack of transparency in economic discourse follows directly if you understand economics as a &lt;i&gt;struggle between class interests&lt;/i&gt;. It is simply that the explanation that fits best with the facts is too empowering to propagate. Broad understanding of the essentials is not to the advantage of the dominant class in society. Anyone caught discussing class is accused of being &lt;a href="http://findarticles.com/p/articles/mi_m1282/is_/ai_70433650" &gt;corrosive&lt;/a&gt; or &lt;a href="http://query.nytimes.com/gst/fullpage.html?res=940DE1D81F3CF935A15753C1A96E948260&amp;amp;sec=&amp;amp;spon=&amp;amp;pagewanted=1" &gt;divisive&lt;/a&gt;. You will not find "class" in 7th grade textbooks.&lt;/p&gt;&lt;p&gt;Simply put, a class-based understanding of economics and society has a higher explanatory, expressive, and predictive power than a "free market-based" ideology. Furthermore, it aligns with a moral imperative to abolish class itself.&lt;/p&gt;&lt;p&gt;To me, the moment in which this clicked for me was in college, when an old socialist teaching a sort of russian studies class mentioned that the socialists, the communists, and the anarchists &lt;i&gt;knew&lt;/i&gt; that World War I was coming, that they wrote about it, that it was an inevitable consequence of the expansion of finance capital (as opposed to land/agricultural or industrial capital). &lt;/p&gt;&lt;p&gt;When your primary interest is financial capital, you form part of the non-productive economy, of the &lt;a href="http://www.vroma.org/~bmcmanus/socialclass.html" &gt;equestrian class&lt;/a&gt;; and capital's imperative being to grow at all costs, you must choose where to invest (not &lt;i&gt;whether&lt;/i&gt; to invest). The highest profits have traditionally been found via exploitation (&lt;a href=" http://dictionary.reference.com/browse/exploitation" &gt;&lt;i&gt;use or utilization, esp. for profit&lt;/i&gt;&lt;/a&gt;) of the undeveloped world. Rubber from Africa, coffee from Latin America, tea from Asia -- not to mention petroleum.&lt;/p&gt;&lt;p&gt;As Eduardo Galeano notes, capital does not go to Latin America because Latin America is poor -- it goes because Latin America is rich, it goes to exploit, to bleed off the "excess value".&lt;/p&gt;&lt;p&gt;When two sugar-frenzied gunpowder-toting finance-laden World Powers happen to coincide -- well from there we have the detentes, the German &lt;a href="http://en.wikipedia.org/wiki/German_colonial_empire" &gt;South-West Africas&lt;/a&gt;, leading to war as an externalization of financial conflict. The losers, of course, are the ones on whose land the fight occurs -- the Hereros, the Balkans, the Iraqis (&lt;i&gt;our armies do not come into your cities and lands as conquerors or enemies, but as &lt;a href="http://www.informationclearinghouse.info/article6337.htm" &gt;liberators&lt;/a&gt;&lt;/i&gt;).&lt;/p&gt;&lt;p&gt;&lt;b&gt;a return&lt;/b&gt;&lt;/p&gt;&lt;p&gt;So, the wine from lunch led me a bit off track. My point is that all real revolutionary analysis and action has taken aim at, among other things, the financial system. Witness the &lt;a href="http://en.wikipedia.org/wiki/Populist_Party_(United_States)" &gt;Populists&lt;/a&gt; of the 1890s, which gave broad understanding of monetary policy to ordinary people, gave them tools with which to critique the machinations of the Morgans and the Chases. The Wobblies, the anarchists, even the reformers of the 30s knew this.&lt;/p&gt;&lt;p&gt;Now we are at a point where broad understanding of monetary policy is essential -- both understanding of the current situation, and knowing what our options are. There has been some excellent economic analysis in Z Magazine recently, in a series by Jack Rasmus.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://www.zcommunications.org/zmag/viewArticle/18717" &gt;Fannie Mae, Freddie Mac&lt;/a&gt; -- Phase two of financial crisis (Sept 08)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://www.zcommunications.org/zmag/viewArticle/17793" &gt;Emerging Epic Recession?&lt;/a&gt; (Jun 08)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://www.zcommunications.org/zmag/viewArticle/17055" &gt;From Financial Crisis to Recession, Part II&lt;/a&gt; -- Symptoms appear of a fundamental financial instability (Apr 08)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://www.zcommunications.org/zmag/viewArticle/16736" &gt;From Global Financial Crisis to Global Recession, Part I&lt;/a&gt; -- Precipitating the fall (Mar 08)&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I believe that first and the last articles are freely available, but the middle two need at least a free registration and possibly a subscription.&lt;/p&gt;&lt;p&gt;&lt;b&gt;subscribe already mkay&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Here's where I get on the stump: If you claim to be a radical, if you want to be a radical, you &lt;i&gt;must&lt;/i&gt; subscribe to radical media. It is completely necessary. Z Magazine, for example, is a great one. Its quality varies, but the high points are pretty high. (It took me some time to appreciate the cartoons.)&lt;/p&gt;&lt;p&gt;More importantly, such fora are crucial for getting out the word about important, constructive things happening on the left -- from Parecon to the IVAW Winter Soldier events, to fights for ecologically sustainable patterns of food, transport, and housing, to checking on what's going on in other facets of the movement -- GLBT rights, anti-racism, etc.&lt;/p&gt;&lt;p&gt;Radical media are a crucial point of bridge-building and solidarity between parts of the radical left. Without them, we are left feeling like we are on our own. So &lt;a href="https://www.zcommunications.org/zsustainers/signup" &gt;subscribe to Z&lt;/a&gt; already!&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Thu, 18 Sep 2008 23:07:05 GMT</pubDate>
      <title>breaking silence, innocuously</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=277</link>
      <guid>http://wingolog.org/archives/2008/09/18/breaking-silence-innocuously</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;Greeting, faerie webfolk.&lt;/p&gt;&lt;p&gt;I have a number of things in yon backlog, but as they build up, they stop up, so I figured with a bottle of wine behind me I could loose the gates on a topic: continuations.&lt;/p&gt;&lt;p&gt;Now, friends of mine: you may not be interested in this topic. If this is the case, treat this as the gristle: it is perhaps not tasty, but it comes with the meat.&lt;/p&gt;&lt;p&gt;But if the topic of call/cc and continuations interests you, you may treat this as the fat in &lt;a href="http://en.wikipedia.org/wiki/Pancetta" &gt;panceta&lt;/a&gt; (I do not agree with their spelling): delicious.&lt;/p&gt;&lt;p&gt;If you bristle at the double-dot: that's ok too.&lt;/p&gt;&lt;p&gt;My point when I started all of this was, Scheme weenies extol the benefits of &lt;tt&gt;call-with-current-continuation&lt;/tt&gt;. (Not until the most recent standard, the controversial &lt;a href="http://www.r6rs.org/" &gt;r6rs&lt;/a&gt;, did the establishment deign to accept the popular spelling, &lt;tt&gt;call/cc&lt;/tt&gt;. Such is the Scheme culture.) Weenies of other languages (Ruby, although Google denies me the references: searching while tipsy, the cop said) also relish in their esoteric delight.&lt;/p&gt;&lt;p&gt;But with all of the literature in the Scheme community about &lt;a href="http://library.readscheme.org/page6.html" &gt;continuations and compilation&lt;/a&gt;, with all the talk about continuation-based web platforms, it's still basically intractable.&lt;/p&gt;&lt;p&gt;The reasons are two, basically. One, you cannot represent all of the continuation of an operation; there is always a level beyond which you cannot represent. This is most basically evident in the state of the connection of the continuation-aware system to the outside world, for example as indicated in the file descriptor table in the kernel. &lt;/p&gt;&lt;p&gt;The second reason is that you almost always grab more information than you want, making call/cc a quite heavy-weight operation. The most brute-force method simply copies the entire C stack from the point of the call/cc on down to some root address, and reinstates on reinvocation -- yet you almost never touch the bottom stack frames in such a continuation. I think stack-copying is a perfectly valid implementation strategy for continuations, in many contexts, but not of the entire C stack down to arbitrary depth.&lt;/p&gt;&lt;p&gt;Now, &lt;i&gt;delimited&lt;/i&gt; continuations and prompts: &lt;i&gt;there&lt;/i&gt; is where the actual useful possibilities are. As always, &lt;a href="http://okmij.org/ftp/Computation/Continuations.html#context-OS" &gt;Oleg&lt;/a&gt; has lots to say on that, including a number of very interesting analogies to processes and operating systems.&lt;/p&gt;&lt;p&gt;I suppose it was Felleisen that first came up with the analogy, and I'm sure he was thinking of it in operating-system contexts -- the REPL is after all a boundary between an operating system and user-space. I'd link to his paper if the ACM weren't a pack of scrooge mcducks. (&lt;i&gt;The theory and practice of first-class prompts&lt;/i&gt;, if that's your thing.)&lt;/p&gt;&lt;p&gt;This post brought to you by Miguel Torres, S.A and the need to compile &lt;a href="http://git.savannah.gnu.org/gitweb/?p=guile.git;a=blob;f=ice-9/r4rs.scm;h=de2aeb2def52a53f0bcc0fcc45242b5ee55d5e39;hb=refs/heads/vm" &gt;r4rs.scm&lt;/a&gt;, about which more later.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Sat, 2 Aug 2008 14:11:37 GMT</pubDate>
      <title>on the many roads to perdition</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=276</link>
      <guid>http://wingolog.org/archives/2008/08/02/on-the-many-roads-to-perdition</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;&lt;b&gt;software failure modes&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Reflecting earlier today on some crappiness in a &lt;a href="http://home.gna.org/guile-lib/" &gt;software project I'm involved in&lt;/a&gt;, my brain started to enumerate the ways that free software projects can fail.&lt;/p&gt;&lt;p&gt;The maintainer can go &lt;a href="http://www.urbandictionary.com/define.php?term=awol" &gt;AWOL&lt;/a&gt;. The major culprits for this are babies, university thesis advisors, and Google.&lt;/p&gt;&lt;p&gt;This is pernicious in two ways: one, the person with the most knowledge about a project is no longer commenting on efforts by others to contribute. Patches go unreviewed, questions go unanswered.&lt;/p&gt;&lt;p&gt;Secondly, the maintainer is in a privileged position -- they typically have sole administrative access to the mailing list, the revision control system, and sometimes the web page. No one else can intervene to fix e.g. a spam problem on the list. But maintainers' privileged position extends to a kind of moral authority as well: "OK, she's been away for three months now... can I make a release without her permission?" The result is that in the meantime, the project's momentum decays, contributors spend their time elsewhere where they are more appreciated.&lt;/p&gt;&lt;p&gt;Even in the lack of a strange interstitial period of limbo, a maintainer's departure usually leads to the badness, as other less familiar, possibly less skilled contributors take control. As prudent as they might be, some bad patches probably slip in. The project enters a time of increasing entropy, of bitrot.&lt;/p&gt;&lt;p&gt;In addition, you have failure modes that have nothing to do with people involved in the project. API changes in a core system library can bitrot reams of dependent code in one commit. It's not enough for the old libraries to be available on the intertubes, they have to be installable on a contemporary computer. Your language specification or runtime could change. And of course those core libraries have dependencies as well: glibc versions, kernel syscalls, not to mention the ever-changing soup of hardware interfaces.&lt;/p&gt;&lt;p&gt;Ultimately behind those changes you will find human desires, "market forces", and even such things as global warming.&lt;/p&gt;&lt;p&gt;Any other failure modes come to mind? Follow on in yon comment bucket!&lt;/p&gt;&lt;p&gt;(To be clear, I'm not saying that guile-lib failed, but the mailing list situation is pretty terrible.)&lt;/p&gt;&lt;p&gt;&lt;b&gt;summertime&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Beaches, bars, and outdoor cinema. Quiet afternoons on the terrace, poking around the house, the neighborhood, a bit hobbitlike.&lt;/p&gt;&lt;p&gt;I'm about to head off travelling in August -- in Seattle for the week of the 11th, down to Portland OR for a few days, overnight train to San Fran, for a few days, then down to LA for the 27th, and back home to BCN on the 5th or so. Amtrak ho!&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Thu, 31 Jul 2008 15:12:42 GMT</pubDate>
      <title>introducing griddy</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=275</link>
      <guid>http://wingolog.org/archives/2008/07/31/introducing-griddy</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;&lt;center&gt;&lt;a href="http://wingolog.org/pub/griddy.ogg" &gt;&lt;img width="320" src="http://wingolog.org/pub/griddy-repl-thumbnail.png" height="192"/&gt;&lt;/a&gt;&lt;br/&gt;&lt;i&gt;5m50s, 2.5 MB, Theora&lt;/i&gt;&lt;/center&gt;&lt;/p&gt;&lt;p&gt;The linked video shows my hackbaby of the last couple months, a hackable 3D compositing window manager written in Scheme. It's not much code, but it's rather fun. I'm still not dogfooding with it yet -- you can see a pause around minute 4:30 or so where I have to unstick keys that Xephyr thinks are pressed.&lt;/p&gt;&lt;p&gt;And it's still a bit hard to compile, because you need bzr guile-gnome, and the latest guile-clutter release, and a guile 1.8 compiled as --with-threads if you want the emacs integration. But if you want to join in on the fun, or read some interesting code, check:&lt;/p&gt;&lt;pre&gt;
bzr branch http://wingolog.org/bzr/griddy
&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Sat, 26 Jul 2008 22:09:10 GMT</pubDate>
      <title>so you want to build a compositor</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=274</link>
      <guid>http://wingolog.org/archives/2008/07/26/so-you-want-to-build-a-compositor</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;&lt;b&gt;a dialog with someone i don't know&lt;/b&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; One way to think about it is that it's like driving a car down the road, and suddenly swapping the steering wheel and brakes out for a tiller and gear shifter. And having to downshift for braking until you learn that the brakes moved to the turn indicator lever. By trial and error. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;That's the internet's Joey Hess, a wonderful writer, &lt;a href="http://joey.kitenet.net/blog/entry/awesome/" &gt;who recently switched window managers&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A while back I &lt;a href="http://wingolog.org/archives/2008/06/10/regarding-decadence" &gt;discussed some new interaction possibilities&lt;/a&gt;, and a lot of them hinged on the relation between people and the set of tasks that they do on the computer -- not just the tasks themselves, but the relationships between the tasks, and with focus.&lt;/p&gt;&lt;p&gt;In the free desktop, the locus of this experience is in the window manager. Again, Joey tries to give analogies:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; Another way to look at it is adopting a new philosophy. Or, in some cases a cult. (In some cases, with crazy cult leaders.) Whether they use Windows or a Mac, or Linux, most computer users are members of a big established religion, with some implicit assumptions, like "thy windows shall be overlapping, like papers on the desktop, and thou shalt move them with thy mouse". &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The obvious step if you want to &lt;a href="http://www.apostasia.es/" &gt;apostatize&lt;/a&gt; yourself from the "desktop metaphor", then, is to start hacking window managers. That's how I spent my hack-time in the last month and a half; this writing is an attempt at exegesis.&lt;/p&gt;&lt;p&gt;&lt;b&gt;descent from the mountain, source in hand&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I wanted to make a 3D compositing window manager. By 3D, I mean that I wanted the pixels behind the monitor glass to come entirely from one process' OpenGL. By "compositing", I mean that the graphical output from other programs should be redirected through my program. (&lt;a href="http://en.wikipedia.org/wiki/Compositing_window_manager" &gt;Compositors&lt;/a&gt; don't necessarily need to be implemented with OpenGL; xcompmgr and metacity's compositor are implemented with XRender.)&lt;/p&gt;&lt;p&gt;As an implementation strategy, I took this opportunity to check out &lt;a href="http://clutter-project.org/" &gt;Clutter&lt;/a&gt;, a GL-based canvas library. What follows is a minimal translation into C of the basic concepts, a broken but fun-to-hack substrate for experimentation.&lt;/p&gt;&lt;pre&gt;
int main (int argc, char *argv[])
{
    prep_clutter (&amp;amp;argc, &amp;amp;argv);
    prep_root ();
    prep_overlay ();
    prep_stage ();
    prep_input ();

    g_main_loop_run (g_main_loop_new (NULL, FALSE));

    return 0;
}
&lt;/pre&gt;&lt;p&gt;The main function is pretty simple. We'll be looking at the various functions one by one, but out of order. Let's start with &lt;tt&gt;prep_root&lt;/tt&gt;:&lt;/p&gt;&lt;pre&gt;
Display *dpy;
Window root;
void prep_root (void)
{
    dpy = clutter_x11_get_default_display ();
    root = DefaultRootWindow (dpy);

    XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic);
    XSelectInput (dpy, root, SubstructureNotifyMask);
}
&lt;/pre&gt;&lt;p&gt;This function does two things of interest: first, it tells the X server to redirect output of all windows into backing pixmaps, such that the contents of all mapped windows are available, even if the X server does not think that they are visible. Second, we ask the X server to give us notification when windows come and go, and when they change size.&lt;/p&gt;&lt;pre&gt;
Window overlay;
void prep_overlay (void)
{
    overlay = XCompositeGetOverlayWindow (dpy, root);
    allow_input_passthrough (overlay);
}
&lt;/pre&gt;&lt;p&gt;The Composite extension, which allows us to redirect window output, also provides for the existence of an "overlay" window, one that is above all other windows. You can draw directly to the overlay window, but the normal way that you use it is as a parent window -- you create your own window, then reparent it to the overlay.&lt;/p&gt;&lt;p&gt;Composite is pretty cool, except that it is only for output -- that is, you can put the output of a window anywhere, like on the corner of a &lt;a href="http://en.wikipedia.org/wiki/Compiz" &gt;Compiz&lt;/a&gt; cube, but you can't redirect input. By that I mean to say that when you have a rotated compiz cube, you can't interact with the window.&lt;/p&gt;&lt;p&gt;The reason for this is that in order to interact with a window, for example to click a button in it, the X server needs to know how to map the pointer position to a position inside a certain window. &lt;a href="http://lists.freedesktop.org/archives/xorg/2007-February/021515.html" &gt;This is a tricky problem&lt;/a&gt; which needs to be done inside the X server, and no solution to this problem has been merged yet.&lt;/p&gt;&lt;p&gt;This upshot is that what happens today with compositing window managers is that the compositor is very careful to make sure that the underlying X window is exactly positioned behind where the compositor is drawing it. Then, when the user clicks on what essentially is the &lt;i&gt;redirected image&lt;/i&gt; of the button, the click actually falls behind the overlay to the actual X window.&lt;/p&gt;&lt;p&gt;Hence, the need to allow events (clicks, pointer motion, etc) to pass through the overlay:&lt;/p&gt;&lt;pre&gt;
void allow_input_passthrough (Window w)
{
    XserverRegion region = XFixesCreateRegion (dpy, NULL, 0);
 
    XFixesSetWindowShapeRegion (dpy, w, ShapeBounding, 0, 0, 0);
    XFixesSetWindowShapeRegion (dpy, w, ShapeInput, 0, 0, region);

    XFixesDestroyRegion (dpy, region);
}
&lt;/pre&gt;&lt;p&gt;Basically we call a few undocumented functions, whose goal is to tell the X server that the window in question is not to receive pointer input events.&lt;/p&gt;&lt;pre&gt;
ClutterActor *stage;
Window stage_win;
void prep_stage (void)
{
    ClutterColor color;

    stage = clutter_stage_get_default ();
    clutter_stage_fullscreen (CLUTTER_STAGE (stage));
    stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
    clutter_color_parse ("DarkSlateGrey", &amp;amp;color);
    clutter_stage_set_color (CLUTTER_STAGE (stage), &amp;amp;color);
    
    XReparentWindow (dpy, stage_win, overlay, 0, 0);
    XSelectInput (dpy, stage_win, ExposureMask);
    allow_input_passthrough (stage_win);
    
    clutter_actor_show_all (stage);
}
&lt;/pre&gt;&lt;p&gt;The next step is to create the clutter "stage", the GLX window to which all of our output will go. We reparent the stage to the overlay, so that it will always be on top, then we allow input events to pass through it as well.&lt;/p&gt;&lt;pre&gt;
Window input;
void prep_input (void)
{
    XWindowAttributes attr;

    XGetWindowAttributes (dpy, root, &amp;amp;attr);
    input = XCreateWindow (dpy, root,
                           0, 0,  /* x, y */
                           attr.width, attr.height,
                           0, 0, /* border width, depth */
                           InputOnly, DefaultVisual (dpy, 0), 0, NULL);
    XSelectInput (dpy, input,
                  StructureNotifyMask | FocusChangeMask | PointerMotionMask
                  | KeyPressMask | KeyReleaseMask | ButtonPressMask
                  | ButtonReleaseMask | PropertyChangeMask);
    XMapWindow (dpy, input);
    XSetInputFocus (dpy, input, RevertToPointerRoot, CurrentTime);

    attach_event_source ();
}
&lt;/pre&gt;&lt;p&gt;So if the events fall through the stage, and fall through the overlay, what happens if they don't fall onto a window? Well, you probably want the stage to get the last crack at them, instead of the root window. So hence this terrible trick, making a separate fullscreen input-only window, located below all windows except the root window. We select for all input on this window, so that we get e.g. key presses as well.&lt;/p&gt;&lt;p&gt;Then we install a &lt;a href="http://library.gnome.org/devel/glib/unstable/glib-The-Main-Event-Loop.html#GSource" &gt;GSource&lt;/a&gt; to process pending X events, redirecting events from the input window to the stage window:&lt;/p&gt;&lt;pre&gt;
GPollFD event_poll_fd;
static GSourceFuncs event_funcs = {
    event_prepare,
    event_check,
    event_dispatch,
    NULL
};
void attach_event_source (void)
{
    GSource *source;

    source = g_source_new (&amp;amp;event_funcs, sizeof (GSource));

    event_poll_fd.fd = ConnectionNumber (dpy);
    event_poll_fd.events = G_IO_IN;

    g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
    g_source_add_poll (source, &amp;amp;event_poll_fd);
    g_source_set_can_recurse (source, TRUE);
    g_source_attach (source, NULL);
}
&lt;/pre&gt;&lt;p&gt;The &lt;tt&gt;prepare()&lt;/tt&gt; and &lt;tt&gt;check()&lt;/tt&gt; functions are a bit boring, but the &lt;tt&gt;dispatch()&lt;/tt&gt; is worth a look:&lt;/p&gt;&lt;pre&gt;
static gboolean
event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
{
    ClutterEvent *event;
    XEvent xevent;

    clutter_threads_enter ();

    while (!clutter_events_pending () &amp;amp;&amp;amp; XPending (dpy)) {
        XNextEvent (dpy, &amp;amp;xevent);
        
        /* here the trickiness */
        if (xevent.xany.window == input) {
            xevent.xany.window = stage_win;
        }

        clutter_x11_handle_event (&amp;amp;xevent);
    }
    
    if ((event = clutter_event_get ())) {
        clutter_do_event (event);
        clutter_event_free (event);
    }

    clutter_threads_leave ();

    return TRUE;
}
&lt;/pre&gt;&lt;p&gt;We just pick off events, translating the input to the stage window, then give the events to clutter.&lt;/p&gt;&lt;p&gt;Obviously this is a crapload of code just to shunt events around; normally with clutter this is not necessary, but with the X compositing architecture being like it is, we have to roll our own GSource to do the event translation.&lt;/p&gt;&lt;p&gt;This brings me back to the beginning, &lt;tt&gt;prep_clutter&lt;/tt&gt;:&lt;/p&gt;&lt;pre&gt;
GType texture_pixmap_type;
void prep_clutter (int *argc, char ***argv)
{
    clutter_x11_disable_event_retrieval ();
    clutter_init (argc, argv);
    clutter_x11_add_filter (event_filter, NULL);
    
    if (getenv ("NO_TFP"))
        texture_pixmap_type = CLUTTER_X11_TYPE_TEXTURE_PIXMAP;
    else
        texture_pixmap_type = CLUTTER_GLX_TYPE_TEXTURE_PIXMAP;
}
&lt;/pre&gt;&lt;p&gt;Here we see that you have to turn off event retrieval before calling &lt;tt&gt;clutter_init&lt;/tt&gt;. Then, we tell Clutter to call a &lt;tt&gt;event_filter&lt;/tt&gt; whenever it gets an X event. I'll get back to that function in a minute.&lt;/p&gt;&lt;p&gt;I suppose that this is as good a time as any to speak of getting window contents into OpenGL. The basic idea is that since we're already storing all of the window's pixels into a backing pixmap (because we are redirecting all output), we don't actually need to transfer the pixels back over the wire to the compositor to have the compositor show the window on the screen. There is a GLX extension, &lt;a href="http://www.opengl.org/registry/specs/EXT/texture_from_pixmap.txt" &gt;texture from pixmap&lt;/a&gt; or TFP, which tells the libGL implementation to get a texture's contents from a pixmap that it already knows about, automatically updating when the pixmap updates.&lt;/p&gt;&lt;p&gt;I digress for a moment to mention something that I did not know when I was getting into all of this. There are two kinds of GLX rendering, direct and indirect. Perhaps you recall these words from running &lt;tt&gt;glxinfo&lt;/tt&gt; to see whether your GL implementation has hardware acceleration or not. In fact, direct vs. indirect exists on a different axis as accelerated vs. software rendering. What "indirect rendering" means is that instead of talking directly to the graphics card through the kernel, a GL application is sending all of its commands over the wire to the X server, which then does the rendering.&lt;/p&gt;&lt;p&gt;But that server-side rendering may be accelerated; indeed, that was the whole point of &lt;a href="http://en.wikipedia.org/wiki/AIGLX" &gt;AIGLX&lt;/a&gt;. Technically, with free drivers, this is implemented via having the server's GLX rendering use the same DRI library as libGL does when doing direct rendering. It is the DRI library which does the accelerated communication with the hardware-specific kernel module (the DRM module).&lt;/p&gt;&lt;p&gt;Indirect rendering is slower, however, and it is advantageous to use direct rendering when possible. The problem comes when wanting to use TFP and direct rendering; if I want to bind a GL texture to a pixmap corresponding to some other application, and I am not going to go through the X server to do so, then obviously the &lt;i&gt;kernel itself&lt;/i&gt; has to know about X drawables. If I have a named pixmap open from one process that was created from another process, there needs to be a unified memory manager in the kernel:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; It's a crude approximation but the most crucial difference between the nvidia architecture and DRI/DRM is that nvidia actually have a memory manager - and a unified one at that. Without a memory manager it's impossible to allocate offscreen buffers (hence, no pbuffers or fbos) and without a unified memory manager it's impossible to reconcile 2D and 3D operations (hence no redirected Direct Rendering). The Accelerated Indirect GLX feature that the freetards were busy raving about is an endless source of confusion - and ultimately a hack to workaround their lack of a memory manager. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;(That from &lt;a href="http://linuxhaters.blogspot.com/2008/06/nitty-gritty-shit-on-open-source.html" &gt;Linux hater&lt;/a&gt;, someone I have warmed to in recent weeks -- I basically agree with &lt;a href="http://blogs.zdnet.com/BTL/?p=9370" &gt;Jeremy Allison's position&lt;/a&gt;.)&lt;/p&gt;&lt;p&gt;Anyway. You can't do direct TFP with free drivers, is the conclusion of that digression. That's OK, because you can always force indirect rendering via setting &lt;tt&gt;LIBGL_ALWAYS_INDIRECT=1&lt;/tt&gt; in your environment. But you can't do &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=16559" &gt;indirect rendering in Xephyr&lt;/a&gt;, only direct, so it's tough to test out window managers. Fortunately, you can get window contents into clutter without TFP, using the fallbacks -- hence the &lt;tt&gt;NO_TFP&lt;/tt&gt; check in &lt;tt&gt;prep_clutter&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;#xE1;nimo, peregrino&lt;/b&gt;&lt;/p&gt;&lt;p&gt;OK, at this point we're almost there. Here's the event handler:&lt;/p&gt;&lt;pre&gt;
static ClutterX11FilterReturn
event_filter (XEvent *ev, ClutterEvent *cev, gpointer unused)
{
    switch (ev-&amp;gt;type) {
    case CreateNotify:
        window_created (ev-&amp;gt;xcreatewindow.window);
        return CLUTTER_X11_FILTER_REMOVE;

    default:
        return CLUTTER_X11_FILTER_CONTINUE;
    }
}
&lt;/pre&gt;&lt;p&gt;It's pretty simple, an X event is a tagged union. We respond to the CreateNotify events, which come because we selected for SubstructureNotifyMask on the root window. It turns out we don't need any more events, because clutter handles the rest:&lt;/p&gt;&lt;pre&gt;
static void
window_created (Window w)
{
    XWindowAttributes attr;    
    ClutterActor *tex;

    if (w == overlay)
        return;

    XGetWindowAttributes (dpy, w, &amp;amp;attr);
    if (attr.class == InputOnly)
        return;
    
    tex = g_object_new (texture_pixmap_type, "window", w,
                        "automatic-updates", TRUE, NULL);

    g_signal_connect (tex, "notify::mapped",
                      G_CALLBACK (window_mapped_changed), NULL);
    g_signal_connect (tex, "notify::window-x",
                      G_CALLBACK (window_position_changed), NULL);
    g_signal_connect (tex, "notify::window-y",
                      G_CALLBACK (window_position_changed), NULL);

    {
        gint mapped, destroyed;
        g_object_get (tex, "mapped", &amp;amp;mapped, NULL);
        if (mapped)
            window_mapped_changed (tex, NULL, NULL);
    }
}
&lt;/pre&gt;&lt;p&gt;Once we create the window, Clutter will listen for changes in its state -- resizes, maps or unmaps, and ultimately its destruction. (Or at least it will, once &lt;a href="http://bugzilla.o-hand.com/show_bug.cgi?id=1020" &gt;#1020&lt;/a&gt; is applied.) Here we connect with the minimum bits necessary to make a window usable. Finally, the functions to show, hide, and resize windows:&lt;/p&gt;&lt;pre&gt;
static void
window_position_changed (ClutterActor *tex, GParamSpec *pspec, gpointer unused)
{
    gint x, y, window_x, window_y;
    g_object_get (tex, "x", &amp;amp;x, "y", &amp;amp;y, "window-x", &amp;amp;window_x,
                  "window-y", &amp;amp;window_y, NULL);
    if (x != window_x || y != window_y)
        clutter_actor_set_position (tex, window_x, window_y);
}

static void
window_mapped_changed (ClutterActor *tex, GParamSpec *pspec, gpointer unused)
{
    gint mapped;
    g_object_get (tex, "mapped", &amp;amp;mapped, NULL);

    if (mapped){
        clutter_container_add_actor (CLUTTER_CONTAINER (stage), tex);
        clutter_actor_show (tex);
        window_position_changed (tex, NULL, NULL);
    } else {
        clutter_container_remove_actor (CLUTTER_CONTAINER (stage), tex);
    }
}
&lt;/pre&gt;&lt;p&gt;&lt;b&gt;final notes&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Code is &lt;a href="http://wingolog.org/pub/mini-clutter-wm.c" &gt;here&lt;/a&gt;, compile as:&lt;/p&gt;&lt;pre&gt;
 gcc `pkg-config --cflags --libs clutter-glx-0.8` \
     -o mini-clutter-wm mini-clutter-wm.c 
&lt;/pre&gt;&lt;p&gt;You might want to run it in a Xephyr; do it with the script &lt;a href="http://wingolog.org/pub/run-xephyr" &gt;here&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;
 ./run-xephyr ./mini-clutter-wm
&lt;/pre&gt;&lt;p&gt;Joey again:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; So ideally, "I switched to a new window manager" doesh't mean "my screen has some different widgets on it now". It means "I'm looking at the screen with new eyes." &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This blog is already way too long, so I'll revisit interface concepts at some point in the future. For now I just wanted to pull together this knowledge in one place. Happy hacking!&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Tue, 22 Jul 2008 23:07:20 GMT</pubDate>
      <title>equanimity</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=273</link>
      <guid>http://wingolog.org/archives/2008/07/22/equanimity</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;&lt;b&gt;word&lt;/b&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;  Equanimous \E*quan"i*mous\, a.&lt;br/&gt;  [L. aequanimus, fr. aequus equal + animus mind.]&lt;/p&gt;&lt;p&gt;  Of an even, composed frame of mind; of a steady temper; not easily elated or depressed.&lt;br/&gt;  [1913 Webster]&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Delightful. Makes me think of &lt;a href="http://medialens.org/cogitations/080216_non_violence_and.php" &gt;Medialens folk&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;b&gt;words&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I have a new favorite orator: &lt;a href="http://en.wikipedia.org/wiki/Michael_Parenti" &gt;Michael Parenti&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A brief search on the interwebs will only find you &lt;a href="http://www.michaelparenti.org/" &gt;his web site&lt;/a&gt;, which is a bit off-putting, and doesn't really show to his strengths. But take a listen to &lt;a href="http://mbanna.radio4all.net/pub/archive2/MP3/parenti-land_of_idols.mp3" &gt;Land of Idols&lt;/a&gt; (40 minutes), then check out the other talks in &lt;a href="http://mbanna.radio4all.net/pub/archive2/MP3/" &gt;that same directory&lt;/a&gt; (search for "parenti").&lt;/p&gt;&lt;p&gt;&lt;b&gt;wheels&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Set off on what must have been a &lt;a href="http://www.gmap-pedometer.com/?r=2078065" &gt;100 km loop&lt;/a&gt; last Sunday on the bike, after coming back from GUADEC; Google thinks the distance was significantly less. Perhaps I should report a bug?&lt;/p&gt;&lt;p&gt;Meanwhile at home, &lt;a href="http://wingolog.org/archives/2007/06/27/mixed-nuts" &gt;yet&lt;/a&gt; &lt;a href="http://wingolog.org/archives/2006/08/21/sittin-in-a-park-in-paris-france" &gt;another&lt;/a&gt; broken spoke.&lt;/p&gt;&lt;p&gt;&lt;b&gt;sense&lt;/b&gt;&lt;/p&gt;&lt;p&gt;It was so quiet walking home this evening that even smelling the street odors made me feel like I was eavesdropping.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Fri, 11 Jul 2008 14:09:03 GMT</pubDate>
      <title>guile ? clutter ? quoi ?</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=272</link>
      <guid>http://wingolog.org/archives/2008/07/11/guile-clutter-quoi-</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;Well, given that I have not figured out how to traverse the great firewall of Bah&amp;#xE7;e&amp;#x15F;ehir for SMTP+TLS, or, that is, no mail sending... may I claim "first post" for language bindings for Clutter 0.8!&lt;/p&gt;&lt;p&gt;Guile-Clutter 0.8 is out! Download it here: &lt;a href="http://ftp.gnu.org/pub/gnu/guile-gnome/guile-clutter/guile-clutter-0.8.0.tar.gz" &gt;ftp.gnu.org/pub/gnu/guile-gnome/blah/dee/blah/dee/blah&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Or check the &lt;a href="http://www.gnu.org/software/guile-gnome/docs/clutter-glx/html/" &gt;fledgling&lt;/a&gt;, &lt;a href="http://www.gnu.org/software/guile-gnome/docs/clutter/html/" &gt;love-needing docs&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Hack hack hack hack hack&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Thu, 10 Jul 2008 15:09:34 GMT</pubDate>
      <title>how to choose between equivalent options</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=271</link>
      <guid>http://wingolog.org/archives/2008/07/10/how-to-choose-between-equivalent-options</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;All the time we are presented with options. Should I get my vegetables from the greengrocer's, the supermarket, or the farmer's market? Should I buy a PC or a Mac? Should I start my new project in Ruby or C#? All of these options are equivalent: they're just vegetables, they're just computers, they're just languages. So how to choose?&lt;/p&gt;&lt;p&gt;Some people make choices on technical grounds: for example, "I'm going to buy a Mac because it has a video editor." This is rational, but its rationality degrades over time. The next time you go to buy a computer, you just buy a Mac because it's what you got last time.&lt;/p&gt;&lt;p&gt;To take another example that Robert Collins mentioned on Monday, if you choose bzr over subversion because bzr does merges, what happens in a few months when subversion finally gets merge support? So you make your decision for a reason that turns out not to mean anything. If people go massively for git because of git's workflow and in-place branching, you can be sure that bzr will get the same workflow in the future, and in fact has some of it now.&lt;/p&gt;&lt;p&gt;What I would suggest is that we should make choices &lt;i&gt;not&lt;/i&gt; on strictly technical bounds. Instead we should make a choice based on &lt;i&gt;culture&lt;/i&gt;. When you choose something to be a part of your future, it affects your culture, the world around you. You invite a tool, a set of people, a set of social relations into your life and into your future.&lt;/p&gt;&lt;p&gt;Technical considerations form a part of culture. Anyone who knows something about Silverlight and Mozilla knows that the technical differences in the projects reflect different values. These values translate into different futures: a world where technology flows from Microsoft, out to the world, or a world in which hackers collaborate in the open to shape their own destiny, our own destiny.&lt;/p&gt;&lt;p&gt;It is especially important &lt;i&gt;not&lt;/i&gt; to make decisions about perceived market share, perceived uptake, or the like. For one, these perceptions are easily manipulated. This is the task of the propaganda industry, euphemistically referred to as "public relations". For another, when we choose to invite e.g. GNU into our lives, we &lt;i&gt;affect&lt;/i&gt; the future, and especially that part of the future that is in our immediate surroundings.&lt;/p&gt;&lt;p&gt;So in conclusion, and for the GNOME audience, we as hackers build the structures that we are going to live in for a long time. When we make decisions about technology, we begin relationships with people, and to some degree take their values on as our own. We should make sure that we recognize this, and that the values of the technologies we choose mesh with our own, as individuals and as a community.&lt;/p&gt;&lt;p&gt;(For another take on "what makes us the same are not technical similarities, but cultural similarities", and especially in relation to a possible GUADEC / aKademy joint event, see &lt;a href="http://www.nhplace.com/kent/PS/Lambda.html" &gt;Lambda, the ultimate political party&lt;/a&gt;.)&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Wed, 9 Jul 2008 12:11:11 GMT</pubDate>
      <title>notes from the bosphorus</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=270</link>
      <guid>http://wingolog.org/archives/2008/07/09/notes-from-the-bosphorus</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;My camera broke; I have only words.&lt;/p&gt;&lt;p&gt;&lt;b&gt;the golden horn&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Istanbul is a town full of wonder. And wander: around the cobbled streets of the old town, in the morning, in the evening, alive at all hours.&lt;/p&gt;&lt;p&gt;Last night I shared a water-pipe under the bridge, looking back on the night silhouette of the old town, smoke rings dissipating over the water. As we were walking back to the hostel some hours later, &lt;a href="http://dimitris.glezos.com/weblog/" &gt;Dimitris&lt;/a&gt; noted the waft of baking bread, the start of a new day.&lt;/p&gt;&lt;p&gt;I stepped out on Sunday morning to the GStreamer mini-summit, but was waylaid by the Blue Mosque. Outside it is grey, hard stone and spired; inside it is lush and tactile, the carpet creeping up between your toes. I believe that space can have rhythm. In that place there was a rich visual soundscape, tiled motifs repeating on the macro level, fractally recursing into micro-vegetation, a symphony of space and lines. I stumbled out into the blue sky.&lt;/p&gt;&lt;p&gt;&lt;b&gt;gstreamer, breakage&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The GStreamer summit was pretty good. We decided to switch to git (from CVS), once some issues are ironed out regarding history and our "common" submodule. We also decided that at some point we should do a new development cycle, but that we needed reasons for doing so; the idea would be to develop a number of features that cannot be done with 0.10 in experimental branches, and once there are enough branches, we pull them together in a quick 0.11 and from there to 0.12 or 1.0. This would be a process that could take a year or two.&lt;/p&gt;&lt;p&gt;In that regard, some interesting points were brought up regarding GLib and GTK+'s plan to break ABI for version 3. The problem is that any library that depends on GLib will break ABI as well, and that includes GStreamer. So given that we will need to break ABI to depend on GLib 3, that gives us a good timetable for a next development series, corresponding to GLib 3's release in about 16 months. I suspect that many projects will want to do the same.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
    <item>
      <pubDate>Thu, 3 Jul 2008 18:07:34 GMT</pubDate>
      <title>stable guile-gnome released</title>
      <link>http://www.advogato.org/person/wingo/diary.html?start=269</link>
      <guid>http://wingolog.org/archives/2008/07/03/stable-guile-gnome-released</guid>
      <description>&lt;content type="xhtml"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div&gt;&lt;p&gt;Hackers, slackers, countrymen and countrywomen:&lt;/p&gt;&lt;p&gt;Guile-Gnome-Platform, that beast of the dual hyphen, has finally reached stability. You might say that the API and the ABI are as stable as the hills, but we like to put it like this: "Write once, run anywhen"&lt;/p&gt;&lt;p&gt;(Amused tittering)&lt;/p&gt;&lt;p&gt;From the &lt;a href="http://article.gmane.org/gmane.lisp.guile.gtk/788" &gt;release notes&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;There are several things that are the awesome about this code:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;It's fully integrated!&lt;br/&gt;Instances of GObject are objects in Scheme; you can query their properties, class hierarchies, etc at runtime. You can derive new types yourself, with signals, properties, and the like. Good stuff!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It's fully documented!&lt;br/&gt;Start with the &lt;a href="http://www.gnu.org/software/guile-gnome/docs/gobject/html/gnome-gobject.html" &gt;tutorial/reference docs for the core GObject wrapper&lt;/a&gt;, then      &lt;a href="http://www.gnu.org/software/guile-gnome/docs/" &gt;branch out into individual modules&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Fully extensible!&lt;br/&gt;Guile-Gnome-Platform also provides a good base off of which to bind other libraries based on GLib. For example, Guile-Clutter binds almost all of the new Clutter library, with documentation, and most of that work was done in a day.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Stable!&lt;br/&gt;Write once, run anywhen! Guile-Gnome's API and ABI will never be changed incompatibly.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Scheme!&lt;br/&gt;You will be assimilated, or alternately, gnawed to death by fingernail clippings.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;More info &lt;a href="http://www.gnu.org/software/guile-gnome/" &gt;at the homepage&lt;/a&gt;. &lt;i&gt;DANGER CAPTAIN: ASSIMILATION IMMINENT&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/content&gt;</description>
    </item>
  </channel>
</rss>
