Taschenorakel.de

Postings tagged with Maemo

Performance and Memory Usage of Evolution Data Server

Openismus asked me to perform some benchmarks on Evolution Data Server. We wanted to track the progress of recent performance improvements and identify possible improvements. Therefore, I tested these versions of EDS:

The code is in a phonebooks-benchmarks repository on Gitorious with a full auotools build, and with a script to build and test all these versions of EDS. So you can try this too, and you can help to correct or improve the benchmarks. See below for details.

EDS offers various APIs to access the address book. The traditional interface was EBook, which has served us well in GNOME 2 and Maemo 5. However, some APIs such as batch saving are missing in the upstream version. Also its asynchronous API doesn't follow the conventions established later by GIO. To overcome these EBook shortcomings, and to make efficient use of GDBus, the EBookClient API was added in EDS 3.2. We can even use the backend EDataBook API, and that lets us measure the overhead imposed by using D-Bus.

I tested the back-ends with different numbers of contacts. For each benchmark, and for each contact count, we create an entirely new private database. D-Bus communication was moved to a private D-Bus session. To avoid swapping, the maximum virtual memory size was limited to 2 GiB per ulimit command. This limit probably caused the crash of Maemo 5's EDS in the test with 12,800 contacts, but I have not checked that yet.

Contact Saving

These benchmarks simply store a list of parsed contacts in the address book. This simulates use cases such as the initial import of contacts upon migration or synchronization.

To avoid possible side effects from lazy parsing, we retrieve the attribute list for each contact before starting the benchmark. With EBook from Maemo 5 and EBookClient since EDS 3.4, contacts are saved in batches of 3,200 contacts. This partitioning was needed to deal with resource limitations in the file backend. All other EDS variants must save their contacts one by one.

Contact saving, without batching

EBook, EBookClient, EDataBook implementation

As expected, the effort for contact saving grows quickly when not using a batch API. This is because a new database transaction must be created and committed for each contact. Things look much better when using the batch saving API which was available in Maemo 5 already, and was recently added to EBookClient:

Contact saving in batches

Batch saving performance of EDS 3.4+ is just excellent: Although slowly growing with the number of contacts, it remains below a threshold of 3 ms per contact even for 12,800 contacts. That growing effort can be accounted to growing attribute indices. The initial peak (until 50 contacts for Maemo 5, and until 400 contacts for EDS 3.4+) can be accounted to database setup cost.

In terms of performance there is no difference between using EBookClient or EDataBook (which avoids D-Bus).

Contact Fetching

A very basic, but essential, benchmark is fetching all contacts. To get a first impression I just fetched all contacts without any constraints.

Fetch all contacts

EBook, EBookClient, EDataBook implementation

Contact fetching performance decreased significantly during the EDS 3 series and then got better again: Fetching all contacts with 3.4 takes about 133% of the time that EDS 2.32 needs and even 225% of Maemo 5's time. With EDS 3.5 contact loading time is improving again, making the EBook version of EDS 3.5 comparable in performance to EDS 2.32. Git archeology and quick testing identifies Christophe Dumez's bugfix as the relevant change. Apparently the file backend didn't make optimal use of Berkeley DB transactions.

Still there is significant room for improvement, because:

  1. simple contact fetching with EBook 3.5 still takes 175% of the time Maemo 5 needs.
  2. EBookClient 3.5 is still 20% slower than EBook 3.5, and 64% slower than EDataBook.

This basic test shows already that the chosen client-server architecture of EDS causes a non-ignorable overhead.

It would be absolutely worth investigating how Maemo 5 reaches its far superior performance: After all it even beats EDataBook. I remember having spent significant time on avoiding vCard parsing and string copying. I also remember having replaced the rather inefficient GList with GPtrArray at several places. Some of the ideas have been ported upstream during Openismus' work for Intel. Apparently there are more gems to recover.

Fetching by UID

Fetching contacts by UID simulates lazy loading of contact lists: Initially, we only fetch contact IDs. We only fetch the full contacts when the device becomes idle, or when contacts become visible on screen. This approach is needed because even the fastest implementation (Maemo 5) needs several seconds to fetch any contact list of realistical size on mobile hardware. Another useful optimization we implemented on the Nokia N9 is fetching of partial contacts, that only contain relevant information, like for instance the person's name. EDS doesn't support this optimization.

As a first test we fetch contacts one-by-one, without using any kind of batch API:

Fetch by UID without batches

EBook, EBookClient, EDataBook implementation

The good news is that this chart shows quite constant performance for each client.

The bad news is that contact fetching is pretty slow: 3.9 ms per contact, as seen with EDS 3.5, translates roughly to 390 ms to fetch only 100 contacts on this hardware. Considering that typical mobile devices are roughly 10 times slower than my notebook, these numbers are disappointing. Especially if you consider that EDS 2.32 was about 4 times, and Maemo 5 even about 13 times faster. This are entirely different worlds. It should be investigated what causes this significant performance regression from EDS 2.32 to EDS 3.2+. One also should try to port the performance fixes of Maemo 5.

The performance reachable under ideal circumstances is shown by the EDataBook client. This only needs about 50 µs (0.05 ms) to fetch one contact by its id. Directly accessing the address book via EDataBook is about two orders of magnitude faster than the current EBookClient. That's the goal that EDS can, and should, aim for. Apparently a significant amount of time is spent on performing D-Bus communication, whereas the requested task can be performed by the backend within almost no time.

However, this data was acquired by fetching the contacts one by one. We can surely do better by using a batch API. That should drastically reduce the overhead caused, for instance, by D-Bus. But neither EBook or EBookClient provide an API to fetch contacts by lists of contact IDs. The thing that comes closest is filtering the contacts by a disjunction of UID field tests:

(or (is "id" "uid1") (is "id" "id2") ...)

So I tried that. The results for such queries, using batches of UIDs, look like this:

Fetch by UID in huge batches

EBook, EBookClient, EDataBook implementation

This chart speaks for itself. To remain responsive and appear fluid while scrolling, applications should render at 60 frames per second. To reach that framerate newly visible contacts must be fetched and rendered within less than 16 ms. EDS apparently cannot meet that performance goal even on desktop computers. Considering the huge performance differences between client-server access and direct access, as seen when fetching contacts one by one, it seems very worthwhile to add dedicated support for fetching multiple contacts by UID. The most obvious approach would be adding a batch API in the spirit of e_book_client_add_contacts(). Another solution would be adding more fast paths to the query processing code.

Filtering

EBook, EBookClient, EDataBook implementation, the queries used

Contact filtering is relatively efficient when using fields such as last-name, for which indices are hit. Still, the D-Bus overhead is noticeable: EDataBook needs less than 60% of EBook's or EBookClient's time.

The times to match long prefixes and suffixes look quite similar when hitting indices.

The behavior of EBook for short name prefixes is a bit strange. The EBook API is now deprecated, but it could still be worthwhile to identify the issue causing this strange behavior, so that it can be avoided in the future:

Interestingly, there seem to be no functional database indices for email addresses or phone numbers in more recent versions of EDS:

The behavior of Maemo 5's EDS is a bit surprising, as I know that Rob spent significant amounts of time on adding Berkeley DB based indices to that EDS version.

It might be worth optimizing index usage in EDS, because prefix and suffix searches are commonly used in mobile applications. Prefix searches need to be fast, for quick feedback during auto completion. Suffix searches need to be fast, for instance to provide instant caller identification.

Memory Usage

Memory is cheap those days. Still, especially on embedded devices, you should keep a close eye on the memory consumption of your software. Obviously, memory consumption grows with the number of contacts used:

Resident Set Size (RSS)

It's nice to see how memory consumption has reduced from release to release. It's also good to see that EBookClient seems to use slightly less memory than EBook.

You might miss the graphs for Maemo 5 and EDS 2.32. I had to drop them for this chart as they show serious memory leaks, preventing any useful examination. Apparently the leak really is in those versions of EDS: The EBook benchmarks for EDS 3.2+ are using exactly the same code but don't show this bad behavior.

Notice that I've accumulated the client's and the backend's memory consumption. This allows us to estimate the cost of EDS's client-server architecture. Apparently this architecture increases memory consumption by about 40% in these benchmarks.

While the RSS usage gives us information about the efficiency and correctness of the code, it's also interesting to check the virtual memory size needed by the benchmarks. Please take the following numbers with a reasonable grain of salt: I got these numbers by simply adding together the virtual memory size of the client and of the backend process, as reported by the processes' status file. A proper measurement would process the maps file to properly account for shared memory regions.

Virtual Memory Size (VMS)

The first issue we notice is the massively increased memory usage of EBookClient 3.2. It's almost 40% more than the others. Fortunately, the issue seems to have been fixed already in EDS 3.4.

At first glance, the very low virtual memory usage of the EDataBook benchmark is impressive. It seems to consume only 40% of the client-server based benchmarks. Still, there is a fairly high chance that this huge delta must be attributed to my poor measurement here: Assuming perfect code segment sharing there only remains a delta of about 20 MiB, which would be nothing but the RSS delta of EDataBook and EBookClient. It would be nice to investigate this in more detail.

RSS usage per contact

This chart shows the memory per contact after the contact saving benchmark. The overall memory usage per contact has grown dramatically by almost 40% in EDS 3+. The most efficient approach is apparently to directly access EDataBook, which consumes only 55% of the RSS per contact, compared to the client-server approaches.

RSS usage per contact, model only

This high memory usage per contact is a bit surprising since, after subtracting effects from library and database initialization, the memory usage per contact remained constant between EDS 2.32 and EDS 3.5. The parallel usage of both Berkeley DB and SQLite in the file backend might be to blame, but this is currently pure speculation from me.

The temporary regression in EDS 3.2 was apparently fixed. The increased memory usage of EBookClient and EDataBook over EBook is because the EBookClient and EDataBook benchmarks, in a slightly unrealistic bias for performance, store both the EContact and the VCard string for each contact.

Conclusions

The developers of Evolution Data Server have paid good attention to performance and have successfully implemented significant improvements. However, EDS releases regularly suffer performance regressions, and the performance of EDS still isn't good enough for usage in mobile devices. Fortunately the performance problems are solvable. Some fixes will be straightforward, such as adding more batch API (or fast paths) for query processing. Others will need careful performance monitoring: For instance when activating more database indices, to speed up queries, we must be careful not to slow down contact saving.

A not so trivial improvement would be adding a direct access API for reading the local database. The speed and memory usage measurements show the value of such API: Direct access is significantly faster than via D-Bus in most usage cases, and it seems to significantly reduce memory usage.

Another significant improvement should be finishing the file backend's transition to SQLite: Using two database backends in parallel significantly increases code complexity and has measurably bad impact on memory consumption.

Usage Instructions

The full source code of this project is in our phonebooks-benchmarks repository on Gitorious. You'll need a fairly recent C++ compiler because I also used this project to get more familiar with the new features of C++11. I've successfully tested g++ 4.6.3 and g++ 4.7.0. Clang 3.0 definitely won't work because of incomplete lambda support.

Other than that, you'll need Boost 1.48 to compile the benchmarks. The optional chart-drawing module uses ImageMagick++ and MathGL 2.0.2.

There is a simple script for building and installing the tested EDS versions. The configure script will give instructions.

To finally run the benchmarks just call src/phonebook-benchmarks, and to draw the charts run src/phonebook-benchmarks-mkcharts.

When doing your own tests that needs a non-trivial vCard generator take look at src/phonebook-benchmarks-mkvcards.

Outlook

It would be interesting to take a more detailed look at the virtual memory usage.

Also it would be educational to compare these results with other address book implementations. The first candidates I have in mind are QtContacts on Tracker and Tizen's native contacts API.

We didn't cover EBookView and EBookClientView yet. These views take a query and notify the application when the contact set matching the query has changed. Typically, every user interface needs to use them.

We also didn't talk about the calendar API yet.

Well, and most importantly we at Openismus would enjoy fixing the identified performance problems.

FOSDEM 2012

FOSDEM is only real with Belgian Waffles FOSDEM in 2012 was an exciting (and naturally, exhaustive) conference again. It's great to have so many relevant people who are all active in the free software world together in one place. It's also a great opportunity to discuss radical new ideas, ideally while experimenting with Belgium beer. Which is what we usually did when we weren't at the conference site.

It was nice to see Jarno and Esko at the conference, too. We even stayed in the same hotel. I hope they enjoyed the Ethiopian lunch as much as I did. And perhaps they're not too angry any more that we lead them to drink Absinthe ;-)

Jon and I gave two talks. Jon's talk (slides) was about Maliit as a project, explaining what Maliit is (and what it is not), combined with a short history lesson about the project. I tried to outline the difficulties of mobile text input in general (slides), picking some use-cases that are known from the desktop world and showing why simply copying the use-cases and their known interaction models does not work very well. I honestly liked Jon's talk more though.

Neither of us two actually managed to visit other talks, even though we wanted to. We had to ask Jarno, Esko and others about what great talks we missed. Apparently there were quite a few :-(

Our Maliit T-Shirts were well received, though we usually only handed them out when someone listened to our Maliit ramblings long enough.

We were asked about accessibility several times, which is currently not within the scope of Maliit but perhaps something to think about in the future.

We also got to talk with the people working on (text) input in Redhat and Intel, mostly in the context of Wayland. There are some interesting opportunities to get things (more) right this time around.

Thanks to our employer, Openismus, for sending us there!

The infrastructure of the Maliit project

Maliit T-Shirts! It took us a while to transform the Maliit project into a real opensource project. At first there was only public code, later some wiki pages @ meego.com together with constantly changing components in the official MeeGo bugtracker, then a public mailing list.

After that we tried to become independent of MeeGo, but neither freedesktop.org nor the GNOME project could give us a suitable home. So we had to go with our own infrastructure in the end, which probably was the best we could do, in any case. We now enjoy our own website (mostly a wiki, for which we can also analyze the traffic), our own IRC channel, our own public bugtracker, our own mailing lists and a build bot. We also make use of other services such as launchpad.org and the openSUSE Build Service, both for packaging but also as part of our continouous integration setup. Both services provide nightly builds for Maliit, for example (though we still lack packages for ARM).

But there was always one thing missing: T-Shirts. Now that this is solved, too, we can finally call Maliit a real opensource project ;-) Hopefully we'll soon have another group photo of the people who've been involved in the project over the years. I'll make sure to bring a couple of T-Shirts to FOSDEM, so make sure grab Jon or me if you want one.

How we enable others to write 3rd party plugins with Maliit

We finally published a video about Maliit - an input method framework including a virtual keyboard - and 3rd party plugins. Kudos goes to Jon for making time for that.

This video highlights one of Maliit's key features: pluggable input methods which come with their very own user interfaces. The Chinese input methods show how Maliit offers support for composed characters. The video is proof that 3rd party development for Maliit (open-source and proprietary) is not only possible but also happening.

maliit.org states that "it should be easy to customize existing input methods or develop powerful new input methods, whether for profit, research or fun", we actually mean it.

The harder question is of course how to motivate others to actually get started on input method development with Maliit. For that, we have a multipronged strategy:

  1. Provide sufficiently polished reference plugins that can show off Maliit capabilities but also serve as inspiration for new plugins (hence the BSD license for reference plugins). Our reference plugins are currently using Qt/C++ (Maliit Keyboard) and QML (Nemo Keyboard). We also have PySide support, but no one contributed a reference plugin yet. This gives choice to interested input method developers, and we think that's important. The reference plugins serve another role when it comes to designing new API: They become our testbed, allowing us to verify our API proposals.

  2. Ship Maliit with a bunch of example plugins and example applications. None of them try to be complete. They are all self-contained though and usually show one feature at a time. This can be tedious to maintain, but we believe that examples need to stay small and focused, otherwise developers won't look at them.

  3. Documentation that is easy to consume. Our documentation is not as concise and clear as we'd like it to be, but it's slowly improving. We also experiment with videos that can serve as an introduction to more in-depth (text) documentation.

  4. Packages for most common Linux distributions. This one seems obvious, but sadly, it's quite a lot of work for us to keep up with it (and we already use automated services such as Launchpad and OpenSuse Build Service). In the hope to attract dedicated packagers we wrote down some packaging guidelines

  5. An architecture that had 3rd party plugins and multiple toolkit support in mind from the start. The plugin developer facing API needs to be easy to use and clearly documented. This will be the focus of the upcoming 0.9x series.

We will demo Maliit @ FOSDEM 2012, hope to see you there!

Into the Wild

We kicked off the new 0.81 release series together with a nice announcement: We have our own bugtracker now!

This means that Maliit has a near complete project infrastructure, all available under *.maliit.org, and all that thanks to Karsten, the always professional and very experienced hostmaster here at Openismus.

