Grussen aus Berlin

So we are in Berlin now with a good amount of people for the hackfest. The apartments are nice, the wireless is working out fine so far and there are plenty of snacks and beer. Though we seem to have run out of beer already, but I heard rumors it's going to be fixed soon ;) One problem is though that the weather outside is too nice to actually sit inside all day and hack. However, it looks like this is going to change Tuesday/Wednesday. This morning we started with presentations after we finished transforming one of the living rooms into a “theatre”. Everybody just fit in the room and it's a pretty funny sight :) I had the honor of starting off the presentations track this morning. I think a lot of people have actually been thinking about the future of GTK+; what new features to add and how to move forward. We hope to have a lot of discussions about all these ideas everybody has. At Imendio we've also been thinking about where we want to go with GTK+. We presented our “vision” on GTK+ during this mornings presentation; my slides can be found here. We hope to have more discussions about this this week. Later on we will post a document with a more elaborate description of these ideas. As for hacking, I was recently inspired by dom's and arc's GDI pixbuf loader. For this week I've decided to do something similar for Mac OS X. The CoreGraphics framework has an ImageIO library with loading and saving support for a lot of image formats. I hope to get a pixbuf loader using this running during the hackweek. It will greatly simplify the build process for GTK+ on the Mac as well as shipping applications.

Attack of the arrow keys

In complex widgets there are often so many possible actions and so little keys. In GtkTreeView this certainly holds for the arrow keys. Since its inception, the arrow keys have been used to move the focus cursor (the dotted rectangle). For GtkTreeView configurations with editable and/or activatable cells (think entries, checkboxes) the left/right keys will allow you to navigate between them. When there is a horizontal scrollbar, the horizonal arrow keys also do scrolling. This makes sense for a lot of people. There is another camp, which claims that left/right should expand/collapse nodes. This is the standard on a lot of operation systems and it does kind of make sense. However in GtkTreeView shift+left/right has been allocated for expanding and collapsing nodes. I've been blocking the idea of making left and right expand and collapse nodes for a very long time, since we really need the arrow keys for moving that focus rectangle. At the beginning of the 2.12 cycle I kind of gave in, since ctrl+left/right was also bound to moving the focus cursor. This basically accompanies ctrl+up/down that moves the focus cursor up/down without changing the selection. And thus left and right now expand and collapse nodes. And guess what, other people now find these new key bindings awkward ;) As examples where this is awkward gconf-editor and tag editors are noted. Now note that both of these are lists, where the usually cited example by the “left and right should expand/collapse” camp are things like nautilus, or any application with a tree and no editable or activable cells. So, as a solution I am currently thinking of the following, to cover both completely different situations and use cases:

  • Left and right moves the focus cursor in lists.
  • Left and right expands and collapses a node if it is a parent. If a node is not a parent and has editable and/or activable cells, move the focus cursor (this will cover testtreefocus even).

When no action is to be done, left and right could scroll as usual. Does any UI person has other suggestions or opinions? Some background information: #105895 – Please add common keybindings for the TreeView #465516 – Impossible to switch cells with the left and right keys

Lowlands 2007

With 4days3hours7mins idle time on IRC I returned last Monday from a Campingflight to Lowlands paradise 2007. Having been there for the fifth time in a row, this year I also enjoyed myself very much despite the crappy line-up. We'd love to see much more punk and metal bands, which seem to be on the decline at this festival. Anyway, we made loads of fun on the festival terrain and did see some of the bands: Heideroosjes, Madcaddies, Editors (partly, I think it was kinda boring because I don't remember what they played), Kasabian (partly, and from the outside while chatting), Eagles of Death Metal, The Killers (partly, because it was boring), Brand New (these guys have an identity crisis or something, seriously, such crap), Games in Concert (partly, this was quite cool: a big Dutch orchestra playing music from video games), The Rifles, Turbonegro, The View, Interpol (this concert, was really, really good; superb sound and lightshow), Kaiser Chiefs (a big contrast, boring music, bad vocals, annoying light show), Balkanbeatz/Russendisko (this is awesome party music), Funeral for a Friend (partly, really as bad as the name), The Answer, Nine Inch Nails (partly, not my kind of music, but the sound blowed people out of the tent), Motörhead (sat outside and enjoyed), Arcade Fire (partly, scarily happy people), Tool (which was just way too awesome). So that's it, I guess we should go again next year if they manage to get a better line-up ;) Oh oh oh, and before I went to GUADEC and vacation and Lowlands this year I finally saw Me First and the Gimme Gimmes! Awesome band, really. (more blog entries later since I am a bit behind).

Back again and left the country again

