diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index 70de75072c..8a0540efc2 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -210,6 +210,11 @@ QPlatformServices *QPlatformIntegration::services() const \value ForeignWindows The platform allows creating QWindows which represent native windows created by other processes or anyway created by using native libraries. + + \value NonFullScreenWindows The platform supports top-level windows which do not + fill the screen. The default implementation returns true. Returning false for + this will cause all windows, including dialogs and popups, to be resized to fill the + screen. */ @@ -227,8 +232,7 @@ QPlatformServices *QPlatformIntegration::services() const bool QPlatformIntegration::hasCapability(Capability cap) const { - Q_UNUSED(cap); - return false; + return cap == NonFullScreenWindows; } QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index ddee6f05c8..bee2ba0caf 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -90,7 +90,8 @@ public: WindowMasks, MultipleWindows, ApplicationState, - ForeignWindows + ForeignWindows, + NonFullScreenWindows }; virtual ~QPlatformIntegration() { } diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp index cd7fa25da7..162a8aa977 100644 --- a/src/plugins/platforms/android/src/androidjnimain.cpp +++ b/src/plugins/platforms/android/src/androidjnimain.cpp @@ -559,7 +559,6 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jobject jSurface) m_surfaceMutex.unlock(); m_androidPlatformIntegration->surfaceChanged(); } else if (m_androidPlatformIntegration && sameNativeWindow) { - QAndroidOpenGLPlatformWindow *window = m_androidPlatformIntegration->primaryWindow(); QPlatformScreen *screen = m_androidPlatformIntegration->screen(); QSize size = QtAndroid::nativeWindowSize(); @@ -567,13 +566,19 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jobject jSurface) QWindowSystemInterface::handleScreenAvailableGeometryChange(screen->screen(), geometry); QWindowSystemInterface::handleScreenGeometryChange(screen->screen(), geometry); - if (window != 0) { - window->lock(); - window->scheduleResize(size); + // Resize all top level windows, since they share the same surface + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + QAndroidOpenGLPlatformWindow *window = + static_cast(w->handle()); - QWindowSystemInterface::handleExposeEvent(window->window(), - QRegion(window->window()->geometry())); - window->unlock(); + if (window != 0) { + window->lock(); + window->scheduleResize(size); + + QWindowSystemInterface::handleExposeEvent(window->window(), + QRegion(window->window()->geometry())); + window->unlock(); + } } m_surfaceMutex.unlock(); diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp index aa8ee57341..4d741807d0 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp @@ -62,16 +62,16 @@ void QAndroidOpenGLContext::swapBuffers(QPlatformSurface *surface) { QEglFSContext::swapBuffers(surface); - QAndroidOpenGLPlatformWindow *primaryWindow = m_platformIntegration->primaryWindow(); - if (primaryWindow == surface) { - primaryWindow->lock(); - QSize size = primaryWindow->scheduledResize(); + if (surface->surface()->surfaceClass() == QSurface::Window) { + QAndroidOpenGLPlatformWindow *window = static_cast(surface); + window->lock(); + QSize size = window->scheduledResize(); if (size.isValid()) { QRect geometry(QPoint(0, 0), size); - primaryWindow->setGeometry(geometry); - primaryWindow->scheduleResize(QSize()); + window->setGeometry(geometry); + window->scheduleResize(QSize()); } - primaryWindow->unlock(); + window->unlock(); } } diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp index 15c6559157..5362906e0e 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp @@ -45,11 +45,21 @@ QT_BEGIN_NAMESPACE +EGLSurface QAndroidOpenGLPlatformWindow::m_staticSurface = 0; +EGLNativeWindowType QAndroidOpenGLPlatformWindow::m_staticNativeWindow = 0; +QReadWriteLock QAndroidOpenGLPlatformWindow::m_staticSurfaceLock; +QBasicAtomicInt QAndroidOpenGLPlatformWindow::m_referenceCount = Q_BASIC_ATOMIC_INITIALIZER(0); + QAndroidOpenGLPlatformWindow::QAndroidOpenGLPlatformWindow(QWindow *window) : QEglFSWindow(window) { } +QAndroidOpenGLPlatformWindow::~QAndroidOpenGLPlatformWindow() +{ + destroy(); +} + bool QAndroidOpenGLPlatformWindow::isExposed() const { return QtAndroid::nativeWindow(false) != 0 && QEglFSWindow::isExposed(); @@ -60,11 +70,57 @@ void QAndroidOpenGLPlatformWindow::invalidateSurface() QWindowSystemInterface::handleExposeEvent(window(), QRegion()); // Obscure event QWindowSystemInterface::flushWindowSystemEvents(); QEglFSWindow::invalidateSurface(); + + m_window = 0; + m_surface = 0; + + if (!m_referenceCount.deref()){ + QWriteLocker locker(&m_staticSurfaceLock); + + EGLDisplay display = (static_cast(window()->screen()->handle()))->display(); + eglDestroySurface(display, m_staticSurface); + + m_staticSurface = 0; + m_staticNativeWindow = 0; + } } void QAndroidOpenGLPlatformWindow::resetSurface() { - QEglFSWindow::resetSurface(); + m_referenceCount.ref(); + if (m_staticSurface == 0) { + QWriteLocker locker(&m_staticSurfaceLock); + QEglFSWindow::resetSurface(); + m_staticSurface = m_surface; + m_staticNativeWindow = m_window; + } else { + QReadLocker locker(&m_staticSurfaceLock); + Q_ASSERT(m_staticSurface != m_surface); + m_window = m_staticNativeWindow; + m_surface = m_staticSurface; + } + + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); // Expose event + QWindowSystemInterface::flushWindowSystemEvents(); +} + +void QAndroidOpenGLPlatformWindow::destroy() +{ + if (!m_referenceCount.deref()) { + QEglFSWindow::destroy(); + } else { + m_window = 0; + m_surface = 0; + } +} + +void QAndroidOpenGLPlatformWindow::raise() +{ +} + +void QAndroidOpenGLPlatformWindow::setVisible(bool visible) +{ + QEglFSWindow::setVisible(visible); QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); // Expose event QWindowSystemInterface::flushWindowSystemEvents(); } diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h index b835cb3246..36a110e1a8 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.h @@ -44,6 +44,7 @@ #include "qeglfswindow.h" #include +#include QT_BEGIN_NAMESPACE @@ -51,6 +52,7 @@ class QAndroidOpenGLPlatformWindow : public QEglFSWindow { public: QAndroidOpenGLPlatformWindow(QWindow *window); + ~QAndroidOpenGLPlatformWindow(); QSize scheduledResize() const { return m_scheduledResize; } void scheduleResize(const QSize &size) { m_scheduledResize = size; } @@ -60,12 +62,23 @@ public: bool isExposed() const; + void raise(); + void invalidateSurface(); void resetSurface(); + void setVisible(bool visible); + + void destroy(); + private: QSize m_scheduledResize; QMutex m_lock; + + static QReadWriteLock m_staticSurfaceLock; + static EGLSurface m_staticSurface; + static EGLNativeWindowType m_staticNativeWindow; + static QBasicAtomicInt m_referenceCount; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp index 4734d47eb3..005758d83d 100644 --- a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp +++ b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp @@ -96,6 +96,7 @@ QDpi QEglFSAndroidHooks::logicalDpi() const EGLNativeWindowType QEglFSAndroidHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format) { + Q_UNUSED(size); ANativeWindow *window = QtAndroid::nativeWindow(); if (window != 0) ANativeWindow_acquire(window); diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp index cbd0f26835..3de6c47ad0 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp @@ -43,6 +43,7 @@ #include "qabstracteventdispatcher.h" #include "androidjnimain.h" #include +#include #include #include #include @@ -85,9 +86,6 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶mList) : m_touchDevice(0) -#ifdef ANDROID_PLUGIN_OPENGL - , m_primaryWindow(0) -#endif { Q_UNUSED(paramList); @@ -116,6 +114,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const { switch (cap) { case ThreadedPixmaps: return true; + case NonFullScreenWindows: return false; default: #ifndef ANDROID_PLUGIN_OPENGL return QPlatformIntegration::hasCapability(cap); @@ -143,28 +142,32 @@ QAbstractEventDispatcher *QAndroidPlatformIntegration::guiThreadEventDispatcher( #else // !ANDROID_PLUGIN_OPENGL QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const { - if (m_primaryWindow != 0) { - qWarning("QAndroidPlatformIntegration::createPlatformWindow: Unsupported case: More than " - "one top-level window created."); - } - - m_primaryWindow = new QAndroidOpenGLPlatformWindow(window); - m_primaryWindow->requestActivateWindow(); + QAndroidOpenGLPlatformWindow *platformWindow = new QAndroidOpenGLPlatformWindow(window); + platformWindow->create(); + platformWindow->requestActivateWindow(); QtAndroidMenu::setActiveTopLevelWindow(window); - return m_primaryWindow; + return platformWindow; } void QAndroidPlatformIntegration::invalidateNativeSurface() { - if (m_primaryWindow != 0) - m_primaryWindow->invalidateSurface(); + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + QAndroidOpenGLPlatformWindow *window = + static_cast(w->handle()); + if (window != 0) + window->invalidateSurface(); + } } void QAndroidPlatformIntegration::surfaceChanged() { - if (m_primaryWindow != 0) - m_primaryWindow->resetSurface(); + foreach (QWindow *w, QGuiApplication::topLevelWindows()) { + QAndroidOpenGLPlatformWindow *window = + static_cast(w->handle()); + if (window != 0) + window->resetSurface(); + } } QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.h b/src/plugins/platforms/android/src/qandroidplatformintegration.h index 3f8cc5a809..8da9fb2ff4 100644 --- a/src/plugins/platforms/android/src/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/src/qandroidplatformintegration.h @@ -95,7 +95,6 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const; void invalidateNativeSurface(); void surfaceChanged(); - QAndroidOpenGLPlatformWindow *primaryWindow() const { return m_primaryWindow; } QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; #endif @@ -138,8 +137,6 @@ private: #ifndef ANDROID_PLUGIN_OPENGL QAbstractEventDispatcher *m_eventDispatcher; QAndroidPlatformScreen *m_primaryScreen; -#else - mutable QAndroidOpenGLPlatformWindow *m_primaryWindow; #endif QThread *m_mainThread; diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 8c31d4ad26..fdc72ee23c 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -52,6 +52,7 @@ #include #include #include "QtGui/private/qwindow_p.h" +#include "QtGui/private/qguiapplication_p.h" #include #include @@ -675,6 +676,16 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) h = qMax(h,extra->minh); } + if (q->isWindow() && q->windowHandle()) { + QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration(); + if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) { + x = 0; + y = 0; + w = q->windowHandle()->width(); + h = q->windowHandle()->height(); + } + } + QPoint oldp = q->geometry().topLeft(); QSize olds = q->size(); QRect r(x, y, w, h); @@ -720,7 +731,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size())); } const QWidgetBackingStore *bs = maybeBackingStore(); - if (bs->store) { + if (bs && bs->store) { if (isResize) bs->store->resize(r.size()); }