Cocoa: Fix qmlscene flicker on startup.
authorMorten Sorvig <morten.sorvig@nokia.com>
Tue, 23 Aug 2011 10:51:11 +0000 (12:51 +0200)
committerGunnar Sletta <gunnar.sletta@nokia.com>
Wed, 31 Aug 2011 14:16:03 +0000 (16:16 +0200)
The SG render thread was racing window creation in
the GUI thread, which would cause flicker if the
window won the race and was shown before the SG
thread had a frame ready.

Send a synchronous expose event before showing the
window - this will wait for the SG render thread.

In addition, don't defer NSwindow creation. The GL
context setup is done before the window is shown
and needs a fully created window.

New API: QWindowSystemInterface::handleSynchronousExposeEvent
Retire: QWindowSystemInterface::handleExposeEvent

Change-Id: I0bb46089d16ec4882aaac8db67b57d15e0f51531
Reviewed-on: http://codereview.qt.nokia.com/3399
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@nokia.com>
src/gui/kernel/qwindowsysteminterface_qpa.cpp
src/gui/kernel/qwindowsysteminterface_qpa.h
src/plugins/platforms/cocoa/qcocoawindow.mm
src/plugins/platforms/wayland/qwaylandwindow.cpp
src/plugins/platforms/windows/qwindowswindow.cpp
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbwindow.cpp

index d6f94b6..d862d05 100644 (file)
@@ -276,10 +276,10 @@ void QWindowSystemInterface::handleUnmapEvent(QWindow *tlw)
     QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
 }
 
-void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion &region)
+void QWindowSystemInterface::handleSynchronousExposeEvent(QWindow *tlw, const QRegion &region)
 {
     QWindowSystemInterfacePrivate::ExposeEvent *e = new QWindowSystemInterfacePrivate::ExposeEvent(tlw, region);
-    QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+    QGuiApplicationPrivate::processWindowSystemEvent(e); // send event immediately.
 }
 
 bool QWindowSystemInterface::sendWindowSystemEvents(QAbstractEventDispatcher *eventDispatcher, QEventLoop::ProcessEventsFlags flags)
index 2f3f8a1..99db5f2 100644 (file)
@@ -105,7 +105,7 @@ public:
     static void handleMapEvent(QWindow *w);
     static void handleUnmapEvent(QWindow *w);
 
-    static void handleExposeEvent(QWindow *w, const QRegion &region);
+    static void handleSynchronousExposeEvent(QWindow *tlw, const QRegion &region);
 
     // Drag and drop. These events are sent immediately.
     static Qt::DropAction handleDrag(QWindow *w, QMimeData *dropData, const QPoint &p);
index 78785a8..ef04fc4 100644 (file)
@@ -121,8 +121,10 @@ void QCocoaWindow::setVisible(bool visible)
         if (window()->transientParent())
             setGeometry(window()->geometry());
 
+        // Make sure the QWindow has a frame ready before we show the NSWindow.
+        QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
+
         [m_nsWindow makeKeyAndOrderFront:nil];
-        QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
     } else {
         [m_nsWindow orderOut:nil];
     }
@@ -319,7 +321,7 @@ QNSWindow * QCocoaWindow::createWindow()
         panel = [[NSPanel alloc] initWithContentRect:frame
                                    styleMask:m_windowAttributes
                                    backing:NSBackingStoreBuffered
-                                   defer:YES];
+                                   defer:NO]; // see window case below
 //  ### crashes
 //        [panel setFloatingPanel:needFloating];
 //        [panel setWorksWhenModal:worksWhenModal];
@@ -330,7 +332,8 @@ QNSWindow * QCocoaWindow::createWindow()
         window  = [[QNSWindow alloc] initWithContentRect:frame
                                             styleMask:(NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask)
                                             backing:NSBackingStoreBuffered
-                                            defer:YES];
+                                            defer:NO]; // Deferring window creation breaks OpenGL (the GL context is set up
+                                                       // before the window is shown and needs a proper window.).
         break;
     }
 
index f685dae..48da7b5 100644 (file)
@@ -125,7 +125,7 @@ void QWaylandWindow::attach(QWaylandBuffer *buffer)
     mBuffer = buffer;
     if (mSurface) {
         wl_surface_attach(mSurface, buffer->buffer(),0,0);
-        QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+        QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
     }
 }
 
index 95b770f..8e10ae6 100644 (file)
@@ -902,7 +902,7 @@ void QWindowsWindow::handleWmPaint(HWND hwnd, UINT,
         if (QWindowsContext::verboseIntegration)
             qDebug() << __FUNCTION__ << this << window() << updateRect;
 
-        QWindowSystemInterface::handleExposeEvent(window(), QRegion(updateRect));
+        QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion(updateRect));
         clearFlag(WithinWmPaint);
         m_hdc = 0;
         EndPaint(hwnd, &ps);
index a8ffc58..c60e066 100644 (file)
@@ -472,7 +472,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
 
     switch (response_type) {
     case XCB_EXPOSE:
-        HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
+        HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleSynchronousExposeEvent);
     case XCB_BUTTON_PRESS:
         HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
     case XCB_BUTTON_RELEASE:
index 0f3d1d5..db8d37e 100644 (file)
@@ -1074,7 +1074,7 @@ QXcbEGLSurface *QXcbWindow::eglSurface() const
 void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
 {
     QRect rect(event->x, event->y, event->width, event->height);
-    QWindowSystemInterface::handleExposeEvent(window(), rect);
+    QWindowSystemInterface::handleSynchronousExposeEvent(window(), rect);
 }
 
 void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *event)