Building LibreOffice with Clang

October 22nd, 2011 by kris

Last week I attended the first LibreOffice conference in Paris together with the Lanedo LibreOffice hackers. Lionel Dricot gives a nice summary of the buzz at the conference in his latest blog post.

I figured I had to put the new crazy-fast machine Lanedo bought me to use at this conference, so I decided to attempt to build LibreOffice using Clang on Mac OS X. My expectation was that this would be too large a task for a single weekend, but to my surprise I managed to get to a completed build during the very last minutes of the conference. Unfortunately, the resulting executable crashes on start up :) So there’s still some work to be done.

The patches that were needed to complete the build have been submitted and I wrote up a wiki page about the remaining issues. See the mailing list post and the “Building LibreOffice with Clang” wiki page.

In the near future, I hope to fix things so that the resulting executable will actually launch and work correctly. Also, it should be interesting to try to compile LibreOffice using Clang on Linux (faster builds! warnings that a human can actually understand!).

Just like the LibreOffice conference, this tiny project has been good fun :)

Change of e-mail address

October 10th, 2011 by kris

Effective immediately I will be reachable at kris (at) loopnest.org instead of my old gtk.org alias (or in addition to gtk.org when gtk.org mail comes online again). The e-mail address attached to my Bugzilla accounts will be changed in the coming days as well.

I will not be rewriting my e-mail address in commit history, but will start committing with my e-mail address from today on.

Making clang GObject aware

September 25th, 2011 by kris

Before it’s Christmas again, I should blog about the nifty hack I did last Christmas, already nine months ago.

Often, I am quickly coding up test cases. Compiling and running usually goes like this (insert cheering after successful compile):

$ clang `pkg-config --libs --cflags gtk+-3.0` -o test/foo3 test/foo3.c
$ ./test/foo3  

(foo3:84880): GLib-GObject-WARNING **: g_object_set_valist: object class `GtkWindow' has no property named `width'

(foo3:84880): GLib-GObject-WARNING **: gsignal.c:2293: signal `delet-event' is invalid for instance `0x101865000'

And insert a sigh of disappointment after witnessing the GObject warnings. I figured that with all the GObject Introspection work going on, it would be quite nice to teach the compiler about GObject Introspection. So while snow was pouring down last Christmas, I hacked up a quick and dirty clang plugin. It looks like this:

$ clang -cc1 -fcolor-diagnostics `pkg-config --cflags gtk+-3.0` -load libGObjectHelper.dylib -plugin gobject-helper test/foo3.c
test/foo3.c:23:25: warning: object 'GtkWindow' has no property 'width'
  g_object_set (window, "width", 320, "height", 240, NULL);
                        ^
test/foo3.c:23:39: warning: object 'GtkWindow' has no property 'height'
  g_object_set (window, "width", 320, "height", 240, NULL);
                                      ^
test/foo3.c:24:29: warning: object 'GtkWindow' has no signal 'delet-event'
  g_signal_connect (window, "delet-event",
                            ^
3 warnings generated.

One of the features I wanted to add before blogging, was to also use the clang-style spelling corrections. For the last warning, it would say "did you mean ‘delete-event’?" Of course, there’s still much more to do than that to make the plugin feature complete.

This plugin will not work just with GTK+ source code. Because it’s using GObject Introspection data, it should work for any GObject library for which the GObject Introspection data has been generated.

The code is not ready for public consumption, so I am not releasing it just yet. My plan is to find time in the very near feature once my critical bugs are under control (or worst case during Christmas again :) and work on bringing the plugin into shape and trying it out on some larger examples. See below why trying it on larger examples first is quite important to figure out whether this plugin will ever be useful for the general public. When that is done, I plan to dump it in a public git repository for all to enjoy.

So, how does it work?

At its very core, the plugin walks over the Abstract Syntax Tree (AST) produced by clang. For the above example we simply handle calls to g_signal_connect_data and g_object_set. In order to verify whether the given signal or property name exists, we need to know the exact type of the object we are calling this function on. This is a problem that cannot always be solved.

What the plugin can currently do to solve this problem, is to determine where exactly the object pointer is assigned in the same function. If the object pointer is a GtkWidget *, we could at least assume that the object contains all signals and properties belonging to GtkWidget objects. In the next line, it is possible that the value of a call to gtk_label_new() is assigned to the object pointer. In this case we know the object is of type GtkLabel and as a result we can catch more errors.

The above strategy works fine on simple examples. The challenge is to make this work for larger programs. It might be a reasonable assumption to say that often an object is created, properties set and signals attached in the same function. However, there might be many cases where an object is created in a separate function and only a GtkWidget * type is returned. When the function is in the same compilation unit, it will still be possible to find out the full type though.

It is already clear that the plugin will never be able to catch all errors. Still I expect it to be pretty helpful. Another case which is interesting to handle is the following:

GtkWidget *widget;

if (can_edit)
  widget = gtk_entry_new ();
else
  widget = gtk_label_new ();

g_object_set (widget, ...

We will never be able to report all possible errors in this case. For example, if widget is assigned a GtkLabel and we use a property from GtkEntry, we cannot catch it. What we can do is tag the widget variable with both the GtkLabel and GtkEntry types and put out an error if a property or signal is used that is neither in GtkLabel nor in GtkEntry.

Why not just program in a higher-level language, then you would not need a plugin like this?

Good question.


To be continued …

ANSI to HTML conversion courtesy of a2h

Merged “treemodel-fix” branch into GTK+: call for testing, blog post series

August 22nd, 2011 by kris

Over the last few months I have been working on a “treemodel-fix” branch, which I just merged into GTK+ as announced on gtk-devel-list. Two commits in February of this year touched the row-deleted handling of GtkTreeModelFilter and GtkTreeModel:row-deleted documentation (0c3da06 and f632956). When exactly GtkTreeModel:row-deleted should be emitted has always been a nasty inconsistency amongst models (I wrote about it in May 2007, which turned out to be wrong), so my interest was sparked into really trying to understand this inconsistency and how to fix it.

This resulted in the “treemodel-fix” branch, which I could only start working on in May this year. After I finally solved the GtkTreeModel:row-deleted issue for real (details will be in my next blog post), I decided it would be good to also solve problems in another area which has never been 100% clear to me: reference counting GtkTreeModelSort and GtkTreeModelFilter. I brought these under unit test and fixed any issue I could find, which took much longer than I expected. And finally, after adding quite some unit tests, I now dared to review and apply a couple of GtkTreeModelSort/GtkTreeModelFilter patches which were waiting in Bugzilla.

The code is now in the master branch and will end up in GTK+ 3.2. For heavy users of GtkTreeModelSort/Filter, this would be a good time to test your code against GTK+ from master and report any regressions you may encounter. If things look good, I will consider merging the branch in GTK+ 2.24 as well in 1 to 2 months from now.

It has been 9 years since I first started working on GtkTreeModelSort and GtkTreeModelFilter. Finally having the feeling that you fully understand what is going in these pieces of code is an interesting one after so many years ;) To make sure this knowledge does not get lost, I wrote extensive documentation containing most of what I’ve learned in the last months, which has been committed as part of the branch (see files gtktreemodel.c, gtktreemodelfilter.c, gtktreemodelsort.c). I will also run a series of blog posts on the matter, covering:

  • The real story behind GtkTreeModel::row-deleted
  • Reference counting in GtkTreeModel
  • Improved performance in GtkTreeModelSort and GtkTreeModelFilter
  • Limitations on visible functions in GtkTreeModelFilter

CoreText backend now in Pango master

April 17th, 2011 by kris

A few days ago I merged the first part of the CoreText backend into Pango’s master branch, after bitrotting on my disk for a full year (apologies for that). The upside is that it also got a year of testing on my machine :) The CoreText backend is enabled by default on machines running Mac OS X 10.5 or higher and used instead of the older ATSUI backend. Because the older ATSUI API has been deprecated since Mac OS X 10.5, and more importantly because the ATSUI API is not fully available in 64-bit mode on Mac OS X 10.6, we were in need of this CoreText backend. When using GTK+ on Mac OS X 10.4, nothing changes, since CoreText is not (publicly) available on these systems.

So far, the CoreText backend was mostly based on the existing ATSUI code, so it should be working nicely for most people. If not, you are welcome to file bugs in the new coretext component in the Pango module in GNOME bugzilla.

There is one missing piece and that is also where the CoreText backend’s structure is going to deviate from the ATSUI backend. The ATSUI backend has never been really good at handling font fallbacks and fonts for non-Latin languages (see 608929). This is one of the things I want to get right in the CoreText backend and will be the second part of this project. I do have some things in place in a local branch on my disk, but it is not working yet as it should. Hopefully, I can find some spare time in the coming months to finish this. Progress can be tracked in bug 647969.

Though up first is a context switch back to GTK+ to review and fix a couple of things around GtkTreeModelFilter, GtkTreeModel’s row-deleted signal and to further extend the unit tests in this area.

GDK 3.0 on Mac OS X

December 29th, 2010 by kris

In the GTK+ 3.0 branch, GDK saw quite some changes recently. Firstly, a last part of Benjamin Otte’s rendering-cleanup was merged, which removes GdkDrawable. Now that GdkPixmap and GdkImage were already removed before (in favor of using their Cairo counterparts), there’s no need to abstract these away behind a GdkDrawable. Only GdkWindow is left to deal with basically.

The other large refactoring is the “GDK backend” branch that was recently merged. Before, you could only select a single backend at compile time, resulting in a libgdk-<platform> and libgtk-<platform>. GDK has now been refactored to properly separate the backends from the generic “core” GDK code. It is now possible to compile multiple backends into the GDK library. Perhaps in the future loadable backends will be possible as well. This work is in particular interesting for linking in both the X11 and Quartz backends on Mac OS X (for testing, comparing and debugging), and X11 and the upcoming Wayland backend on Linux. I am pretty eager to try a both X11 and Quartz enabled GDK on Mac OS X, but still some work is left to do sorting out the platform-specific code in libgtk. But once that is done, it should be possible, the GDK part is already done.

All in all, I am pretty excited about all the attention GDK has received in the last months after being neglected for a long time. In GTK+ 3.0, GDK is much easier to port to other platforms than it was before. I hope a trend has been set and GDK will be further simplified in the future.

I have tried my best to keep the OS X backend up to date over all these changes and refactorings. It seems to be working fine, so it is in shape for GTK+ 3.0. Let’s say it is at least as good as the last GTK+ 2.x releases, maybe even better.

I really hope we are done with refactoring for a while now, so I can focus again on reviewing and implementing missing features in the backend :).

Refactoring GtkTreeView using GtkCellArea

December 29th, 2010 by kris

Over the last few months Tristan van Berkom has been working on GtkCellArea. GtkCellArea can be described as a generic class that can be used for layouting and rendering sets of GtkCellRenderers. Before, widgets dealing with GtkCellRenders, such as GtkTreeView, GtkCellView and GtkIconview, all implemented this by themselves. In GtkTreeView, most of this code was hidden in gtk_tree_view_column_cell_process_action(), a function that not many people dared to touch and a function more fragile than a box of wine glasses.

I tried to support Tristan by showing him around in the more obscure parts of the GtkTreeView code, showing him some interesting corner cases and by reviewing the new code. As soon as it was possible I attempted a migration of GtkTreeViewColumn to use the new GtkCellArea. To my surprise, this was much less painful than I had expected, which is a good thing :) After that we had to spend a lot of time polishing things and fixing corner cases, finally everything was merged in the GTK+ 3 branch. Furthermore, Tristan has worked on porting GtkComboBox/GtkCellView and GtkIconView over to use GtkCellArea as well. We expect these changes to be merged in time for GTK+ 3.0 as well. What is great is that we managed to do all of this without introducing API incompatible changes, so existing GTK+2 code using GtkTreeView will continue to compile and work as is.

I think the end result is great, the GtkTreeViewColumn code got a well-needed refactoring, code duplication amongst GtkTreeView/GtkIconView/etc. has been reduced and we have paved the road to properly support height-for-width in GtkTreeView. We hope to work on the height-for-width support in the near future, this will not be trivial task as we will have to take a closer look at the validation machinery of GtkTreeView and perhaps revamp that as well. During this process I hope to incorporate some changes I made to the validation code in a local branch, with these changes it is possible to remove the idle handler that goes over all rows in the GtkTreeModel in the background for measurement[1] by trading in scrollbar accuracy and perfectly sized columns. With this, we can support large models without having to explicitly enable fixed height mode (in fact, this mode can then be removed). There is a possibility that we end up moving this code into a separate class (maybe GTK+-internal at first) as well, which can be re-used by GtkIconView to support displaying very large models (currently GtkIconView will likely fall apart when you try that).

Rests me to thank Tristan for the hard work!

 


[1] Footnote for users of large GtkTreeModels: However, the entire model will still be fully iterated because of the reference counting mechanism in GtkTreeView/GtkTreeModel. Properly supporting lazy loading of models will require different changes to GtkTreeView but mainly to the GtkTreeModel interface to have real support for this.

Optimizing legacy code

October 21st, 2010 by kris

Earlier this week, I finally traced down an interesting “bug” in GTK+’s Mac backend. People were complaining that scrolling in certain applications worked very slowly. Which got me puzzled for a good while, since all tests I use showed no obvious performance problems. Profiling a test that did expose this slowness showed that a lot of time was spent on color conversion. Also, it turned out this problem only occurred when drawing to a GdkPixmap first and later copying this GdkPixmap to a window.

So why was this color conversion going on? We were creating a CGImage backing the GdkPixmap using the colorspace returned by CGColorSpaceCreateDeviceRGB(). Judging from the function name, this seems alright. But closely, very closely, reading the documentation revealed the gory details. After switching this to use a different, now generic, color space (as suggested by the documentation), all performance issues were solved. Basically, color conversion from the “device” color space to the “generic” color space was happening, which is now no longer needed.