There is one more thing that we need (as demonstrated by me when I made my first broken release), and that's a simple build bot setup for continuous integration. Right now, we still rely on Nokia's infrastructure. I am confident that buildbot will fit all of our requirements, as long as it is trivial to maintain.

I am also happy that we improved our documentation significantly, thanks to Dave. He translated the important documentation bits into proper English and made it more accessible, demonstrating his doxygen skills. As a bonus, he also updated the project's README files, something we had neglected for a long time.

Future development

Regarding the Maliit development, I think we have simplified things a lot. D-Bus activation for the Maliit server (which finally means one server instance per user session) and the new support for plain QML plugins makes it almost trivial to get started with Maliit. We also let go of the critically acclaimed MeeGo Keyboard in Maliit upstream, which made me a bit sad of course.

Still, it probably was the right decision: MeeGo Keyboard is heavily fine-tuned for Nokia's N9 and it has some dependencies that are hard to satisfy outside of Harmattan. Over time, with ever changing requirements, the code has naturally evolved into a rather complex design. The result, however, is a very polished product, and ultimately, that's the only thing that matters (even though many opensource developers will disagree, strangely enough). Everyone in the team is proud of what we have achieved.

At the same time, I can understand how new contributors will be put off by all the complexity. So Maliit upstream will instead focus on the very basic but almost trivial to build Maliit Keyboard. For new contributors, that's a good thing. For us, it means the possibility to fix shortcomings in the plugin API. This is important, as one of our main goals has always been to enable others to write great input method plugins for Maliit, which will then run on any platform that Maliit supports. The Swype VKB plugin and the Japanese VKB plugin for example both demonstrate that we are on a good way, but I think we can do better.

Maliit itself still needs a good reference plugin, of course, even if only as a showcase (though I want it to be more). All this doesn't mean that MeeGo Keyboard goes away; its development will continue in the MeeGo Touch repositories, just as before (effectively degraded as just another Maliit plugin). But what we can take over, hopefully, is our experience when it comes to creating one of the best virtual keyboards currently available.

Qt Quick best practices: Using Components

The next article in the series about Qt Quick best practices has been published (but don't miss out the other one about property bindings). This time, I talked about Components, and how they can help to keep your QML code clean and maintainable. The team behind the N9 Developer blog has been a great help to me, especially Ville Lavonious and Matti Airas. I am also thankful for the additional input (and proof reading!) from Jon Nordby and Sauli Kauppi. Thanks guys!

Miniature 0.5 'London 1851' released

From the release notes: "Miniature now supports different languages thanks to a determined community of translators. Thank you for your effort! This is why we are dedicating this release to the first international chess tournament, celebrated in London on 1851.

Miniature 0.5 is being released for MeeGo Harmattan (Nokia N9 & N950) and Maemo (Nokia N900). Thanks to everybody involved in the initial Maemo attempts and the experimental version that was made available after the Miniature 0.4 release."

We also improved usability, compared to the previous release, but there's still a ton of work left.

A bit of history

I started working on Miniature – a chess client for freechess.org – in November 2009, after reading the Call for Contributors. Even though we had a pretty cool P2P feature (based on Telepathy and developed mostly by Dariusz Mikulski), it never quite reached the original goal: playing chess online. Back then I was learning how to create UI's with Qt Graphics View, which was all the rage at the time. Well, we now know that writing real UI's with that technology is a major PITA, but for my pet project, it was just too much. I got lost in the struggle.

For the next 18 months, Miniature was basically dead. Another failed project that started so promising. Quim did not want to give up though. After the N9 announcement, he launched a second Call for Contributors.

Perhaps I responded to his mail because I was embarrased at the idea of people wasting time trying to salvage the working parts of Miniature; there simply wasn't much to salvage! So I started again, this time with a very clear goal: online chess, and online chess only. Let others create the actual UI and whatnot. Focusing on one prominent feature and not having to worry about the UI worked well for me, even though I had to iterate over some architecture ideas until I felt comfortable. Quim in the meantime started to prototype the UI with QML. It was impressive to see his results, a level of polish I could have never achieved with my Qt Graphics View approach. At some point the backend was good enough to be sewn together with the frontend and suddenly we had achieved where I failed before: A touch enabled chess client for the N9 that can play chess online.

Having my own useful application available on the N9, published through OVI store, means a lot to me. I hope others will enjoy Miniature as much as we enjoyed re-creating it the second time around.

Using MeeGo Keyboard from git on your Nokia N9

Usually AEGIS, the N9's security framework, protects system packages from being replaced. As such, files belonging to a system package can't be overwritten. And that's definitely a good thing, because otherwise each download from OVI store would put the user at a considerable risk.

Maliit is such a system package, but its flexible architecture allows for a creative way to replace the MeeGo Keyboard with a more recent version. This can be useful if you want to testdrive new features and to … nah whom am I kidding, it's purely for fun!

Be warned though, the following hack requires you to enable developer mode on your N9. Don't ever activate it unless you're absolutely sure what you're doing to your N9. It would be unforgivable to brick this beauty because of some misguided hack the planet attitude.

First we need to find a MeeGo Keyboard tag that will be compatible with the installed Maliit framework version on your device. Check that the output of

$ apt-cache showpkg meego-keyboard

matches the dependencies mentioned in the tag's Debian control file and the packages installed in your scratchbox ARMEL target.

Apply the community patch on top of the chosen tag. It renames the package to meego-keyboard-community and only installs the plug-in's .so file, together with a renamed CSS file (libmeegotouch requires that CSS file names match with library names).

This mean that we won't uninstall the regular package, as we still depend on most the other files that meego-keyboard installs.

Now build the Debian package. Copy it over and login to the device, then gain root access via devel-su. It's recommended to make a backup of /usr/lib/meego-im-plugins before installing the package.

After installing libmeego-keyboard-community, remove libmeego-keyboard.so from /usr/lib/meego-im-plugins, to avoid in-fights between the two plug-ins. Use

$ gconftool-2 -s /meegotouch/inputmethods/onscreen/enabled -t list --list-type string [libmeego-keyboard-community.so, en_gb.xml]
$ gconftool-2 -s /meegotouch/inputmethods/onscreen/active -t list --list-type string [libmeego-keyboard-community.so, en_gb.xml]

to activate the community plug-in. The language settings applets will most likely get confused, so be prepared that enabling new language layouts might only work directly via GConf from now on.

Gain user access and kill meego-im-uiserver. It should now load the new community plug-in. If you want to get the original MeeGo Keyboard back, uninstall the community package and copy the .so back from your backup. Alternately, you can try to reinstall it:

$ apt-get install --reinstall meego-keyboard

Have fun!

Best practices in using Qt Quick

I am writing a series about best practices in using Qt Quick. It will be published on the official N9 Developer blog. The introduction and first article have already appeared. Your feedback on that series is very much welcomed.

Better GTK+ support in Maliit

So far, using Maliit's virtual keyboard in GTK+ applications required fetching and compiling a GTK+ input method brigde yourself. Not any more. With the latest release, GTK+ applications should just work out of the box, thanks to Jon's integration efforts. Right at the same time, Łukasz was looking into using Maliit together with GTK+ applications on his Ubuntu desktop. He did a great job testing Jon's improvement and also contributed patches to properly update GTK+'s input method module cache. When compared to the Qt support, the gap in terms of supported features is quite large. We would like to further improve the GTK+ support and contributions are certainly welcome.

Better key override support for Maliit

Dynamic key overrides in Maliit's Quick plugin

Krzesimir Nowak joined Openismus in the beginning of August this year. Not only is he a very talented developer (or, as I once said, the first one to actually fill the gap Daniel left), but he's also fun to work with.

Just before I went on my vacations in September, I left him with some nice tasks to improve one of the cool features in Maliit: Dynamic key overrides. The way I had set up the tasks I knew he would trip over bits of hideous code and seeing how he could deal with it was part of the exercise.

For now, Krzesimir's work on Maliit is finished. With 25 commits, two of them being bug fixes in said ugly code, Krzesimir did an outstanding job while thoroughly understanding and fixing one of Maliit's core features in a rather short time span. Of course he will tell you that it took him way too long ;-)

Thanks for your contribution, Krzesimir, and well done!

Real users, real feedback

Maliit on the N9

