Qt and the Peril of Multi-platform Deployment
Every once in a while when developing w/ Qt, I’ll get caught unawares by some gnarly platform specific bug. This blog, while a bit out of date and coming from a very different time in the life of the Qt Project, expresses a frustration I strongly sympathize with. By writing a single API which wraps around native functionality, you’re depending on not only the native framework to be bug-free, but the Qt framework as well.
At my lovely place of employment, we’re continuing to use the Qt 4.8.x releases in our product. Every feature release we’ve migrated to (4.4 and up) has introduced new and surprising regressions, often specific to a single platform, for which we have patched fixes into the libraries we distribute. It will likely be some time before we work up the gumption to tackle moving to Qt 5.
When we moved to Qt 4.7, we also attempted to migrate from Carbon to Cocoa. OSX has two native APIs, which you must choose between when compiling Qt: Carbon the legacy C API, and Cocoa the modern 64bit Objective C API. This was motivated by wanting a 64bit client, as well as sticking with platforms officially supported by Nokia/Digia. We found severe performance issues in parts of our application which had many, many widgets in a scroll view. Unacceptable performance issues, which required us to go back to using Carbon. Fortunately, a fix was in the works for the upcoming release.
After many months of waiting, we migrated to Qt 4.8.1. Alas! Deep into testing the release, several internal custom Qt 4.8 patches, and many work-arounds later, we discovered scrolling in QWebView w/ OSX had become incredibly laggy. Other folks seem to have noticed it as well. Should you be curious, compile the Fancy Browser demo included in Qt 4.8 and navigate to a website of appreciable complexity and length. Using a touch pad, quickly swipe up / down, sit back and sip a cup of tea while the screen gradual animates scrolling through the page. In addition to the scrolling lag, perceived as a show stopper by our stakeholders, it turned out that (surprise!) QtWebKit did not support NPAPI plugins (such as flash, java) when compiled for Cocoa. Don’t you wish this was documented somewhere?
In researching a solution, we learned Qt has several graphics systems it can use to draw applications on screen. Early in Qt4, Linux relied on X11, OSX relied on CoreGraphics, but Windows had something unique. Instead of rendering with the native framework, the developers instead chose to write their own raster renderer. One of Trolltech/Nokia/Digia’s engineers goes into depth on this topic in the Digia blog.
By Qt 4.8, they were confident enough to have this as the default for Linux and Windows, but with several issues still unresolved OSX got left out. By default, OSX Qt applications will use the native graphics system (i.e. CoreGraphics). It appears that the Qt developers intended raster to be the default as of Qt 4.8 (alongside the introduction of Alien Widgets), but were unable to stabilize it in time for release. See QTBUG-12615 to see if any of the open bugs affect you.
In short, changing the graphics system to raster resulted in a complete elimination of the scroll lag we had been seeing in QWebView. Other folks online appear to have treated this as purely a mouse scroll issue, where as I assumed (without doing any of the neccessary debugging, sorry) the issue was similar to the scroll issues experienced before Alien Widgets: drawing widgets w/ the native graphics system on OSX is simply much slower than on other platforms. Try compiling the Fancy Browser example, using the raster graphics system, and see how much smoother scrolling is. To do this, add the following line before creating your QApplication object in main.cpp:
One last note. One of Digia’s support techs has since patched in support for NPAPI plugins into QtWebKit for Cocoa. Alas, last I checked this did not appear to work when using the raster graphics system.