Howto get fullscreen in Qtopia
Thanks to Eon Games for giving permission to mirror their article. To access the
original page click
here.
2002-02-28: The woes of fullscreen in Qtopia
Welcome to my first Developer Diary installment. In this episode I recount
the adventure of writing fullscreen mode Qtopia applications. Who would have
thought it would be such a challenge...
When I got the source for Strategic Assault it quickly became apparent
that I needed true fullscreen mode. Anyone that has used Qtopia knows about
the ever-present taskbar at the bottom of the screen. I figured there had
to be some way of disabling it. While hanging out in #zaurus on
irc.openprojects.net, someone mentioned that the media player can
play back video using true fullscreen mode.
That said, I quickly found the magic function, showFullScreen()
. Excited to have found the solution I quickly added this method to the
constructor of the display widget. I recompiled and started the game and...
nothing. I looked at the player code again and found the second magic piece
of code.
resize(qApp->desktop()->size());
However, after adding this code, I still had no success. After some experimentation,
I finally got my first fullscreen experience. The solution was to use QTimer
to call the showFullScreen() method with a short delay (thus effectively
calling it after the widget had been shown). The success was short-lived.
The taskbar sometimes came back (for example when viewing the builtin help).
This is when the fun really started. I tried putting the events in an
overloaded show(). This didn't work and was a very bad idea
since showFullScreen() happens to invoke show(). I also
added a check in the main game loop (timerEvent()). It worked but
when I called it all the time, it was too slow. After adding a check that
only tried to set fullscreen if the current widget size differed from the
screen size, the performance issue was solved. I also added functionality
to restore fullscreen after the help widget was closed. This worked fine
in the development environment until I placed the binary in the Qtopia binary
directory and launched the application by clicking on the icon. Back to the
drawing board.
When I tried to figure out what the difference might have been, I finally
thought of the idea of using the resizeEvent() callback. This simple
action did fix the problem with I had with launching the application from
within Qtopia. I released another beta version claiming that the fullscreen
/ taskbar issue most likely was solved. However Qtopia once again bit me
in the face.
This time the problem surfaced when another application was launched.
After the application quit, the taskbar stayed. As a last resort, I looked
into the various states (i.e isEnabled(), isActiveWindow()
etc). I figured out that when another application was launched, Strategic
Assault was no longer active. This led me to try using the focusInEvent()
callback. This worked. It finally worked. All known cases handled. This
is were I am now. A new beta will soon be released and who knows - maybe
this time I nailed it.
The conclusion is that writing a fullscreen application in Qtopia is a
very painful experience. What should be simple and straighforward is anything
but that. If the focusInEvent() solution works, I have learned
a valuable lesson for future applications. I hope that this article will
be useful for all you other Qtopia developers out there. The code which
might be it can be seen below.
void focusInEvent(QFocusEvent *) { setFixedSize(qApp->desktop()->size()); // set size showNormal(); // set normal mode showFullScreen(); // set fullscreen }
I should note that the showNormal() method call is there already
fullscreen..to make sure that showFullScreen() is actually fully
executed. It seems like Qtopia knows that the application is already
fullscreen...
30 minutes later...
It's now some 30 minutes after I finished writing this article. I spent
most of those 30 minutes trying to fix an issue which the above "fix" broke
- when I hide and then show the game our friend TASKBAR came back.
Solution? Re-implement the resizeEvent() callback. However I
now got a new issue I hadn't seen before. Namely, the titlebar sometimes
appeared when the game was restored to its fullscreen glory. After some digging
in the Qt source, I realize why. showNormal() resets the window
flags with a reparent() call. Unfortunately, as I said above, the
call to showNormal() is required for showFullScreen() to
work. The solution? Call reparent() with the correct window flags
directly after the call to showNormal().
I have now been unable to produce an case where the taskbar reappears
(and doesn't go away when it should). I consider, cross your fingers, this
code the final solution:
void resizeEvent(QResizeEvent *) { if(size() != qApp->desktop()->size()) { // Widget is not the correct size, so do the fullscreen magic enableFullscreen(); } } void focusInEvent(QFocusEvent *) { // Always do it here, no matter the size. enableFullscreen(); } void enableFullscreen() { // Make sure size is correct setFixedSize(qApp->desktop()->size()); // This call is needed because showFullScreen won't work // correctly if the widget already considers itself to be fullscreen. showNormal(); // This is needed because showNormal() forcefully changes the window // style to WSTyle_TopLevel. reparent(0, WStyle_Customize | WStyle_NoBorder, QPoint(0,0)); // Enable fullscreen. showFullScreen(); }
I will end this revised article with a plea to Trolltech:
Please take a good look at the fullscreen handling in Qtopia.
It shouldn't require many hours of experimentation and source code reading
to figure out how it works. I think that a single call to showFullScreen()
should be enough. If the application is hidden or covered another widget,
it should automatically restore itself to fullscreen mode once it again
is active.
|