diff options
author | Jani Hautakangas <jani.hautakangas@nokia.com> | 2011-12-16 09:08:46 (GMT) |
---|---|---|
committer | Jani Hautakangas <jani.hautakangas@nokia.com> | 2011-12-16 10:25:33 (GMT) |
commit | 69df8bf72da01f194bac66e80417b6483d00decb (patch) | |
tree | b7babb89f9a058f6a799518cb6987c31ea282e38 | |
parent | 3a4728e169ef59896f8f1c7f1c9a3abc814c83cf (diff) | |
download | Qt-69df8bf72da01f194bac66e80417b6483d00decb.zip Qt-69df8bf72da01f194bac66e80417b6483d00decb.tar.gz Qt-69df8bf72da01f194bac66e80417b6483d00decb.tar.bz2 |
Fix to incorrect ApplicationActivate event in QtOpenGL
QEvent::ApplicationActivate is sent incorrectly when application
goes to background if OpenGL graphics system is used. The problem
is that hidden global shared QGLWidget used by QtOpenGL for root
context is added to CONE stack. Qt destroys shared GL widget
when application goes to background and underlying CCoeControl
is removed from CONE stack which causes CONE to handle
stack changes. CONE tries to focus next control in stack which
causes incorrect focus events in Qt leading to
ApplicationActivate event. GL global share widget must not
be added to CONE stack because it's hidden utility widget
and don't belong to UI widget stack.
Task-number: QTBUG-23195
Task-number: ou1cimx1#946477
Reviewed-by: Murray Read
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 49 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 18 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 8 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 25 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl_p.h | 1 |
6 files changed, 69 insertions, 33 deletions
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 587c0f2..48767b8 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -552,11 +552,13 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) // the control's window qwidget->d_func()->createExtra(); - SetFocusing(true); - m_longTapDetector = QLongTapTimer::NewL(this); - m_doubleClickTimer.invalidate(); - - DrawableWindow()->SetPointerGrab(ETrue); + if (!qwidget->d_func()->isGLGlobalShareWidget) { + SetFocusing(true); + m_longTapDetector = QLongTapTimer::NewL(this); + m_doubleClickTimer.invalidate(); + + DrawableWindow()->SetPointerGrab(ETrue); + } } #ifdef Q_SYMBIAN_TRANSITION_EFFECTS @@ -590,25 +592,27 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) QSymbianControl::~QSymbianControl() { - // Ensure backing store is deleted before the top-level - // window is destroyed - QT_TRY { - qt_widget_private(qwidget)->topData()->backingStore.destroy(); - } QT_CATCH(const std::exception&) { - // ignore exceptions, nothing can be done - } - - if (S60->curWin == this) - S60->curWin = 0; - if (!QApplicationPrivate::is_app_closing) { + if (!qwidget->d_func()->isGLGlobalShareWidget) { // GLGlobalShareWidget doesn't interact with scene + // Ensure backing store is deleted before the top-level + // window is destroyed QT_TRY { - setFocusSafely(false); + qt_widget_private(qwidget)->topData()->backingStore.destroy(); } QT_CATCH(const std::exception&) { // ignore exceptions, nothing can be done } + + if (S60->curWin == this) + S60->curWin = 0; + if (!QApplicationPrivate::is_app_closing) { + QT_TRY { + setFocusSafely(false); + } QT_CATCH(const std::exception&) { + // ignore exceptions, nothing can be done + } + } + S60->appUi()->RemoveFromStack(this); + delete m_longTapDetector; } - S60->appUi()->RemoveFromStack(this); - delete m_longTapDetector; } void QSymbianControl::setWidget(QWidget *w) @@ -1535,6 +1539,10 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) if (m_ignoreFocusChanged || (qwidget->windowType() & Qt::WindowType_Mask) == Qt::Desktop) return; + // just in case + if (qwidget->d_func()->isGLGlobalShareWidget) + return; + #ifdef Q_WS_S60 if (S60->splitViewLastWidget) return; @@ -1723,6 +1731,9 @@ TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) void QSymbianControl::setFocusSafely(bool focus) { + if (qwidget->d_func()->isGLGlobalShareWidget) + return; + // The stack hack in here is very unfortunate, but it is the only way to ensure proper // focus in Symbian. If this is not executed, the control which happens to be on // the top of the stack may randomly be assigned focus by Symbian, for example diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 9ac9479..94c1d63 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -916,6 +916,7 @@ public: void reparentChildren(); void registerTouchWindow(); QList<WId> widCleanupList; + uint isGLGlobalShareWidget : 1; #endif }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index a37c265..fefa781 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -393,16 +393,18 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de stackingFlags = ECoeStackFlagStandard; } control->MakeVisible(false); - QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags)); - // Avoid keyboard focus to a hidden window. - control->setFocusSafely(false); - RDrawableWindow *const drawableWindow = control->DrawableWindow(); - // Request mouse move events. - drawableWindow->PointerFilter(EPointerFilterEnterExit - | EPointerFilterMove | EPointerFilterDrag, 0); - drawableWindow->EnableVisibilityChangeEvents(); + if (!isGLGlobalShareWidget) { + QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags)); + // Avoid keyboard focus to a hidden window. + control->setFocusSafely(false); + RDrawableWindow *const drawableWindow = control->DrawableWindow(); + // Request mouse move events. + drawableWindow->PointerFilter(EPointerFilterEnterExit + | EPointerFilterMove | EPointerFilterDrag, 0); + drawableWindow->EnableVisibilityChangeEvents(); + } } q->setAttribute(Qt::WA_WState_Created); diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index df09dfd..89153d9 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -106,6 +106,10 @@ class QMacWindowChangeEvent; class QWSGLWindowSurface; #endif +#ifdef Q_OS_SYMBIAN +extern bool qt_initializing_gl_share_widget(); +#endif + #ifndef QT_NO_EGL class QEglContext; #endif @@ -183,6 +187,10 @@ public: #endif { isGLWidget = 1; +#if defined(Q_OS_SYMBIAN) + if (qt_initializing_gl_share_widget()) + isGLGlobalShareWidget = 1; +#endif } ~QGLWidgetPrivate() {} diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index a15084b..d512946 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -184,28 +184,29 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) class QGLGlobalShareWidget { public: - QGLGlobalShareWidget() : widget(0), initializing(false) { + QGLGlobalShareWidget() : widget(0), init(false) { created = true; } QGLWidget *shareWidget() { - if (!initializing && !widget && !cleanedUp) { - initializing = true; + if (!init && !widget && !cleanedUp) { + init = true; widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer)); #ifdef Q_OS_SYMBIAN if (!widget->context()->isValid()) { delete widget; widget = 0; - initializing = false; + init = false; return 0; } #endif + widget->resize(1, 1); // We don't need this internal widget to appear in QApplication::topLevelWidgets() if (QWidgetPrivate::allWidgets) QWidgetPrivate::allWidgets->remove(widget); - initializing = false; + init = false; } return widget; } @@ -232,12 +233,17 @@ public: cleanedUp = false; } + bool initializing() + { + return init; + } + static bool cleanedUp; static bool created; private: QGLWidget *widget; - bool initializing; + bool init; }; bool QGLGlobalShareWidget::cleanedUp = false; @@ -268,6 +274,13 @@ void qt_destroy_gl_share_widget() _qt_gl_share_widget()->destroy(); } +bool qt_initializing_gl_share_widget() +{ + if (QGLGlobalShareWidget::created) + return _qt_gl_share_widget()->initializing(); + return false; +} + const QGLContext *qt_gl_share_context() { QGLWidget *widget = qt_gl_share_widget(); diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index 91d1f9e..6c8b71f 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -68,6 +68,7 @@ struct QGLWindowSurfacePrivate; Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget(); Q_OPENGL_EXPORT void qt_destroy_gl_share_widget(); +bool qt_initializing_gl_share_widget(); class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice { |