The Rake’s Song

today is my last day here, at Intel.

it’s been an honour and a privilege working with one of the best teams in one of the best companies in the world. as I leave behind people that humbled me and made me a better engineer, I cannot but feel a bit sad; still, all good things must come to an end — and I’m sure that the good things done will, in time, temper the bad things that happened during these nearly four years.

what will happen on Monday, I’ll leave for a latter blog post — but suffice it to say that I’m going to stick around the free and open source software community at large (and GNOME in particular) for a while longer.

I know what your question will be: what happens to Clutter’s maintainership? well, if the demise of Moblin and MeeGo, and the rise of Tizen, haven’t killed Clutter I suppose nothing short of an asteroid impact will. so if you were already planning to open the champagne bottle and celebrate me stepping down from my self-appointed position of Clutter (almost) benevolent dictator, I’m afraid you’ll have to postpone the party for a long while.

I also want to thank all the people that voted for me, as well as the other candidates in the GNOME Foundation elections for the Board of Directors.

finally, see you all at GUADEC 2012:

GUADEC 2012 Badge

where I’ll give a talk about Clutter 2.0 and GTK+ 4.0.

We Heaved Relief as Scores of Innocents Died

after all the changes in this series of blogs, and all the big changes I tried to introduce in them, this is mostly a coda — one in which I just want to mention a couple of new features that don’t fall in the previous apocalypses but that I think are interesting nonetheless.

ClutterTimeline and ClutterAlpha

the timeline class gained a new property, repeat-count which replaces the venerable loop one; whilst loop would just make the timeline loop indefinitely (until forcibly stopped), repeat-count allows you to set a ceiling to the number of repeats.

another change in the Timeline class is the introduction of the progress-mode property, which allows you to control how the progress property is computed. this effectively deprecates ClutterAlpha, even if the class itself hasn’t been marked for deprecation (as we still need it for other API).

these two changes hopefully will make using ClutterTimeline a better experience, and remove some custom code.

Support localizable strings in ClutterScript

if you currently define UI elements in ClutterScript you’ll notice that all the strings are not translatable; this is clearly sub-optimal, and prevents people from actually writing proper applications using this format, just like they do with GtkBuilder.

I recently added the ability to describe translatable strings inside the JSON format, using a syntax like:


  {
    ...
    "a-label-property" : {
      "translatable" : true,
      "string" : "A Translatable String",
      "context" : "Some Context",
      "domain" : "Gettext-Domain"
    },
    ...
  }

the domain and context members are optional, and allow you to specify a gettext domain and context for a specific string; you can assign a domain to the ClutterScript instance, using clutter_script_set_translation_domain(), or use the Gettext domain specified by the application itself upon initialization with bindtextdomain().

obviously, this is just a step: the real support for localization can only come after intltool is updated to handle the JSON format used by ClutterScript, to extract the translatable strings and place them into the POT file; this is planned, but it’s not ready yet.

see you in 6 months!

well, I hope you enjoyed this series of blog posts; oh, more accurately: I hope you haven’t been bored to death by it.

what will happen in six months is, very likely, a 1.12 release of Clutter, with a couple of other Apocalypses landing (a way to animate layout management by using the easing states and transition API instead of the half-aborted animation API inside ClutterLayoutManager; and the ClutterActorModel API, to get rid of the ClutterClones).

ideally, I’d really like to have the first 2.0 alpha release at about the same time — in order to give people the feel of the changes, as well as time to port their applications and start complaining about the missing functionality while I can still add, change, or remove API. what’s certain is that between 6 and 12 months I want to have Clutter 2.0 out of the door and into your systems; whether or not that will happen sooner or later it entirely depends on the time I’ll be able to spend on it, as well as the contributions I may receive. so, if I have to close with a familiar exhortation: patches welcome!

until then, have fun with Clutter!

And I Believe California Succumbed to the Fault Line

Clutter’s description, and I quote from the website, is:

an open source software library for creating fast, compelling, portable, and dynamic graphical user interfaces.

and yet, the API to build a user interface is static: you create the actor tree, you tell it how to paint its contents, and only then you animate it to create a compelling and dynamic result.

