An introduction (of sorts) to JavaScript desktop application development with Gjs and Clutter

  • warning: Illegal string offset 'data' in /home/townxorg/public_html/includes/ on line 110.
  • warning: Illegal string offset 'data' in /home/townxorg/public_html/includes/ on line 110.
  • warning: Illegal string offset 'data' in /home/townxorg/public_html/includes/ on line 110.
  • warning: Illegal string offset 'data' in /home/townxorg/public_html/includes/ on line 110.

This turned into a pretty long blog entry. To help you decide whether you want to stick it out, it's about:

  • My experience with C development for Moblin
  • JavaScript for desktop applications
  • Gjs, GObject introspection, and GIR repository installation
  • Running JavaScript Clutter applications using gjs
  • Interesting movements in the JavaScript world


I started work at Intel's Open Source Technology Centre 6 weeks ago (just realised I haven't written about that here yet), working on the Moblin SDK. Moblin is a Linux-based platform for mobile devices (netbooks, UMPCs, that sort of thing); my role in the project is working as part of the SDK team - basically trying to help third-party developers outside Intel develop software which runs on Moblin. So far, this has involved learning as much about the Moblin stack and ecosystem as possible, as well as helping organise and add to the content on Moblin-related websites. (It's challenging, exciting work and I'm thoroughly enjoying it so far.)

Currently, software development on Moblin is comparable to generic Linux development: languages like Python, Ruby, C++, Perl, Java, C# (via Mono) etc. are all available. However, if you want to make use of the full range of Moblin libraries (like our stuff for managing media metadata or interacting with social networking sites), and combine them with Clutter (our GUI toolkit), the best approach (at the moment) is to program in C. While many of the Moblin libraries have bindings to other languages (like Python and Perl), C gives you the best, most consistent access to all of them (as they're all written in C). You'll also find Moblin development easier if you're familiar with GNOME and glib, both of which are fairly C-centric.