The last months have been very busy. Lots of stuff to do, exams, little stress and not feeling all that well mentally. Fortunately fixed most of the stuff up in the week before GUADEC by dropping some things, something that was really, really needed. This took a long time, because I felt really bad about dropping it. Eventually got over it and hope people will pick up the work (which I am sure they will). Heard I passed one of the exams (which I thought I ruined), don't know about the other one yet. Bought a ticket for Lowlands (5th time!!!) anyway, even though I might have to do a re-take the day after. Then off to GUADEC. Had a really good time there, meeting up with a lot of people. I think my talk went okay as well, my slides can be found here for the people that are interested. I will post notes/minutes of the GTK+ meeting we had at the GUADEC Monday ASAP. Flew back to the Netherlands on Sunday, and right now, on Monday, I am sitting in Berlin having a beer. We don't know where we will go next since we didn't book hotels yet, but it looks like a nice start of a really needed vacation. I will be trying to work a lot on my BSc thesis though, since I want to receive my BSc in September… I also started hacking on a new application!! More on that later, it is not very special though and people are telling me that I should really start using something called “git”. My co-workers are still in the process on learning how to pronounce the Dutch “sch”., they are getting there though.

Column resizing, part two

People will remember my post on column resizing from about a month ago. I did some more work on this over the last few days, based on the nice suggestions left in the comments of that blog entry and some discussions with people. I ended up implementing something which basically only recalculates the expand values when the width of the tree view itself changes, or the number of expand columns. So if the user resizes a column, the expand values will not be changed and the weird/chaotic behavior is gone. You can find the results in the latest patch in the bug (#316087). A small side effect at this moment is that when the expand flag is turned off, the column will be “reset” to use its original requested size (see the last comment in the bug report for some more detail). I am not yet really sure if I like this. Opinions appreciated of course. At this stage I am pretty happy with the behavior, so good chance that this patch will find its way into GTK+ 2.11.x soonish.

Annotating the past

When I am busy hacking on bugs (which is about the only thing I do these days when I have time for hacking …) a thing which I use very, very frequently is cvs/svn annotate in the viewcvs web interface. For files as big as gtktreeview.c (almost 15000 lines), it is impossible to remember every little detail of the code; why is it like this? which parts are affected when I change this? Before changing things I usually check the history of that code portion using annotate, to see what kind of changes were made before. With a few little clicks I can find reasonings, old bug reports with stack traces and test cases. I know you can use svn annotate from the command line, but having it in a web interface with cross reference is much more convenient. For me annotate in a terminal is useless. I was pretty disappointed to see that on svn.gnome.org, annotation is not possible in the web interface. Is there any way this can be made possible? I am pretty sure a lot of other people would also appreciate to have this feature back, since it is so useful for tracing back changes. (This has been filed as #395908 — together with the request for the old “theme” of the revision log page, which is much more clear IMHO). For now I continue using cvs.gnome.org for this, but at some point the amount of changes between the last cvs version and svn will be so big that this won't be useful anymore …

New tooltips API in GTK+ trunk

Well, it finally happened, the new tooltips API hit GTK+ trunk. Ever been annoyed by the fact that GTK+ does not support tooltips on insensitive widgets? Ever wondered about an easy way to implement tooltips for specific tree view rows? The new tooltips API solves these and other issues, to get started quickly see the example application aka test program: gtk+/tests/testtooltips.c. There will be some more improvements in trunk as the code matures; probably a bug fix here and there, and the positioning code isn't quite right yet…

GtkTreeView column resizing

The infamous column resizing bug, #316087, has a good amount of duplicates. While it might look like a programming bug which needs to be fixed, there is actually much more involved: what you see happening is actually "correct", but it looks really strange. I've been looking at some other toolkits to see whether they support a likewise expand flag and how they solve this issue. More details under the cut, since it's a pretty lengthy piece. The columns in GtkTreeView support live resizing, in fact non-live resizing isn't even supported. In general this works very well. However, GtkTreeViewColumn also has an "expand" property. All extra horizontal space left after allocating size to the columns is equally divided between all columns with the expand flag set to true. This is really useful in cases where you want to give the most important column in your view the extra space, when it is not the last (rightmost) column (by default this rightmost column gets the extra space). For example: if you are writing a media player, you would probably set the expand flag on the column holding the track name / title. What's the big deal here? Create a tree view with two expandable columns, make all columns resizable, look what happens when resizing. Let me elaborate. Suppose we have the following columns:

   [column0][expandable1    ][column2][expandable3    ][column4] 

If you try to resize the column “expandable1” (using the handle between “expandable1” and “column2”) you will notice that as soon as you press the mouse button the column separator will jump to the right. What's actually happening here? Well, the column is set to use-resized-width mode, and the resized-width has just been set to the actual width of the column PLUS the extra size from expand (that's where the mouse cursor was when you pressed the button). Of course, since the column is still expandable, it receives extra space on top of the resized-width. What happens if you try to resize column2? Column2 grows, while both expandable1 and expandable3 shrink. Because column2 is growing, there is less extra space to divide between expandable1 and expandable3. It looks really weird, but the behavior is 100% correct. A possible bug fix which came to mind: as soon as a user resizes a column, turn expand off on all columns, and for all columns set the width to their requested width plus the extra space allocated to them. This should actually work if you apply the patch from comment #26 in #316087. Automatically turning off the expand flags is not the nicest solution of course. After a suggestion from Nickolay, I started to look how other toolkits handle this. I've only had a quick look at some toolkits; if there are errors in my quick analysis or if there's a toolkit with a really nice resizing mode missing out, please let me know. From a quick look I figured that Windows does not support live resizing, so it falls out of the scope of this discussion. Java's Swing has a pretty thought out approach to resizing (I've looked at JTable here). The actual resizing happens in the doLayout() method. If the table itself resizes, the change of width will be distributed to all columns in the table. If one of the columns changes width, JTable will do resizing according to the resize mode set by the programmer:

  • resize-off: column widths won't be adjusted, a horizontal scroll bar is used when the sum of the column widths is bigger than the width allocated to the table.
  • resize-next: use the column after the resizing column to absorb the change in width. With this mode the column separator between adjacent columns can be changed without affected the other columns.
  • resize-subsequent: use all columns after the resizing column to absorb the changes.
  • resize-last-column: adjusts the size of the last column only.
  • resize-all-columns: with this mode all columns are adjusted, also the one which is being resized. It does look a little awkward.

The minimum and maximum column widths are respected if they are set. You can find some nice graphics which might make everything more clear here: http://java.sun.com/products/jlf/ed1/dg/higp.htm#999756. JTable does not seem to have an expand flag for columns. Cocoa's NSTableView has likewise resizing modes (although a little different here and there) since Mac OS X 10.4. It does not support an expand flag on columns. ETree/ETable does not support an expand flag like GtkTreeView does. Instead you set an expansion value and columns all get a share of the extra space based on their expansion value. Interesting is that it seems that only columns marked as resizable are allocated extra space. When live resizing, only columns to the right of the column being resized actually change width. So all in all it looks pretty similar to the (default) “resize subsequent” mode in JTable, however in ETable only resizable columns are modified. QListView in Qt3 has a resize mode property too, however it only supports none, all or the last column (deciding which column will be resized to fit the list view). Qt4 does not seem to have support for this; when the layout is updated columns are sizes based on a per-column size hint. Both do not support an expand flag. Being able to set a resize mode like in JTable in GTK+ might be nice, but the only thing it can solve is nicely resizing columns without increasing the width of the list view (ie. avoiding a horizontal scroll bar). Introducing this won't help our expand flag problems, since also with a resize mode resizing will look weird. (Unless somebody comes up with a brilliant special resize mode with takes expandable columns into account). Another interesting observation in the bug report by John Bryant says that the expand flag is actually only really used to get nice sizes for the column “on start up”. After that the expandable flag is of course still active, but the changes most probably aren't that huge. In summary, after writing this piece, I actually think that disabling the expand flags after the first column resize by the user is a fair way to solve this problem. We should keep in memory that adding resizes modes might be nice in the future. Suggestions, comments are of course welcome. If nobody has better ideas I will probably end up committing something like the patch in comment 26 mentioned above.

Scrolling bugs fixing spree

This has been going on for a while already :) The fixing spree actually began already 2 months ago, and I decided it was about time to finally write a GtkTreeView scrolling test suite. I've been wanting to write such a test suite since my scrolling bugs fixing spree around GTK+ 2.6 and 2.7. Back then I had a bunch of test cases in my ~/testcases/ and before committing I would check whether a fix would break any of those test cases. A lot of work and prone to errors. Around that time I was already thinking about combining those test cases to one test app. Of course it never happened. Of course I also lost track of the test cases I was testing with. So during Imendio conf this year (back in November) I slowly started working on this test suite. Finishing it took much, much longer than expected and I kept finding small bugs and adding tests. But finally I ended up with a pretty useful test application, it already helped me a lot when testing a bunch of fixes which will go into GTK+ HEAD today. For those interested, the source is here (reading it in a browser messes up the formatting btw): http://www.babi-pangang.org/~kris/testcases/testtreescroll-26dec06.c It does need some more improvements at this point, it relies on the font used and the speed of the machine for example. And of course I intend to add a test case to this thing for each new scrolling bug I get. When GTK+ gets a proper testing framework I hope to integrate this test suite with that testing framework. I hope most bugs are gone now. If you find any regressions or new scrolling bugs in HEAD, please file a bug. So what's next? Writing a test suite for tree models. I already have some notes on this, hopefully I can write the code during January. (I suspect I will be mostly busy partying during the SVN cut-off :) ). (And of course, a happy 2007 to all of you!)

Quartz GTK+ and Intel Macs

Oh anyway, if you want to play with the OS X port of GTK+ on your Intel Mac, you want to have this Cairo patch: https://bugs.freedesktop.org/show_bug.cgi?id=8939 From what I've been told Cairo might switch to another Quartz backend soon. From reading the code it looks like that one suffers from the same issue but I haven't been able to test for myself since the new backend seems to be far from compiling on my machine …