diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-04-22 16:35:41 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-04-22 16:35:43 +0200 |
commit | 4c231d5df3040dbf4545a9a77145ee0e1f9c380c (patch) | |
tree | 2cc5b71a5d2b464214cf5372776913fbe4622e1e /src/plugins | |
parent | 7df16fb4ccbe0476bc34274a77e98eec4e8d2d93 (diff) | |
parent | d672ef07681a959d9559dd1e11e70db1f448a7f1 (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Change-Id: I059725e3b7d7ffd5a16a0931e6c17200917172b5
Diffstat (limited to 'src/plugins')
55 files changed, 393 insertions, 146 deletions
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index 3c61a69480..1113194136 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -252,14 +252,14 @@ void TableGenerator::parseIncludeInstruction(QString line) processFile(line); } -ushort TableGenerator::keysymToUtf8(uint32_t sym) +ushort TableGenerator::keysymToUtf8(quint32 sym) { QByteArray chars; int bytes; chars.resize(8); if (needWorkaround(sym)) { - uint32_t codepoint; + quint32 codepoint; if (sym == XKB_KEY_KP_Space) codepoint = XKB_KEY_space & 0x7f; else @@ -284,14 +284,14 @@ ushort TableGenerator::keysymToUtf8(uint32_t sym) return ch->unicode(); } -uint32_t TableGenerator::stringToKeysym(QString keysymName) +quint32 TableGenerator::stringToKeysym(QString keysymName) { - uint32_t keysym; + quint32 keysym; QByteArray keysymArray = keysymName.toLatin1(); const char *name = keysymArray.constData(); if ((keysym = xkb_keysym_from_name(name, (xkb_keysym_flags)0)) == XKB_KEY_NoSymbol) - qWarning() << QString("Qt Warrning - invalid keysym: %1").arg(keysymName); + qWarning() << QString("Qt Warning - invalid keysym: %1").arg(keysymName); return keysym; } diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h index 11e7b2b422..cc1db20432 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h @@ -109,8 +109,8 @@ protected: bool findSystemComposeDir(); QString systemComposeDir(); - ushort keysymToUtf8(uint32_t sym); - uint32_t stringToKeysym(QString keysymName); + ushort keysymToUtf8(quint32 sym); + quint32 stringToKeysym(QString keysymName); void readLocaleMappings(); void initPossibleLocations(); diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp index 36d95b0816..162a8aa977 100644 --- a/src/plugins/platforms/android/src/androidjnimain.cpp +++ b/src/plugins/platforms/android/src/androidjnimain.cpp @@ -74,9 +74,7 @@ # include "qandroidopenglplatformwindow.h" #endif -#if __ANDROID_API__ > 8 -# include <android/native_window_jni.h> -#endif +#include <android/native_window_jni.h> static jmethodID m_redrawSurfaceMethodID = 0; @@ -543,32 +541,6 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/) env->DeleteGlobalRef(m_bitmapDrawableClass); } -#ifdef ANDROID_PLUGIN_OPENGL -#if __ANDROID_API__ < 9 -struct FakeNativeWindow -{ - long long dummyNativeWindow;// force 64 bits alignment -}; - -class FakeSurface: public FakeNativeWindow -{ -public: - virtual void FakeSurfaceMethod() - { - fakeSurface = 0; - } - - int fakeSurface; -}; - -EGLNativeWindowType ANativeWindow_fromSurface(JNIEnv *env, jobject jSurface) -{ - FakeSurface *surface = static_cast<FakeSurface *>(env->GetIntField(jSurface, m_surfaceFieldID)); - return static_cast<EGLNativeWindowType>(static_cast<FakeNativeWindow*>(surface)); -} -#endif // __ANDROID_API__ < 9 -#endif // ANDROID_PLUGIN_OPENGL - static void setSurface(JNIEnv *env, jobject /*thiz*/, jobject jSurface) { #ifndef ANDROID_PLUGIN_OPENGL @@ -587,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(); @@ -595,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<QAndroidOpenGLPlatformWindow *>(w->handle()); + + if (window != 0) { + window->lock(); + window->scheduleResize(size); - QWindowSystemInterface::handleExposeEvent(window->window(), - QRegion(window->window()->geometry())); - window->unlock(); + QWindowSystemInterface::handleExposeEvent(window->window(), + QRegion(window->window()->geometry())); + window->unlock(); + } } m_surfaceMutex.unlock(); @@ -753,12 +730,7 @@ static int registerNatives(JNIEnv *env) #ifdef ANDROID_PLUGIN_OPENGL FIND_AND_CHECK_CLASS("android/view/Surface"); -#if __ANDROID_API__ < 9 -# define ANDROID_VIEW_SURFACE_JNI_ID "mSurface" -#else -# define ANDROID_VIEW_SURFACE_JNI_ID "mNativeSurface" -#endif - GET_AND_CHECK_FIELD(m_surfaceFieldID, clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); + GET_AND_CHECK_FIELD(m_surfaceFieldID, clazz, "mNativeSurface", "I"); #endif jmethodID methodID; 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<QAndroidOpenGLPlatformWindow *>(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<QEglFSScreen *>(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 <QtCore/qmutex.h> +#include <QtCore/qreadwritelock.h> 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 <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/qguiapplication.h> #include <qpa/qwindowsysteminterface.h> #include <QThread> #include <qpa/qplatformwindow.h> @@ -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<QAndroidOpenGLPlatformWindow *>(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<QAndroidOpenGLPlatformWindow *>(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/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm index 0eb4edef72..6adcb27817 100644 --- a/src/plugins/platforms/cocoa/main.mm +++ b/src/plugins/platforms/cocoa/main.mm @@ -59,6 +59,9 @@ public: QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, const QStringList& paramList) { Q_UNUSED(paramList); + + QCocoaAutoReleasePool pool; + if (system.toLower() == "cocoa") return new QCocoaIntegration; diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 34192e85b0..25780e79f4 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -180,7 +180,8 @@ bool shouldBeIgnored(QAccessibleInterface *interface) // state. Ignore interfaces with those flags set. const QAccessible::State state = interface->state(); if (state.invisible || - state.offscreen) + state.offscreen || + state.invalid) return true; // Some roles are not interesting. In particular, container roles should be @@ -189,12 +190,13 @@ bool shouldBeIgnored(QAccessibleInterface *interface) if (role == QAccessible::Border || // QFrame role == QAccessible::Application || // We use the system-provided application element. role == QAccessible::MenuItem || // The system also provides the menu items. - role == QAccessible::ToolBar) // Access the tool buttons directly. + role == QAccessible::ToolBar || // Access the tool buttons directly. + role == QAccessible::Pane || // Scroll areas. + role == QAccessible::Client) // The default for QWidget. return true; NSString *mac_role = macRole(interface); if (mac_role == NSAccessibilityWindowRole || // We use the system-provided window elements. - mac_role == NSAccessibilityGroupRole || mac_role == NSAccessibilityUnknownRole) return true; diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 1d6797e51a..f7c945c50d 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -151,6 +151,7 @@ [kids addObject: element]; [element release]; } + // ### maybe we should use NSAccessibilityUnignoredChildren(kids); this needs more profiling return kids; } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { @@ -256,7 +257,7 @@ // misc - (BOOL)accessibilityIsIgnored { - return false; //QCocoaAccessible::shouldBeIgnored(QAccessible::accessibleInterface(id)); + return QCocoaAccessible::shouldBeIgnored(QAccessible::accessibleInterface(axid)); } - (id)accessibilityHitTest:(NSPoint)point { diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 5c487b0bdd..2ac9a5dac9 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -741,11 +741,14 @@ void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window) // when we stop the _current_ modal session (which is the session on top of // the stack, and might not belong to 'window'). int stackSize = cocoaModalSessionStack.size(); + int endedSessions = 0; for (int i=stackSize-1; i>=0; --i) { QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; + if (!info.window) + endedSessions++; if (info.window == window) { info.window = 0; - if (i == stackSize-1) { + if (i + endedSessions == stackSize-1) { // The top sessions ended. Interrupt the event dispatcher to // start spinning the correct session immediately. Like in // beginModalSession(), we call interrupt() before clearing diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 7093d27efe..071edb5b60 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -61,6 +61,8 @@ #include <stdlib.h> #include <qabstracteventdispatcher.h> #include "qcocoaautoreleasepool.h" +#include <QFileSystemWatcher> +#include <QDir> #include <qpa/qplatformnativeinterface.h> @@ -72,6 +74,30 @@ QT_FORWARD_DECLARE_CLASS(QFileInfo) QT_FORWARD_DECLARE_CLASS(QWindow) QT_USE_NAMESPACE +class CachedEntries: public QObject { +public: + CachedEntries(QDir::Filters filters) : mFilters(filters) { + QObject::connect(&mFSWatcher, &QFileSystemWatcher::directoryChanged, this, &CachedEntries::updateDirCache); + } + QString directory() const { + const QStringList &dirs = mFSWatcher.directories(); + return (dirs.count() ? dirs[0] : QString()); + } + QStringList entries() const { + return mQDirFilterEntryList; + } + void updateDirCache(const QString &path) { + mFSWatcher.removePaths(mFSWatcher.directories()); + mFSWatcher.addPath(path); + mQDirFilterEntryList = QDir(path).entryList(mFilters); + } + +private: + QFileSystemWatcher mFSWatcher; + QStringList mQDirFilterEntryList; + QDir::Filters mFilters; +}; + typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; @class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate); @@ -91,9 +117,8 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; int mReturnCode; SharedPointerFileDialogOptions mOptions; - QString *mLastFilterCheckPath; + CachedEntries *mCachedEntries; QString *mCurrentSelection; - QStringList *mQDirFilterEntryList; QStringList *mNameFilterDropDownList; QStringList *mSelectedNameFilter; } @@ -137,8 +162,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; [mSavePanel setDelegate:self]; mReturnCode = -1; mHelper = helper; - mLastFilterCheckPath = new QString; - mQDirFilterEntryList = new QStringList; + mCachedEntries = new CachedEntries(mOptions->filter()); mNameFilterDropDownList = new QStringList(mOptions->nameFilters()); QString selectedVisualNameFilter = mOptions->initiallySelectedNameFilter(); mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]); @@ -171,8 +195,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; - (void)dealloc { - delete mLastFilterCheckPath; - delete mQDirFilterEntryList; + delete mCachedEntries; delete mNameFilterDropDownList; delete mSelectedNameFilter; delete mCurrentSelection; @@ -303,12 +326,11 @@ static QString strippedText(QString s) QString qtFileName = QT_PREPEND_NAMESPACE(QCFString::toQString)(filename); QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C))); QString path = info.absolutePath(); - if (path != *mLastFilterCheckPath){ - *mLastFilterCheckPath = path; - *mQDirFilterEntryList = info.dir().entryList(mOptions->filter()); + if (mCachedEntries->directory() != path) { + mCachedEntries->updateDirCache(path); } // Check if the QDir filter accepts the file: - if (!mQDirFilterEntryList->contains(info.fileName())) + if (!mCachedEntries->entries().contains(info.fileName())) return NO; // No filter means accept everything diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index e2d867e623..821e10de52 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -122,7 +122,9 @@ void QCocoaScreen::updateGeometry() m_physicalSize = QSizeF(size.width, size.height); m_logicalDpi.first = 72; m_logicalDpi.second = 72; - float refresh = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(dpy)); + CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(dpy); + float refresh = CGDisplayModeGetRefreshRate(displayMode); + CGDisplayModeRelease(displayMode); if (refresh > 0) m_refreshRate = refresh; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 0fe4c48510..bde9ded14f 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -97,7 +97,6 @@ static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader() if (![menuItem tag]) return YES; - QCocoaMenuItem* cocoaItem = reinterpret_cast<QCocoaMenuItem *>([menuItem tag]); return cocoaItem->isEnabled(); } @@ -308,13 +307,54 @@ void QCocoaMenu::setVisible(bool visible) void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) { + QCocoaAutoReleasePool pool; + QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : 0; NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil; NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil; - NSPoint nsPos = NSMakePoint(pos.x(), pos.y()); - [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:view]; - // The call above blocks, and also swallows any mouse release event, + // Ideally, we would call -popUpMenuPositioningItem:atLocation:inView:. + // However, this showed not to work with modal windows where the menu items + // would appear disabled. So, we resort to a more artisanal solution. Note + // that this implies several things. + if (nsItem) { + // If we want to position the menu popup so that a specific item lies under + // the mouse cursor, we resort to NSPopUpButtonCell to do that. This is the + // typical use-case for a choice list, or non-editable combobox. We can't + // re-use the popUpContextMenu:withEvent:forView: logic below since it won't + // respect the menu's minimum width. + NSPopUpButtonCell *popupCell = [[[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO] + autorelease]; + [popupCell setAltersStateOfSelectedItem:NO]; + [popupCell setTransparent:YES]; + [popupCell setMenu:m_nativeMenu]; + [popupCell selectItem:nsItem]; + NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10); + [popupCell performClickWithFrame:cellFrame inView:view]; + } else { + // Else, we need to transform 'pos' to window or screen coordinates. + NSPoint nsPos = NSMakePoint(pos.x() - 1, pos.y()); + if (view) { + nsPos.y = view.frame.size.height - nsPos.y; + } else if (!QGuiApplication::screens().isEmpty()) { + QScreen *screen = QGuiApplication::screens().at(0); + nsPos.y = screen->availableVirtualSize().height() - nsPos.y; + } + + // Finally, we need to synthesize an event. + NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown + location:nsPos + modifierFlags:0 + timestamp:0 + windowNumber:view ? view.window.windowNumber : 0 + context:nil + eventNumber:0 + clickCount:1 + pressure:1.0]; + [NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view]; + } + + // The calls above block, and also swallow any mouse release event, // so we need to clear any mouse button that triggered the menu popup. if ([view isKindOfClass:[QNSView class]]) [(QNSView *)view resetMouseButtons]; @@ -356,6 +396,8 @@ QList<QCocoaMenuItem *> QCocoaMenu::merged() const void QCocoaMenu::syncModalState(bool modal) { + QCocoaAutoReleasePool pool; + if (!m_enabled) modal = true; diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index c0c8caed05..b880db16a2 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -114,6 +114,8 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) { + QCocoaAutoReleasePool pool; + QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu); if (!m_menus.contains(menu)) { qWarning() << Q_FUNC_INFO << "Trying to remove a menu that does not belong to the menubar"; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index dd99a6f3bc..350ef8a16a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -218,8 +218,6 @@ NSMenuItem *QCocoaMenuItem::sync() mergeItem = [loader aboutMenuItem]; else mergeItem = [loader aboutQtMenuItem]; - - m_merged = true; } else if (m_text.startsWith(tr("Config"), Qt::CaseInsensitive) || m_text.startsWith(tr("Preference"), Qt::CaseInsensitive) || m_text.startsWith(tr("Options"), Qt::CaseInsensitive) @@ -240,9 +238,9 @@ NSMenuItem *QCocoaMenuItem::sync() if (mergeItem) { m_merged = true; + [mergeItem retain]; [m_native release]; m_native = mergeItem; - [m_native retain]; // balance out release! [m_native setTag:reinterpret_cast<NSInteger>(this)]; } else if (m_merged) { // was previously merged, but no longer @@ -256,13 +254,12 @@ NSMenuItem *QCocoaMenuItem::sync() m_native = [[NSMenuItem alloc] initWithTitle:QCFString::toNSString(m_text) action:nil keyEquivalent:@""]; - [m_native retain]; [m_native setTag:reinterpret_cast<NSInteger>(this)]; } // [m_native setHidden:YES]; // [m_native setHidden:NO]; - [m_native setHidden: !m_isVisible]; + [m_native setHidden: !m_isVisible]; [m_native setEnabled: m_enabled]; QString text = m_text; QKeySequence accel = m_shortcut; diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index f0f1f56d90..84261ad273 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -85,10 +85,8 @@ void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resource void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { - if (!window->handle()) { - qWarning("QCocoaNativeInterface::nativeResourceForWindow: Native window has not been created."); + if (!window->handle()) return 0; - } if (resourceString == "nsopenglcontext") { return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext(); @@ -228,6 +226,11 @@ void QCocoaNativeInterface::setWindowContentView(QPlatformWindow *window, void * void QCocoaNativeInterface::registerTouchWindow(QWindow *window, bool enable) { + // Make sure the QCocoaWindow is created when enabling. Disabling might + // happen on window destruction, don't (re)create the QCocoaWindow then. + if (enable) + window->create(); + QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()); if (cocoaWindow) cocoaWindow->registerTouch(enable); diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index e613dbbd1b..af817bd4c5 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -176,7 +176,7 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() QHash<QPlatformTheme::Palette, QPalette*> palettes; QColor qc; for (int i = 0; mac_widget_colors[i].paletteRole != QPlatformTheme::NPalettes; i++) { - QPalette pal = *qt_mac_createSystemPalette(); + QPalette &pal = *qt_mac_createSystemPalette(); if (mac_widget_colors[i].active != 0) { qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].active); pal.setColor(QPalette::Active, QPalette::Text, qc); @@ -223,7 +223,7 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() pal.setBrush(QPalette::Disabled, QPalette::Base, pal.brush(QPalette::Active, QPalette::Base)); } - palettes.insert(mac_widget_colors[i].paletteRole, new QPalette(pal)); + palettes.insert(mac_widget_colors[i].paletteRole, &pal); } return palettes; } diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index f8eed0ebf1..8337e00eb6 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -290,6 +290,8 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const sizes << 16 << 32 << 64 << 128; return QVariant::fromValue(sizes); } + case QPlatformTheme::PasswordMaskDelay: + return QVariant(QChar(kBulletUnicode)); default: break; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 4e567c6c63..5ff1bf83ae 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -283,6 +283,10 @@ void QCocoaWindow::setVisible(bool visible) parentCocoaWindow->m_activePopupWindow = window(); // QTBUG-30266: a window should not be resizable while a transient popup is open // Since this isn't a native popup, the window manager doesn't close the popup when you click outside +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 + && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask)) +#endif [parentCocoaWindow->m_nsWindow setStyleMask: (parentCocoaWindow->windowStyleMask(parentCocoaWindow->m_windowFlags) & ~NSResizableWindowMask)]; } @@ -346,7 +350,12 @@ void QCocoaWindow::setVisible(bool visible) } else { [m_contentView setHidden:YES]; } - if (parentCocoaWindow && window()->type() == Qt::Popup) + if (parentCocoaWindow && window()->type() == Qt::Popup +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 + && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask) +#endif + ) // QTBUG-30266: a window should not be resizable while a transient popup is open [parentCocoaWindow->m_nsWindow setStyleMask:parentCocoaWindow->windowStyleMask(parentCocoaWindow->m_windowFlags)]; } @@ -471,6 +480,8 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; if (iconButton == nil) { + if (icon.isNull()) + return; NSString *title = QCFString::toNSString(window()->title()); [m_nsWindow setRepresentedURL:[NSURL fileURLWithPath:title]]; iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; @@ -852,7 +863,7 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState) // if content view width or height is 0 then the window animations will crash so // do nothing except set the new state NSRect contentRect = [contentView() frame]; - if (contentRect.size.width <= 0 || contentRect.size.height <= 0) { + if (contentRect.size.width < 0 || contentRect.size.height < 0) { qWarning() << Q_FUNC_INFO << "invalid window content view size, check your window geometry"; m_synchedWindowState = newState; return; @@ -905,7 +916,7 @@ QCocoaMenuBar *QCocoaWindow::menubar() const void QCocoaWindow::registerTouch(bool enable) { m_registerTouchCount += enable ? 1 : -1; - if (m_registerTouchCount == 1) + if (enable && m_registerTouchCount == 1) [m_contentView setAcceptsTouchEvents:YES]; else if (m_registerTouchCount == 0) [m_contentView setAcceptsTouchEvents:NO]; diff --git a/src/plugins/platforms/cocoa/qmacmime.mm b/src/plugins/platforms/cocoa/qmacmime.mm index 89539de331..51c39357ea 100644 --- a/src/plugins/platforms/cocoa/qmacmime.mm +++ b/src/plugins/platforms/cocoa/qmacmime.mm @@ -553,10 +553,8 @@ QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteA a.size(), kCFAllocatorNull); QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0); image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); - - // ### TODO (msorvig) QPixmap conversion - //if (image != 0) - // ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage()); + if (image != 0) + ret = QVariant(qt_mac_toQImage(image)); return ret; } diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index e7ea3d8f8d..68145ec914 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -63,7 +63,6 @@ QT_END_NAMESPACE QWindow *m_window; QCocoaWindow *m_platformWindow; Qt::MouseButtons m_buttons; - QAccessibleInterface *m_accessibleRoot; QString m_composingText; bool m_sendKeyEvent; QStringList *currentCustomDragTypes; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 568cc4bebf..52e2d781ee 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -121,7 +121,6 @@ static QTouchDevice *touchDevice = 0; m_window = window; m_platformWindow = platformWindow; - m_accessibleRoot = 0; m_sendKeyEvent = false; #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR @@ -130,15 +129,13 @@ static QTouchDevice *touchDevice = 0; static bool skipAccessibilityForInspectorWindows = false; if (!skipAccessibilityForInspectorWindows) { - m_accessibleRoot = window->accessibleRoot(); + // m_accessibleRoot = window->accessibleRoot(); AccessibilityInspector *inspector = new AccessibilityInspector(window); skipAccessibilityForInspectorWindows = true; inspector->inspectWindow(window); skipAccessibilityForInspectorWindows = false; } -#else - m_accessibleRoot = window->accessibleRoot(); #endif [self registerDragTypes]; diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm index e3b8cf6532..c43c0b5068 100644 --- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm +++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm @@ -45,6 +45,7 @@ #include "qcocoahelpers.h" #include "qcocoaaccessibility.h" #include "qcocoaaccessibilityelement.h" +#include <qpa/qplatformintegration.h> #include <QtGui/private/qaccessible2_p.h> #include <QtCore/QDebug> @@ -60,22 +61,26 @@ } - (id)accessibilityAttributeValue:(NSString *)attribute { + + // activate accessibility updates + QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) { - if (m_accessibleRoot) - return QCocoaAccessible::macRole(m_accessibleRoot); + if (m_window->accessibleRoot()) + return QCocoaAccessible::macRole(m_window->accessibleRoot()); return NSAccessibilityUnknownRole; } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) { return NSAccessibilityRoleDescriptionForUIElement(self); } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { - if (!m_accessibleRoot) + if (!m_window->accessibleRoot()) return [super accessibilityAttributeValue:attribute]; // Create QCocoaAccessibleElements for each child if the // root accessible interface. - int numKids = m_accessibleRoot->childCount(); + int numKids = m_window->accessibleRoot()->childCount(); NSMutableArray *kids = [NSMutableArray arrayWithCapacity:numKids]; for (int i = 0; i < numKids; ++i) { - QAccessibleInterface *child = m_accessibleRoot->child(i); + QAccessibleInterface *child = m_window->accessibleRoot()->child(i); Q_ASSERT(child); QAccessible::Id childAxid = QAccessible::uniqueId(child); QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithId:childAxid parent:self]; @@ -90,10 +95,10 @@ } - (id)accessibilityHitTest:(NSPoint)point { - if (!m_accessibleRoot) + if (!m_window->accessibleRoot()) return [super accessibilityHitTest:point]; - QAccessibleInterface *childInterface = m_accessibleRoot->childAt(point.x, qt_mac_flipYCoordinate(point.y)); + QAccessibleInterface *childInterface = m_window->accessibleRoot()->childAt(point.x, qt_mac_flipYCoordinate(point.y)); // No child found, meaning we hit the NSView if (!childInterface) { return [super accessibilityHitTest:point]; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 4748005f1a..2dedf99582 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -364,6 +364,9 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const case QPaintDevice::PdmDepth: val = 24; break; + case QPaintDevice::PdmDevicePixelRatio: + val = 1; + break; default: val = 0; qWarning("QPrinter::metric: Invalid metric command"); diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 64e11b4e07..615b69f7d9 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -145,7 +145,8 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const { - QPlatformWindow *w = new QEglFSWindow(window); + QEglFSWindow *w = new QEglFSWindow(window); + w->create(); w->requestActivateWindow(); return w; } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 68cef6253e..ebf8e4af85 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -59,10 +59,6 @@ QEglFSWindow::QEglFSWindow(QWindow *w) #ifdef QEGL_EXTRA_DEBUG qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_winid)); #endif - - setWindowState(Qt::WindowFullScreen); - - create(); } QEglFSWindow::~QEglFSWindow() @@ -72,6 +68,8 @@ QEglFSWindow::~QEglFSWindow() void QEglFSWindow::create() { + setWindowState(Qt::WindowFullScreen); + if (m_window) return; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index a351b4a6f4..67a64973ce 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -68,10 +68,12 @@ public: virtual void invalidateSurface(); virtual void resetSurface(); -private: - WId m_winid; +protected: EGLSurface m_surface; EGLNativeWindowType m_window; + +private: + WId m_winid; EGLConfig m_config; QSurfaceFormat m_format; }; diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h index 442b37f1b3..3d3ba58049 100644 --- a/src/plugins/platforms/ios/qiosapplicationdelegate.h +++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h @@ -42,9 +42,12 @@ #import <UIKit/UIKit.h> #import <QtGui/QtGui> +#import "qiosviewcontroller.h" + @interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) QIOSViewController *qiosViewController; @end diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm index 41a3fff84f..10cbe529c4 100644 --- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm +++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm @@ -46,6 +46,7 @@ @implementation QIOSApplicationDelegate @synthesize window; +@synthesize qiosViewController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -85,6 +86,7 @@ - (void)dealloc { + [qiosViewController release]; [window release]; [super dealloc]; } diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm index 566ff3a672..f3c1af2b2d 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.mm +++ b/src/plugins/platforms/ios/qiosbackingstore.mm @@ -52,7 +52,11 @@ QIOSBackingStore::QIOSBackingStore(QWindow *window) , m_context(new QOpenGLContext) , m_device(0) { - m_context->setFormat(window->requestedFormat()); + QSurfaceFormat fmt = window->requestedFormat(); + fmt.setDepthBufferSize(16); + fmt.setStencilBufferSize(8); + + m_context->setFormat(fmt); m_context->setScreen(window->screen()); m_context->create(); } diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h index 3be9f8bb21..fd328c9171 100644 --- a/src/plugins/platforms/ios/qiosglobal.h +++ b/src/plugins/platforms/ios/qiosglobal.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QPlatformScreen; bool isQtApplication(); -QIOSViewController *rootViewController(); +QIOSViewController *qiosViewController(); CGRect toCGRect(const QRect &rect); QRect fromCGRect(const CGRect &rect); diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index 5860078372..d26eca54e5 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -58,10 +58,14 @@ bool isQtApplication() return isQt; } -QIOSViewController *rootViewController() +QIOSViewController *qiosViewController() { + // If Qt controls the application, we have created a root view controller were we place top-level + // QWindows. Note that in a mixed native application, our view controller might later be removed or + // added as a child of another controller. To protect against that, we keep an explicit pointer to the + // view controller in cases where this is the controller we need to access. static QIOSViewController *c = isQtApplication() ? - static_cast<QIOSViewController *>([UIApplication sharedApplication].delegate.window.rootViewController) : nil; + static_cast<QIOSApplicationDelegate *>([UIApplication sharedApplication].delegate).qiosViewController : nil; return c; } diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index d86ed5f090..b73f9c3cbc 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -142,7 +142,7 @@ QIOSScreen::QIOSScreen(unsigned int screenIndex) if (isQtApplication()) { // When in a non-mixed environment, let QScreen follow the current interface orientation: - setPrimaryOrientation(toQtScreenOrientation(UIDeviceOrientation(rootViewController().interfaceOrientation))); + setPrimaryOrientation(toQtScreenOrientation(UIDeviceOrientation(qiosViewController().interfaceOrientation))); } [pool release]; diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index d7a2fa1a75..5edf81af93 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -375,7 +375,7 @@ void QIOSWindow::setVisible(bool visible) requestActivateWindow(); } else { // Activate top-most visible QWindow: - NSArray *subviews = rootViewController().view.subviews; + NSArray *subviews = qiosViewController().view.subviews; for (int i = int(subviews.count) - 1; i >= 0; --i) { UIView *view = [subviews objectAtIndex:i]; if (!view.hidden) { @@ -431,7 +431,7 @@ void QIOSWindow::setParent(const QPlatformWindow *parentWindow) UIView *parentView = reinterpret_cast<UIView *>(parentWindow->winId()); [parentView addSubview:m_view]; } else if (isQtApplication()) { - [rootViewController().view addSubview:m_view]; + [qiosViewController().view addSubview:m_view]; } } diff --git a/src/plugins/platforms/ios/qtmain.mm b/src/plugins/platforms/ios/qtmain.mm index 916224f936..19c98f2c59 100644 --- a/src/plugins/platforms/ios/qtmain.mm +++ b/src/plugins/platforms/ios/qtmain.mm @@ -56,7 +56,8 @@ extern int qt_main(int argc, char *argv[]); - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; - self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease]; + self.qiosViewController = [[[QIOSViewController alloc] init] autorelease]; + self.window.rootViewController = self.qiosViewController; #ifdef QT_DEBUG self.window.backgroundColor = [UIColor cyanColor]; diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h index a5df7d05d3..28546aed88 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.h +++ b/src/plugins/platforms/offscreen/qoffscreencommon.h @@ -73,12 +73,14 @@ public: QScopedPointer<QPlatformCursor> m_cursor; }; +#ifndef QT_NO_DRAGANDDROP class QOffscreenDrag : public QPlatformDrag { public: QMimeData *platformDropData() { return 0; } Qt::DropAction drag(QDrag *) { return Qt::IgnoreAction; } }; +#endif class QOffscreenBackingStore : public QPlatformBackingStore { diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index e3fcc7ebb0..5b74ad3b8d 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -106,7 +106,9 @@ QOffscreenIntegration::QOffscreenIntegration() m_fontDatabase.reset(new QBasicFontDatabase()); #endif +#ifndef QT_NO_DRAGANDDROP m_drag.reset(new QOffscreenDrag); +#endif m_services.reset(new QPlatformServices); QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher); @@ -149,10 +151,12 @@ QPlatformFontDatabase *QOffscreenIntegration::fontDatabase() const return m_fontDatabase.data(); } +#ifndef QT_NO_DRAGANDDROP QPlatformDrag *QOffscreenIntegration::drag() const { return m_drag.data(); } +#endif QPlatformServices *QOffscreenIntegration::services() const { diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h index eb03100ec9..b403ce83b3 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h @@ -60,7 +60,9 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; +#ifndef QT_NO_DRAGANDDROP QPlatformDrag *drag() const; +#endif QPlatformServices *services() const; QPlatformFontDatabase *fontDatabase() const; @@ -71,7 +73,9 @@ public: private: QAbstractEventDispatcher *m_eventDispatcher; QScopedPointer<QPlatformFontDatabase> m_fontDatabase; +#ifndef QT_NO_DRAGANDDROP QScopedPointer<QPlatformDrag> m_drag; +#endif QScopedPointer<QPlatformServices> m_services; }; diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index f1bebee9b2..a351ec865a 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -172,6 +172,7 @@ void QQnxWindow::setGeometry(const QRect &rect) { const QRect oldGeometry = setGeometryHelper(rect); +#if !defined(QT_NO_OPENGL) // If this is an OpenGL window we need to request that the GL context updates // the EGLsurface on which it is rendering. The surface will be recreated the // next time QQnxGLContext::makeCurrent() is called. @@ -184,6 +185,7 @@ void QQnxWindow::setGeometry(const QRect &rect) if (m_platformOpenGLContext != 0 && bufferSize() != rect.size()) m_platformOpenGLContext->requestSurfaceChange(); } +#endif // Send a geometry change event to Qt (triggers resizeEvent() in QWindow/QWidget). @@ -353,13 +355,12 @@ void QQnxWindow::setBufferSize(const QSize &size) // Create window buffers if they do not exist if (m_bufferSize.isEmpty()) { + val[0] = m_screen->nativeFormat(); #if !defined(QT_NO_OPENGL) // Get pixel format from EGL config if using OpenGL; // otherwise inherit pixel format of window's screen if (m_platformOpenGLContext != 0) { val[0] = platformWindowFormatToNativeFormat(m_platformOpenGLContext->format()); - } else { - val[0] = m_screen->nativeFormat(); } #endif diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index f222deeeac..63b4370dc2 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -52,7 +52,9 @@ #include <QtCore/qsettings.h> #include <QtGui/qaccessible.h> #include <QtGui/private/qaccessible2_p.h> +#include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformnativeinterface.h> +#include <qpa/qplatformintegration.h> #include <QtGui/qwindow.h> #include <QtGui/qguiapplication.h> @@ -245,6 +247,8 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) { /* For UI Automation */ } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { + // Start handling accessibility internally + QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); #if 1 // Ignoring all requests while starting up // ### Maybe QPA takes care of this??? diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index b40aefa225..dfbbe3069c 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -146,7 +146,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) #endif QImage::Format format = QWindowsNativeImage::systemFormat(); if (format == QImage::Format_RGB32 && rasterWindow()->window()->format().hasAlpha()) - format = QImage::Format_ARGB32; + format = QImage::Format_ARGB32_Premultiplied; m_image.reset(new QWindowsNativeImage(size.width(), size.height(), format)); } } diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index b66a16ae58..cf6cb199c7 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -178,6 +178,20 @@ void QWindowsClipboard::unregisterViewer() } } +static bool isProcessBeingDebugged(HWND hwnd) +{ + DWORD pid = 0; + if (!GetWindowThreadProcessId(hwnd, &pid) || !pid) + return false; + const HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!processHandle) + return false; + BOOL debugged = FALSE; + CheckRemoteDebuggerPresent(processHandle, &debugged); + CloseHandle(processHandle); + return debugged != FALSE; +} + void QWindowsClipboard::propagateClipboardMessage(UINT message, WPARAM wParam, LPARAM lParam) const { if (!m_nextClipboardViewer) @@ -189,6 +203,12 @@ void QWindowsClipboard::propagateClipboardMessage(UINT message, WPARAM wParam, L qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO); return; } + // Also refuse if the process is being debugged, specifically, if it is + // displaying a runtime assert, which is not caught by isHungAppWindow(). + if (isProcessBeingDebugged(m_nextClipboardViewer)) { + qWarning("%s: Cowardly refusing to send clipboard message to application under debugger...", Q_FUNC_INFO); + return; + } SendMessage(m_nextClipboardViewer, message, wParam, lParam); } diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 5fa954cb12..7fedc27951 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1173,7 +1173,7 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal fontFile->Release(); fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, pixelSize, - m_fontEngineData); + sharedFontData()); // Get font family from font data fontEngine->fontDef.family = font.familyName(); diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 5b6ce695d8..c0f1b3a000 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -220,6 +220,7 @@ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *di fontDef.pixelSize = pixelSize; collectMetrics(); + cache_cost = (m_ascent.toInt() + m_descent.toInt()) * m_xHeight.toInt() * 2000; } QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite() @@ -740,6 +741,8 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, if (familyNames != NULL) familyNames->Release(); + if (fontFamily) + fontFamily->Release(); if (FAILED(hr)) qErrnoWarning(hr, "initFontInfo: Failed to get family name"); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index da3e2a6a6a..ae66ef8a3d 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1052,8 +1052,16 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) // Do we already have a DC entry for that window? QWindowsWindow *window = static_cast<QWindowsWindow *>(surface); const HWND hwnd = window->handle(); - if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, hwnd)) + if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, hwnd)) { + // Repeated calls to wglMakeCurrent when vsync is enabled in the driver will + // often result in 100% cpuload. This check is cheap and avoids the problem. + // This is reproducable on NVidia cards and Intel onboard chips. + if (wglGetCurrentContext() == contextData->renderingContext + && wglGetCurrentDC() == contextData->hdc) { + return true; + } return wglMakeCurrent(contextData->hdc, contextData->renderingContext); + } // Create a new entry. const QOpenGLContextData newContext(m_renderingContext, hwnd, GetDC(hwnd)); if (!newContext.hdc) diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 03e4925c3b..73df3ec032 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -113,6 +113,8 @@ public: Q_INVOKABLE QString registerWindowClass(const QString &classNameIn, void *eventProc) const; + Q_INVOKABLE void beep() { MessageBeep(MB_OK); } // For QApplication + bool asyncExpose() const; void setAsyncExpose(bool value); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 9b2b67619d..2a5e08cf41 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1802,6 +1802,19 @@ QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwex } #ifndef Q_OS_WINCE +void QWindowsWindow::setAlertState(bool enabled) +{ + if (isAlertState() == enabled) + return; + if (enabled) { + alertWindow(0); + setFlag(AlertState); + } else { + stopAlertWindow(); + clearFlag(AlertState); + } +} + void QWindowsWindow::alertWindow(int durationMs) { DWORD timeOutMs = GetCaretBlinkTime(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 1148440f05..2117ca50b8 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -132,7 +132,8 @@ public: SynchronousGeometryChangeEvent = 0x400, WithinSetStyle = 0x800, WithinDestroy = 0x1000, - TouchRegistered = 0x2000 + TouchRegistered = 0x2000, + AlertState = 0x4000 }; struct WindowData @@ -255,6 +256,8 @@ public: void setWindowIcon(const QIcon &icon); #ifndef Q_OS_WINCE + void setAlertState(bool enabled); + bool isAlertState() const { return testFlag(AlertState); } void alertWindow(int durationMs = 0); void stopAlertWindow(); #endif diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 08e72ed5ce..6241898462 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -57,6 +57,10 @@ #include "qglxintegration.h" #endif +#ifndef XCB_USE_XLIB +# include <stdio.h> +#endif + QT_BEGIN_NAMESPACE class QXcbResourceMap : public QMap<QByteArray, QXcbNativeInterface::ResourceType> @@ -84,6 +88,16 @@ QXcbNativeInterface::QXcbNativeInterface() : { } +void QXcbNativeInterface::beep() // For QApplication::beep() +{ +#ifdef XCB_USE_XLIB + ::Display *display = (::Display *)nativeResourceForScreen(QByteArrayLiteral("display"), QGuiApplication::primaryScreen()); + XBell(display, 0); +#else + fputc(7, stdout); +#endif +} + void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) { QByteArray lowerCaseResource = resourceString.toLower(); diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 75d42ac6b0..db0fa3e2ca 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -53,6 +53,7 @@ class QXcbConnection; class QXcbNativeInterface : public QPlatformNativeInterface { + Q_OBJECT public: enum ResourceType { Display, @@ -89,6 +90,8 @@ public: static void *eglContextForContext(QOpenGLContext *context); static void *glxContextForContext(QOpenGLContext *context); + Q_INVOKABLE void beep(); + private: const QByteArray m_genericEventFilterType; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5af6a9ec9d..68ccbfb8c0 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -189,6 +189,7 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_usingSyncProtocol(false) , m_deferredActivation(false) , m_embedded(false) + , m_alertState(false) , m_netWmUserTimeWindow(XCB_NONE) , m_dirtyFrameMargins(false) #if defined(XCB_USE_EGL) @@ -2047,4 +2048,17 @@ void QXcbWindow::setMask(const QRegion ®ion) #endif // !QT_NO_SHAPE +void QXcbWindow::setAlertState(bool enabled) +{ + if (m_alertState == enabled) + return; + const NetWmStates oldState = netWmStates(); + m_alertState = enabled; + if (enabled) { + setNetWmStates(oldState | NetWmStateDemandsAttention); + } else { + setNetWmStates(oldState & ~NetWmStateDemandsAttention); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index f4bd2d96ff..300596845e 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE class QXcbScreen; class QXcbEGLSurface; class QIcon; - class QXcbWindow : public QXcbObject, public QPlatformWindow { public: @@ -120,6 +119,9 @@ public: void setMask(const QRegion ®ion); #endif // !QT_NO_SHAPE + void setAlertState(bool enabled); + bool isAlertState() const { return m_alertState; } + xcb_window_t xcb_window() const { return m_window; } uint depth() const { return m_depth; } QImage::Format imageFormat() const { return m_imageFormat; } @@ -194,6 +196,7 @@ private: bool m_deferredExpose; bool m_configureNotifyPending; bool m_embedded; + bool m_alertState; xcb_window_t m_netWmUserTimeWindow; QSurfaceFormat m_format; |