But not so fast! This change seemed to work fine, after all it is just a color space change, but for the particular test case I was debugging it introduced very awkward drawing issues. This took a long while to track down and it turned out to be another problem with how we implemented GdkPixmaps. Also this has been fixed.

(For details see bug 615917 and especially 624025).

People may wonder why I am spending my copious spare time on debugging GdkPixmaps while all of this is removed in GTK+ 3. The reasons are twofold, firstly debugging problems like this greatly extend my understanding of the Mac platform. This will also help when I am profiling GTK+ 3 code in the future, perhaps the same problems are encountered.

Secondly, I want to leave GTK+ 2.x in a mostly stable shape before fully turning my attention to GTK+ 3. I am planning to fix two more rendering issues in 2.x: one rendering glitch with scrolling windows that are inside an offscreen window and another with drawing depth 1 pixmaps. After that, GTK+ 2.x should be in a pretty good shape rendering-wise.

That might be a good point to switch focus to GTK+ 3.x. Of course, we can always backmerge changes to GTK+ 2.x if useful, for example fixes and improvements to the GtkSelection/DnD code.

To end with a brief note on Mac OS Tiger compatibility. We have always attempted to keep GTK+ working on both (Snow) Leopard and Tiger. I think we will continue with that for the time being, since I still have access to a machine running Tiger. However, in case Cairo goes Leopard-only and drops support for Tiger and earlier, GTK+ will have to follow suit.

Unfortunately, I couldn’t make it to the GTK+ hackfest this year. There seems to be good stuff going on, particularly interested in the GTK+ 4 plans but haven’t seen much elaboration on those yet.

More GTK+ rendering cleanup and Mac

October 14th, 2010 by kris

Since my last blog post two or more rendering-cleanup branches followed, which all got merged into master. So some more debugging was needed to get everything to work again on Mac. An interesting observation is that with each subsequent rendering cleanup, it became easier to get things going again on Mac. Very likely a good sign that we are on the right track to make GDK more X11-agnostic and easier to port.

Either way, as far as I can see GTK+ master runs pretty well on OS X now (including offscreen windows). The last rendering thing that really needed fixing was GtkTreeView (surprising or not?), which was actually sometimes resizing its GdkWindow while in the expose handler. This has mostly worked for a decade, but fell apart on OS X recently, since Cairo Quartz does not support resizing surfaces, so instead we destroy and re-create. The tree view is now patched in such a way that all resizing is done before we get to the draw method, so this resizing is no longer needed from inside the draw handler. I added a bunch of old scrolling test cases to the main tree view scrolling unit test, and all tests pass, so we should be safe. If your application depends heavily on tree view scrolling and you experience issues with GTK+ master, report this ASAP and we can get it fixed. Stand-alone test cases are appreciated as always :)

With the rendering working fine again on Mac, I hope to focus on other improvements now.

Finally: the work that has been done on the resize grip for GtkWindows is actually great news for GTK+ on Mac. Mac applications typically don’t have a window manager frame and thus rely on a resize grip. We had to leave the default Mac resize grip enabled, even though the GTK+ application didn’t expect such a grip there, obviously leading to sometimes awkward situations. So far I didn’t turn off the Mac resize grip (they seem to work fine together), since for GtkWindows without resize grip we still need some kind of fallback.

GUADEC, and the GTK+ rendering-cleanup branch and Mac

August 12th, 2010 by kris

Lanedo was so generous again to provide accommodation for GUADEC so I could be around for pretty much the entire week. For the first time in years we had proper space for hacking, so a bunch of my colleagues and me spent most of the week hacking. We also talked with people, honest! Also power was plentiful available (often a problem). In its entirety GUADEC was pretty well arranged this year, thanks to all volunteers involved!

Either way, for most of the week I worked on getting GTK+’s rendering-cleanup branch to work properly with GTK+’s native Mac port. This involved debugging a bunch of evil/nasty clipping issues and hunting for missing cairo_destroy() calls after I figured that that can actually be an issue (on Mac). Result: the rendering-cleanup branch works fine on Mac now. As a second project I got offscreen windows to work in the Mac port, for now only in the rendering-cleanup branch. I hear all of this was merged in master yesterday!

The good part is that most of the rendering code has now been dealt with and doesn’t need much additional work as far I can see now. There’s still enough to do though, should be looking into selection/clipboard support (there’s some patches pending for this), keyboard/input methods, perhaps some of the performance issues people have mentioned (though in general, performance is pretty okay), etc. Ah yea, I must really finish up the CoreText backend for Pango as well before my code for that starts bitrotting…