the ethos of an API should be to Do The Right Thing™ by default — and make it harder if not impossible to Do The Wrong Thing™ — so why is it that you have a simple function to make an actor jump at a given position, and you have a really complex function, full of side-effects and options, to make an actor tween between the current position and the desired new one?

Scumbag Steve meme - top caption says: "Promises dynamic user interfaces", bottom caption says: "makes everything static by default"

wouldn’t it be better, and even easier, if the simple function did the tweening, and if the complex function just went away because, well: who needs it, anyway?

so we need to identify properties that should be animated when changed, and we have to make every setter for that property perform a transition from the current value to the desired value, using a predefined duration (that can be changed), and a predefined easing mode (that can be changed). easy, right?

well, sort of. we already have all the pieces in place: we have the timeline, to define the duration and progress of a transition; we have the interval, to define the initial and final states, as well as the interpolation between the two; and we have the introspection capabilities of GObject to determine whether a property can be animated, and how. all we need to do is connect the dots inside ClutterActor. hence, the introduction of ClutterTransition and of the easing state. the former is a simplified version of ClutterAnimation, that ties a ClutterInterval directly into a ClutterTimeline to avoid signal emissions and weird memory management rules; the latter is a way of describing the duration, delay, and easing mode of all subsequent transitions. Clutter will manage everything behind the scenes for you, so you just need to tell it how long, and how paced, are your transitions.

so, in short, this call:


  clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 250,
                         "x", 100.0,
                         "y", 100.0,
                         "width", 200.0,
                         "height", 200.0,
                         NULL);

becomes:


  clutter_actor_save_easing_state (actor);
  clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC);
  clutter_actor_set_easing_duration (actor, 250);
  clutter_actor_set_position (actor, 100, 100);
  clutter_actor_set_size (actor, 200, 200);
  clutter_actor_restore_easing_state (actor);

which does not seem much, but:

  • you get back all the type safety you need;
  • the code becomes easy to follow;
  • you can use the convenience API instead of a per-property set.

for instance, try throwing things like scaling or rotating:


  ClutterVertex vertex = CLUTTER_VERTEX_INIT (x, y, z);

  clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 250,
                         "rotation-angle-y", 360.0,
                         "fixed:rotation-center-y", &vertex,
                         "scale-x", 2.0,
                         "scale-y", 2.0,
                         "fixed:scale-gravity", CLUTTER_GRAVITY_CENTER,
                         NULL);

becomes the much more familiar:


  clutter_actor_save_easing_state (actor);
  clutter_actor_set_scale_with_gravity (actor, 2.0, 2.0, CLUTTER_GRAVITY_CENTER);
  clutter_actor_set_rotation (actor, CLUTTER_Y_AXIS, 360.0, x, y, z);
  clutter_actor_restore_easing_state (actor);

well, I cheated a bit: the easing mode of CLUTTER_EASE_OUT_CUBIC and the easing duration of 250 milliseconds are the default when creating a new easing state — but that’s just another benefit: you don’t need to specify an easing mode and a duration if you want to use the sensible defaults, whereas clutter_actor_animate() forces you to do that every time.

job done!

Darth Vader filling a jug with water filtered from the sea

we still don’t want existing Clutter applications to change behaviour and start animating everything just because you updated Clutter from 1.8 to 1.10; for this reason, all actors start off with an easing state with a duration of zero milliseconds — which means that all transitions happen immediately. at least, this will be true for the 1.x API series: for 2.x, the initial easing state will have a non-zero duration, which means that if you want to make an actor jump at a specified state then you’ll have to begin a zero-milliseconds duration.

well, kind of

Success Kid Meme image; top caption is: "Follows API ethos", bottom caption is: "Makes the World Better"

it’s important to make sure that every time you want to change a user interface you think of it as an animation; this API should immediately give you have a visual feedback of what that change is going to provide — without structuring your code around lots of variadic argument functions, with pretty loose type checking and “interesting” corner cases.