We released Maliit 0.80.7 on Friday. Over these last days, I am doubly proud about our project. Not only did the N9's virtual keyboard get astonishing reviews across the board, but what's even better: We managed to keep this software open-source. In our communities, there will always be those who focus too much on technical aspects. I remember the technical struggles we had even within MeeGo! But now we get feedback from real users who couldn't care less about what Qt or MeeGo Touch is, and to be honest, that's a refreshing change.

Being here at Qt's Developer Days 2011, it feels great to get such feedback directly, from first-time users of the Nokia N9. Especially the fine haptic feedback and the keyboard's accuracy gets noticed.

I also had the possibility to see a Japanese input method — running on the N9 and powered by Maliit. Seeing how well this plugin already integrates with the platform, I feel that our architecture yet again has been justified. I am looking forward to see more Maliit plugins, and more platforms using Maliit!

Using C++ enums in QML

When mapping Qt/C++ API's to QML, or, to put it more precisely, making a Qt/C++ API available to QML, road bumps are to be expected. One such bump is the mapping of C++ enums.

If you happen to create enums inside a QObject, then it will be exported to QML via the Q_ENUMS helper:

SomeEnumsWrapper
    : public QObject
{
    Q_OBJECT
    Q_ENUMS(SomeState)
public:
    enum SomeState {
        BeginState,        // Remember that in QML, enum values must start
        IntermediateState, // with a capital letter!
        EndState
    };
};

You will still need to declare this class as an abstract type for QML to be able to use enums from it (put in your main function for example):

qmlRegisterUncreatableType<SomeEnumsWrapper>("com.mydomain.myproject", 1, 0,
                                             "SomeEnums", "This exports SomeState enums to QML");

Now in QML, the enums can be accessed as '''SomeEnums.BeginState'''. Note how the enum is accessed through the exported type name, not an instance.

But what if you've put your enums into a dedicated C++ namespace? Then the same mechanism can be used. Let's start with the namespace:

namespace SomeEnums {
    enum SomeState {
        BeginState,
        IntermediateState,
        EndState
    };
}

We can re-use the idea of wrapping enums in a QObject type, with one tiny change:

SomeEnumsWrapper
    : public QObject
{
    Q_OBJECT
    Q_ENUMS(SomeState)
public:
    enum SomeState {
        BeginState = SomeEnums::BeginState, // Keeps enum values in sync!
        IntermediateState = SomeEnums::IntermediateState,
        EndState = SomeEnums::EndState
    };
};

The process of forwarding all your enums through this mechanism can be tedious, but being able to use enums properly in QML properly will improve the readability and maintainability of your QML code.

For a fully working example check Maliit's Qt Quick support

So there are people who say that Nokia's N9 isn't MeeGo ...

... and those people are right, if we followed the MeeGo Compliance Spec to the letter.

But at the same time, Nokia's N9 is one of those devices that the MeeGo community has always been waiting for.

Nokia's N9

If "This is not MeeGo!" is the only thing that comes to your mind whilst reading about all the N9 excitement then you still haven't realized MeeGo's biggest problem: No. Compelling. Devices. And if - at the same time - you are one of the MeeGo project leaders, then you should do yourself and everyone else involved with MeeGo a favor and simply resign.

We need more visionary leaders than you.

Brave New World

Today, we managed to get out the first release of Maliit as an independent project. As far as possible without API break, we started to use our own Maliit naming convention for installation paths, library names, etc.

During that cleanup, Jan Arne did a tremendous job improving our build infrastructure. Instead of Qt's .prf files, Maliit now uses pkg-config everywhere. Plugin developers don't have to think about install paths - they can simply read it from the .pc files, for instance:

pkg-config --variable pluginsdir maliit-plugins-0.80

The version number at the end indicates another nice improvement: versioned libraries and plugin interfaces, which means several Maliit versions can be installed in parallel (although you never want to run more than one server per session).

To install the Maliit framework into a custom directory (say, $HOME/install), simply use:

qmake -r M_IM_PREFIX=$HOME/install

Afterwards, set your PKG_CONFIG_PATH to $HOME/install/lib/pkgconfig and compile the Maliit plugins. Quite honestly, it has never been easier to develop input methods for Maliit than with this release.

Qt Contributors Summit is over

Really enjoyed the Qt Contributors Summit. Nice, open minded people. Café Moskau turned out as awesome location for technical orientated meetings.

Even held my own little session about my griefs with QObject life-cycle. We found some few chances for improvement, but we also sadly had to conclude that proper two-phase construction and destruction isn't possible in C++, unless you forbid stack allocation and usage of the delete operator. Actually had my little pervert moment of pleasure when realising that Thiago seems a bit jealous for the freedom GObject gets from plain C.

Still wondering a bit if there's really no way to implement proper two-phase destruction in C++. Must we really bribe the C++ standard committee to enhance the specification?

I am attending the Qt Contributors' Summit

Input methods and Wayland in Qt5

I was attending the Qt Contributors' Summit 2011. During the key note, it was promised that everything is up for discussion so I took my chance to discuss about improving input methods support for Qt5.

Maliit Architecture Overview

After some initial discussions with Kristian Høgsberg (Wayland, of course) and Jørgen Lind (who works on Qt Lighhouse), I also addressed Wayland. It became clear that one needs some kind of input method interface directly in Wayland. Kristian immediately started with a small prototype, in order to explain better how a Wayland compositor can provide a much better window management policy than what we currently have with Maliit and X11.

I think the session itself was really successful. I was surprised at the strong interest in this topic.

It became apparent that we should do something about Qt's input context API. For instance, add more input methods hints, come up with a better interface that describes the focus widget, preedit handling, orientation support and so on.

Now we only need to agree on how to make it happen :-)

Decent examples, at last!

Jon spent a lot of time in the last weeks improving our documentation for Maliit. However, while documentation is good (and necessary), Jon thinks that examples are better. I can only agree with that.

I am planning to use Jon's example material for an input method workshop at one of the upcoming MeeGo Freedays (German only) here in Berlin, just to see how useful it is for newcomers.

Maliit starts to feel more and more like a real open-source project, and I am proud of that. Just compare our wiki from end of February with the current, information-packed version, or take a look at the steady traffic on our own mailing list (started only in March this year). Or perhaps just try googling it!

I am really happy to eventually see real contributions and input method plugins from others, which makes me think that we are on a good way.

But this is still only the beginning, and more interesting news will follow soon.

Maliit Session at MeeGo Spring Conference 2011

I was attending the MeeGo Spring Conference as an invited speaker, talking about Maliit - the MeeGo Input Methods - and how to develop custom input method plugins for it.

Maliit Architecture Overview

We had more people going to the talk in Dublin than to this one, but at least the slides and the recording are available online now.

Questions for MeeGo

The MeeGo Spring Conference in San Francisco was nice, perhaps not so much for the press folks (uninspiring key note, no product announcements). As a speaker, I was fortunate enough to receive sponsorship from the Linux Foundation (special thanks to Brian Warner for the unbureaucratic approach to this). I got to meet a lot of people face-to-face and the hallway track spawned interesting discussions, circling around questions such as:

And, of course the poisonous:

(I am going to be mean and won't answer the questions for you, as I am too opionated here, sorry.)

Other than that, San Francisco was of course great. I also spend some time travelling through California; the country side is simply gorgeous.

Writing QML-based input methods for Maliit

This week I pushed a simple QML-based virtual keyboard to our MeeGo Keyboard repository. It's functional, but don't expect too much. This functionality will most likely never arrive in MeeGo 1.2, sorry folks.

Getting Started

Let's continue with the good parts instead: The required C++ code was kept to an absolute minimum and in fact it's only needed to wrap the QML resources into a Qt/C++ plugin that can be loaded by our framework. If you want to write your own QML-based input method plugin for Maliit, then this is the required interface:

class MyQmlBasedInputMethodPlugin
    : public QObject, public MInputMethodQuickPlugin
{
    Q_OBJECT
    Q_INTERFACES(MInputMethodQuickPlugin MInputMethodPlugin)

public:
    MyQmlBasedInputMethodPlugin();

    //! \reimpl
    virtual QString name() const;
    virtual QString qmlFileName() const;
    //! \reimpl_end
};

The plugin's name is used for a specific GConf key. Once set to that name, the framework will load this plugin as the currently active one:

$ gconftool-2 -s /meegotouch/inputmethods/plugins/onscreen -t string "WhateverNameYouCameUpWith"

qmlFileName returns the (absolute) file name (or URL) to your main QML file. The framework will set up the required QML environment and try to load this file.

QML components can interface with the application through a set of properties and slots, tied to a root context named MInputMethodQuick. It exposes the following read-only Qt properties:

Additionally, QML components can invoke the following Qt slots:

Please refer to the header file of MInputMethodQuick to access the full documentation (sorry, not available in MeeGo API docs).

Also, big thanks to Kimmo Surakka and Miika Silfverberg for all their help with this side project.

Self Compositing

Testdriving Maliit on the N900

Any QML plugin using MInputMethodQuickPlugin will support self compositing out of the box. That is, instead of letting the system compositor blend the application window and virtual keyboard window together into one, the virtual keyboard bypasses the system compositor and redirects the application's window to itself. This usually improves raw FPS but also cuts down on latency. Try running the MeeGo Input Methods service like so:

$ meego-im-uiserver -use-self-composition

This should result in a noticable speedup for your QML plugin. Self compositing is tricky, as it requires a well-behaving window manager (and believe it or not, mcompositor is the only one available getting it nearly 100% right). Usually an additional parameter combination of -manual-redirection, -bypass-wm-hint and -software will do the trick. For MeeGo 1.3, we want to activate self compositing by default, so it's good to know that your QML-based plugin will support this useful feature for free.

A QML-based virtual keyboard for Fremantle

MeeGo Keyboard Quick available in Maemo's devel-extras repo.

As part of the exercise I also packaged MeeGo Keyboard Quick for Fremantle - it's available from Maemo's extras-devel repository. Be warned though, this is a rough tech demo and as such, fairly useless. A nice advantage of it is that it allowed me to package a MeeGo Input Methods version for Fremantle that is completely free of any MTF/libmeegotouch components.

How to testdrive:

Instead of the test application, one should be able to use it in any other Qt application, as long as the MeeGo Input Methods service is running and the QT_IM_MODULE environment variable is set correctly.

To fight wrong expectations: I won't have the time to polish or to maintain this port, and from my first tests it would need undefined amounts of integration work to get it to run properly in Fremantle, starting with proper GTK+/Hildon support. If you are, however, interested in furthering this port, then please don't hesitate to contact us.

Qt Contributors' Summit

I am attending the Qt Contributors' Summit.

A bit odd for something with my background? Does that mean I am leaving the GNOME universe?

No. It just happens in Berlin, and I've just spent lots of time on letting QtContacts use some awesome GNOME technology (tracker). On the summit I'll try to convince some Qt core guys, that maybe UTF-8 would be a much better choice for the Linux port of Qt. It would improve interaction with kernel, DBus and GNOME libraries so much. Well, and maybe I can get them to consider more reasonable memory management for QObject: With Qt leaving the GUI corner it's simple parent-ownership model doesn't fit anymore. QtQuick already skips that obsolete model. Now let's also let C++ components benefit.

PS: If someone ever wants to modernize libebook, then looking at QtContacts API is a good exercise. It was designed to explicitly fix the issues we had with libebook during Fremantle. Actually even thought of making a GIR typelib for QtContacts - but that's a different story and maybe even doesn't make sense.

Painting Strategy in MeeGo's Virtual Keyboard

I've never been happy with the conclusion in the influential blog post "Qt Graphics and Performance — The Cost of Convenience" by Gunnar Sletta: If you want performance, downgrade QGraphicsView to a mere canvas with a single QGraphicsItem. It defeats the whole purpose of decomposing the problem into many small QGraphicsItems and is therefore entirely counter-intuitive. One might be quick to ask what Qt Graphics View is good for (and one might find the answer here), but instead I would like to present an alternate solution to Gunnar's which reaches the same performance but embraces the very nature of Qt Graphics View.

Flashback

Gunnar took the example of a virtual keyboard (which doesn't really do anything, it just sits there and paints itself). And as it happens, I've been working on a real virtual keyboard. At one point, our painting strategy was exactly following the advice of Gunnar, but once new requirements piled up, it became increasingly harder to deal with that painting strategy.

The new requirements were custom key sizes, flexible layouts, custom font sizes for each label, custom font colours, custom key background and custom key labels. And all that dynamically during runtime please.

In MeeGo 1.3, applications will be able to make us of that. For example, when writing an email, the application can temporarily turn the enter key on the virtual keyboard into a "Send" button. Should the user enter an invalid email address, the application might choose to disable the "Send" button until the mistake has been fixed.

Reinventing QGraphicsItems - or not?

As the required logic for keys becomes more complex, so does the data structure representing keys. The paint method we used in the single keyboard item was about to become a real mess. Especially after I added geometry to keys, I knew that I was, in fact, reimplementing QGraphicsItems. But I could not reuse them because of performance reasons! Or was it possible that Gunnar's blog post pointed into the wrong direction?

Maliit's overlay item strategy

So I thought about my dilemma and figured out that the actual constraint is rather the amount of paint event calls per frame, and eventually, how much screen area needs updating. With the single QGraphicsItem approach, every change triggers a scheduled repaint for the whole keyboard - even if it's only the label position in one key.

I then realized that only pressed or customized keys would need to be actively painted, and there we had it: An alternate painting strategy that blits the idle keyboard view into a single QGraphicsItem but lets active keys paint themselves as overlays. The rest of our team was sceptical about the idea, so Viacheslav Sobolev - a colleague of mine during my 11 months in Helsinki - had to first improve the performance benchmarks before the team would accept the fact that indeed we managed to keep the same performance, and even improve it for Qt's raster engine.

The Strategy

Even if the general idea of overlay items is very simple, I summarized the following steps that one needs to take care of:

As a bonus, you can find the basics of the strategy in a modified benchmark of the original blog post. I added two new options "-overlayitems" and "-fullscreen". The latter is useful for N900 where it helps to get rid of system compositor noise.

Is MeeGo Keyboard conquering GNOME3?

Maliit in GNOME3

You'd probably like me more if I had spend my time testing the upcoming release of MeeGo Tablet UX on this shiny new WeTab (I ♥ Openismus), but Jon couldn't resist to test-drive GNOME3 first. Well, and since we like our virtual keyboard so much, we just had to make it work of course.

Jon also wrote about the features shown in the video.

New features in MeeGo Keyboard

This week we published new features for the MeeGo Keyboard, including accent popups (activated through long-press on certain keys) and support for Chinese Input Methods. The latter still requires an IM engine that supports Cangjie for example to be really useful (not provided by MeeGo Input Methods).

Ubuntu users can easily test it out, as I updated the packages in the MeeGo Input Methods PPA. I also enabled all language layouts by default for those packages, as we yet have no real UI for the Desktop to control such settings. You will have to install the additional layouts package manually though (package is called meego-keyboard-zh-layouts).

One can switch to another language by swiping to the left or right (on the keyboard itself), which is admittedly a bit stressful with a mouse (and nigh impossible with touchpads!). It works quite nicely though when using touch screens. I am sorry for the strange transition animation, it apparently needs some adjustments for the desktop.

We'll also have some GNOME3-related news soon, so stay tuned!

Customizing the MeeGo Keyboard

The look & feel of the MeeGo Keyboard (comes with the MeeGo Input Methods) can be easily adjusted to your needs. In the last post I already gave a brief example on how to modify the graphical assets. In fact, you will find that the look is mostly defined by the graphics contained in that one SVG file. The elements' id's are referenced from the keyboard's CSS file, so it is a good idea to just leave them as-is, unless you really need more graphical elements. The CSS file is installed to a slightly different folder than the SVG file:

/usr/share/themes/base/meegotouch/libmeego-keyboard/style/libmeego-keyboard.css

If that looks a bit complex then it's probably because it is. When hit by new design requirements we didn't always manage to find a clean solution in time. But at least it works and there's even documentation available.

Most containers are named MImAbstractKeyAreaStyle - they describe the style of the widgets that we use to represent keyboard layouts. You won't find containers that describe the actual keys though (am sorry for that). Other than the CSS syntax, those containers don't share much with regular CSS attributes - MeeGo Touch allows you to define your own custom attributes, and that's exactly what I did, to quite some extent.

Reactive areas

The whole keyboard responds to touch events or mouse clicks. That is, the reactive areas of the keys cover the whole keyboard. A single key's reactive area is usually aligned with its bounding rectangle, unless spacers are involved. Spacers expand to fill the remaining width in a row, thus allowing flexible alignment of keys. Usability studies showed us that people expect a spacer's area to be consumed by the reactive area of the neighboring keys. The diagram to the left visualizes how reactive areas are constructed from key margins, keyboard paddings and spacers. Keyboard paddings override key margins, e.g, the top margin of key is replaced by the top padding of the keyboard, if that key is located in the top-most row.

For each keyboard layout, the amount of keys defines its style mode (only works if the amount of keys is in range of 10-15 or 30-45 and if sync-style-mode-with-key-count is enabled). These keyboard layouts can get a fully customized styling on their own, e.g., different paddings, key sizes, images, etc. This helps with pixel-perfect designs, but can also be a lot of work.

We avoided to blend CSS attributes with the keyboard layout files, in order to keep the latter reusable for any kind of device. The basic idea is that - for a new form factor - only the CSS file would need to be adjusted. However, there are certain XML attributes in the layout files that can be controlled from the CSS file. For example: A row of keys can carry a height attribute (small, medium, large, x-large, xx-large) which is then mapped to key-height-* CSS attribute, where the concrete height of each group is eventually specified. Thus, the declarative nature of the XML files is preserved.

I hope this post made it less daunting to go and create your own MeeGo Keyboard design. I would love to see some concepts that could potentially replace the current design!

Updated MeeGo Input Methods packages

Translucent MeeGo Input Methods on Lucid

I published new versions of the MeeGo Input Methods (framework and keyboard plugin) on the project's Launchpad PPA. It contains the API/ABI break that was announced in the beginning of this month.

At first I thought I would do this packaging only for others but I have to admit that I start to enjoy using my host system for input method development - it's really easier than having to use the MeeGo SDK or scratchbox even.

I also added some patches so that the on-screen keyboard docks itself to the bottom of the screen. For MeeGo Touch applications, focus widget relocation will work on the desktop now. If that's not enough for you then how about a slightly translucent keyboard background? For this to come true, you only need to modify the keyboard's SVG file, located at:

/usr/share/themes/base/meegotouch/svg/meegotouch-virtual-keyboard.svg

Search for this section:

<g id="meegotouch-keyboard-background">
  <g>
     <rect x="100" y="100" width="64" height="64"/>
  </g>
</g>

and add a opacity style property to the rect element like so:

  <rect style="opacity:0.5;" x="100" y="100" width="64" height="64"/>

You need to restart the meego-im-uiserver process to see the effects though. I will explain the other theming possibilities in another blog post.

The packaging problems I encountered in my last blog post are also solved: A Launchpad PPA keeps all packages in one repository, so one needs to explicitly mention the Ubuntu version in the package names, otherwise they can easily supersede each other.

MeeGo Input Methods for your desktop

Taken from http://wiki.meego.com/File:Text-input-2a.png I've been working on the MeeGo Input Methods project (codename "Maliit") for nearly a year now. The project provides a pluggable framework for input methods. It comes with a reference plug-in for a multi-touch-capable virtual keyboard.

It had bothered me that, even though our source code was available at gitorious.org, there were nearly no contributions from the outside. I attribute that to the difficulties when it comes to compiling all required components, but also to the lack of perceived openness.

We now offer packages for Ubuntu, through the Openismus PPA for MeeGo Input Methods, thanks to the packaging efforts of Jon. This is an offer for those interested in developing input methods for MeeGo. It's not targeting end-users (yet?) - a virtual keyboard might not be useful on a desktop, unless you have a touchscreen.

We also have a public wiki and if you wish you can visit us in #meego-inputmethods @ freenode.net.

Operator Overloading

Just wondered right now why Qt doesn't provide a greater-than operator for QSize.

Well, indeed: How would you define this operator? Maybe like this?

inline bool 
operator >(const QSize &a, const QSize &b)
{
    return a.width() * a.height() > b.width() * b.height();
}

Or is this the proper definition?

inline bool 
operator >(const QSize &a, const QSize &b)
{
    return (a.width() > b.width() || a.height() > b.height());
}

Mathematician might intuitively choose the first alternative, aka. covered area. I claim for UI problems usually the second interpretation is useful.

Funnily the Qt author(s) of QSize implicitly agree with my claim, as they provide:

inline bool QSize::isValid() const
{
    return wd>=0 && ht>=0; 
}

Which gives "(b - a).isValid()" computing the same result as my preferred interpretion of the greater-than operator.

Well, my currently preferred interpretion, within the scope of my current problem. Oh, and sans integer overflows and such "minor problems" - of course. Someone really cares about such "minor details"? :-)

So what tells this? API design is fun. Even more if you add operator overloading to the soup.

*Disclaimer: There is nothing Qt specific in this post. It only provides the example. *

Miniature goes Telepathy

Thanks to the work of Dariusz and Alban we now have P2P via Telepathy for Miniature.

Maybe it's worth to notice that we use Maemo's contact chooser here, and that it blends perfectly with our Qt application (we still have some crashes on our side though). Nice job from the Fremantle team! there!

About missing flights

Frequent fliers will know this, but to everyone else: If you ever should be that stupid to miss a flight, call the airline where you booked that missed flight as soon as possible. Otherwise they will cancel your inbound flight and bet on charging you an incredible amout of money for your previously reserved seat. For me they lost their €700 bet yesterday. Just took another airline.

Using DBus as lock-daemon

Recently I found this comment in the source code I am working with:

// what if both processes read in the same time and write at the same time, no increment

Please! Don't do such things! Don't just leave such comments in hope someone else will come around and will fix later. Please take the time to apply a locking mechanism.

Obvious choice when dealing with files would be to create a lock file. Unfortunately creating a file based lock isn't trivial, especially when you deal with portable software. Questions arise like: Is that system call really atomic in this context? Is the feature even available? Which characters can be used in the file name? Can it start with a dot? How much time does it take? Will it reduced lifetime of my flash media?

Uh, my head is spinning! Stop!!!

Somewhat understandable that my colleague just left a comment.

Well, fortunatly there is a more trivial solution for that problem. If you have DBus available. More experienced DBus hackers already know and will feel bored now, but to everyone else:

DBus service names can be used as locking mechanism!

Implementation would look similar to this:

bus.request_name('de.taschenorakel.locker.example')
bus.wait_for_name('de.taschenorakel.locker.example')

now some work...

bus.release_name('de.taschenorakel.locker.example')

Easy, not? Doesn't hit the file system. Fully implemented. Ready to use. Daily tested at your desktop.

One implementation of that concept can be found in qtcontacts-tracker.

GCC 4.5 - Awesome Release!

GCC 4.5 just was has been released yesterday. It's a really awesome release according to its summary of changes. My favorites:

Awesome release! Really awesome release!

QML Hype

So yesterday I've skipped the chance to watch some "exciting" QML demos in Helsinki. This was quite surprising to some of my KDE rooted team mates. They didn't understand how I could not show the slightest sign of excitement.

Well, but actually I wonder for months: What's actually the fancy and awesome, the brilliant new, the exciting part of QML? It doesn't seem to be rocket science. It's nothing new. Declarative UIs are done for ages. To name some very few implementations there are Windows and PM/Shell RC files, Glade, GtkBuilder. You want to mix declarations with managed code? XUL and XAML have visited that land. You want to use JavaScript for your UIs? Flash, XUL, Dynamic HTML and Web Widgets, GObject Introspection.

So what am I missing except that Qt finally catches up to its competition? It's a welcome addition, but why should I be overly excited and die of excitement?

Logging facility for Miniature

On Maemo 5, log output from your app isn't always accessible to the user. This has created problems for Miniature bug reports (see bug #8124). To solve this, I created a "Game Log" screen which allows to filter the messages (by a given log level, I might want to allow combinations, too). It also has a nice fat "Copy all" button, so that the log output can be quickly attached to a bug report.

Now I "only" need to add useful log information =D

Thanks to Openismus for letting me work on this.

Testdriving the UI Extensions for Mobile on Maemo 5

Reading about Nokia's UI Extensions for Mobile (sources available) I wanted to quickly try it myself. So I looked at the provided examples, and this video is the result of what I came up with (well, of course it is FOSDEM-induced). The provided API allowed me to easily apply my previous Qt knowledge, which is a nice touch. Sources for the example in the video app can be found here and here. Happy hacking!

Update: The UI Extensions for Mobile will not compile on 64bit architectures.

First Miniature .debs sighted!

Thanks to Mathias, Miniature is now suitable for debian packaging. He also uploaded a first test balloon which at least allows you to move pieces around. Feedback is of course more than welcome.

Personally I wish the board's cell size could have been made bigger, but 60x60 pixels is already the upper limit. It is now up to us - the Miniature team - to come up with clever techniques to make the board handling as finger-friendly as possible.

Qt 4.6 for Maemo: It works!

Today at work, David King kindly informed me that there was some new Qt package in extras-devel. This could only mean one thing - I immediately fired up my scratchbox environment and installed the packages, trying to confirm that this new version would run with Qlom. And in fact, it was surprisingly painless. Thanks to autotroll, a simple QT_PATH env variable did all the magic, hooray!

Both of us were impressed with the UI improvements. It's certainly a big step forward regarding the Hildonisation of Qt on Maemo5. The application menues look correct now. Button sizes, colors, animations, etc - it all comes together nicely, finally.

There are still some widgets that need more work, but for a tech preview this is a pleasant surprise.

Miniature

On another note, the timing for the Miniature project could not have been much better. We immediately switched to Qt 4.6, and it even runs on the N900. It feels good to know that we can stop using hacks and that we can start to do (most) things properly, staying as cross-platform as possible. Needless to say, Quim was happy, too.

Miniature - it moves!

How it begun

Miniature

When I read Quim's thread about the idea for a better Maemo chess app I knew I wanted to join the project. To me, it's all about the device and the sparkling Hildon UX. I really want a good chess app, for myself! I want to play chess online, everywhere! And I want to analyze games as (OK, maybe after =p) they happen. No more "I'll check this position later" (we all know this rarely happens).

So I finally started last friday. At this point, Quim and Andreas had already created a beautiful, content-rich wiki page. It took a while for me to digest it all, and I added information where appropiate.

Kick-starting the development

Andreas had registered a garage project, but we eventually decided to use gitorious for our repository. Gitorious' UI definitely improved over the recent months, and the possibility to have teams working on a single project - also known as not-so-extreme-dvcs-development - makes gitorious a better choice than github, at the moment.

Saturday night (what better things to do than coding some Qt - my soul will be forever lost) I had a first running example (see screenshot). Currently, Miniature can move between positions, using next/prev menu navigation (we don't need this functionality per se, but it's perhaps a good demonstration that the simple approach I took works).

So no matter the toolkit, no matter the outdated packages or the endless confusion I had with the various Qt repos at gitorious - this project is really fun! Hopefully we get to make a 0.1 release soon.

Show me your home screen!

To me the empty home screen* of the N900 looked like an invitation, so I tried to fill it up with useless stuff as quickly as possible. The home screen configuration menu offers app launchers (shortcuts), bookmarks, widgets and contacts. Let's go through all four options in detail:

So what's on my current home screen?

My current home screen

I know - it looks as if this was a Symbian smartphone (that is, ugly and horribly crowded). But I like it this way, at least for now =)

