diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-03-24 07:37:43 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-03-24 07:38:02 +0100 |
commit | 135ebe4f3d268121047fdbfee49f2dd52006165e (patch) | |
tree | 6b303103f36e69e29cfa860b8b7afc584c55d6f3 /src/plugins | |
parent | e7feb956280105113b3e58f12e5f32f54199a95a (diff) | |
parent | 1e8f50a8d069c97ea6a4f00d664c12e594884f54 (diff) |
Merge remote-tracking branch 'origin/5.5' into dev
Change-Id: If5d2e621c2fa5476c3ab687a3f4620c54fc3b32e
Diffstat (limited to 'src/plugins')
45 files changed, 480 insertions, 209 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index b30aab5b11..47018bfece 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -61,40 +61,40 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) QT_BEGIN_NAMESPACE -static JavaVM *m_javaVM = Q_NULLPTR; -static jclass m_applicationClass = Q_NULLPTR; -static jobject m_classLoaderObject = Q_NULLPTR; -static jmethodID m_loadClassMethodID = Q_NULLPTR; -static AAssetManager *m_assetManager = Q_NULLPTR; -static jobject m_resourcesObj = Q_NULLPTR; -static jobject m_activityObject = Q_NULLPTR; -static jmethodID m_createSurfaceMethodID = Q_NULLPTR; -static jmethodID m_setSurfaceGeometryMethodID = Q_NULLPTR; -static jmethodID m_destroySurfaceMethodID = Q_NULLPTR; +static JavaVM *m_javaVM = nullptr; +static jclass m_applicationClass = nullptr; +static jobject m_classLoaderObject = nullptr; +static jmethodID m_loadClassMethodID = nullptr; +static AAssetManager *m_assetManager = nullptr; +static jobject m_resourcesObj = nullptr; +static jobject m_activityObject = nullptr; +static jmethodID m_createSurfaceMethodID = nullptr; +static jmethodID m_setSurfaceGeometryMethodID = nullptr; +static jmethodID m_destroySurfaceMethodID = nullptr; static bool m_activityActive = true; // defaults to true because when the platform plugin is // initialized, QtActivity::onResume() has already been called -static jclass m_bitmapClass = Q_NULLPTR; -static jmethodID m_createBitmapMethodID = Q_NULLPTR; -static jobject m_ARGB_8888_BitmapConfigValue = Q_NULLPTR; -static jobject m_RGB_565_BitmapConfigValue = Q_NULLPTR; +static jclass m_bitmapClass = nullptr; +static jmethodID m_createBitmapMethodID = nullptr; +static jobject m_ARGB_8888_BitmapConfigValue = nullptr; +static jobject m_RGB_565_BitmapConfigValue = nullptr; static bool m_statusBarShowing = true; -static jclass m_bitmapDrawableClass = Q_NULLPTR; -static jmethodID m_bitmapDrawableConstructorMethodID = Q_NULLPTR; +static jclass m_bitmapDrawableClass = nullptr; +static jmethodID m_bitmapDrawableConstructorMethodID = nullptr; extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application -static Main m_main = Q_NULLPTR; -static void *m_mainLibraryHnd = Q_NULLPTR; +static Main m_main = nullptr; +static void *m_mainLibraryHnd = nullptr; static QList<QByteArray> m_applicationParams; struct SurfaceData { ~SurfaceData() { delete surface; } - QJNIObjectPrivate *surface = Q_NULLPTR; - AndroidSurfaceClient *client = Q_NULLPTR; + QJNIObjectPrivate *surface = nullptr; + AndroidSurfaceClient *client = nullptr; }; QHash<int, AndroidSurfaceClient *> m_surfaces; @@ -103,7 +103,7 @@ static QMutex m_surfacesMutex; static int m_surfaceId = 1; -static QAndroidPlatformIntegration *m_androidPlatformIntegration = Q_NULLPTR; +static QAndroidPlatformIntegration *m_androidPlatformIntegration = nullptr; static int m_desktopWidthPixels = 0; static int m_desktopHeightPixels = 0; @@ -111,7 +111,7 @@ static double m_scaledDensity = 0; static volatile bool m_pauseApplication; -static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = Q_NULLPTR; +static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr; @@ -325,7 +325,7 @@ namespace QtAndroid { m_surfacesMutex.lock(); const int surfaceId = m_surfaceId++; - m_surfaces[surfaceId] = Q_NULLPTR; // dummy + m_surfaces[surfaceId] = nullptr; // dummy m_surfacesMutex.unlock(); jint x = 0, y = 0, w = -1, h = -1; @@ -419,7 +419,7 @@ namespace QtAndroid static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobject applicationAssetManager*/) { - m_androidPlatformIntegration = Q_NULLPTR; + m_androidPlatformIntegration = nullptr; m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler(); return true; } @@ -447,7 +447,7 @@ static void *startMainMethod(void */*data*/) static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring paramsString, jstring environmentString) { - m_mainLibraryHnd = Q_NULLPTR; + m_mainLibraryHnd = nullptr; { // Set env. vars const char *nativeString = env->GetStringUTFChars(environmentString, 0); const QList<QByteArray> envVars = QByteArray(nativeString).split('\t'); @@ -473,7 +473,7 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para // Obtain a handle to the main library (the library that contains the main() function). // This library should already be loaded, and calling dlopen() will just return a reference to it. m_mainLibraryHnd = dlopen(m_applicationParams.first().data(), 0); - if (m_mainLibraryHnd == Q_NULLPTR) { + if (m_mainLibraryHnd == nullptr) { qCritical() << "dlopen failed:" << dlerror(); return false; } @@ -490,16 +490,16 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para } pthread_t appThread; - return pthread_create(&appThread, Q_NULLPTR, startMainMethod, Q_NULLPTR) == 0; + return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0; } static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/) { Q_UNUSED(env); - m_androidPlatformIntegration = Q_NULLPTR; + m_androidPlatformIntegration = nullptr; delete m_androidAssetsFileEngineHandler; - m_androidAssetsFileEngineHandler = Q_NULLPTR; + m_androidAssetsFileEngineHandler = nullptr; } static void terminateQt(JNIEnv *env, jclass /*clazz*/) @@ -518,16 +518,16 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/) env->DeleteGlobalRef(m_RGB_565_BitmapConfigValue); if (m_bitmapDrawableClass) env->DeleteGlobalRef(m_bitmapDrawableClass); - m_androidPlatformIntegration = Q_NULLPTR; + m_androidPlatformIntegration = nullptr; delete m_androidAssetsFileEngineHandler; - m_androidAssetsFileEngineHandler = Q_NULLPTR; + m_androidAssetsFileEngineHandler = nullptr; } static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h) { QMutexLocker lock(&m_surfacesMutex); const auto &it = m_surfaces.find(id); - if (it.value() == Q_NULLPTR) // This should never happen... + if (it.value() == nullptr) // This should never happen... return; if (it == m_surfaces.end()) { @@ -572,7 +572,7 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidPlatformIntegration) return; - if (QGuiApplication::instance() != Q_NULLPTR) { + if (QGuiApplication::instance() != nullptr) { foreach (QWindow *w, QGuiApplication::topLevelWindows()) { QRect availableGeometry = w->screen()->availableGeometry(); if (w->geometry().width() > 0 && w->geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0) @@ -778,8 +778,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) __android_log_print(ANDROID_LOG_INFO, "Qt", "qt start"); UnionJNIEnvToVoid uenv; - uenv.venv = Q_NULLPTR; - m_javaVM = Q_NULLPTR; + uenv.venv = nullptr; + m_javaVM = nullptr; if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "GetEnv failed"); diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 5384b6faca..eb96bf11f0 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -88,19 +88,19 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA return &m_androidStyle->m_styleData; } else - return Q_NULLPTR; + return nullptr; } if (resource == "AndroidStandardPalette") { if (m_androidStyle) return &m_androidStyle->m_standardPalette; else - return Q_NULLPTR; + return nullptr; } if (resource == "AndroidQWidgetFonts") { if (m_androidStyle) return &m_androidStyle->m_QWidgetsFonts; else - return Q_NULLPTR; + return nullptr; } if (resource == "AndroidDeviceName") { static QString deviceName = QtAndroid::deviceName(); @@ -110,9 +110,9 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA } QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶mList) - : m_touchDevice(0) + : m_touchDevice(nullptr) #ifndef QT_NO_ACCESSIBILITY - , m_accessibility(0) + , m_accessibility(nullptr) #endif { Q_UNUSED(paramList); @@ -183,7 +183,7 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ QGuiApplicationPrivate::instance()->setApplicationState(m_defaultApplicationState); } -bool QAndroidPlatformIntegration::needsBasicRenderloopWorkaround() +static bool needsBasicRenderloopWorkaround() { static bool needsWorkaround = QtAndroid::deviceName().compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0 @@ -200,11 +200,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const case NativeWidgets: return true; case OpenGL: return true; case ForeignWindows: return true; - case ThreadedOpenGL: - if (needsBasicRenderloopWorkaround()) - return false; - else - return true; + case ThreadedOpenGL: return !needsBasicRenderloopWorkaround(); case RasterGLSurface: return true; default: return QPlatformIntegration::hasCapability(cap); diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index c0a9229056..ccf683e253 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -117,10 +117,8 @@ public: void setTouchDevice(QTouchDevice *touchDevice) { m_touchDevice = touchDevice; } static void setDefaultApplicationState(Qt::ApplicationState applicationState) { m_defaultApplicationState = applicationState; } - EGLDisplay m_eglDisplay; private: - static bool needsBasicRenderloopWorkaround(); - + EGLDisplay m_eglDisplay; QTouchDevice *m_touchDevice; QAndroidPlatformScreen *m_primaryScreen; @@ -140,8 +138,6 @@ private: static Qt::ApplicationState m_defaultApplicationState; QPlatformFontDatabase *m_androidFDB; - QImage *m_FbScreenImage; - QPainter *m_compositePainter; QAndroidPlatformNativeInterface *m_androidPlatformNativeInterface; QAndroidPlatformServices *m_androidPlatformServices; diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h index cad90b33f1..061dfac156 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h @@ -38,6 +38,8 @@ #include <QtGui> #include <qpa/qplatformaccessibility.h> +QT_BEGIN_NAMESPACE + class QCocoaAccessibility : public QPlatformAccessibility { public: @@ -81,4 +83,6 @@ id getValueAttribute(QAccessibleInterface *interface); } +QT_END_NAMESPACE + #endif diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index e13a9c2b19..03f585d19d 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -35,6 +35,8 @@ #include <QtGui/qaccessible.h> #include <private/qcore_mac_p.h> +QT_BEGIN_NAMESPACE + QCocoaAccessibility::QCocoaAccessibility() { @@ -371,3 +373,6 @@ id getValueAttribute(QAccessibleInterface *interface) } } // namespace QCocoaAccessible + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 7349236455..84d60df3ef 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -40,6 +40,7 @@ #import <AppKit/NSAccessibility.h> +QT_USE_NAMESPACE static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0) { diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.h b/src/plugins/platforms/cocoa/qcocoaapplication.h index ab6a756001..bcb0d0ee48 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplication.h +++ b/src/plugins/platforms/cocoa/qcocoaapplication.h @@ -92,8 +92,8 @@ - (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader); - (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel; -- (void)qt_sendPostedMessage:(NSEvent *)event; -- (BOOL)qt_filterEvent:(NSEvent *)event; +- (void)QT_MANGLE_NAMESPACE(qt_sendPostedMessage):(NSEvent *)event; +- (BOOL)QT_MANGLE_NAMESPACE(qt_filterEvent):(NSEvent *)event; @end @interface QT_MANGLE_NAMESPACE(QNSApplication) : NSApplication { diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.mm b/src/plugins/platforms/cocoa/qcocoaapplication.mm index adaabc3c15..79399e4183 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplication.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplication.mm @@ -98,7 +98,7 @@ QT_USE_NAMESPACE | NSFontPanelStrikethroughEffectModeMask; } -- (void)qt_sendPostedMessage:(NSEvent *)event +- (void)QT_MANGLE_NAMESPACE(qt_sendPostedMessage):(NSEvent *)event { // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! // That is why we need to split the address in two parts: @@ -126,7 +126,7 @@ QT_USE_NAMESPACE static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSEvent"); -- (BOOL)qt_filterEvent:(NSEvent *)event +- (BOOL)QT_MANGLE_NAMESPACE(qt_filterEvent):(NSEvent *)event { if (qApp && qApp->eventDispatcher()-> filterNativeEvent(q_macLocalEventType, static_cast<void*>(event), 0)) @@ -135,7 +135,7 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE if ([event type] == NSApplicationDefined) { switch ([event subtype]) { case QtCocoaEventSubTypePostMessage: - [NSApp qt_sendPostedMessage:event]; + [NSApp QT_MANGLE_NAMESPACE(qt_sendPostedMessage):event]; return true; default: break; @@ -163,7 +163,7 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE // be called instead of sendEvent if redirection occurs. // 'self' will then be an instance of NSApplication // (and not QNSApplication) - if (![NSApp qt_filterEvent:event]) + if (![NSApp QT_MANGLE_NAMESPACE(qt_filterEvent):event]) [self qt_sendEvent_original:event]; } @@ -171,7 +171,7 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE { // This method will be called if // no redirection occurs - if (![NSApp qt_filterEvent:event]) + if (![NSApp QT_MANGLE_NAMESPACE(qt_filterEvent):event]) [super sendEvent:event]; } diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 2c71d07256..f3a0216870 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -80,12 +80,14 @@ QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE static QCocoaApplicationDelegate *sharedCocoaApplicationDelegate = nil; static void cleanupCocoaApplicationDelegate() { [sharedCocoaApplicationDelegate release]; } +QT_END_NAMESPACE @implementation QCocoaApplicationDelegate diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h index 31f9ea3ae2..8b2a9f3788 100644 --- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h @@ -35,9 +35,10 @@ #define QCOCOAAUTORELEASEPOOL_H #undef slots - +#include <qglobal.h> #include <Cocoa/Cocoa.h> +QT_BEGIN_NAMESPACE class QCocoaAutoReleasePool { public: @@ -47,5 +48,6 @@ public: private: NSAutoreleasePool *pool; }; +QT_END_NAMESPACE #endif // QCOCOAAUTORELEASEPOOL_H diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm index 2c240c2570..8f30365186 100644 --- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm @@ -33,6 +33,8 @@ #include "qcocoaautoreleasepool.h" +QT_BEGIN_NAMESPACE + QCocoaAutoReleasePool::QCocoaAutoReleasePool() { pool = [[NSAutoreleasePool alloc] init]; @@ -42,3 +44,5 @@ QCocoaAutoReleasePool::~QCocoaAutoReleasePool() { [pool release]; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h index 058941939c..e087fcee26 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.h +++ b/src/plugins/platforms/cocoa/qcocoadrag.h @@ -67,6 +67,8 @@ private: NSEvent *m_lastEvent; NSView *m_lastView; Qt::DropAction m_executed_drop_action; + + QPixmap dragPixmap(QDrag *drag, QPoint &hotSpot) const; }; class QCocoaDropData : public QInternalMimeData diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index a80b32a0b8..4466d28128 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -37,6 +37,8 @@ QT_BEGIN_NAMESPACE +static const int dragImageMaxChars = 26; + QCocoaDrag::QCocoaDrag() : m_drag(0) { @@ -116,10 +118,8 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) m_drag = o; m_executed_drop_action = Qt::IgnoreAction; - QPixmap pm = m_drag->pixmap(); - if (pm.isNull()) - pm = defaultPixmap(); - + QPoint hotSpot = m_drag->hotSpot(); + QPixmap pm = dragPixmap(m_drag, hotSpot); NSImage *nsimage = qt_mac_create_nsimage(pm); QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND); @@ -128,8 +128,8 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) NSPoint event_location = [m_lastEvent locationInWindow]; NSPoint local_point = [m_lastView convertPoint:event_location fromView:nil]; - local_point.x -= m_drag->hotSpot().x(); - CGFloat flippedY = m_drag->pixmap().height() - m_drag->hotSpot().y(); + local_point.x -= hotSpot.x(); + CGFloat flippedY = pm.height() - hotSpot.y(); local_point.y += flippedY; NSSize mouseOffset = NSMakeSize(0.0, 0.0); NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; @@ -153,6 +153,50 @@ void QCocoaDrag::setAcceptedAction(Qt::DropAction act) m_executed_drop_action = act; } +QPixmap QCocoaDrag::dragPixmap(QDrag *drag, QPoint &hotSpot) const +{ + const QMimeData* data = drag->mimeData(); + QPixmap pm = drag->pixmap(); + + if (pm.isNull()) { + QFont f(qApp->font()); + f.setPointSize(12); + QFontMetrics fm(f); + + if (data->hasImage()) { + const QImage img = data->imageData().value<QImage>(); + if (!img.isNull()) { + pm = QPixmap::fromImage(img).scaledToWidth(dragImageMaxChars *fm.averageCharWidth()); + } + } + + if (pm.isNull() && (data->hasText() || data->hasUrls()) ) { + QString s = data->hasText() ? data->text() : data->urls().first().toString(); + if (s.length() > dragImageMaxChars) + s = s.left(dragImageMaxChars -3) + QChar(0x2026); + if (!s.isEmpty()) { + const int width = fm.width(s); + const int height = fm.height(); + if (width > 0 && height > 0) { + pm = QPixmap(width, height); + QPainter p(&pm); + p.fillRect(0, 0, pm.width(), pm.height(), Qt::color0); + p.setPen(Qt::color1); + p.setFont(f); + p.drawText(0, fm.ascent(), s); + p.end(); + hotSpot = QPoint(pm.width() / 2, pm.height() / 2); + } + } + } + } + + if (pm.isNull()) + pm = defaultPixmap(); + + return pm; +} + QCocoaDropData::QCocoaDropData(NSPasteboard *pasteboard) { dropPasteboard = reinterpret_cast<CFStringRef>(const_cast<const NSString *>([pasteboard name])); diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index e89bc662b7..a3c72c58b9 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -42,6 +42,8 @@ #import <Cocoa/Cocoa.h> +QT_BEGIN_NAMESPACE + static inline QByteArray getGlString(GLenum param) { if (const GLubyte *s = glGetString(param)) @@ -351,3 +353,6 @@ bool QCocoaGLContext::isSharing() const { return m_shareContext != nil; } + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 4fadc2f60a..867526ff52 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -45,6 +45,8 @@ #include "qcocoawindow.h" #import "qnsview.h" +QT_BEGIN_NAMESPACE + NSString *qt_mac_removePrivateUnicode(NSString* string) { int len = [string length]; @@ -71,6 +73,8 @@ static inline QCocoaMenuLoader *getMenuLoader() return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)]; } +QT_END_NAMESPACE + @interface QT_MANGLE_NAMESPACE(QCocoaMenuDelegate) : NSObject <NSMenuDelegate> { QCocoaMenu *m_menu; } diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 5d8082d347..764a01370d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -42,6 +42,8 @@ #include <QtGui/QGuiApplication> #include <QtCore/QDebug> +QT_BEGIN_NAMESPACE + static QList<QCocoaMenuBar*> static_menubars; static inline QCocoaMenuLoader *getMenuLoader() @@ -382,3 +384,5 @@ NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r) return Q_NULLPTR; } +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index d6813749a4..bf12c0f2ce 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -44,6 +44,8 @@ #include <QtCore/QDebug> +QT_BEGIN_NAMESPACE + static inline QCocoaMenuLoader *getMenuLoader() { return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)]; @@ -72,6 +74,9 @@ NSString *keySequenceToKeyEqivalent(const QKeySequence &accel) QChar cocoa_key = qt_mac_qtKey2CocoaKey(Qt::Key(accel_key)); if (cocoa_key.isNull()) cocoa_key = QChar(accel_key).toLower().unicode(); + // Similar to qt_mac_removePrivateUnicode change the delete key so the symbol is correctly seen in native menubar + if (cocoa_key.unicode() == NSDeleteFunctionKey) + cocoa_key = NSDeleteCharacter; return [NSString stringWithCharacters:&cocoa_key.unicode() length:1]; } @@ -420,3 +425,5 @@ void QCocoaMenuItem::setIconSize(int size) { m_iconSize = size; } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index 8a986c52d2..037ae6ba1a 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -39,6 +39,8 @@ #include "qt_mac_p.h" +QT_BEGIN_NAMESPACE + class QCocoaPrinterSupport : public QPlatformPrinterSupport { public: @@ -53,5 +55,7 @@ public: QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; }; +QT_END_NAMESPACE + #endif // QT_NO_PRINTER #endif // QCOCOAPRINTERSUPPORT_H diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm index 602d0fb4bd..42ef084e16 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -40,6 +40,8 @@ #include <private/qprinterinfo_p.h> +QT_BEGIN_NAMESPACE + QCocoaPrinterSupport::QCocoaPrinterSupport() { } @@ -94,4 +96,6 @@ QString QCocoaPrinterSupport::defaultPrintDeviceId() const return QString(); } +QT_END_NAMESPACE + #endif //QT_NO_PRINTER diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index c87a871ad0..fba97c2629 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -265,6 +265,7 @@ public: // for QNSView QPointer<QWindow> m_enterLeaveTargetWindow; bool m_windowUnderMouse; + bool m_ignoreWindowShouldClose; bool m_inConstructor; bool m_inSetVisible; bool m_inSetGeometry; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 8aed9da9c5..6c90e99238 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -371,6 +371,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_synchedWindowState(Qt::WindowActive) , m_windowModality(Qt::NonModal) , m_windowUnderMouse(false) + , m_ignoreWindowShouldClose(false) , m_inConstructor(true) , m_inSetVisible(false) , m_inSetGeometry(false) @@ -442,9 +443,12 @@ QCocoaWindow::~QCocoaWindow() m_parentCocoaWindow->removeChildWindow(this); } else if (parent()) { [m_contentView removeFromSuperview]; - } else if (m_qtView) { - [[NSNotificationCenter defaultCenter] removeObserver:m_qtView - name:nil object:m_nsWindow]; + } + + // Make sure to disconnect observer in all case if view is valid + // to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute + if (m_qtView) { + [[NSNotificationCenter defaultCenter] removeObserver:m_qtView]; } // The QNSView object may outlive the corresponding QCocoaWindow object, @@ -1220,6 +1224,9 @@ void QCocoaWindow::windowDidEndLiveResize() bool QCocoaWindow::windowShouldClose() { + // might have been set from qnsview.mm + if (m_ignoreWindowShouldClose) + return false; bool accepted = false; QWindowSystemInterface::handleCloseEvent(window(), &accepted); QWindowSystemInterface::flushWindowSystemEvents(); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1c87b90450..fd989cb840 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1443,6 +1443,10 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QObject *fo = QGuiApplication::focusObject(); if (m_sendKeyEvent && fo) { + // if escape is pressed we don't want interpretKeyEvents to close a dialog. This will be done via QWindowSystemInterface + if (keyCode == Qt::Key_Escape) + m_platformWindow->m_ignoreWindowShouldClose = true; + QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints); if (QCoreApplication::sendEvent(fo, &queryEvent)) { bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool(); @@ -1452,6 +1456,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) [self interpretKeyEvents:[NSArray arrayWithObject:nsevent]]; } } + + m_platformWindow->m_ignoreWindowShouldClose = false;; } if (m_resendKeyEvent) m_sendKeyEvent = true; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro index dcfb4cd26d..33f219db96 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro @@ -6,6 +6,9 @@ load(qt_plugin) QT += core-private gui-private platformsupport-private eglfs_device_lib-private +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + INCLUDEPATH += $$PWD/../.. CONFIG += egl QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp index 6e5421d5b9..455d78035a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp @@ -66,7 +66,9 @@ void QEglFSMaliIntegration::platformInit() vinfo.green.offset = 8; vinfo.red.offset = 16; vinfo.transp.offset = 24; +#if 0 vinfo.yres_virtual = 2 * vinfo.yres; +#endif if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) qErrnoWarning(errno, "Unable to set double buffer mode!"); @@ -90,7 +92,7 @@ EGLNativeWindowType QEglFSMaliIntegration::createNativeWindow(QPlatformWindow *w void QEglFSMaliIntegration::destroyNativeWindow(EGLNativeWindowType window) { - free(window); + free((void*)window); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp index 2a46c87862..359b90f205 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -154,6 +154,10 @@ void QEGLDeviceIntegration::platformInit() qWarning("EGLFS: Failed to open %s", fbDev.constData()); qFatal("EGLFS: Can't continue without a display"); } + +#ifdef FBIOBLANK + ioctl(framebuffer, FBIOBLANK, VESA_NO_BLANKING); +#endif } void QEGLDeviceIntegration::platformDestroy() diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm index 0e12da9d57..7c32784e9d 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.mm +++ b/src/plugins/platforms/ios/qiosfiledialog.mm @@ -95,8 +95,10 @@ bool QIOSFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window Q_UNUSED(windowFlags); Q_UNUSED(windowModality); + bool acceptOpen = options()->acceptMode() == QFileDialogOptions::AcceptOpen; QString directory = options()->initialDirectory().toLocalFile(); - if (directory.startsWith(QLatin1String("assets-library:"))) { + + if (acceptOpen && directory.startsWith(QLatin1String("assets-library:"))) { m_viewController = [[QIOSImagePickerController alloc] initWithQIOSFileDialog:this]; UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : [UIApplication sharedApplication].keyWindow; diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index a558ebe1f7..2ebd87f29c 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -540,6 +540,9 @@ void QIOSInputContext::setFocusObject(QObject *focusObject) qImDebug() << "clearing focus object" << focusObject << "as hide-keyboard gesture is active"; clearCurrentFocusObject(); return; + } else if (focusObject == m_imeState.focusObject) { + qImDebug() << "same focus object as last update, skipping reset"; + return; } reset(); @@ -575,37 +578,30 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties) // Mask for properties that we are interested in and see if any of them changed updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImPlatformData); - if (updatedProperties & Qt::ImEnabled) { - // Switching on and off input-methods needs a re-fresh of hints and platform - // data when we turn them on again, as the IM state we have may have been - // invalidated when IM was switched off. We could defer this until we know - // if IM was turned on, to limit the extra query parameters, but for simplicity - // we always do the update. - updatedProperties |= (Qt::ImHints | Qt::ImPlatformData); - } - qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject(); + // Perform update first, so we can trust the value of inputMethodAccepted() Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties); - if (m_textResponder && changedProperties & (Qt::ImHints | Qt::ImPlatformData)) { - qImDebug() << "current IM state requires new text responder"; - [m_textResponder autorelease]; - m_textResponder = 0; - } if (inputMethodAccepted()) { - if (!m_textResponder) { + if (!m_textResponder || [m_textResponder needsKeyboardReconfigure:changedProperties]) { qImDebug() << "creating new text responder"; + [m_textResponder autorelease]; m_textResponder = [[QIOSTextInputResponder alloc] initWithInputContext:this]; + } else { + qImDebug() << "no need to reconfigure keyboard, just notifying input delegate"; + [m_textResponder notifyInputDelegate:changedProperties]; } - if (![m_textResponder isFirstResponder]) - [m_textResponder becomeFirstResponder]; - [m_textResponder notifyInputDelegate:changedProperties]; + if (![m_textResponder isFirstResponder]) { + qImDebug() << "IM enabled, making text responder first responder"; + [m_textResponder becomeFirstResponder]; + } if (changedProperties & Qt::ImCursorRectangle) scrollToCursor(); } else if ([m_textResponder isFirstResponder]) { + qImDebug() << "IM not enabled, resigning text responder as first responder"; [m_textResponder resignFirstResponder]; } } @@ -635,6 +631,8 @@ bool QIOSInputContext::inputMethodAccepted() const */ void QIOSInputContext::reset() { + qImDebug() << "updating Qt::ImQueryAll and unmarking text"; + update(Qt::ImQueryAll); [m_textResponder setMarkedText:@"" selectedRange:NSMakeRange(0, 0)]; @@ -651,6 +649,8 @@ void QIOSInputContext::reset() */ void QIOSInputContext::commit() { + qImDebug() << "unmarking text"; + [m_textResponder unmarkText]; [m_textResponder notifyInputDelegate:Qt::ImSurroundingText]; } diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h index c22c43e455..0fe318dce7 100644 --- a/src/plugins/platforms/ios/qiosintegration.h +++ b/src/plugins/platforms/ios/qiosintegration.h @@ -48,6 +48,7 @@ class QIOSServices; class QIOSIntegration : public QPlatformNativeInterface, public QPlatformIntegration { Q_OBJECT + Q_PROPERTY(bool debugWindowManagement READ debugWindowManagement WRITE setDebugWindowManagement); public: QIOSIntegration(); @@ -87,6 +88,9 @@ public: void *nativeResourceForWindow(const QByteArray &resource, QWindow *window); + void setDebugWindowManagement(bool); + bool debugWindowManagement() const; + private: QPlatformFontDatabase *m_fontDatabase; QPlatformClipboard *m_clipboard; @@ -96,6 +100,8 @@ private: QIOSServices *m_platformServices; mutable QPlatformAccessibility *m_accessibility; QIOSFileEngineFactory m_fileEngineFactory; + + bool m_debugWindowManagement; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index fcfd6c7cc8..e395c832f1 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -67,6 +67,7 @@ QIOSIntegration::QIOSIntegration() , m_inputContext(0) , m_platformServices(new QIOSServices) , m_accessibility(0) + , m_debugWindowManagement(false) { if (![UIApplication sharedApplication]) { qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n" \ @@ -249,6 +250,16 @@ void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWind return 0; } +void QIOSIntegration::setDebugWindowManagement(bool enabled) +{ + m_debugWindowManagement = enabled; +} + +bool QIOSIntegration::debugWindowManagement() const +{ + return m_debugWindowManagement; +} + // --------------------------------------------------------- #include "moc_qiosintegration.cpp" diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 992668805f..dfab835579 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -128,7 +128,8 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; if (m_selectedRow == -1) m_selectedRow = 0; - self.toolbar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 100, 44)] autorelease]; + self.toolbar = [[[UIToolbar alloc] init] autorelease]; + self.toolbar.frame.size = [self.toolbar sizeThatFits:self.bounds.size]; self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; UIBarButtonItem *spaceButton = [[[UIBarButtonItem alloc] @@ -201,7 +202,6 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; - (void)closeMenu { - [self listenForKeyboardWillHideNotification:NO]; if (!m_visibleMenuItems.isEmpty()) QIOSMenu::currentMenu()->handleItemSelected(m_visibleMenuItems.at(m_selectedRow)); else @@ -210,7 +210,6 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; - (void)cancelMenu { - [self listenForKeyboardWillHideNotification:NO]; QIOSMenu::currentMenu()->dismiss(); } @@ -466,12 +465,14 @@ void QIOSMenu::toggleShowUsingUIPickerView(bool show) } else { Q_ASSERT(focusObjectWithPickerView); focusObjectWithPickerView->removeEventFilter(this); - qApp->inputMethod()->update(Qt::ImEnabled | Qt::ImPlatformData); focusObjectWithPickerView = 0; Q_ASSERT(m_pickerView); + [m_pickerView listenForKeyboardWillHideNotification:NO]; [m_pickerView release]; m_pickerView = 0; + + qApp->inputMethod()->update(Qt::ImEnabled | Qt::ImPlatformData); } } diff --git a/src/plugins/platforms/ios/qiostextresponder.h b/src/plugins/platforms/ios/qiostextresponder.h index 4cb8a9c815..96d30ea89a 100644 --- a/src/plugins/platforms/ios/qiostextresponder.h +++ b/src/plugins/platforms/ios/qiostextresponder.h @@ -34,6 +34,7 @@ #import <UIKit/UIKit.h> #include <QtCore/qstring.h> +#include <QtGui/qevent.h> class QIOSInputContext; @@ -41,12 +42,15 @@ class QIOSInputContext; { @private QIOSInputContext *m_inputContext; + QInputMethodQueryEvent *m_configuredImeState; QString m_markedText; BOOL m_inSendEventToFocusObject; BOOL m_inSelectionChange; } - (id)initWithInputContext:(QIOSInputContext *)context; +- (BOOL)needsKeyboardReconfigure:(Qt::InputMethodQueries)updatedProperties; + - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties; @property(readwrite, retain) UIView *inputView; diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index f0cb021da0..5d2a675f90 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -166,8 +166,9 @@ m_inSelectionChange = NO; m_inputContext = inputContext; - QVariantMap platformData = [self imValue:Qt::ImPlatformData].toMap(); - Qt::InputMethodHints hints = Qt::InputMethodHints([self imValue:Qt::ImHints].toUInt()); + m_configuredImeState = new QInputMethodQueryEvent(m_inputContext->imeState().currentState); + QVariantMap platformData = m_configuredImeState->value(Qt::ImPlatformData).toMap(); + Qt::InputMethodHints hints = Qt::InputMethodHints(m_configuredImeState->value(Qt::ImHints).toUInt()); self.returnKeyType = platformData.value(kImePlatformDataReturnKeyType).isValid() ? UIReturnKeyType(platformData.value(kImePlatformDataReturnKeyType).toInt()) : @@ -211,9 +212,42 @@ { self.inputView = 0; self.inputAccessoryView = 0; + delete m_configuredImeState; + [super dealloc]; } +- (BOOL)needsKeyboardReconfigure:(Qt::InputMethodQueries)updatedProperties +{ + if ((updatedProperties & Qt::ImEnabled)) { + Q_ASSERT([self currentImeState:Qt::ImEnabled].toBool()); + + // When switching on input-methods we need to consider hints and platform data + // as well, as the IM state that we were based on may have been invalidated when + // IM was switched off. + + qImDebug() << "IM was turned on, we need to check hints and platform data as well"; + updatedProperties |= (Qt::ImHints | Qt::ImPlatformData); + } + + // Based on what we set up in initWithInputContext above + updatedProperties &= (Qt::ImHints | Qt::ImPlatformData); + + if (!updatedProperties) + return NO; + + for (uint i = 0; i < (sizeof(Qt::ImQueryAll) * CHAR_BIT); ++i) { + if (Qt::InputMethodQuery property = Qt::InputMethodQuery(int(updatedProperties & (1 << i)))) { + if ([self currentImeState:property] != m_configuredImeState->value(property)) { + qImDebug() << property << "has changed since text responder was configured, need reconfigure"; + return YES; + } + } + } + + return NO; +} + - (BOOL)canBecomeFirstResponder { return YES; @@ -258,7 +292,7 @@ if ([UIResponder currentFirstResponder] == [self nextResponder]) { // We have resigned the keyboard, and transferred first responder back to the parent view Q_ASSERT(!FirstResponderCandidate::currentCandidate()); - if ([self imValue:Qt::ImEnabled].toBool()) { + if ([self currentImeState:Qt::ImEnabled].toBool()) { // The current focus object expects text input, but there // is no keyboard to get input from. So we clear focus. qImDebug() << "no keyboard available, clearing focus object"; @@ -320,7 +354,7 @@ QCoreApplication::sendEvent(focusObject, &e); } -- (QVariant)imValue:(Qt::InputMethodQuery)query +- (QVariant)currentImeState:(Qt::InputMethodQuery)query { return m_inputContext->imeState().currentState.value(query); } @@ -337,7 +371,7 @@ -(UITextPosition *)endOfDocument { - int endPosition = [self imValue:Qt::ImSurroundingText].toString().length(); + int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length(); return [QUITextPosition positionWithIndex:endPosition]; } @@ -361,8 +395,8 @@ - (UITextRange *)selectedTextRange { - int cursorPos = [self imValue:Qt::ImCursorPosition].toInt(); - int anchorPos = [self imValue:Qt::ImAnchorPosition].toInt(); + int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt(); + int anchorPos = [self currentImeState:Qt::ImAnchorPosition].toInt(); return [QUITextRange rangeWithNSRange:NSMakeRange(qMin(cursorPos, anchorPos), qAbs(anchorPos - cursorPos))]; } @@ -370,7 +404,7 @@ { int s = static_cast<QUITextPosition *>([range start]).index; int e = static_cast<QUITextPosition *>([range end]).index; - return [self imValue:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString(); + return [self currentImeState:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString(); } - (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange @@ -482,8 +516,8 @@ if (!m_markedText.isEmpty()) return CGRectZero; - int cursorPos = [self imValue:Qt::ImCursorPosition].toInt(); - int anchorPos = [self imValue:Qt::ImAnchorPosition].toInt(); + int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt(); + int anchorPos = [self currentImeState:Qt::ImAnchorPosition].toInt(); NSRange r = static_cast<QUITextRange*>(range).range; QList<QInputMethodEvent::Attribute> attrs; @@ -547,7 +581,7 @@ int p = static_cast<QUITextPosition *>(position).index; if (direction == UITextLayoutDirectionLeft) return [QUITextRange rangeWithNSRange:NSMakeRange(0, p)]; - int l = [self imValue:Qt::ImSurroundingText].toString().length(); + int l = [self currentImeState:Qt::ImSurroundingText].toString().length(); return [QUITextRange rangeWithNSRange:NSMakeRange(p, l - p)]; } @@ -555,7 +589,7 @@ { // No API in Qt for determining this. Use sensible default instead: Q_UNUSED(point); - return [QUITextPosition positionWithIndex:[self imValue:Qt::ImCursorPosition].toInt()]; + return [QUITextPosition positionWithIndex:[self currentImeState:Qt::ImCursorPosition].toInt()]; } - (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range @@ -563,14 +597,14 @@ // No API in Qt for determining this. Use sensible default instead: Q_UNUSED(point); Q_UNUSED(range); - return [QUITextPosition positionWithIndex:[self imValue:Qt::ImCursorPosition].toInt()]; + return [QUITextPosition positionWithIndex:[self currentImeState:Qt::ImCursorPosition].toInt()]; } - (UITextRange *)characterRangeAtPoint:(CGPoint)point { // No API in Qt for determining this. Use sensible default instead: Q_UNUSED(point); - return [QUITextRange rangeWithNSRange:NSMakeRange([self imValue:Qt::ImCursorPosition].toInt(), 0)]; + return [QUITextRange rangeWithNSRange:NSMakeRange([self currentImeState:Qt::ImCursorPosition].toInt(), 0)]; } - (void)setMarkedTextStyle:(NSDictionary *)style diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index d144b419aa..9abd105d94 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -41,6 +41,7 @@ #include <QtGui/private/qwindow_p.h> +#include "qiosintegration.h" #include "qiosscreen.h" #include "qiosglobal.h" #include "qioswindow.h" @@ -64,6 +65,56 @@ @implementation QIOSDesktopManagerView +- (id)init +{ + if (!(self = [super init])) + return nil; + + QIOSIntegration *iosIntegration = QIOSIntegration::instance(); + if (iosIntegration && iosIntegration->debugWindowManagement()) { + static UIImage *gridPattern = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CGFloat dimension = 100.f; + + UIGraphicsBeginImageContextWithOptions(CGSizeMake(dimension, dimension), YES, 0.0f); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextTranslateCTM(context, -0.5, -0.5); + + #define gridColorWithBrightness(br) \ + [UIColor colorWithHue:0.6 saturation:0.0 brightness:br alpha:1.0].CGColor + + CGContextSetFillColorWithColor(context, gridColorWithBrightness(0.05)); + CGContextFillRect(context, CGRectMake(0, 0, dimension, dimension)); + + CGFloat gridLines[][2] = { { 10, 0.1 }, { 20, 0.2 }, { 100, 0.3 } }; + for (size_t l = 0; l < sizeof(gridLines) / sizeof(gridLines[0]); ++l) { + CGFloat step = gridLines[l][0]; + for (int c = step; c <= dimension; c += step) { + CGContextMoveToPoint(context, c, 0); + CGContextAddLineToPoint(context, c, dimension); + CGContextMoveToPoint(context, 0, c); + CGContextAddLineToPoint(context, dimension, c); + } + + CGFloat brightness = gridLines[l][1]; + CGContextSetStrokeColorWithColor(context, gridColorWithBrightness(brightness)); + CGContextStrokePath(context); + } + + gridPattern = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [gridPattern retain]; + }); + + self.backgroundColor = [UIColor colorWithPatternImage:gridPattern]; + } + + return self; +} + - (void)didAddSubview:(UIView *)subview { Q_UNUSED(subview); diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index fd04ecf474..95a4c28246 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -120,7 +120,7 @@ void QIOSWindow::setVisible(bool visible) if (visible && shouldAutoActivateWindow()) { requestActivateWindow(); - } else if (!visible && qGuiApp->focusWindow() == window()) { + } else if (!visible && [m_view isActiveWindow]) { // Our window was active/focus window but now hidden, so relinquish // focus to the next possible window in the stack. NSArray *subviews = m_view.viewController.view.subviews; @@ -206,6 +206,25 @@ void QIOSWindow::applyGeometry(const QRect &rect) bool QIOSWindow::isExposed() const { + // Note: At startup of an iOS app it will enter UIApplicationStateInactive + // while showing the launch screen, and once the application returns from + // applicationDidFinishLaunching it will hide the launch screen and enter + // UIApplicationStateActive. Technically, a window is not exposed until + // it's actually visible on screen, and Apple also documents that "Apps + // that use OpenGL ES for drawing must not use didFinishLaunching to + // prepare their drawing environment. Instead, defer any OpenGL ES + // drawing calls to applicationDidBecomeActive". Unfortunately, if we + // wait until the applicationState reaches ApplicationActive to signal + // that the window is exposed, we get a lag between hiding the launch + // screen and blitting the first pixels of the application, as Qt + // spends some time drawing those pixels in response to the expose. + // In practice there doesn't seem to be any issues starting GL setup + // and drawing from within applicationDidFinishLaunching, and this is + // also the recommended approach for other 3rd party GL toolkits on iOS, + // so we 'cheat', and report that a window is exposed even if the app + // is in UIApplicationStateInactive, so that the startup transition + // between the launch screen and the application content is smooth. + return qApp->applicationState() > Qt::ApplicationHidden && window()->isVisible() && !window()->geometry().isEmpty(); } diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index 065c52f881..dfe0927b00 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -56,6 +56,7 @@ class QIOSWindow; - (id)initWithQIOSWindow:(QIOSWindow *)window; - (void)sendUpdatedExposeEvent; +- (BOOL)isActiveWindow; @end @interface QUIView (Accessibility) diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index f36cbaf685..8be3515cb5 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -73,6 +73,20 @@ self.hidden = YES; self.multipleTouchEnabled = YES; + + if (QIOSIntegration::instance()->debugWindowManagement()) { + static CGFloat hue = 0.0; + CGFloat lastHue = hue; + for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabsf(hue - lastHue)) + hue = drand48(); + + #define colorWithBrightness(br) \ + [UIColor colorWithHue:hue saturation:0.5 brightness:br alpha:1.0].CGColor + + self.layer.backgroundColor = colorWithBrightness(0.5); + self.layer.borderColor = colorWithBrightness(1.0); + self.layer.borderWidth = 1.0; + } } return self; @@ -247,6 +261,23 @@ return YES; } +- (BOOL)isActiveWindow +{ + // Normally this is determined exclusivly by being firstResponder, but + // since we employ a separate first responder for text input we need to + // handle both cases as this view being the active Qt window. + + if ([self isFirstResponder]) + return YES; + + UIResponder *firstResponder = [UIResponder currentFirstResponder]; + if ([firstResponder isKindOfClass:[QIOSTextInputResponder class]] + && [firstResponder nextResponder] == self) + return YES; + + return NO; +} + // ------------------------------------------------------------------------- diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index 5407fa66dc..91708c0a47 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -264,9 +264,6 @@ static bool switchToGraphicsMode(int ttyfd, int *oldMode) return false; } - // No blankin' screen, no blinkin' cursor!, no cursor! - const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c"; - QT_WRITE(ttyfd, termctl, sizeof(termctl)); return true; } @@ -274,10 +271,6 @@ static void resetTty(int ttyfd, int oldMode) { ioctl(ttyfd, KDSETMODE, oldMode); - // Blankin' screen, blinkin' cursor! - const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; - QT_WRITE(ttyfd, termctl, sizeof(termctl)); - QT_CLOSE(ttyfd); } diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 9e037723fe..d5708e4f9c 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1682,101 +1682,71 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, int dpi, const QSharedPointer<QWindowsFontEngineData> &data) { -#if !defined(QT_NO_DIRECTWRITE) - bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) - || (request.hintingPreference == QFont::PreferVerticalHinting); - IDWriteFont *directWriteFont = 0; -#else - bool useDirectWrite = false; -#endif + QFontEngine *fe = 0; LOGFONT lf = fontDefToLOGFONT(request); const bool preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY; - HFONT hfont = 0; - hfont = CreateFontIndirect(&lf); - if (!hfont) { - qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); - hfont = QWindowsFontDatabase::systemFont(); - } - - bool ttf = false; - int avWidth = 0; - BOOL res; - HGDIOBJ oldObj = SelectObject(data->hdc, hfont); + if (request.stretch != 100) { + HFONT hfont = CreateFontIndirect(&lf); + if (!hfont) { + qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); + hfont = QWindowsFontDatabase::systemFont(); + } - TEXTMETRIC tm; - res = GetTextMetrics(data->hdc, &tm); - avWidth = tm.tmAveCharWidth; - ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; - SelectObject(data->hdc, oldObj); + HGDIOBJ oldObj = SelectObject(data->hdc, hfont); + TEXTMETRIC tm; + if (!GetTextMetrics(data->hdc, &tm)) + qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__); + else + lf.lfWidth = tm.tmAveCharWidth * request.stretch / 100; + SelectObject(data->hdc, oldObj); - if (!useDirectWrite) { - if (!ttf || request.stretch != 100) { - DeleteObject(hfont); - if (!res) - qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__); - lf.lfWidth = avWidth * request.stretch/100; - hfont = CreateFontIndirect(&lf); - if (!hfont) { - qErrnoWarning("%s: CreateFontIndirect with stretch failed", __FUNCTION__); - hfont = QWindowsFontDatabase::systemFont(); - } - } + DeleteObject(hfont); } #if !defined(QT_NO_DIRECTWRITE) - else { - // Default to false for DirectWrite (and re-enable once/if everything turns out okay) - useDirectWrite = false; - if (initDirectWrite(data.data())) { - const QString fam = QString::fromWCharArray(lf.lfFaceName); - const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); - if (nameSubstitute != fam) { - const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); - lf.lfFaceName[nameSubstituteLength] = 0; - } + bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) + || (request.hintingPreference == QFont::PreferVerticalHinting); + if (useDirectWrite && initDirectWrite(data.data())) { + const QString fam = QString::fromWCharArray(lf.lfFaceName); + const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); + if (nameSubstitute != fam) { + const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); + lf.lfFaceName[nameSubstituteLength] = 0; + } - HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont); + IDWriteFont *directWriteFont = 0; + HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont); + if (FAILED(hr)) { + qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); + } else { + IDWriteFontFace *directWriteFontFace = NULL; + hr = directWriteFont->CreateFontFace(&directWriteFontFace); if (FAILED(hr)) { - qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); + qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); } else { - DeleteObject(hfont); - useDirectWrite = true; + QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, + request.pixelSize, + data); + fedw->initFontInfo(request, dpi, directWriteFont); + fe = fedw; } + + directWriteFont->Release(); } } -#endif +#endif // QT_NO_DIRECTWRITE - QFontEngine *fe = 0; - if (!useDirectWrite) { - QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, lf, data); + if (!fe) { + QWindowsFontEngine *few = new QWindowsFontEngine(request.family, lf, data); if (preferClearTypeAA) few->glyphFormat = QFontEngine::Format_A32; few->initFontInfo(request, dpi); fe = few; } -#if !defined(QT_NO_DIRECTWRITE) - else { - IDWriteFontFace *directWriteFontFace = NULL; - HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace); - if (SUCCEEDED(hr)) { - QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, - request.pixelSize, - data); - fedw->initFontInfo(request, dpi, directWriteFont); - fe = fedw; - } else { - qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); - } - - directWriteFont->Release(); - } - -#endif - return fe; } diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index c25b90e98c..ef2ad110ca 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -264,12 +264,12 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa */ QWindowsFontEngine::QWindowsFontEngine(const QString &name, - HFONT _hfont, LOGFONT lf, + LOGFONT lf, const QSharedPointer<QWindowsFontEngineData> &fontEngineData) : QFontEngine(Win), m_fontEngineData(fontEngineData), _name(name), - hfont(_hfont), + hfont(0), m_logfont(lf), ttf(0), hasOutline(0), @@ -286,6 +286,12 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name, designAdvancesSize(0) { qCDebug(lcQpaFonts) << __FUNCTION__ << name << lf.lfHeight; + hfont = CreateFontIndirect(&m_logfont); + if (!hfont) { + qErrnoWarning("%s: CreateFontIndirect failed for family '%s'", __FUNCTION__, qPrintable(name)); + hfont = QWindowsFontDatabase::systemFont(); + } + HDC hdc = m_fontEngineData->hdc; SelectObject(hdc, hfont); const BOOL res = GetTextMetrics(hdc, &tm); @@ -1361,11 +1367,8 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) // Get here if original font is not DirectWrite or DirectWrite creation failed for some // reason - HFONT hfont = CreateFontIndirect(&lf); - if (hfont == 0) - hfont = QWindowsFontDatabase::systemFont(); - return new QWindowsFontEngine(fam, hfont, lf, data); + return new QWindowsFontEngine(fam, lf, data); } bool QWindowsFontEngine::supportsTransformation(const QTransform &transform) const diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 703c978eb6..6df69c34db 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -63,7 +63,7 @@ class QWindowsFontEngine : public QFontEngine friend class QWindowsMultiFontEngine; public: - QWindowsFontEngine(const QString &name, HFONT hfont, LOGFONT lf, + QWindowsFontEngine(const QString &name, LOGFONT lf, const QSharedPointer<QWindowsFontEngineData> &fontEngineData); ~QWindowsFontEngine(); @@ -137,7 +137,7 @@ private: const QString _name; QString uniqueFamilyName; - const HFONT hfont; + HFONT hfont; const LOGFONT m_logfont; uint ttf : 1; uint hasOutline : 1; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 2fd0f12c26..fc389ecf15 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1074,7 +1074,8 @@ QWindowsWindowData void QWindowsWindow::setVisible(bool visible) { - qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd << visible; + const QWindow *win = window(); + qCDebug(lcQpaWindows) << __FUNCTION__ << this << win << m_data.hwnd << visible; if (m_data.hwnd) { if (visible) { show_sys(); @@ -1082,11 +1083,13 @@ void QWindowsWindow::setVisible(bool visible) // When the window is layered, we won't get WM_PAINT, and "we" are in control // over the rendering of the window // There is nobody waiting for this, so we don't need to flush afterwards. - if (isLayered()) { - QWindow *w = window(); - fireExpose(QRect(0, 0, w->width(), w->height())); - } + if (isLayered()) + fireExpose(QRect(0, 0, win->width(), win->height())); + // QTBUG-44928, QTBUG-7386: This is to resolve the problem where popups are + // opened from the system tray and not being implicitly activated + if (win->type() == Qt::Popup && !win->parent() && !QGuiApplication::focusWindow()) + SetForegroundWindow(m_data.hwnd); } else { if (hasMouseCapture()) setMouseGrabEnabled(false); @@ -2298,7 +2301,7 @@ void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTou const bool ret = QWindowsContext::user32dll.isTouchWindow(m_data.hwnd, &touchFlags); // Return if it is not a touch window or the flags are already set by a hook // such as HCBT_CREATEWND - if (!ret || touchFlags != 0) + if (ret || touchFlags != 0) return; if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, (ULONG)touchTypes)) setFlag(TouchRegistered); diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro index 29fddeabd4..29b6d1d2f7 100644 --- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro @@ -4,6 +4,6 @@ contains(QT_CONFIG, egl):contains(QT_CONFIG, egl_x11) { SUBDIRS += xcb_egl } -contains(QT_CONFIG, xcb-xlib):!contains(QT_CONFIG, opengles2) { +contains(QT_CONFIG, xcb-xlib): contains(QT_CONFIG, opengl): !contains(QT_CONFIG, opengles2) { SUBDIRS += xcb_glx } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 11ff313144..0ca141526e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -231,9 +231,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) QXcbIntegration::instance()->destroyScreen(screen); - // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be - // no QScreen instances; a Qt application can survive this situation, and - // start rendering again later when there is a screen again. + // QTBUG-40174, QTBUG-42985: If all screens are removed, wait + // and start rendering again later if a screen becomes available. } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { // New XRandR output is available and it's enabled @@ -293,13 +292,15 @@ void QXcbConnection::initializeScreens() { xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int xcbScreenNumber = 0; // screen number in the xcb sense - QXcbScreen* primaryScreen = NULL; + QXcbScreen* primaryScreen = Q_NULLPTR; + xcb_screen_t *xcbScreen = Q_NULLPTR; + bool hasOutputs = false; while (it.rem) { // Each "screen" in xcb terminology is a virtual desktop, // potentially a collection of separate juxtaposed monitors. // But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.) // which will become virtual siblings. - xcb_screen_t *xcbScreen = it.data; + xcbScreen = it.data; QList<QPlatformScreen *> siblings; int outputCount = 0; int connectedOutputCount = 0; @@ -356,6 +357,7 @@ void QXcbConnection::initializeScreens() QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); siblings << screen; ++connectedOutputCount; + hasOutputs = true; m_screens << screen; // There can be multiple outputs per screen, use either @@ -381,6 +383,20 @@ void QXcbConnection::initializeScreens() ++xcbScreenNumber; } // for each xcb screen + // If there's no randr extension, or there was some error above, or we found a + // screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X), + // but the dimensions are known anyway, and we don't already have any lingering + // (possibly disconnected) screens, then showing windows should be possible, + // so create one screen. (QTBUG-31389) + if (xcbScreen && !hasOutputs && xcbScreen->width_in_pixels > 0 && xcbScreen->height_in_pixels > 0 && m_screens.isEmpty()) { + QXcbScreen *screen = createScreen(0, xcbScreen, 0, Q_NULLPTR); + screen->setVirtualSiblings(QList<QPlatformScreen *>() << screen); + m_screens << screen; + primaryScreen = screen; + primaryScreen->setPrimary(true); + qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen; + } + // Ensure the primary screen is first in the list if (primaryScreen) { Q_ASSERT(!m_screens.isEmpty()); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 0dde679a7a..eabebffdab 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -319,6 +319,12 @@ void QXcbWindow::create() // currently no way to implement it for frame-exclusive geometries. QRect rect = window()->geometry(); QPlatformWindow::setGeometry(rect); + QXcbScreen *currentScreen = xcbScreen(); + QPlatformScreen *newScreen = screenForGeometry(rect); + + if (newScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + const int dpr = int(devicePixelRatio()); QSize minimumSize = window()->minimumSize(); @@ -583,9 +589,18 @@ void QXcbWindow::setGeometry(const QRect &rect) propagateSizeHints(); - const QRect xRect = mapToNative(rect, int(devicePixelRatio())); + QXcbScreen *currentScreen = xcbScreen(); + QPlatformScreen *newScreen = screenForGeometry(rect); + if (!newScreen) + newScreen = currentScreen; + + const QRect xRect = mapToNative(rect, int(newScreen->devicePixelRatio())); const QRect wmGeometry = windowToWmGeometry(xRect); + + if (newScreen != currentScreen) + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + if (qt_window_private(window())->positionAutomatic) { const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const qint32 values[] = { @@ -1919,7 +1934,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * if (newScreen != screen()) { if (newScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - int newDpr = devicePixelRatio(); + int newDpr = newScreen->devicePixelRatio(); if (newDpr != dpr) { QRect newRect = mapGeometryFromNative(nativeRect, newDpr); QPlatformWindow::setGeometry(newRect); diff --git a/src/plugins/printsupport/cocoa/main.cpp b/src/plugins/printsupport/cocoa/main.cpp index 57d768770a..d0925bbc34 100644 --- a/src/plugins/printsupport/cocoa/main.cpp +++ b/src/plugins/printsupport/cocoa/main.cpp @@ -38,6 +38,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PRINTER + class QCocoaPrinterSupportPlugin : public QPlatformPrinterSupportPlugin { Q_OBJECT @@ -65,6 +67,8 @@ QPlatformPrinterSupport *QCocoaPrinterSupportPlugin::create(const QString &key) return platformPrinterSupport; } +#endif + QT_END_NAMESPACE #include "main.moc" |