so, for the 1.10 cycle you should start opting in into this way of writing your application, and use easing states instead of using clutter_actor_animate().

You and Me and The War at The End Times

the actor tree is only the representation of what your user interface is composed of: textures, reactive items, containers to give them structure. if nothing is painted, though, it’s not much of a user interface.

with the current stable version of Clutter, if you want to get something on the screen you either use one of the pre-canned sub-classes of ClutterActor provided by Clutter itself — ClutterTexture, ClutterRectangle, and ClutterCairoTexture — or you end up using something written outside of Clutter — Mx widgets, for instance; or you write your own UI elements. if you chose to write something from scratch, you will have to sub-class ClutterActor and override the ClutterActor::paint virtual function. ((yes, it’s a signal, which means that you can also attach a handler to an existing actor and completely change how said actor paints itself; this is incredibly evil, and will not be possible in 2.0, so if you’re doing that, stop right now, or I will tell mom, and you won’t be invited to the Buffy marathon next time.))

what happens inside a paint virtual function implementation is usually this:

  • you use Cogl API to set up the state of the graphics pipeline;
  • you use Cogl API to submit geometry to the graphics pipeline;
  • you recursively call clutter_actor_paint() on your children, if any.

the third step can now be taken care of Clutter itself, as any actor now has access to the section of the actor tree with itself as the local root. the first and second steps are kind of tricky: you have to remember a lot of things about how to use the Cogl API. it would be nice if Clutter provided some convenience API to Do The Right Thing™ instead.

it would also be nicer if we could structure that API to build a representation of an entire frame, decoupling what gets painted from what is the logical unit of the user interface, because then we could keep it (either as parts or the entire thing) around between frames, manipulating the former without affecting the latter. the keen readers will already have said: you want a retained drawing model. good job! ten points for Gryffindor!

this new API is provided by paint nodes; each paint node is an element on the render tree — and every time you should paint an actor, you get passed a local root that you can use to attach your nodes. each paint node contains the pipeline state and the geometry to submit. once the tree has been built, Clutter will decide how to paint it. the base entry point for this operation is the ClutterActor::paint_node() virtual function. inside it, you’re supposed to paint only the actor — the children will be painted by Clutter itself. the paint_node() virtual should be considered orthogonal to the paint() one, though the latter will probably remain in 2.0 to give you control over which of your children you may decide to paint. Clutter provides predefined paint nodes for texture, solid colors, text, and even for custom pipelines; to each node you can add a rectangle (with or without texture coordinates), paths, or even Cogl primitive objects if you decide to use the experimental Cogl 2.0 API.

currently, given that we allow app and toolkit developers to use a direct drawing model, we still need to maintain that invariant, otherwise stuff will break; but we can already start migrating towards a retained drawing model, and have it fully in place by the time we hit 2.0. instead of setting up all the transformations and modifying the modelview and clip states, we’ll be able to attach transformation and clip nodes, and even be able to discard sections of the render tree without hitting the GPU. from there, we could go anywhere; we could hand off rendering into a separate thread and never block the main loop; or we could do the reverse, and thread everything else instead — event processing, layouting — without having application code left to deal with the fact that only one thread at a time can access a GL context.

obviously, most developers will not want to care about this; apps usually draw textures and text anyway, fancy as they may be. app developers should get a better API to achieve that, though, and the current model of sub-classes of ClutterActor is not serving them well enough; if you sub-class ClutterTexture you get a ton of behaviours, and most of them are really not at all nice, especially if all you want was to get some image data on the screen. I won’t even speak about ClutterCairoTexture, which encodes an implementation detail (that is not even true nowadays) into the class structure.

so, for 1.10 I introduced the ClutterContent interface, and a couple of trivial implementations for displaying image data and for drawing using Cairo. the classes are side-effect-free because they only know about one thing: painting some state. implementing a ClutterContent to paint something custom is easier than sub-classing ClutterActor, just like it’s easier to implement a ClutterLayoutManager to manage the layout policy of the children of an actor. all the cleverness on where and when to paint the content associated to an actor is where it belongs: inside the actor itself, leaving you to care just about what to paint.