So what's on your current home screen?

*: I still think dashboard is a better name.

Computer chess and the N900

My first chess computer

Years ago, when I was thoroughly fascinated by chess, I always wanted a portable chess computer. When I finally got one (a Novag Piccolo, for the odd chance someone else had the same device) I'd take it with me whenever possible. It got worn out quickly, moving the small plastic figures required more and more pressure to make the computer acknowledge my moves. For each move you first had to "touch" the figure you wanted to move. The computer would beep and show 2 LEDs (one for each row and line), for a lack of better feedback. Then you'd put the figure to its target location and "touch" it again, with the same feedback procedure for a valid move. If the move wasn't valid the error LED was lit. Perhaps this wasn't the best user interface in the world (I yearned for a self-moving Mephisto Phantom which actually was a Fidelity Phantom), but it worked for me and I was happy.

The problem with computer chess

The downside came when I realized there was a set of moves for each difficulty level that would always win. Later when Deep Blue won vs Garry Kasparov I lost interest in computer chess, because it seemed you could either have an imperfect machine that was boring to play (a certain set of moves would always win), or a nearly perfect machine that would bruteforce its way to victory. At least that's how the future looked to me in 1996.

Could computer chess ever be fun again?

With the N900 device lease programme from the Maemo Summit I think I finally got my very own special version of a Mephisto Phantom: The chess app that is installed by default moves "by itself" (duh ...), and with Hildon's finger touch paradigm I have a similar "board feeling" as with my old Novag Piccolo. And damn - this N900 surely is portable!