My background isn't in low-level system programming. I have been learning C since starting at Intel, and have enjoyed it thoroughly, but there are several aspects of it I could live without:

  • Memory management is my main bugbear. I really don't want to have to care about allocating memory for data structures, then cleaning up when I'm finished with them. Learning how to (still learning...) has definitely enhanced my understanding of how programs actually work under the bonnet, but dealing with memory directly is not, in general, fun. I'd rather the runtime dealt with it.
  • autotools (aka the GNU Build System) are not straightforward, especially if you're used to build tools like Ant and Rake (or even Maven). I know they are extremely powerful and flexible, and ubiquitous for open source projects, but I defy anyone to tell me they are simple, easy to learn, or well documented. In fact, the autotools (automake, autoconf) actually wrap other tools (make) which are even more complicated. This is partly a consequence of the job they do (making it possible to compile software across different platforms), but means they are not approachable. See the diagram on the autools Wikipedia page to get an idea of how complicated they are.
  • Pseudo object oriented programming (in C) isn't really as pleasant as full OOP (in a language like Ruby). GObject for C (part of GLib) gives you some of the facilities of full OOP, but (as far as I understand it) it's not possible to encapsulate data with the methods which act upon it. It also seems tremendously complicated. Even with GObject, you are still basically doing imperative programming, so encapsulation relies on namespacing and (kind of) casting objects to the right class before passing them to a function (as classes don't seem to know about their parent class, as such). Having said all this, one smart feature GObject does support is introspection, which makes it possible to automate binding other languages to a C library.

So, with my background, and with the goal of making Moblin development easy and attractive, I am keen to find alternatives to having to program in C all the time. Dynamic, interpreted languages (like Ruby or JavaScript) seem to me to be better suited to exploratory, iterative programming: the kind of programming most people do most of the time. This is a goal shared by the GObject Introspection project:

C is good for graphics, multimedia, and lower level systems work. However, writing complex software is difficult and error-prone without garbage collection. A managed runtime such as JavaScript, Python, Java, Lua, .NET, Scheme etc. makes a lot of sense for non-fast-path application logic such as configuration, layout, dialogs, etc. ... Thus, one of the major goals of the GObject introspection project is to be a convenient bridge between these two worlds, and allow you to choose the right tool for the job, rather than being limited inside one or the other. (from

GObject Introspection is already being used in GNOME development, to generate JavaScript bindings for the GNOME libraries: the next version of the GNOME desktop (in GNOME 3), GnomeShell, uses JavaScript extensively (calling Clutter, the Moblin graphics library, incidentally). Gjs is the name of the project producing the bindings, as well as being the home of the JavaScript engine itself (also called gjs, and based on Mozilla's implementation of JavaScript in C, SpiderMonkey).

JavaScript is an interesting language. I've used it in web applications for quite a long time (since about 2000), but never entertained the idea of using it for anything other than client-side web programming. Occasionally I'd come across server-side JavaScript (persevere), JavaScript implementations like Rhino, and even wrote some ASP code in JScript (as Microsoft called it) a few years ago. Frameworks like jQuery and the thorough integration of JavaScript with Rails meant that I've done more of it in recent months, but I never thought of using it as a general purpose language, or one for desktop development.

Looking for an alternative to C, and hearing from my colleagues about JavaScript, made me decide to get a feel for Gjs et al, as well as write something to run on Moblin. I decided to write a JavaScript application which made use of the Moblin graphics library, Clutter. Eventually, I ended up successfully writing a JavaScript implementation of tic-tac-toe, using Clutter for the user interface, and even including some simple animation. As an application, it is a bit scrappy (the code is attached), but as a learning aid, doing the project was very useful. It wasn't an easy journey, but it was an eventually satisfying one.

Using JavaScript for the not-web

I did my development work on a Fedora Core 11 laptop, with an Intel chipset.

I tried a variety of ways to install all the pieces I needed for JavaScript development with Gjs, GObject Introspection, GNOME libraries, and Moblin libraries. Even getting an idea of what all the pieces do is painful, and the documentation is pretty woeful. I ended up doing lots of source code grep-ing and googling.

In the end, it turns out that the following packages are available for Fedora Core:

  • gobject-introspection: This provides tools and APIs for working with GIR XML files and typelib (binary versions of the GIR files): these are two formats for storing introspection data about GObject classes (basically, mapping the API of a C library into language-neutral descriptions of the APIs). The metadata for several common libraries (like GLib) is part of this package.
  • gir-repository: This provides more introspection metadata about other common libraries (like GTK+ and DBus-GLib)
  • gjs: This enables you to use the gobject-introspection data to access C libraries from JavaScript (i.e. it's the JavaScript bindings for GNOME libraries).

Now, unfortunately, the versions in the repositories for Fedora 11 are out of date: generating the Clutter bindings requires gobject-introspection-1.0, which isn't available. Plus, this code is so new that it's changing very rapidly, and you probably need the latest version from the source repository to get stuff to work.

To compile all these bits, you're going to need the basic build tools. On Fedora, that means this lot:

$ sudo yum install git flex bison gnome-common libgnome-devel libffi-devel \
    python-devel libtool automake autoconf make gtk-doc xulrunner-devel

(And maybe others: I lost track. But if you're trying to do this yourself, you'll probably know what to do if something's missing. Anyway, Josh is going to sort some packages out before long, hopefully. If you know a better way, let me know.)

Once you've got those installed, though, you should be able to build everything from source fairly easily.

As we're installing into /usr/local, first thing to do is make sure the compiler/linker can find your custom-compiled packages. In your ~/.bashrc file, add this line:

export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig

This tells the pkg-config tool (used by autotools to locate libraries and headers) where your custom installations are. Then reload your bash settings with:

$ source ~/.bashrc

to make sure they're picked up. Any future bash sessions will use this setting. Now you're ready to build.


$ git clone git://
$ cd gobject-introspection
$ ./ --prefix=/usr/local
$ make
$ sudo make install


$ git clone git://
$ cd gir-repository
$ ./ --prefix=/usr/local
$ make
$ sudo make install


$ git clone git://
$ cd gjs
$ ./ --prefix=/usr/local
$ make
$ sudo make install

You can check gjs is working by doing:

$ /usr/local/bin/gjs
gjs> 1+1

It's a good idea to add /usr/local/bin to your path, again in ~/.bashrc:

export PATH=$PATH:/usr/local/bin

(and source ~/.bashrc to pick it up if necessary)

To compile Clutter itself, you'll also need these library headers:

$ sudo yum install glib2-devel mesa-libGL-devel libXext-devel \
    libXfixes-devel libXdamage-devel pango-devel cairo-devel

(Again, maybe others too.)

Once you've got those too, you can checkout Clutter using git, and build it with introspection turned on:

$ git clone git://
$ cd clutter
$ ./ --prefix=/usr/local --enable-introspection
$ make
$ sudo make install

The final step is one which doesn't appear to be documented anywhere, but which is utterly vital: without it, gjs can't find any of the introspection metadata, and won't be able to call any of the C libraries through their JavaScript bindings. Add this line to your ~/.bashrc file:

export GI_TYPELIB_PATH=$GI_TYPELIB_PATH:/usr/local/share/gir-1.0/

(Again, use source if necessary.)

Testing gjs with Clutter

To test the install, and make sure the Clutter JavaScript bindings are working, put this code into a file test.js:

const Clutter =;
Clutter.init (0, null);
let stage = Clutter.Stage.get_default ();
stage.title = "Test";
stage.set_color(new Clutter.Color( {red:150, blue:0, green:0, alpha:255} )); ();
Clutter.main ();
stage.destroy ();

Run it from a command line with:

$ gjs test.js

You should see something like this:

If this works, you should be able to run my tic-tac-toe (semi-)implementation, linked at the end of this blog entry. To run it, copy the two files into a directory, remove the .txt suffixes, then get a command line in that directory and run:

$ gjs ox.js

There's no AI (so you'll have to play both sides), but notice the use of a scale animation as each move is written to the board. Also interesting is how you can use anonymous JavaScript functions to define callbacks for signals.

I've not experimented extensively, beyond calling a few bits of the Clutter and Netbook Toolkit APIs. If you want more examples, have a look at the GnomeShell tests and UI code. The mx tests are another source of sample code I used.

Another tip: if you're trying to work out what's available in the JavaScript bindings, there's unfortunately no nice way to do it at the moment. Your only recourse is to grep the XML GIR files, which are located in:


Reading these is a bit of a chore, and I also found it difficult to figure out what was in the API. For example, if you're trying to use a Clutter constant like CLUTTER_X_AXIS, the GIR file has this entry:

<namespace name="Clutter"

... loads of cruft ...

  <enumeration name="RotateAxis"
                  doc="Axis of a rotation."

    <member name="x_axis"


... loads more cruft ...


So, to reference the CLUTTER_X_AXIS constant, my first thought was look up the member element with a c:identifier corresponding to the constant I want; then use the path from the namespace, through the enumeration name, to the member name, i.e.:


But in fact it's:


(the name attribute, capitalised).

I also found that some methods and classes in the GIR for GLib didn't work (like GLib.printf). I'm sure there's a good reason why, it's just I couldn't work it out.

What's missing?

I spent quite a few hours figuring this stuff out, and stumbled a lot along the way. Partly because I'm not a C programmer, partly because I'm new to GNOME, I'm sure. But I think there are a few things which would have improved my experience:

  • Decent documentation, particularly of the JavaScript APIs generated for C libraries like GLib - at the moment, working out what's going to be available in the JavaScript bindings is very tedious
  • An easy installation process (see above) - largely though because I'm using libraries which are too bleeding edge, just because they're the only ones which worked well
  • An intelligible module system, for modularising code - at the moment my application will only run from the directory where the files are, as I've yet to work out how to get the path to the directory containing the script programmatically; I'm not sure how you'd organise large groups of files spread over lots of directories
  • A decent packaging system with dependency tracking, so that you can distribute JS apps and know they'll work
  • Functions to make developers' lives easier, like a decent REPL (gjs doesn't even have a print function - there is a patch to gjs which will give you that - see here: - but you'll have to patch manually at the moment to get it)

And finally, it might be worth taking a look at Seed, which is an alternative JavaScript implementation, but one which still understands GObject introspection. Seed is interesting in that it seems to provide more niceties, like a better REPL environment, more documentation, and a fuller standard library (filesystem and environment interfaces in particular).

What's next for JavaScript?

It looks as if the JavaScript world is hotting up at the moment. This is a recent news report on the state of JavaScript:

It mentions the CommonJS standardisation effort, which is attempting to resolve some of the shortcomings of JavaScript as a general purpose language.

Reading through the CommonJS wiki, I was particularly interested in Narwhal, which resolves some of the issues I mentioned in the last section: it includes a package manager, module system, and standard library. It also provides support for different JavaScript engine back-ends: currently this includes a SpiderMonkey adapter. Given that Gjs is broadly based on SpiderMonkey, it seems likely that creating a Gjs back-end for Narwhal wouldn't be too onerous.

One other thing which could potentially be useful in Narwhal is the availability of separate Narwhal environments (called "seas") with their own set of packages. This could help isolate applications from each other in an environment like Moblin, where you want third parties to be able to develop applications without trampling on each other's libraries.

Another tool of interest is jake, a port of Ruby rake to JavaScript, which seems to be optimised to work with Narwhal. This could provide a reasonable alternative to autotools for the simpler build requirements of a JavaScript application (where there's no need for a compile step or library linking).

A combination of Narwhal (packaging/modules), with the power of Gjs binding to pretty much any C library, would make an attractive environment to develop in.

I should also mention node.js, server-side JavaScript primarily designed for building network programs, but which incorporates a CommonJS module system. It's built on Google's V8 JavaScript engine. It's also interesting because it is designed to be highly performant and memory-efficient, and has an interesting event-driven I/O model, like EventMachine or Twisted.

I'm definitely looking forward to seeing what happens next.

ox.js.txt5.31 KB
board.js.txt3.46 KB


Can I use your information?

I'm doing a step by step tutorial for begginers in the wiki of gnome
Can I use your information and code?

Meanwhile I add it because the information is very great and your example it's very useful, but nobody except me know about this wiki page, so if you don't like it, I delete your information and code an reference to your page.

Thank you in advance

Sorry I haven't replied

Sorry I haven't replied sooner. Providing I get an attribution, any content on this blog can be used under the terms of the CC Attribution-Share Alike licence. Cheers.

Desktop application and javascript

Its really nice to read about clutter and memory management in your blog. I also like to add that using such javascript in Desktop Application Development would be great experience and its really helpful to the user as well as programer. One can use javascriptMVC for development as it is an open source. I also like your fedora tools and utilization of it.

I'm trying to get a simple

I'm trying to get a simple cairo drawing drawn to a clutter window using the javascript bindings. My problem is, apart from half the functions being named slightly differently, is no matter what I try, the cairo drawing does not show up. I used a example from python, which does work, and ported it to javascript. I'm also using introspection to get the Clutter module instance. I'm also using gjs version 0.7.14. Can anyone tell me what is going wrong? Thank you in advance,

I haven't tried to use gjs

I haven't tried to use gjs for a long time now, so I can't really help (I'd have to build the whole lot again to do the testing). Sorry.

Have you taken a look at

Have you taken a look at haXe and the Neko VM? I think these might be great projects for Intel / Nokia to get involved in - write programs in JavaScript syntax and compile them to byte code that runs in a super fast (garbage collected) VM written entirely in ANSI C.

I would love to see MeeGo (and hopefully even the MeeGo SDK) support this combination.

Having recently made my first foray into mobile programming I was shocked at how unpleasant it currently is - particularly, as you rightly say, tasks like memory management that really should just happen auto-magically in the 21st century. haXE/Neko avoids such unpleasantness.

Please do take a look.


The tutorial is written for GJS, but do you know if the same instructions are more or less applicable for Seed (a similar framework based on WebKit's JS engine) as well?

I'm going to guess "yes". I

I'm going to guess "yes". I haven't tried Seed yet (I keep meaning to), but there's very little in here which is specific to Gjs (as far as I know). The only thing that might cause an issue is how I add search paths in my application (at the top of ox.js), which may differ in Seed. Also, you obviously would need to build Seed, rather than Gjs, and I'm not sure whether there are things to do in that process to make it aware of your GIR files (i.e. I'm not sure GI_TYPELIB_PATH is applicable). Let me know how you get on if you give it a try.

About the module system


For modularising your code, you can use GJS_PATH to define where to look for modules. So, if you have a directory structure like:


You can just run your app with wrapper script with something like:

export GJS_PATH=/myappdir/stuff:/myappdir/morestuff:/myappdir/yabadaba/
gjs /myappdir/main.js

In your code, you'll be able to import those files like this:

const File1 = imports.ui.file1;
const File2 =;
const File3 =;
const File4 = imports.var.file4;

Directories in the path can also have function in a module file init.js. So, suppose you have a init.js in the /myappdir/stuff/ui/ directory with a function called myFunction. You'd be able to access this function like this:

let v = imports.ui.myFunction()

The gjs style guide brings some hints on how we agreed to best write GNOME-based javascript code. See doc/Style_Guide.txt in gjs tree.

Hope that helps :-)

Thanks Lucas, very

Thanks Lucas, very helpful.

I read the style guide, which was very useful. I did attempt to follow it (to an extent) in the longer code samples I wrote.

Good work on gjs, by the way: I'm really enjoying JS development with it.