Had a dream

as I wrote already in a previous blog post, if you try and compile an existing Clutter application with the current master, the first thing you will notice is that the compiler will start complaining about deprecated symbols.

a lot.

some of these symbols are little used API variants, or baggage we’ve been stringing along since the 0.x days and that we never managed to deprecate until now — and if you’ve been using them, then I’m not sure I want to know why, and you’ll have to trust me when I say that you’re better off not using them.

on the other hand, many of the deprecated symbols have been pretty central as to how a Clutter app is built and works; clutter_container_add_actor()? clutter_actor_raise()? ClutterBox? clutter_timeline_set_loop()?

in reality, not much has changed per se: the deprecation warnings will tell you how to port an app from the old API to the new one, and in basically all cases it’s juts a matter of changing functions or classes; plus, deprecated classes and functions will still work until we break API and release Clutter 2.0.

what really changed is how a Clutter app should be written from the get go — and this has more to do with the intent of the API, more than the actual form of the API.

case in point: if you look at the replacement for many of the deprecated functionality, as well as the new API introduced in 1.10, you will notice that it is overwhelmingly inside the ClutterActor class; the 1.9 development cycle stats for the clutter-actor.[ch] files alone are:


 git diff --stat clutter-1.8... clutter/clutter-actor.[ch]
 clutter/clutter-actor.c |20516 +++++++++++++++++++++++++++++------------------
 clutter/clutter-actor.h |  803 +-
 2 files changed, 13350 insertions(+), 7969 deletions(-)

so ClutterActor just gained around 5000 lines ((yes, I’m cheating a little bit, as a lot of documentation is inlined inside the source code, so that balloons the size of the delta)).

this growth reflects one of the fundamental tenets of how Clutter should be used:

it’s all about actors

Actors are not the base, abstract class for elements on the UI: they are now a concrete class that should be used directly, instead of through sub-classes. the ClutterActor class is the element of the scene graph; it holds children, it paints them, it lays them out. there is one API to learn, one class that holds the keys to all the behaviour, and one class to inherit from for custom controls.

obviously, ClutterActor cannot do everything by itself; but instead of creating sub-classes to specialize the behaviour right within Clutter, a delegation pattern was preferred. layout is now deferred to ClutterLayoutManager; painting is delegated to ClutterContent.

delegation means that composition is the approach for creating apps; Clutter is, now more than ever, like a set of blocks that can be composed together to achieve a compelling, dynamic user interface.

let’s start from an actual example: whereas until 1.8 you had to use the ClutterContainer interface as the public side for building and manipulating the actor tree, now ClutterActor owns the entire list of public entry points for adding, removing, and iterating children; this also applies to the implementation of container actors: the ClutterContainer interface is implemented directly by the ClutterActor class, so you can just subclass the latter and use the default implementation without having to care about internal children, or memory management, or mapping and unmapping. even painting and picking by default will do the right thing — so you don’t have to care any more. when you subclass the ClutterActor class you can now concentrate only on the things your class has to do — instead of having to care about Clutter internals.

moving all the API from within the containers to the actors also meant being able to add a bunch of convenience functions for manipulating and iterating the actor tree; usually, these functions had to be provided by container classes, and thus had to be re-implemented over, and over, and over again. now, instead, you can get the first and last child of an actor, and iterate over their siblings; or you can create a simple, stack allocated iterator structure, and safely iterate over the children of an actor. you can insert actors at a specific index in the paint and allocation sequence, or you can replace a child atomically. finally, you can remove, or destroy, all the children of an actor in one fell swoop.

implementing the Container interface inside ClutterActor also allowed us to seamlessly migrate the ClutterLayoutManager delegate over to ClutterActor; this means that every actor can now delegate the layout of its children to any layout manager without requiring weird incantations. ((the layout manager API still needs some adaptations, which will come in the 1.12 time frame))

building the actor tree, though, it’s just part of the job of creating a Clutter app; we’ll see in the next blog post what changes happened when you want to fill an app with content…

Calamity Song

I have written a bunch of blog posts about the Clutter Apocalypses that have landed in Git, as well as how I see the Clutter API evolving after this cycle and towards the 2.0 API break; they should appear in the next few hours, staggered a bit to avoid clogging the intertubes.

hopefully, I won’t bore you to death — but I’ll understand if you want to filter me out.

I’ll keep the comments section open, but feel free to use the clutter-devel mailing list: it’s much, much better than a comment in a blog.

Bridges and Balloons

after a rather interesting, albeit not really eventful, journey that spanned cars, buses, a train, and a plane, I’m finally in the lovely Brno — with 2 degrees Celsius and a lot of snow — for the 2012 GTK+ hackfest.

unlike the previous two hackfests, and against my usual inability to write interesting stuff, I’ll try and live-blog the event as much as I can.

as you can see on the wiki page, the agenda is pretty dense, and it’s going to be an intense 6 days hackathon, filled with discussions as much as coding. my part? talking about rainbows and unicorns, obviously.

a lot happened in the months between the Desktop Summit in Berlin, where we first sat down and talked about what Clutter does, and what GTK needs; there has been various progress in the Clutter API towards a sane base for a 2.0 release. if you try and compile an existing application using Clutter with the 1.9 developers snapshots, you’ll notice the depth and breadth of deprecations and API additions. a lot more needs to change — and some of this work on getting from here to there is detailed on the Clutter wiki, under the not at all threatening name of Clutter Apocalypses. I’ll try and write other blog posts about how I envision those changes, and why I think they are necessary for a 2.0 API version.

Days of Elaine

oh man, it’s getting harder to find blog post titles…

clutter 1.8 — last Friday I rolled the first release of the new stable 1.8 cycle, and Rob rolled the first stable release of the now standalone Cogl. it’s been six months of intense development, with lots of contributions, and I’d like to thank everyone who submitted patches, opened bugs, added a translation, or even dropped by in the #clutter IRC channel to tell us that they were using Clutter for their awesome project.

clutter 1.9 — instead of resting after pushing 1.8 out of the door, we’re already hard at work on what will become 1.10 in six months. while Cogl is getting more and more refactoring to make the code base more understandable and reliable, as well as preparing the way for new features, Clutter is also getting some refactoring. today, for instance, I worked on building Clutter with multiple backends in the same shared object. one of my first major contributions to Clutter, back in the OpenedHand days, was to provide the ability to have multiple backends — and it worked pretty well: after the GLX backend we got a Windows backend, then a framebuffer backend, then an OS X backend. during the years, the implementation was amended here and there to avoid leaking the backend implementation all over the place, and we always resisted the temptation (and the outside pressure) to provide a full abstraction library for the windowing system akin to GDK. this allowed us to maintain the backend code lean and lightweight, to the point that it took me literally an hour this morning to go from the current HEAD of master to a test running with either GDK or GLX (depending on an environment variable) — and most of my changes were in the build system, not in the code.

as an example, this is a simple test program that checks the backend support at both compile and run time; using Clutter from the multi-backend branch, compiled with --enable-x11 and --enable-gdk, you can run the example on X11 using:

$ CLUTTER_BACKEND=x11 ./test-backend &
$ CLUTTER_BACKEND=gdk ./test-backend &
multiple backends, same great taste

and have two instances, one using the native X11 backend and the other using the GDK backend.

there’s still some work to do, namely fixing Clutter-GTK to work with a multi-backend Clutter, and making it use the GDK backend by default, if found. there’s also the issue of being able to use the GLX_EXT_texture_from_pixmap extension under the GDK backend on X11, if available, so that we can efficiently embed GTK widgets rendered off-screen like we can already do when using the Clutter X11 backend.

all in all, this work will help towards the goal of using Clutter and GTK together in a more organic fashion, and with fewer blocks and hacks in the middle.

Constraints

last time, I described the Effects in Clutter as anything that should affect the way an actor paints itself without sub-classing.

this kind of modification of the behaviour of an Actor can also be applied to other areas, and leads to defining three different kinds of modifiers:

  • Effects, which modify the way an actor paints itself
  • Actions, which modify the way an actor responds to user events
  • Constraints, which modify the way an actor is positioned or sized