How to make it less fun

Now you would think that with an ARM Cortex-A8 it should be possible to play challenging but also fun games. But here comes the frustration again: gnuchess - the chess engine being used - comes without the opening book. Of course there might be valid reasons to not include the opening book/end game database:

Only that chess engines are still too dumb to come up with meaningful opening moves on their own. Worse yet, gnuchess wasn't configured to randomize the outcome of its evaluation function. Which means: this device is still susceptible to the same strategy I used vs. my first chess computer nearly two decades ago!

Conclusion

The solution could of course be easy: Include the opening book and let gnuchess pick the worst move (even better: choose one randomly) from the lookup tables on easier difficulty levels, or limit how many moves into the game it is allowed to play "by the book". Also introduce random noise to force gnuchess into mistakes that are exploitable for casual players.

I will continue to play chess games with the N900. Let's try to improve the chess app though!

Who wants my feedback for the Maemo6-Qt tech preview?

During the Maemo Summit there were several talks about the upcoming Maemo 6 platform and also about the transition from GTK+/Hildon to Qt. One of them - the "(Introduction to the) Harmattan UI framework" also mentioned where to get the code for the Maemo 6 UI Framework from. So I went there and cloned the two available repos (tech preview of the framework, tech preview of the homescreen) together with the most recent Qt version that is also on that site.

But sadly, compiling the code wasn't possible for me. Apparantly because some header files were missing. The talk didn't mention a specific resource for feedback so I tried Maemo's Bugzilla. An e-mail to the git repo maintainer didn't yield any response (yet), either.

I reckon that my bug report on the Maemo bugtracker was filed against the wrong module (Qt on Fremantle), but where else should I post problems like that? Even if at this stage the above mentioned repos are probably not much more than a widget gallery it seems like a wasted opportunity to collect feedback, no?

Back from Maemo Summit 2009

So I am back from Maemo Summit 2009. Great people. Great show. Great talks. Great venue: Enjoyed it quite much to walk arround in the Westerpark, Marc-André loved the petting zoo.

Hotest topic, of course: The N900. Thank you Nokia for lending those devices: Feels so good to finally have one for personal use! Finally got ideas for some private N900 hacking when reflecting responses to Travis' and my talk.

Another hot topic was DRM on Harmattan. Fortunately David Greaves came to similar conclusions like I've reached so far: Maemo Security - Lockdown or Liberation. Could be I'm just a weirdo, but I seriously hope for game developers targeting Maemo: Already called Rover "My next Wii" in jokes for its nice screen and the acceleration sensor.

Well, and then there still was this disappointment about Nokia moving to Qt as their prefered UI toolkit. Actually I wonder why people see this as problem: GTK+ was created without Microsoft or IBM holding our hands, so why does everyone expect Nokia to hold our hands for Maemo? If we really care about this platform, it should be absolutely possible for us to provide a proper GTK+ based toolkit for Maemo 6. Ideally Nokia would publish Layout guides and stuff early, so that we would not have to play catchup too much after device launch. Motivation and specs. More should not be needed. Really.

Application Theming Tricks

From time to time applications need custom theming rules. Especially when the project has professional UI designers involved. So how to achieve this with GTK+?

Trivial Theming

Most easy and very wrong:

if (gdk_color_parse ("pink", &color))
    gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &color);

This will break and look childish as soon as your users use a custom color scheme.

Better:

static void
style_set_cb (GtkWidget *widget,
              GtkStyle *old_style)
{
    GtkStyle *style = gtk_widget_get_style (widget);

    if (gtk_style_lookup_color (style, "SecondaryTextColor", &color))
        gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &color);
}

static void
my_widget_init (MyWidget *widget)
{
    g_signal_connect (widget, "style-set", G_CALLBACK (style_set_cb), NULL);
}

This will allow theme designers to override your color choice. Notice that you'll have to update those color overrides when the theme changes. Btw, the "style-set" signal is emitted when the widget is realized, therefore you don't have to manually invoke the callback during widget construction.

Guess it's also worth to mention that Hildon provides convenience API for simple theming requirements.

Complex Problems

So for simple requirements GTK+ (and Hildon) have reasonable API support. Things become troublesome when your designers invent rules like "this widget has a rounded border and drop shadow, but only within buttons". Obviously border and drop shadow radius should be themeable and therefore are implemented as style properties, but how to impose this rule?

