This post is actually about a bug that I ran into while developing a mobile application using Qt 4.6.3. The bug can cause a Qt widget to take up a size that is larger than the screen area available for the application, which means that a part of the application is rendered outside of the screen. I spent a lot of time searching for a workaround for this bug, but was unable to find anything useful. In the end, I decided to try to devise a workaround by myself.

This bug was first reported in version 4.6.0, and was even mentioned as a known issue in versions from 4.6.0 to 4.6.3.

The bug usually doesn`t affect the application`s functionality, but it doesn`t look nice when only a part of the application is visible on screen. In some cases it can even cause that some important part of the application is hidden from the user, e.g., a button or a progress bar.

By examining resize events that my application was receiving, I noticed that they contain incorrect size values when the bug happens, this part was expected, but the interesting part was that it is always possible to get the correct size using the following code:

QApplication::desktop()->availableGeometry()

The next step was to somehow replace the incorrect size values with the correct ones. The idea was to intercept and modify resize events in one of several possible ways:

  • By installing an event filter on the QCoreApplication instance,
  • By installing an event filter on the actual widget,
  • By overriding resizeEvent method of the widget, etc.

 

I couldn’t successfully modify resize events in any of those cases. I also tried calling widget’s resize method with the correct values when an event with the wrong size information was received. Unfortunately this also didn’t work. The resize method calls were probably ignored because they were made while the widget was resizing itself. To verify this assumption, I tried scheduling a resize at some later time, and to my astonishment, this approach worked.

In order to delay the resize method calls, a QTimer::singleShot method can be called in the resizeEvent method. Scheduling resize events with correct values fixed the resizing issue, but after the resize method was called the application stopped responding properly to screen orientation changes. The screen would rotate as expected, but the widget wouldn`t resize itself. This happened because resize method forces a widget to have a fixed static size. A fix for this was very simple, I just called showMaximized() after resize and everything worked as expected once again. Method showMaximized() was called because my application doesn`t run in full screen, if you have a full screen application, you would call showFullScreen() instead.

Here is the solution that worked for me:

resizeEvent method:

QSize size = event->size();
QSize screenSize =
  QApplication::desktop()->availableGeometry().size();

if (size != screenSize)
{
  QTimer::singleShot(500, this, SLOT(fixResize()));
}

fixResize method:

QSize screenSize =
  QApplication::desktop()->availableGeometry().size();

this->resize(screenSize);
this->showMaximized();

The idea is to analyze resize events by overriding resizeEvent method of a widget. When an event with an incorrect size value is detected, we simply schedule a resize with the correct value.

0 comments