being capable of being dragged using the pointer can be defined as an action: it changes the way an Actor responds to user events (button press, motion, button release). in the same way, update the X position using the X position of another actor is a constraint placed on an Actor.

Clutter already has signals, properties and virtual functions for dealing with these modifiers, and they can be seen as the building blocks. What’s missing is a set of classes that wrap those building blocks into something that leads to run-time composition of effects, actions and constraints on top of an existing Actor class.

last week I started working on the implementation of these modifiers, and now I’m pretty close to a finalized API for Clutter 1.4. the usage of an action is pretty simple:

  ClutterAction *action = clutter_drag_action_new ();
  g_signal_connect (action, "drag-motion",
                    G_CALLBACK (on_drag_motion),
                    NULL);

  clutter_actor_add_action (some_actor, action)
  clutter_actor_set_reactive (actor, TRUE);

the simplest implementation of a ClutterDragAction::drag-motion signal handler is:

  static void
  on_drag_motion (ClutterDragAction *action,
                  ClutterActor      *actor,
                  float              delta_x,
                  float              delta_y)
  {
    clutter_actor_move_by (actor, delta_x, delta_y);
  }

there’s no fundamental difference for the constraints API; for instance, this positions an actor in the middle of another:

  ClutterConstraint *constraint;

  constraint = clutter_align_constraint_new (parent, CLUTTER_ALIGN_X_AXIS, 0.5);
  clutter_actor_add_constraint (some_actor, constraint);

  constraint = clutter_align_constraint_new (parent, CLUTTER_ALIGN_Y_AXIS, 0.5);
  clutter_actor_add_constraint (some_actor, constraint);

it’s important to note that parent in this case can be any actor, and not necessarily the scene graph parent of some_actor.

this example binds the X coordinate of an actor to the X coordinate of another one, while keeping it Y aligned at the center of its parent:

  ClutterConstraint *constraint;

  constraint = clutter_bind_constraint_new (source, CLUTTER_BIND_X, 0.0);
  clutter_actor_add_constraint_with_name (some_actor, "x-bind", source);

  constraint = clutter_align_constraint_new (parent, CLUTTER_ALIGN_Y_AXIS, 0.5);
  clutter_actor_add_constraint_with_name (some_actor, "y-bind", constraint);

Update: I’ve updated the example to use the newly added add_constraint_with_name() instead of set_name()+add_constraint(); I also changed the constraint names.

now, I’ve added a call to clutter_actor_meta_set_name() in the mix because I might decide to animate the offset property of the ClutterBindConstraint using a specific syntax for ClutterAnimation ((the change is contained in ClutterActor so I’m not over-complicating the parsing code in the animation class itself; which also means that ClutterAnimator and the upcoming ClutterState classes will be able to use the same syntax to address action, effect and constraint properties)):

  float new_offset = clutter_actor_get_width (source) + h_padding;
  clutter_actor_animate (some_actor, CLUTTER_EASE_OUT_CUBIC, 500,
                         "@constraints.x-bind.offset", new_offset,
                         "opacity", 128,
                         NULL);

the new syntax is still type checked, so you’ll get warnings if you’re using the wrong type or the wrong interval ((I’m still considering using a dotted notation; I might switch to a colon notation, or a slash notation. and yes: I know that it looks like the syntax for key access in CoreAnimation; it turns out that there aren’t many new ways to access an item in a path)).

caveat: obviously, a constraint only applies to an actor that is in a fixed positioning layout manager.

the new classes and API are available in the wip/actor-actions branch here and wip/constraints branch here; there are also a couple of interactive tests that show you how actions and constraints can be used with existing actors. if all goes according to plan, I’ll merge them by the end of the week — following Frederic’s blog post, I want to make a 1.3 snapshot release in time for GNOME 2.31.2.

Clutter Q&A

since there are free slots here at GCDS I was wondering if somebody wanted to have a sit down and ask questions about Clutter; bugs and feature requests for 1.2 are also welcomed. just send me an email at: ebassi at gnome dot org.