You could scan the widget hierarchy when choosing default values for your style properties:

button = gtk_widget_get_ancestor (widget, GTK_TYPE_BUTTON);
gtk_widget_style_get (widget, "border-radius", &border_radius, NULL);

if (button)
    border_radius = (button ? 12 : 0);

You'll quickly notice the flawed hard coded default value. Also such things are hard to override in theme files. So it's probably better to apply a custom theming rule via gtk_rc_parse_string():

static void
my_widget_class_init (MyWidgetClass *class)
{
    ...
    gtk_rc_parse_string
        ("style 'my-widget-style-clickable' {"
         "    MyWidget::border-radius = 2"
         "}"
         "widget_class '*.<GtkButton>.MyWidget'"
         "style 'my-widget-style-clickable''");
    ...
}

Application Theme Files

Looks like a perfect solution, until you realize that this rule is applied after all rules loaded from gtkrc files!

So how to inject this rule before the user's theming rules? This was a big question to me until I've found gtk_rc_add_default_file(). Well almost: This function only adds files to the end of the search path. Therefore it suffers from the same issues as gtk_rc_parse_string(). Fortunately the API author was smart enough to also provide gtk_rc_get_default_files() and gtk_rc_set_default_files(). Those functions can be used to apply application specific theming rules, which can be overwritten by the user - drum roll please:

static void
inject_rc_file (const char *filename)
{
    char **system_rc_files, **p;
    GPtrArray *custom_rc_files;

    system_rc_files = gtk_rc_get_default_files ();
    custom_rc_files = g_ptr_array_new ();

    g_ptr_array_add (custom_rc_files, g_strdup (filename));

    for (p = system_rc_files; *p; ++p)
            g_ptr_array_add (custom_rc_files, g_strdup (*p));

    g_ptr_array_add (custom_rc_files, NULL);

    gtk_rc_set_default_files ((gpointer) custom_rc_files->pdata);
    g_strfreev ((gpointer) g_ptr_array_free (custom_rc_files, FALSE));
}

int
main (int argc,
      char **argv)
{
    ...
    inject_rc_file (PKGDATADIR "/gtkrc." PACKAGE);
    gtk_init (&argc, &argv);
    ...
}

Update: Benjamin Berg just pointed out that priorities can be assigned to styles. So the following should work fine:

gtk_rc_parse_string
    ("style 'my-widget-style-clickable' {"
     " MyWidget::border-radius = 2"
     "}"
     "widget_class '*.<GtkButton>.MyWidget'"
     "style : lowest 'my-widget-style-clickable''");

Awesome, little know feature.

Well, and it is a phone!

So after months of denial it turns out, that the/we Maemo folks really built a phone!

N900 with Contacts application

GTK+ Hackfest is over

So the GTK+ Hackfest really ended yesterday. I absolutely enjoyed having all you guys arround me. I am absolutely confident, that all the ideas collected and exchanged here will lead to some great GTK+ 3.0 release. It cannot be said often enough, but even in our highly connected world face-to-face meetings are invaluable for our work. This can be understand as invitation to order your tickets for Istanbul right now, if you are uncertain still.

The big BVG strick was a littlebit unfortunate - so we could not use all the U-Bahn stations arround us, to visit other exciting places. Well, but considering how exhausted many were at the end of the week, this reduced mobility probably was a good thing. We could have risked to party too much.

Guess I've learned alot about event organization during that week. Most importantly and as a hint for any successor: Next time I'll sleep on-site instead of driving 50km per day to sleep at home.

I have to thank Behdad for asking me to organize this event and Murray for allowing me to organize this on Openismus time. Thank you dad for helping with the chairs. Thank you Michael for being there on Wednesday. Thank you Ulrike and Marc-André your patience.

Linking to library.gnome.org

Recently the brave gtk-doc guys introduced a tool called gtkdoc-rebase, which updates external links in your API docs to point on the GNOME Library. The gtk-doc.make script has been updated to run gtkdoc-rebase on make dist. Unfortunatly all this pretty stuff doesn't work out of the box on Gutsy, as two premise have to be fulfilled to make this voodoo work:

Updating all the gtk-docs I've got would have been a boring task. So I wrote a little script which updates the uncompressed index files, when documentation exists in the GNOME Library:

Use it carefully, as it sends HEAD requests to library.gnome.org for every gtk-doc package not having that <ONLINE> tag yet.

Did I mention already, that this script processes uncompressed index files only? So call sudo gunzip /usr/share/gtk-doc/html/*/index.sgml.gz before using it.

Canvas Review

As announced by Murray already I am working for Openismus now. First task I got assigned was providing patches for some binding glitches in GooCanvas. Seems I complained too much about GooCanvas' code during that task. So Murray asked me to review GooCanvas, HippoCanvas and libccc to figure out which canvas would fit best for diagrams and reports in Glom.

As we have that nice canvas overview on the GNOME Wiki already, I added additional information to that wiki page. Thank you Emmanuele for updating the clutter records, btw.

HippoCanvas dropped out quickly for lacking printing support and more importantly for its boxed, HTML/CSS like layout. This approach doesn't seem to be flexible enough to support things like table relationship diagrams.

GooCanvas seems to be the most complete canvas, but it has some issues:

By provinding a function to pass a custom cairo context to the rendering routines its does only the trivial part of printing, but leaves pagination, which is the hard part of printing, to its users. Pagination usually is not trivial as you have to avoid splitting text lines and pictures on page boundaries:

Borken text due improper pagination

Techniques to avoid this glichtes include moving of short paragraphs and pictures to the next page, cutting paragraphs and text at cell and line boundaries, rewrapping text and rescaling pictures. I could not find hooks for doing this in GooCanvas, so when using GooCanvas for Glom at least the hooks for such features would have to be added to that canvas.

As it seems grid fitting is implemented for tables only. This causes a blurry and unprofessional look. It also lowers rendering performance as unnecessary antialiasing and resampling operations have to be applied.

Demonstration for pixel alignment

GooCanvas currently also has problems in its code architecture. Its data model structures are all public which puts quite some burden on maintainers willing to provide a stable API. This can be fixed easily as most/all of the fields exposed are be accessable by getters and setters.

A more serious problem is the optional model/view split which causes huge amounts of code duplication in GooCanvas. Currently GooCanvas gives you view items and model object, which in fact just are containers for the very same model data structure. View and model objects provide the same set of properties and methods to manipulate that shared data structure. This obviously is wrong: When there are view and model objects, all the model data should be stored in the model objects. At least there shouldn't be separate model data structures. The view objects should reference their model objects. But even that approach would be too complicated in my opinion, as in my opinion the canvas items itself are the model and the canvas, cell renderers, ... are the views. When the items have to store view specific data this issue should be handled internally (and not exposed to the user). I am pretty sure this change would reduce the lines of code GooCanvas needs by at least one third.

libccc is quite similiar to GooCanvas, which is not very suprising considering both want to provide a cairo based replacement for GNOME Canvas. libccc puts high emphasis on creating clean API and modern programming techiques. Usually this is a good thing, but considering the shear amount of other projects Sven is working on, it also directly leads to the biggest problem of libccc: Although being much older than GooCanvas 1), libccc has still lists "work in progress" for many features.

It is ahead of GooCanvas with its clean model/view separation. Beside the mandatory canvas widget the libraries provides additional view implementations like a GtkCellRenderer or a camera item (picture-in-picture). In addition to the features of GooCanvas it provides inline text editing and moves the burden of grid fitting from the canvas items to the views.

Conclusion

Without requiring printing support and high quality (pixel aligned) rendering the choice would be simple: Take GooCanvas, as it seems to be more complete. When if its feature matrix fits your needs, it's most reasonable to use this canvas widget.

Things shift when you figure out that you have add features. In that case GooCanvas' unnecessary code complexity hurts. You have to choose between investing alot of time on working with that complex and fragile code or convincing Damon (and the other people on the mailing list) of dropping the optional model/view split first - which also would need quite some time. Considering my weak mailing list discussion skills I'd most probably choose finishing libccc, instead of wasting that time on discussing and refactoring GooCanvas - but that's my personal opinion. People with better mailing list skills and better contact to Damon probably will vote different.

1) In opposition to common believe libccc really was started before GooCanvas. Sven demonstrated me libccc on 20C3 which was held in 2003, whereas GooCanvas was started in 2005.