Andrew Olmsted built the first FBReader packages for Harmattan, after tweaking the build system a bit. The desktop version of FBReader already used Qt 4, and ran almost unmodified, but with some bugs (segfault on task switch) and ugly UI.

I started with the Ubuntu packages for FBReader, since they used a more sane build system for .debs (compared to upstream's funky shell script). Some tweaks were needed to make it build in Scratchbox: since GTK+ and Hildon libraries aren't available on Harmattan, I had to disable the building of -gtk and -maemo versions of libzlui. I also got to learn a new tool — quilt.

Fixing the segfault took a couple of days of debugging, studying the source code of both FBReader and Qt itself, and asking for help on IRC. Turns out FBReader was holding an active QPainter instance for too long, and its backing pixmap got destroyed (or, rather, converted from an OpenGL texture to a plain X11 pixmap) during a task switch, causing the crash. I'm probably describing this wrong BTW, but, in any case, adding QPainter::begin() and QPainter::end() calls in the paintEvent handler fixed the segfault.

Next, a small tweak in the .desktop file to make FBReader a single-instance application: change Exec=FBReader to Exec=single-instance /usr/bin/FBReader (I'm paraphrasing slightly).

Then, a more ambitious goal: making FBReader intercept volume keys and use them for scrolling. Google gave me a pointer to QmKeys, which was the wrong API to use here, but gave me a lead to qmkeyd2, which appears to be an open source daemon, which gave me a lead to sysuid, another open source daemon, which in turn gave me a lead to libresourceqt, and that was the right API at last.

Volume keys generate regular key events for XF86AudioRaiseVolume and XF86AudioLowerVolume, but they're also intercepted by qmkeyd2, which tells all subscribers (and sysuid is one) about them. Which subscriber gets to react is determined by the resource policy framework. So what I needed to do in FBReader was acquire the ScaleButtonResource when FBReader starts up or gets focus, and release it when FBReader quits or goes into background. That also required some IRC help until I discovered installEventFilter() and the ApplicationActivate/ApplicationDeactivate events. And QApplication::instance().

The various tools available in the developer firmware were invaluable: openssh, gdb, valgrind, strace, xev, xprop, lsof, netstat. Also, I would not have achieved my second goal without being able to look at the sources of Meego system components (qmkeyd, sysuid). Yay open source!

Here are my changes to the source code. You can find my modified Debian packaging files, as well as prebuilt binary packages (with full debug info, for gdb goodness), in my experimental harmattan apt repository. The UI is still ugly and non-native, but it doesn't matter much in fullscreen mode :) .

Note to self: when next building fbreader, make sure the 2 megabyte tags file doesn't end up in the .diff.gz. And speaking of crud in source packages, the vim package I built for Harmattan the other day contains the entire 50 meg .hg in the .orig.tar.gz. I need to figure out how to tell dh_make to omit it.