In the beginning of the year 2000, with the 1.2 release nearly out of the door,
the GNOME project was beginning to lay down the groundwork for the design and
development of the 2.0 release cycle. The platform had approached a good level
of stability for the basic, day to day use; whatever rough edges were present,
they could be polished in minor releases, while the core components of the
platform were updated and transitioned incrementally towards the next major
version. Before mid-2000, we already started seeing a 1.3 branch for GTK, and
new libraries like Pango and GdkPixbuf were in development to provide advanced
text rendering and replace the old and limited imlib image loading library,
respectively. Of course, once you get the ball rolling it’s easy to start piling
features, refactorings, and world breaking fixes on top of each other.
If X11 finally got support for loading True Type fonts, then we would need a
better API to render text. If we got a better API to render text, we would need
a better API to compose Unicode glyphs coming from different writing systems,
outside of the plain Latin set.
If we had a better image loading library, we could use better icons. We could
even use SVG icons all over the platform, instead of using the aging XPM format.
By May 2000, what was supposed to be GTK 1.4 turned into the development cycle
for the first major API break since the release of GTK 1.0, which happened just
the year before. Of course, the 1.2 cycle would continue, and would now cover
not just GNOME 1.2, but the 1.4 release as well.
It wasn’t GTK itself that led the charge, though. In a way, breaking GTK’s API
was the side effect of a much deeper change.
As we’ve seen in the first chapter’s side episode on GTK, GLib was a simple C
utility library for the benefit of GTK itself; the type system for writing
widgets and other toolkit-related data using object orientation was part of GTK,
and required depending on GTK for writing any type of object oriented C. It
turns out that various C projects in the GNOME ecosystem—projects like GdkPixbuf
and Pango—liked the idea of having a type system written in C and, more
importantly, the ability to easily build language bindings for any API based on
that type system. Those projects didn’t really need, or want, a dependency on a
GUI toolkit, with its own dependency on image loading libraries, or windowing
systems. Moving the type system to a lower level library, and then reusing it in
GTK would have neatly solved the problem, and made it possible to create a
semi-standard C library shared across various projects.
Of course, since no solution survives contact with software developers, people
depending on GLib for basic data structures, like a hash table, didn’t want to
suddenly have a type system as well. For that reason, GLib acquired a second
shared library containing the GTK type system, upgraded and on steroid; the
“signal” mechanism to invoke a named list of functions, used by GTK to deliver
windowing system events; and a base object class, called GObject, to replace
GTK’s own GtkObject. On top of that, GObject provided properties associated to
object instances; interface types; dynamic types for loadable modules; type
wrappers for plain old data types; generic function wrappers for language
bindings; and a richer set of memory management semantics.
Another important set of changes finding their way down to GLib was the
portability layer needed to make sure that GTK applications could run on both
Unix-like, and non-Unix-like operating systems. Namely, Windows, for which GTK
was getting a backend, alongside additional backends for BeOS, macOS, and direct
framebuffer rendering. The Windows backend for GTK was introduced to make GIMP
build and work on that platform, and increase its visibility, and possibly the
amount of contributions—something that free and open source software communities
always strive towards, even if it does increase the amount of feature request,
bug reports, and general work for the maintainers. It’s important to note that
GTK wasn’t suddenly becoming a cross-platform toolkit, meant to be used to write
applications targeting multiple platforms; the main goal was always to allow extant
Linux applications to be easily ported to other operating systems first, and
write native, non-Linux applications as a distant second.
With a common, low level API provided by GLib and GObject, we start to see
the beginning of a more comprehensive software development platform for GNOME;
if all the parts of the platform, even the ones that are not directly tied to
the windowing system, follow the same semantics when it comes to memory
management, type inheritance, properties, signals, and coding practices, then
writing documentation becomes easier; developing bindings for various
programming languages becomes a much more tractable problem; creating new, low
level libraries for, say, sending and receiving data from a web server, and
leveraging the existing community becomes possible. With the release of GLib
and GTK 2.0, the GNOME software development platform moves from a collection
of libraries with a bunch of utilities built on top of GTK to a comprehensive
set of functionality centered on GLib and GObject, with GTK as the GUI toolkit,
and a collection of libraries fullfilling specific tasks to complement it.
Of course, that still means having libraries like libgnome and libgnomeui lying
around, as a way to create GNOME applications that integrate with the GNOME
ecosystem, instead of just GTK applications. GTK gaining more GNOME-related
features, or more GNOME-related integration points, was a source of contention
inside the community. GTK was considered by some GNOME contributors to be
a “second party” project; it had its own release schedule, and its own release
manager; it incorporated feedback from GNOME application and library developers,
but it was also trying to serve non-GNOME communities, by providing a useful
generic GUI toolkit out of the box. On the other side of the spectrum, some GNOME
developers wanted to keep the core as lean as possible, and accrue functionality
inside the GNOME libraries, like libgnome and libgnomeui, even if those
libraries were messier and didn’t receive as much scrutiny as GLib and GTK.
Most of 2001 was spent developing GObject and Pango, with the latter proving to
be one of the lynchpins of the whole platform release. As we’ve seen in episode
1.5, Pango provided support for complex, non-latin text, a basic requirement for
creating GUI applications that could be used outside of the US and Europe; in
order to get there, though, various pieces of the puzzle had to come together first.
The first, big piece, was adding the ability for applications to render TrueType
fonts on X11, using fontconfig to configure, enumerate, and load the fonts
installed in a system, and the Xft library, for rendering glyphs. Before Xft, X
applications only had access to core bitmap fonts, which may look impressive if
all you have a is thin terminal in 1987, but compared to the font rendering
available on Windows and macOS they were already painfully out of date by about
10 years. During the GNOME 1.x cycle some components with custom rendering code
already started using Xft directly, instead of going through GTK’s text
rendering wrappers around X11’s core API; this led to the interesting result of,
for instance, the text rendering in Nautilus pre-1.0 looking miles better than
every other GTK 1 application, including the rest of the desktop components.
The other big piece of the puzzle was Unicode. Up until GTK 2.0, all text inside
GTK applications was pretty much passed as it was to the underlying windowing
system text rendering primitives; that mostly meant either ASCII, or one of the
then common ISO encodings; this not only imposed restrictions on what kind of
text could be rendered, but it also introduced additional hilarity when it came
to running applications localized by somebody in Europe on a computer in the
US, or in Russia, or in Japan.
Taking advantage of Unicode to present text meant adding various pieces of API
to GLib, mostly around the Unicode tables, text measurement, and iteration. More
importantly, though, it meant changing all text used inside GTK and GNOME
applications to UTF-8. It meant that file system paths, translations, and data
stored on non-Unicode systems had to be converted—if the original encoding was
available—or entirely rewritten, if you didn’t want your GUI to be a tragedy of
If the written word was in the process of being transformed to another format,
pictures were not in a better position. The state of the art for raster images
in a GTK application was still XPM, a bitmap format that was optimised for
storage inside C sources, and compiled with the rest of the application. Sadly,
the results were less than stellar, compared to more common formats like JPEG
and PNG; additionally, the main library used to read image assets, imlib, was
very much outdated, and mostly geared towards loading image data into X11
pixmaps. Imlib provided entry points for integrating with the GTK drawing API,
but it was a separate project, part of the Enlightenment window manager—which
was already moving to its replacement, imlib2. The work to replace imlib with a
new GNOME-driven library, called GdkPixbf, began in 1999, and was merged into
the GTK repository as a way to provide API to load images in various formats
like PNG, GIF, JPEG, and Windows BMP and ICO files directly into GTK widgets.
As an additional feature, GdkPixbuf had an extensible plugin system which
allowed writing out of tree modules for loading image formats without
necessarily adding new dependencies to GTK. Another feature of GdkPixbuf was
a transformation and compositing API, something that imlib did not provide.
All in all, it took almost 2 years of development for GTK 1.3 to turn into GTK
2.0, with the first stable releases of GLib, Pango, and GTK cut in March 2002,
after a few months of feature freeze needed to let GNOME and application
developers catch up with the changes, and port their projects to the new API.
The process of porting went without a hitch, with everyone agreeing that the new
functionality was incredibly easy to use, and much better than what came before.
Developers were so eager to move to the new libraries that they started doing so
during the development cycle, and constantly kept up with the changes so that
every source code change was just a few lines of code.
Yes, of course I’m lying.
Porting proceeded in fits and jumps, and it was either done at the very
beginning, when the difference between major versions of the libraries were
minimal and gave a false impression of what the job entailed; or it happened at
the very end of the cycle, with constant renegotiation of every single change
in the platform, a constant barrage of questions of why platform developers were
trying to impose misery on the poor application developers, why won’t you think
of the application developers…
Essentially, like every single major version change in every project, ever.
On top of the usual woes of porting, we have to remember that GNOME 1.4 started
introducing technology previews for GNOME 2.0, like GConf, the new configuration
storage. While Havoc Pennington had written GConf between 2000 and 2001, and
concentrated mostly on the development of GTK 2 after that, it was now time to
start using GConf as part of the desktop itself, as a replacement for the
configuration storage used by components by the Panel, and by applications using
libgnome, which is when things got heated.
Ximian developer Dieter Maurer thought that some of the trade-offs of the GConf
implementation, mostly related to its use of CORBA’s type system, were enough of
a road block that they decided to write their own configuration client API,
called bonobo-config, which re-implemented the GConf design with a more
pervasive use of CORBA types and interfaces, thanks to the libbonobo work that
was pursued as part of the GNOME componentisation effort. Bonoboc-config had
multiple backends, one of which would wrap GConf, as, you might have guessed it
already, a way to route around a strongly opinionated maintainer, working for a
The last bit is probably the first real instance of a massive flame war caused
by strife between commercial entities vying for the direction of the project.
The flames started off as a disagreement in design and technical direction
between GConf and bonobo-config maintainers, confined to the GConf development
mailing list, but soon spiralled out of control once libgnome was changed to use
bonobo-config, engulfing multiple mailing list in fires that burned brighter
than a thousand suns. Accusations of attempting to destroy the GNOME projects
flew through the air, followed by rehashing of every single small roadblock ever
put in the way of each interested party. The newly appointed release manager for
GNOME 2.0 and committer of the dependency on bonobo-config inside libgnome,
Martin Baulig, dramatically quit his role and left the community (only to come
back a bit later), leaving Anders Carlsson to revert the controversial
change—followed by a new round of accusations.
Totally normal community interactions in a free software project.
In the end, concessions were made, hatred simmered, and bonobo-config was left
behind, to be used only be applications that decided to opt into its usage, and
even then it was mostly used as a wrapper around GConf.
“Fonts, Unicode, and icons” seems like a small set of user-visibile features for
a whole new major version of a toolkit, and desktop environment. Of course, that
byline kind of ignores all the work laid down behind the scenes, but end users
don’t care about that, right? We’ll see what happens when a major refactoring to
pay down the technical debt accrued over the first 5 years of GNOME, and clear
the rubble to build something that didn’t make designers, documentation writers,
and QA testers cry tears of blood, in the next episode, “Release Day”, which
will be out in two weeks time, as next week I’m going to be at the GTK
hackfest, trying to pay down the technical debt accrued over the 3.0 development
cycle of the toolkit. I’m sure it’ll be fine, this time. It’s fine. We’re going
to be fine. It’s fine. We’re fine.