summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp27
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp12
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.h5
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp86
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h7
-rw-r--r--src/plugins/platforms/android/qandroidplatformbackingstore.cpp21
-rw-r--r--src/plugins/platforms/android/qandroidplatformbackingstore.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp3
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm157
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm28
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm23
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.h129
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm502
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.mm104
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h15
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm92
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm12
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm40
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm521
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac_p.h26
-rw-r--r--src/plugins/platforms/cocoa/qt_mac_p.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp51
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm62
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm4
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm13
-rw-r--r--src/plugins/platforms/qnx/qblackberrytheme.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.cpp5
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp18
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.cpp32
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.cpp314
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.h19
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.cpp3
-rw-r--r--src/plugins/platforms/winrt/winrt.pro5
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp15
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp20
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp12
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro5
67 files changed, 1860 insertions, 715 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index 55d44b7377..9efdcad158 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -67,8 +67,6 @@ namespace QtAndroidInput
static QPointer<QWindow> m_mouseGrabber;
- static int m_lastCursorPos = -1;
-
void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd)
{
AttachedJNIEnv env;
@@ -78,21 +76,6 @@ namespace QtAndroidInput
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd;
#endif
- if (candidatesStart == -1 && candidatesEnd == -1 && selStart == selEnd) {
- // Qt only gives us position inside the block, so if we move to the
- // same position in another block, the Android keyboard will believe
- // we have not changed position, and be terribly confused.
- if (selStart == m_lastCursorPos) {
-#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- qDebug() << ">>> FAKEUPDATESELECTION" << selStart+1;
-#endif
- env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID,
- selStart+1, selEnd+1, candidatesStart, candidatesEnd);
- }
- m_lastCursorPos = selStart;
- } else {
- m_lastCursorPos = -1;
- }
env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID,
selStart, selEnd, candidatesStart, candidatesEnd);
}
@@ -517,6 +500,12 @@ namespace QtAndroidInput
}
}
+ // maps 0 to the empty string, and anything else to a single-character string
+ static inline QString toString(jint unicode)
+ {
+ return unicode ? QString(QChar(unicode)) : QString();
+ }
+
static void keyDown(JNIEnv */*env*/, jobject /*thiz*/, jint key, jint unicode, jint modifier)
{
Qt::KeyboardModifiers modifiers;
@@ -533,7 +522,7 @@ namespace QtAndroidInput
QEvent::KeyPress,
mapAndroidKey(key),
modifiers,
- QChar(unicode),
+ toString(unicode),
false);
}
@@ -553,7 +542,7 @@ namespace QtAndroidInput
QEvent::KeyRelease,
mapAndroidKey(key),
modifiers,
- QChar(unicode),
+ toString(unicode),
false);
}
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index b112e265a5..224a8ca9f7 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -262,18 +262,20 @@ private:
AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler()
: m_assetsCache(std::max(5, qgetenv("QT_ANDROID_MAX_ASSETS_CACHE_SIZE").toInt()))
, m_hasPrepopulatedCache(false)
+ , m_hasTriedPrepopulatingCache(false)
{
m_assetManager = QtAndroid::assetManager();
- prepopulateCache();
}
AndroidAssetsFileEngineHandler::~AndroidAssetsFileEngineHandler()
{
}
-void AndroidAssetsFileEngineHandler::prepopulateCache()
+void AndroidAssetsFileEngineHandler::prepopulateCache() const
{
- QMutexLocker locker(&m_assetsCacheMutext);
+ Q_ASSERT(!m_hasTriedPrepopulatingCache);
+ m_hasTriedPrepopulatingCache = true;
+
Q_ASSERT(m_assetsCache.isEmpty());
// Failsafe: Don't read cache files that are larger than 1MB
@@ -364,7 +366,11 @@ QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &file
if (!path.size())
path = fileName.left(fileName.length() - 1).toUtf8();
+
m_assetsCacheMutext.lock();
+ if (!m_hasTriedPrepopulatingCache)
+ prepopulateCache();
+
QSharedPointer<AndroidAssetDir> *aad = m_assetsCache.object(path);
m_assetsCacheMutext.unlock();
if (!aad) {
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h
index d56367d4d8..ac16ad7b79 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h
@@ -58,12 +58,13 @@ public:
QAbstractFileEngine *create(const QString &fileName) const;
private:
- void prepopulateCache();
+ void prepopulateCache() const;
AAssetManager *m_assetManager;
mutable QCache<QByteArray, QSharedPointer<AndroidAssetDir>> m_assetsCache;
mutable QMutex m_assetsCacheMutext;
- bool m_hasPrepopulatedCache;
+ mutable bool m_hasPrepopulatedCache;
+ mutable bool m_hasTriedPrepopulatingCache;
};
#endif // QANDROIDASSETSFILEENGINEHANDLER_H
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 326972e71e..bfb13811e3 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -81,7 +81,7 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new
env->ReleaseStringChars(text, jstr);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- qDebug() << "@@@ COMMIT" << str;
+ qDebug() << "@@@ COMMIT" << str << newCursorPosition;
#endif
return m_androidInputContext->commitText(str, newCursorPosition);
}
@@ -160,7 +160,7 @@ static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, ji
const QString &text = m_androidInputContext->getTextAfterCursor(length, flags);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- qDebug() << "@@@ GET" << length << text;
+ qDebug() << "@@@ GETA" << length << text;
#endif
return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
}
@@ -172,7 +172,7 @@ static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, j
const QString &text = m_androidInputContext->getTextBeforeCursor(length, flags);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- qDebug() << "@@@ GET" << length << text;
+ qDebug() << "@@@ GETB" << length << text;
#endif
return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
}
@@ -188,7 +188,7 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji
env->ReleaseStringChars(text, jstr);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- qDebug() << "@@@ SET" << str;
+ qDebug() << "@@@ SET" << str << newCursorPosition;
#endif
return m_androidInputContext->setComposingText(str, newCursorPosition);
}
@@ -271,6 +271,18 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
return m_androidInputContext->paste();
}
+static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ UPDATECURSORPOS";
+#endif
+ m_androidInputContext->updateCursorPosition();
+ return true;
+}
+
static JNINativeMethod methods[] = {
{"commitText", "(Ljava/lang/String;I)Z", (void *)commitText},
@@ -288,7 +300,8 @@ static JNINativeMethod methods[] = {
{"cut", "()Z", (void *)cut},
{"copy", "()Z", (void *)copy},
{"copyURL", "()Z", (void *)copyURL},
- {"paste", "()Z", (void *)paste}
+ {"paste", "()Z", (void *)paste},
+ {"updateCursorPosition", "()Z", (void *)updateCursorPosition}
};
@@ -404,7 +417,9 @@ void QAndroidInputContext::updateCursorPosition()
{
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull() && !m_blockUpdateSelection) {
- const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ // make sure it also works with editors that have not been updated to the new API
+ QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+ const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
QtAndroidInput::updateSelection(cursorPos, cursorPos, -1, -1); //selection empty and no pre-edit text
}
}
@@ -422,9 +437,9 @@ void QAndroidInputContext::invokeAction(QInputMethod::Action action, int cursorP
#warning TODO Handle at least QInputMethod::ContextMenu action
Q_UNUSED(action)
Q_UNUSED(cursorPosition)
-
- if (action == QInputMethod::Click)
- commit();
+ //### click should be passed to the IM, but in the meantime it's better to ignore it than to do something wrong
+ // if (action == QInputMethod::Click)
+ // commit();
}
QRectF QAndroidInputContext::keyboardRect() const
@@ -573,6 +588,12 @@ QString QAndroidInputContext::getSelectedText(jint /*flags*/)
QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
{
+ QVariant textAfter = queryFocusObjectThreadSafe(Qt::ImTextAfterCursor, QVariant(length));
+ if (textAfter.isValid()) {
+ return textAfter.toString().left(length);
+ }
+
+ //compatibility code for old controls that do not implement the new API
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return QString();
@@ -587,15 +608,21 @@ QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
{
+ QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length));
+ if (textBefore.isValid()) {
+ return textBefore.toString().left(length);
+ }
+
+ //compatibility code for old controls that do not implement the new API
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return QString();
+ int cursorPos = query->value(Qt::ImCursorPosition).toInt();
QString text = query->value(Qt::ImSurroundingText).toString();
if (!text.length())
return text;
- int cursorPos = query->value(Qt::ImCursorPosition).toInt();
const int wordLeftPos = cursorPos - length;
return text.mid(wordLeftPos > 0 ? wordLeftPos : 0, cursorPos);
}
@@ -621,8 +648,9 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull() && !m_blockUpdateSelection) {
- int cursorPos = query->value(Qt::ImCursorPosition).toInt();
- int preeditLength = text.length();
+ QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+ const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
+ const int preeditLength = text.length();
QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, cursorPos, cursorPos+preeditLength);
}
@@ -650,16 +678,19 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
Therefore, the length of the region is end - start
*/
int length = end - start;
+ int localPos = query->value(Qt::ImCursorPosition).toInt();
+ QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+ int blockPosition = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0;
+ int localStart = start - blockPosition; // Qt uses position inside block
bool updateSelectionWasBlocked = m_blockUpdateSelection;
m_blockUpdateSelection = true;
QString text = query->value(Qt::ImSurroundingText).toString();
- m_composingText = text.mid(start, length);
+ m_composingText = text.mid(localStart, length);
- //in the Qt text controls, cursor pos is the start of the preedit
- int cursorPos = query->value(Qt::ImCursorPosition).toInt();
- int relativeStart = start - cursorPos;
+ //in the Qt text controls, the cursor position is the start of the preedit
+ int relativeStart = localStart - localPos;
QList<QInputMethodEvent::Attribute> attributes;
@@ -669,6 +700,9 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, length,
QVariant(underlined)));
+ // Keep the cursor position unchanged (don't move to end of preedit)
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, localPos - localStart, length, QVariant()));
+
QInputMethodEvent event(m_composingText, attributes);
event.setCommitString(QString(), relativeStart, length);
sendInputMethodEvent(&event);
@@ -720,6 +754,26 @@ jboolean QAndroidInputContext::paste()
return JNI_FALSE;
}
+
+Q_INVOKABLE QVariant QAndroidInputContext::queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument)
+{
+ return QInputMethod::queryFocusObject(query, argument);
+}
+
+QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument)
+{
+ bool inMainThread = qGuiApp->thread() == QThread::currentThread();
+ QVariant retval;
+
+ QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe",
+ inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
+ Q_RETURN_ARG(QVariant, retval),
+ Q_ARG(Qt::InputMethodQuery, query),
+ Q_ARG(QVariant, argument));
+
+ return retval;
+}
+
QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries)
{
#warning TODO make qGuiApp->focusObject() thread safe !!!
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index 041bd0dc49..2fb54a97c4 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -114,14 +114,19 @@ public:
jboolean copyURL();
jboolean paste();
+public slots:
+ void updateCursorPosition();
+
private:
QSharedPointer<QInputMethodQueryEvent> focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll);
void sendInputMethodEvent(QInputMethodEvent *event);
+ Q_INVOKABLE QVariant queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument);
+ QVariant queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument);
+
private slots:
virtual void sendEvent(QObject *receiver, QInputMethodEvent *event);
virtual void sendEvent(QObject *receiver, QInputMethodQueryEvent *event);
- void updateCursorPosition();
private:
ExtractedText m_extractedText;
diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp
index b85b1157a8..ff49f59076 100644
--- a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp
+++ b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp
@@ -50,11 +50,8 @@ QT_BEGIN_NAMESPACE
QAndroidPlatformBackingStore::QAndroidPlatformBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
- Q_ASSERT(window->handle());
- if (window->surfaceType() == QSurface::RasterSurface)
- (static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->setBackingStore(this);
- else
- qWarning("QAndroidPlatformBackingStore does not support GL windows.");
+ if (window->handle())
+ setBackingStore(window);
}
QPaintDevice *QAndroidPlatformBackingStore::paintDevice()
@@ -64,9 +61,11 @@ QPaintDevice *QAndroidPlatformBackingStore::paintDevice()
void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
- Q_UNUSED(window);
Q_UNUSED(offset);
+ if (!m_backingStoreSet)
+ setBackingStore(window);
+
(static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->repaint(region);
}
@@ -78,4 +77,14 @@ void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &stat
m_image = QImage(size, window()->screen()->handle()->format());
}
+void QAndroidPlatformBackingStore::setBackingStore(QWindow *window)
+{
+ if (window->surfaceType() == QSurface::RasterSurface) {
+ (static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->setBackingStore(this);
+ m_backingStoreSet = true;
+ } else {
+ qWarning("QAndroidPlatformBackingStore does not support GL windows.");
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.h b/src/plugins/platforms/android/qandroidplatformbackingstore.h
index e6ea3dcce0..4c24e129c3 100644
--- a/src/plugins/platforms/android/qandroidplatformbackingstore.h
+++ b/src/plugins/platforms/android/qandroidplatformbackingstore.h
@@ -56,9 +56,10 @@ public:
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
virtual void resize(const QSize &size, const QRegion &staticContents);
const QImage image() { return m_image; }
-
+ void setBackingStore(QWindow *window);
protected:
QImage m_image;
+ bool m_backingStoreSet = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 2cca974b41..9adefd5b2c 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -152,7 +152,8 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
case ThreadedOpenGL:
if (needsWorkaround())
return false;
- // fall through
+ else
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index d8cd32255c..a60f4adc28 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -81,7 +81,7 @@ HEADERS += qcocoaintegration.h \
RESOURCES += qcocoaresources.qrc
-LIBS += -framework Cocoa -framework Carbon -framework IOKit
+LIBS += -framework Cocoa -framework Carbon -framework IOKit -lcups
QT += core-private gui-private platformsupport-private
@@ -90,11 +90,13 @@ qtHaveModule(widgets) {
qpaintengine_mac.mm \
qprintengine_mac.mm \
qcocoaprintersupport.mm \
+ qcocoaprintdevice.mm \
HEADERS += \
qpaintengine_mac_p.h \
qprintengine_mac_p.h \
qcocoaprintersupport.h \
+ qcocoaprintdevice.h \
QT += widgets-private printsupport-private
}
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 1371eb3658..0f99a414a0 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -130,7 +130,7 @@ static void populateRoleMap()
roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole;
roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole;
roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole;
- roleMap[QAccessible::Link] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Link] = NSAccessibilityLinkRole;
roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole;
roleMap[QAccessible::Splitter] = NSAccessibilitySplitGroupRole;
roleMap[QAccessible::List] = NSAccessibilityListRole;
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 66c7727f15..bc98d002f0 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -91,6 +91,13 @@
// attributes
++ (id) lineNumberForIndex: (int)index forText:(const QString &)text
+{
+ QStringRef textBefore = QStringRef(&text, 0, index);
+ int newlines = textBefore.count(QLatin1Char('\n'));
+ return [NSNumber numberWithInt: newlines];
+}
+
- (NSArray *)accessibilityAttributeNames {
static NSArray *defaultAttributes = nil;
@@ -121,6 +128,19 @@
[attributes addObject : NSAccessibilityValueAttribute];
}
+ if (iface->textInterface()) {
+ [attributes addObjectsFromArray: [[NSArray alloc] initWithObjects:
+ NSAccessibilityNumberOfCharactersAttribute,
+ NSAccessibilitySelectedTextAttribute,
+ NSAccessibilitySelectedTextRangeAttribute,
+ NSAccessibilityVisibleCharacterRangeAttribute,
+ NSAccessibilityInsertionPointLineNumberAttribute,
+ nil
+ ]];
+
+// TODO: multi-selection: NSAccessibilitySelectedTextRangesAttribute,
+ }
+
return [attributes autorelease];
}
@@ -167,23 +187,150 @@
return nil;
return QCocoaAccessible::getValueAttribute(iface);
+
+ } else if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface())
+ return [NSNumber numberWithInt: text->characterCount()];
+ return nil;
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ text->selection(0, &start, &end);
+ return text->text(start, end).toNSString();
+ }
+ return nil;
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ if (text->selectionCount() > 0) {
+ text->selection(0, &start, &end);
+ } else {
+ start = text->cursorPosition();
+ end = start;
+ }
+ return [NSValue valueWithRange:NSMakeRange(quint32(start), quint32(end - start))];
+ }
+ return [NSValue valueWithRange: NSMakeRange(0, 0)];
+ } else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
+ // FIXME This is not correct and may impact performance for big texts
+ return [NSValue valueWithRange: NSMakeRange(0, iface->textInterface()->characterCount())];
+
+ } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ QString textBeforeCursor = text->text(0, text->cursorPosition());
+ return [NSNumber numberWithInt: textBeforeCursor.count(QLatin1Char('\n'))];
+ }
+ return nil;
+ }
+
+ return nil;
+}
+
+- (NSArray *)accessibilityParameterizedAttributeNames {
+
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface) {
+ qWarning() << "Called attribute on invalid object: " << axid;
+ return nil;
+ }
+
+ if (iface->textInterface()) {
+ return [[NSArray alloc] initWithObjects:
+ NSAccessibilityStringForRangeParameterizedAttribute,
+ NSAccessibilityLineForIndexParameterizedAttribute,
+ NSAccessibilityRangeForLineParameterizedAttribute,
+ NSAccessibilityRangeForPositionParameterizedAttribute,
+// NSAccessibilityRangeForIndexParameterizedAttribute,
+ NSAccessibilityBoundsForRangeParameterizedAttribute,
+// NSAccessibilityRTFForRangeParameterizedAttribute,
+// NSAccessibilityStyleRangeForIndexParameterizedAttribute,
+ NSAccessibilityAttributedStringForRangeParameterizedAttribute,
+ nil
+ ];
+ }
+
+ return nil;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface) {
+ qWarning() << "Called attribute on invalid object: " << axid;
+ return nil;
}
+ if (!iface->textInterface())
+ return nil;
+
+ if ([attribute isEqualToString: NSAccessibilityStringForRangeParameterizedAttribute]) {
+ NSRange range = [parameter rangeValue];
+ QString text = iface->textInterface()->text(range.location, range.location + range.length);
+ return text.toNSString();
+ }
+ if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
+ int index = [parameter intValue];
+ NSNumber *ln = [QCocoaAccessibleElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
+ return ln;
+ }
+ if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
+ int lineNumber = [parameter intValue];
+ QString text = iface->text(QAccessible::Value);
+ int startOffset = 0;
+ // skip newlines until we have the one we look for
+ for (int i = 0; i < lineNumber; ++i)
+ startOffset = text.indexOf(QLatin1Char('\n'), startOffset) + 1;
+ if (startOffset < 0) // invalid line number, return the first line
+ startOffset = 0;
+ int endOffset = text.indexOf(QLatin1Char('\n'), startOffset + 1);
+ if (endOffset == -1)
+ endOffset = text.length();
+ return [NSValue valueWithRange:NSMakeRange(quint32(startOffset), quint32(endOffset - startOffset))];
+ }
+ if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) {
+ NSRange range = [parameter rangeValue];
+ QRect firstRect = iface->textInterface()->characterRect(range.location);
+ QRect lastRect = iface->textInterface()->characterRect(range.location + range.length);
+ QRect rect = firstRect.united(lastRect); // This is off quite often, but at least a rough approximation
+ return [NSValue valueWithRect: NSMakeRect((CGFloat) rect.x(),(CGFloat) qt_mac_flipYCoordinate(rect.y() + rect.height()), rect.width(), rect.height())];
+ }
+ if ([attribute isEqualToString: NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
+ NSRange range = [parameter rangeValue];
+ QString text = iface->textInterface()->text(range.location, range.location + range.length);
+ return [[NSAttributedString alloc] initWithString: text.toNSString()];
+ }
return nil;
}
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface)
+ return nil;
+
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- return NO; // YES to handle keyboard input
- } else {
- return NO;
+ return iface->state().focusable ? YES : NO;
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
+ return iface->textInterface() ? YES : NO;
}
+ return NO;
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
- Q_UNUSED(value);
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface)
+ return;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
-
+ if (QAccessibleActionInterface *action = iface->actionInterface())
+ action->doAction(QAccessibleActionInterface::setFocusAction());
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ NSRange range = [value rangeValue];
+ if (range.length > 0)
+ text->setSelection(0, range.location, range.location + range.length);
+ else
+ text->setCursorPosition(range.location);
+ }
}
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 327ca00ad6..f8411845dc 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -223,8 +223,9 @@ static void cleanupCocoaApplicationDelegate()
// events while the event loop is still running.
const QWindowList topLevels = QGuiApplication::topLevelWindows();
for (int i = 0; i < topLevels.size(); ++i) {
- topLevels.at(i)->close();
+ QWindowSystemInterface::handleCloseEvent(topLevels.at(i));
}
+ QWindowSystemInterface::flushWindowSystemEvents();
QGuiApplication::exit(0);
startedQuit = false;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index ce8ebbc79e..a33373c4c1 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -59,6 +59,7 @@ public:
QPaintDevice *paintDevice();
void flush(QWindow *widget, const QRegion &region, const QPoint &offset);
+ QImage toImage() const Q_DECL_OVERRIDE;
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
CGImageRef getBackingStoreCGImage();
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 3ca611b537..d76645c668 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -59,25 +59,20 @@ QCocoaBackingStore::~QCocoaBackingStore()
QPaintDevice *QCocoaBackingStore::paintDevice()
{
- if (m_qImage.size() / m_qImage.devicePixelRatio() != m_requestedSize) {
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
+ int windowDevicePixelRatio = int(cocoaWindow->devicePixelRatio());
+
+ // Receate the backing store buffer if the effective buffer size has changed,
+ // either due to a window resize or devicePixelRatio change.
+ QSize effectiveBufferSize = m_requestedSize * windowDevicePixelRatio;
+ if (m_qImage.size() != effectiveBufferSize) {
CGImageRelease(m_cgImage);
m_cgImage = 0;
- int scaleFactor = 1;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
- if (cocoaWindow && cocoaWindow->m_contentView && [cocoaWindow->m_contentView window]) {
- scaleFactor = int([[cocoaWindow->m_contentView window] backingScaleFactor]);
- }
- }
-#endif
-
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient)
? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
- m_qImage = QImage(m_requestedSize * scaleFactor, format);
- m_qImage.setDevicePixelRatio(scaleFactor);
+ m_qImage = QImage(effectiveBufferSize, format);
+ m_qImage.setDevicePixelRatio(windowDevicePixelRatio);
if (format == QImage::Format_ARGB32_Premultiplied)
m_qImage.fill(Qt::transparent);
}
@@ -101,6 +96,11 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion &region, const QPoint
}
}
+QImage QCocoaBackingStore::toImage() const
+{
+ return m_qImage;
+}
+
void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
{
m_requestedSize = size;
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 13f6423701..592bfc8e50 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -308,8 +308,22 @@ NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap *bitmap, const QBit
NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoint hotspot)
{
- NSPoint hotSpot = NSMakePoint(hotspot.x(), hotspot.y());
- NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
+ NSPoint hotSpot = NSMakePoint(hotspot.x() / pixmap.devicePixelRatio(),
+ hotspot.y() / pixmap.devicePixelRatio());
+ NSImage *nsimage;
+ if (pixmap.devicePixelRatio() > 1.0) {
+ QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio();
+ QPixmap scaledPixmap = pixmap.scaled(layoutSize);
+ nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap));
+ CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage());
+ NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
+ [nsimage addRepresentation:imageRep];
+ [imageRep release];
+ CGImageRelease(cgImage);
+ } else {
+ nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
+ }
+
NSCursor *nsCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot];
[nsimage release];
return nsCursor;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 9b4d8fd96f..3f61bd81ee 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -194,7 +194,7 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
{
- Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+ Q_ASSERT(surface->surface()->supportsOpenGL());
QCocoaAutoReleasePool pool;
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 8975605e5c..a73944c07c 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -102,21 +102,31 @@ CGImageRef qt_mac_toCGImage(const QImage &inImage)
uint cgflags = kCGImageAlphaNone;
switch (image.format()) {
case QImage::Format_ARGB32_Premultiplied:
- cgflags = kCGImageAlphaPremultipliedFirst;
+ cgflags = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
break;
case QImage::Format_ARGB32:
- cgflags = kCGImageAlphaFirst;
+ cgflags = kCGImageAlphaFirst | kCGBitmapByteOrder32Host;
break;
case QImage::Format_RGB32:
- cgflags = kCGImageAlphaNoneSkipFirst;
+ cgflags = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
break;
case QImage::Format_RGB888:
- cgflags |= kCGImageAlphaNone;
- break;
+ cgflags = kCGImageAlphaNone | kCGBitmapByteOrder32Big;
+ break;
+ case QImage::Format_RGBA8888_Premultiplied:
+ cgflags = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
+ break;
+ case QImage::Format_RGBA8888:
+ cgflags = kCGImageAlphaLast | kCGBitmapByteOrder32Big;
+ break;
+ case QImage::Format_RGBX8888:
+ cgflags = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big;
+ break;
default:
+ Q_ASSERT(false); // Should never be reached.
break;
}
- cgflags |= kCGBitmapByteOrder32Host;
+
QCFType<CGDataProviderRef> dataProvider = qt_mac_CGDataProvider(image);
return CGImageCreate(image.width(), image.height(), 8, 32,
image.bytesPerLine(),
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index b1b73e5f08..24adc7a95b 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -129,6 +129,7 @@ public:
QCocoaServices *services() const;
QVariant styleHint(StyleHint hint) const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const;
QList<int> possibleKeys(const QKeyEvent *event) const;
void updateScreens();
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 1892a5b6bf..65a9f87e2d 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -375,6 +375,7 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case WindowMasks:
case MultipleWindows:
case ForeignWindows:
+ case RasterGLSurface:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
@@ -464,6 +465,11 @@ QVariant QCocoaIntegration::styleHint(StyleHint hint) const
return QPlatformIntegration::styleHint(hint);
}
+Qt::KeyboardModifiers QCocoaIntegration::queryKeyboardModifiers() const
+{
+ return QCocoaKeyMapper::queryKeyboardModifiers();
+}
+
QList<int> QCocoaIntegration::possibleKeys(const QKeyEvent *event) const
{
return mKeyboardMapper->possibleKeys(event);
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.h b/src/plugins/platforms/cocoa/qcocoakeymapper.h
index 0629de9317..4f419b3651 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.h
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.h
@@ -83,6 +83,7 @@ class QCocoaKeyMapper
public:
QCocoaKeyMapper();
~QCocoaKeyMapper();
+ static Qt::KeyboardModifiers queryKeyboardModifiers();
QList<int> possibleKeys(const QKeyEvent *event) const;
bool updateKeyboard();
void deleteLayouts();
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
index 0745cc2254..e46eaff6be 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
@@ -346,6 +346,11 @@ QCocoaKeyMapper::~QCocoaKeyMapper()
deleteLayouts();
}
+Qt::KeyboardModifiers QCocoaKeyMapper::queryKeyboardModifiers()
+{
+ return qt_mac_get_modifiers(GetCurrentEventKeyModifiers());
+}
+
bool QCocoaKeyMapper::updateKeyboard()
{
const UCKeyboardLayout *uchrData = 0;
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 329c7a264a..35e8fdebb4 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -127,6 +127,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
{
QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
QScopedLoopLevelCounter loopLevelCounter(QGuiApplicationPrivate::instance()->threadData);
+ QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
cocoaItem->activated();
}
@@ -268,7 +269,7 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *
QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
QCocoaMenuItem *beforeItem = static_cast<QCocoaMenuItem *>(before);
- menuItem->setParent(this);
+ SET_COCOA_MENU_ANCESTOR(menuItem, this);
cocoaItem->sync();
if (beforeItem) {
int index = m_menuItems.indexOf(beforeItem);
@@ -325,8 +326,8 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
return;
}
- if (menuItem->parent() == this)
- menuItem->setParent(0);
+ if (COCOA_MENU_ANCESTOR(menuItem) == this)
+ SET_COCOA_MENU_ANCESTOR(menuItem, 0);
m_menuItems.removeOne(cocoaItem);
if (!cocoaItem->isMerged()) {
@@ -550,7 +551,7 @@ void QCocoaMenu::syncModalState(bool modal)
void QCocoaMenu::setMenuBar(QCocoaMenuBar *menuBar)
{
m_menuBar = menuBar;
- setParent(menuBar);
+ SET_COCOA_MENU_ANCESTOR(this, menuBar);
}
QCocoaMenuBar *QCocoaMenu::menuBar() const
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h
index 1e69ed5a4b..b0169b9746 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h
@@ -118,6 +118,9 @@ private:
quintptr m_tag;
};
+#define COCOA_MENU_ANCESTOR(m) ((m)->property("_qCocoaMenuAncestor").value<QObject *>())
+#define SET_COCOA_MENU_ANCESTOR(m, ancestor) (m)->setProperty("_qCocoaMenuAncestor", QVariant::fromValue<QObject *>(ancestor))
+
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 3bba1ee1d5..2246d2ce46 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -126,13 +126,13 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
{
if (menu == m_menu)
return;
- if (m_menu && m_menu->parent() == this)
- m_menu->setParent(0);
+ if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
+ SET_COCOA_MENU_ANCESTOR(m_menu, 0);
QCocoaAutoReleasePool pool;
m_menu = static_cast<QCocoaMenu *>(menu);
if (m_menu) {
- m_menu->setParent(this);
+ SET_COCOA_MENU_ANCESTOR(m_menu, this);
} else {
// we previously had a menu, but no longer
// clear out our item so the nexy sync() call builds a new one
@@ -217,12 +217,12 @@ NSMenuItem *QCocoaMenuItem::sync()
mergeItem = [loader preferencesMenuItem];
break;
case TextHeuristicRole: {
- QObject *p = parent();
+ QObject *p = COCOA_MENU_ANCESTOR(this);
int depth = 1;
QCocoaMenuBar *menubar = 0;
while (depth < 3 && p && !(menubar = qobject_cast<QCocoaMenuBar *>(p))) {
++depth;
- p = p->parent();
+ p = COCOA_MENU_ANCESTOR(p);
}
if (depth == 3 || !menubar)
break; // Menu item too deep in the hierarchy, or not connected to any menubar
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index bf7e85619a..efdd433d8f 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -136,10 +136,19 @@ private:
// Request a unified title and toolbar look for the window.
static void setContentBorderThickness(QWindow *window, int topThickness, int bottomThickness);
+ // Request a unified title and toolbar look for the window by registering
+ // an area. Multiple callers can register areas and the platform plugin
+ // will extend the "unified" area to cover them.
+ static void registerContentBorderArea(QWindow *window, quintptr identifer, int upper, int lower);
+
+ // Enable the unified title and toolbar area.
+ static void enableContentBorderArea(QWindow *window, bool enable);
+
// Sets a NSToolbar instance for the given QWindow. The
// toolbar will be attached to the native NSWindow when
// that is created;
static void setNSToolbar(QWindow *window, void *nsToolbar);
+
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 5e57200ebc..d6a5be8d52 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -125,6 +125,10 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setEmbeddedInForeignView);
if (resource.toLower() == "setcontentborderthickness")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderThickness);
+ if (resource.toLower() == "registercontentborderarea")
+ return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerContentBorderArea);
+ if (resource.toLower() == "enablecontentborderarea")
+ return NativeResourceForIntegrationFunction(QCocoaNativeInterface::enableContentBorderArea);
if (resource.toLower() == "setnstoolbar")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar);
@@ -287,11 +291,28 @@ void QCocoaNativeInterface::setContentBorderThickness(QWindow *window, int topTh
cocoaWindow->setContentBorderThickness(topThickness, bottomThickness);
}
-void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar)
+void QCocoaNativeInterface::registerContentBorderArea(QWindow *window, quintptr identifier, int upper, int lower)
{
if (!window)
return;
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ if (cocoaWindow)
+ cocoaWindow->registerContentBorderArea(identifier, upper, lower);
+}
+
+void QCocoaNativeInterface::enableContentBorderArea(QWindow *window, bool enable)
+{
+ if (!window)
+ return;
+
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ if (cocoaWindow)
+ cocoaWindow->enableContentBorderArea(enable);
+}
+
+void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar)
+{
QCocoaIntegration::instance()->setToolbar(window, static_cast<NSToolbar *>(nsToolbar));
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h
new file mode 100644
index 0000000000..30a2155bc7
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOAPRINTDEVICE_H
+#define QCOCOAPRINTDEVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformprintdevice.h>
+
+#ifndef QT_NO_PRINTER
+
+#include "qt_mac_p.h"
+
+#include <cups/ppd.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCocoaPrintDevice : public QPlatformPrintDevice
+{
+public:
+ QCocoaPrintDevice();
+ explicit QCocoaPrintDevice(const QString &id);
+ QCocoaPrintDevice(const QCocoaPrintDevice &other);
+ virtual ~QCocoaPrintDevice();
+
+ QCocoaPrintDevice *clone();
+
+ bool operator==(const QCocoaPrintDevice &other) const;
+
+ bool isValid() const Q_DECL_OVERRIDE;
+ bool isDefault() const Q_DECL_OVERRIDE;
+
+ QPrint::DeviceState state() const Q_DECL_OVERRIDE;
+
+ QPageSize defaultPageSize() const Q_DECL_OVERRIDE;
+
+ QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation,
+ int resolution) const Q_DECL_OVERRIDE;
+
+ int defaultResolution() const Q_DECL_OVERRIDE;
+
+ QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE;
+
+ QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE;
+
+ QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE;
+
+ QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE;
+
+ PMPrinter macPrinter() const;
+ PMPaper macPaper(const QPageSize &pageSize) const;
+
+protected:
+ void loadPageSizes() const Q_DECL_OVERRIDE;
+ void loadResolutions() const Q_DECL_OVERRIDE;
+ void loadInputSlots() const Q_DECL_OVERRIDE;
+ void loadOutputBins() const Q_DECL_OVERRIDE;
+ void loadDuplexModes() const Q_DECL_OVERRIDE;
+ void loadColorModes() const Q_DECL_OVERRIDE;
+ void loadMimeTypes() const Q_DECL_OVERRIDE;
+
+private:
+ QPageSize createPageSize(const PMPaper &paper) const;
+ bool openPpdFile();
+
+ // Mac Core Printing
+ PMPrinter m_printer;
+ PMPrintSession m_session;
+ mutable QHash<QString, PMPaper> m_macPapers;
+
+ // PPD File
+ ppd_file_t *m_ppd;
+
+ QMarginsF m_customMargins;
+ mutable QHash<QString, QMarginsF> m_printableMargins;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTER
+#endif // QCOCOAPRINTDEVICE_H
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
new file mode 100644
index 0000000000..3061e84470
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcocoaprintdevice.h"
+
+#include <QtCore/qmimedatabase.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PRINTER
+
+static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode)
+{
+ if (mode == kPMDuplexTumble)
+ return QPrint::DuplexShortSide;
+ else if (mode == kPMDuplexNoTumble)
+ return QPrint::DuplexLongSide;
+ else // kPMDuplexNone or kPMSimplexTumble
+ return QPrint::DuplexNone;
+}
+
+QCocoaPrintDevice::QCocoaPrintDevice()
+ : QPlatformPrintDevice(),
+ m_printer(0),
+ m_session(0),
+ m_ppd(0)
+{
+}
+
+QCocoaPrintDevice::QCocoaPrintDevice(const QString &id)
+ : QPlatformPrintDevice(id),
+ m_printer(0),
+ m_session(0),
+ m_ppd(0)
+{
+ if (!id.isEmpty()) {
+ m_printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(id));
+ if (m_printer) {
+ m_name = QCFString::toQString(PMPrinterGetName(m_printer));
+ m_location = QCFString::toQString(PMPrinterGetLocation(m_printer));
+ CFStringRef cfMakeAndModel;
+ if (PMPrinterGetMakeAndModelName(m_printer, &cfMakeAndModel) == noErr)
+ m_makeAndModel = QCFString::toQString(cfMakeAndModel);
+ Boolean isRemote;
+ if (PMPrinterIsRemote(m_printer, &isRemote) == noErr)
+ m_isRemote = isRemote;
+ if (PMCreateSession(&m_session) == noErr)
+ PMSessionSetCurrentPMPrinter(m_session, m_printer);
+
+ // No native api to query these options, need to use PPD directly, note is deprecated from 1.6 onwards
+ if (openPpdFile()) {
+ // Note this is if the hardware does multiple copies, not if Cups can
+ m_supportsMultipleCopies = !m_ppd->manual_copies;
+ // Note this is if the hardware does collation, not if Cups can
+ ppd_option_t *collate = ppdFindOption(m_ppd, "Collate");
+ if (collate)
+ m_supportsCollateCopies = true;
+ m_supportsCustomPageSizes = m_ppd->custom_max[0] > 0 && m_ppd->custom_max[1] > 0;
+ m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]);
+ m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]);
+ m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3],
+ m_ppd->custom_margins[2], m_ppd->custom_margins[1]);
+ }
+ }
+ }
+}
+
+QCocoaPrintDevice::QCocoaPrintDevice(const QCocoaPrintDevice &other)
+ : QPlatformPrintDevice(other),
+ m_printer(0),
+ m_session(0),
+ m_ppd(0)
+{
+ m_printer = other.m_printer;
+ PMRetain(m_printer);
+ m_session = other.m_session;
+ PMRetain(m_session);
+ m_macPapers = other.m_macPapers;
+ foreach (PMPaper paper, m_macPapers.values())
+ PMRetain(paper);
+ openPpdFile();
+ m_customMargins = other.m_customMargins;
+ m_printableMargins = other.m_printableMargins;
+}
+
+QCocoaPrintDevice::~QCocoaPrintDevice()
+{
+ if (m_ppd)
+ ppdClose(m_ppd);
+ foreach (PMPaper paper, m_macPapers.values())
+ PMRelease(paper);
+ // Releasing the session appears to also release the printer
+ if (m_session)
+ PMRelease(m_session);
+ else if (m_printer)
+ PMRelease(m_printer);
+}
+
+QCocoaPrintDevice *QCocoaPrintDevice::clone()
+{
+ return new QCocoaPrintDevice(*this);
+}
+
+bool QCocoaPrintDevice::operator==(const QCocoaPrintDevice &other) const
+{
+ return (m_id == other.m_id);
+}
+
+bool QCocoaPrintDevice::isValid() const
+{
+ return m_printer ? true : false;
+}
+
+bool QCocoaPrintDevice::isDefault() const
+{
+ return PMPrinterIsDefault(m_printer);
+}
+
+QPrint::DeviceState QCocoaPrintDevice::state() const
+{
+ PMPrinterState state;
+ if (PMPrinterGetState(m_printer, &state) == noErr) {
+ if (state == kPMPrinterIdle)
+ return QPrint::Idle;
+ else if (state == kPMPrinterProcessing)
+ return QPrint::Active;
+ else if (state == kPMPrinterStopped)
+ return QPrint::Error;
+ }
+ return QPrint::Error;
+}
+
+QPageSize QCocoaPrintDevice::createPageSize(const PMPaper &paper) const
+{
+ QCFString key;
+ double width;
+ double height;
+ QCFString localizedName;
+ if (PMPaperGetPPDPaperName(paper, &key) == noErr
+ && PMPaperGetWidth(paper, &width) == noErr
+ && PMPaperGetHeight(paper, &height) == noErr
+ && PMPaperCreateLocalizedName(paper, m_printer, &localizedName) == noErr) {
+ return(QPlatformPrintDevice::createPageSize(key, QSize(width, height), localizedName));
+ }
+ return QPageSize();
+}
+
+void QCocoaPrintDevice::loadPageSizes() const
+{
+ m_pageSizes.clear();
+ foreach (PMPaper paper, m_macPapers.values())
+ PMRelease(paper);
+ m_macPapers.clear();
+ m_printableMargins.clear();
+ CFArrayRef paperSizes;
+ if (PMPrinterGetPaperList(m_printer, &paperSizes) == noErr) {
+ int count = CFArrayGetCount(paperSizes);
+ for (int i = 0; i < count; ++i) {
+ PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(paperSizes, i)));
+ QPageSize pageSize = createPageSize(paper);
+ if (pageSize.isValid()) {
+ m_pageSizes.append(pageSize);
+ PMRetain(paper);
+ m_macPapers.insert(pageSize.key(), paper);
+ PMPaperMargins printMargins;
+ PMPaperGetMargins(paper, &printMargins);
+ m_printableMargins.insert(pageSize.key(), QMarginsF(printMargins.left, printMargins.top,
+ printMargins.right, printMargins.bottom));
+ }
+ }
+ }
+ m_havePageSizes = true;
+}
+
+QPageSize QCocoaPrintDevice::defaultPageSize() const
+{
+ QPageSize pageSize;
+ PMPageFormat pageFormat;
+ PMPaper paper;
+ if (PMCreatePageFormat(&pageFormat) == noErr
+ && PMSessionDefaultPageFormat(m_session, pageFormat) == noErr
+ && PMGetPageFormatPaper(pageFormat, &paper) == noErr) {
+ pageSize = createPageSize(paper);
+ PMRelease(pageFormat);
+ }
+ return pageSize;
+}
+
+QMarginsF QCocoaPrintDevice::printableMargins(const QPageSize &pageSize,
+ QPageLayout::Orientation orientation,
+ int resolution) const
+{
+ Q_UNUSED(orientation)
+ Q_UNUSED(resolution)
+ if (!m_havePageSizes)
+ loadPageSizes();
+ if (m_printableMargins.contains(pageSize.key()))
+ return m_printableMargins.value(pageSize.key());
+ return m_customMargins;
+}
+
+void QCocoaPrintDevice::loadResolutions() const
+{
+ m_resolutions.clear();
+ UInt32 count;
+ if (PMPrinterGetPrinterResolutionCount(m_printer, &count) == noErr) {
+ // 1-based index
+ for (UInt32 i = 1; i <= count; ++i) {
+ PMResolution resolution;
+ if (PMPrinterGetIndexedPrinterResolution(m_printer, i, &resolution) == noErr)
+ m_resolutions.append(int(resolution.hRes));
+ }
+ }
+ m_haveResolutions = true;
+}
+
+int QCocoaPrintDevice::defaultResolution() const
+{
+ int defaultResolution = 72;
+ PMPrintSettings settings;
+ if (PMCreatePrintSettings(&settings) == noErr) {
+ PMResolution resolution;
+ if (PMSessionDefaultPrintSettings(m_session, settings) == noErr
+ && PMPrinterGetOutputResolution(m_printer, settings, &resolution) == noErr) {
+ // PMPrinterGetOutputResolution usually fails with -9589 kPMKeyNotFound as not set in PPD
+ defaultResolution = int(resolution.hRes);
+ }
+ PMRelease(settings);
+ }
+ // If no value returned (usually means not set in PPD) then use supported resolutions which
+ // OSX will have populated with at least one default value (but why not returned by call?)
+ if (defaultResolution <= 0) {
+ if (!m_haveResolutions)
+ loadResolutions();
+ if (m_resolutions.count() > 0)
+ return m_resolutions.at(0); // First value or highest? Only likely to be one anyway.
+ return 72; // TDOD More sensible default value???
+ }
+ return defaultResolution;
+}
+
+void QCocoaPrintDevice::loadInputSlots() const
+{
+ // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+ // TODO Deal with concatenated names like Tray1Manual or Tray1_Man,
+ // will currently show as CustomInputSlot
+ // TODO Deal with separate ManualFeed key
+ // Try load standard PPD options first
+ m_inputSlots.clear();
+ if (m_ppd) {
+ ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot");
+ if (inputSlots) {
+ for (int i = 0; i < inputSlots->num_choices; ++i)
+ m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i]));
+ }
+ // If no result, try just the default
+ if (m_inputSlots.size() == 0) {
+ inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot");
+ if (inputSlots)
+ m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0]));
+ }
+ }
+ // If still no result, just use Auto
+ if (m_inputSlots.size() == 0)
+ m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot());
+ m_haveInputSlots = true;
+}
+
+QPrint::InputSlot QCocoaPrintDevice::defaultInputSlot() const
+{
+ // No native api to query, use PPD directly
+ // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+ // Try load standard PPD option first
+ if (m_ppd) {
+ ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot");
+ if (inputSlot)
+ return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]);
+ // If no result, then try a marked option
+ ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot");
+ if (defaultChoice)
+ return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice);
+ }
+ // Otherwise return Auto
+ return QPlatformPrintDevice::defaultInputSlot();
+}
+
+void QCocoaPrintDevice::loadOutputBins() const
+{
+ // No native api to query, use PPD directly
+ // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+ m_outputBins.clear();
+ if (m_ppd) {
+ ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin");
+ if (outputBins) {
+ for (int i = 0; i < outputBins->num_choices; ++i)
+ m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i]));
+ }
+ // If no result, try just the default
+ if (m_outputBins.size() == 0) {
+ outputBins = ppdFindOption(m_ppd, "DefaultOutputBin");
+ if (outputBins)
+ m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0]));
+ }
+ }
+ // If still no result, just use Auto
+ if (m_outputBins.size() == 0)
+ m_outputBins.append(QPlatformPrintDevice::defaultOutputBin());
+ m_haveOutputBins = true;
+}
+
+QPrint::OutputBin QCocoaPrintDevice::defaultOutputBin() const
+{
+ // No native api to query, use PPD directly
+ // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+ // Try load standard PPD option first
+ if (m_ppd) {
+ ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin");
+ if (outputBin)
+ return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]);
+ // If no result, then try a marked option
+ ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin");
+ if (defaultChoice)
+ return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice);
+ }
+ // Otherwise return AutoBin
+ return QPlatformPrintDevice::defaultOutputBin();
+}
+
+void QCocoaPrintDevice::loadDuplexModes() const
+{
+ // No native api to query, use PPD directly
+ // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+ // Try load standard PPD options first
+ m_duplexModes.clear();
+ if (m_ppd) {
+ ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex");
+ if (duplexModes) {
+ for (int i = 0; i < duplexModes->num_choices; ++i)
+ m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice));
+ }
+ // If no result, try just the default
+ if (m_duplexModes.size() == 0) {
+ duplexModes = ppdFindOption(m_ppd, "DefaultDuplex");
+ if (duplexModes)
+ m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice));
+ }
+ }
+ // If still no result, or not added in PPD, then add None
+ if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
+ m_duplexModes.append(QPrint::DuplexNone);
+ m_haveDuplexModes = true;
+}
+
+QPrint::DuplexMode QCocoaPrintDevice::defaultDuplexMode() const
+{
+ QPrint::DuplexMode defaultMode = QPrint::DuplexNone;
+ PMPrintSettings settings;
+ if (PMCreatePrintSettings(&settings) == noErr) {
+ PMDuplexMode duplexMode;
+ if (PMSessionDefaultPrintSettings(m_session, settings) == noErr
+ && PMGetDuplex(settings, &duplexMode) == noErr) {
+ defaultMode = macToDuplexMode(duplexMode);
+ }
+ PMRelease(settings);
+ }
+ return defaultMode;
+}
+
+void QCocoaPrintDevice::loadColorModes() const
+{
+ // No native api to query, use PPD directly
+ m_colorModes.clear();
+ m_colorModes.append(QPrint::GrayScale);
+ if (!m_ppd || (m_ppd && m_ppd->color_device))
+ m_colorModes.append(QPrint::Color);
+ m_haveColorModes = true;
+}
+
+QPrint::ColorMode QCocoaPrintDevice::defaultColorMode() const
+{
+ // No native api to query, use PPD directly
+ // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync
+ // Not a proper option, usually only know if supports color or not, but some
+ // users known to abuse ColorModel to always force GrayScale.
+ if (m_ppd && supportedColorModes().contains(QPrint::Color)) {
+ ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel");
+ if (!colorModel)
+ colorModel = ppdFindOption(m_ppd, "ColorModel");
+ if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray")))
+ return QPrint::Color;
+ }
+ return QPrint::GrayScale;
+}
+
+void QCocoaPrintDevice::loadMimeTypes() const
+{
+ // TODO Check how settings affect returned list
+ m_mimeTypes.clear();
+ QMimeDatabase db;
+ PMPrintSettings settings;
+ if (PMCreatePrintSettings(&settings) == noErr) {
+ CFArrayRef mimeTypes;
+ if (PMPrinterGetMimeTypes(m_printer, settings, &mimeTypes) == noErr) {
+ int count = CFArrayGetCount(mimeTypes);
+ for (int i = 0; i < count; ++i) {
+ CFStringRef mimeName = static_cast<CFStringRef>(const_cast<void *>(CFArrayGetValueAtIndex(mimeTypes, i)));
+ QMimeType mimeType = db.mimeTypeForName(QCFString::toQString(mimeName));
+ if (mimeType.isValid())
+ m_mimeTypes.append(mimeType);
+ }
+ }
+ PMRelease(settings);
+ }
+ m_haveMimeTypes = true;
+}
+
+bool QCocoaPrintDevice::openPpdFile()
+{
+ if (m_ppd)
+ ppdClose(m_ppd);
+ m_ppd = 0;
+ CFURLRef ppdURL = NULL;
+ char ppdPath[MAXPATHLEN];
+ if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr
+ && ppdURL != NULL
+ && CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) {
+ m_ppd = ppdOpenFile(ppdPath);
+ }
+ CFRelease(ppdURL);
+ return m_ppd ? true : false;
+}
+
+PMPrinter QCocoaPrintDevice::macPrinter() const
+{
+ return m_printer;
+}
+
+// Returns a cached printer PMPaper, or creates and caches a new custom PMPaper
+// Caller should never release a cached PMPaper!
+PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const
+{
+ if (!m_havePageSizes)
+ loadPageSizes();
+ // If keys match, then is a supported size or an existing custom size
+ if (m_macPapers.contains(pageSize.key()))
+ return m_macPapers.value(pageSize.key());
+ // For any other page size, whether custom or just unsupported, needs to be a custom PMPaper
+ PMPaper paper = 0;
+ PMPaperMargins paperMargins;
+ paperMargins.left = m_customMargins.left();
+ paperMargins.right = m_customMargins.right();
+ paperMargins.top = m_customMargins.top();
+ paperMargins.bottom = m_customMargins.bottom();
+ PMPaperCreateCustom(m_printer, QCFString(pageSize.key()), QCFString(pageSize.name()),
+ pageSize.sizePoints().width(), pageSize.sizePoints().height(),
+ &paperMargins, &paper);
+ m_macPapers.insert(pageSize.key(), paper);
+ return paper;
+}
+
+#endif // QT_NO_PRINTER
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h
index a48790ef34..61c1bfd3ec 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h
+++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h
@@ -55,14 +55,10 @@ public:
QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE;
QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE;
- QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const Q_DECL_OVERRIDE;
- QList<QPair<QString, QSizeF> > supportedSizesWithNames(const QPrinterInfo &) const Q_DECL_OVERRIDE;
- QList<QPrinterInfo> availablePrinters() Q_DECL_OVERRIDE;
- QPrinterInfo printerInfo(const QString &printerName) Q_DECL_OVERRIDE;
-
-private:
- QPrinterInfo printerInfoFromPMPrinter(const PMPrinter &printer);
+ QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE;
+ QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE;
+ QString defaultPrintDeviceId() const Q_DECL_OVERRIDE;
};
#endif // QT_NO_PRINTER
diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm
index cb2aa7132b..5853135dfb 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm
@@ -42,10 +42,10 @@
#include "qcocoaprintersupport.h"
#ifndef QT_NO_PRINTER
+
+#include "qcocoaprintdevice.h"
#include "qprintengine_mac_p.h"
-#include <QtPrintSupport/QPrinter>
-#include <QtPrintSupport/QPrinterInfo>
#include <private/qprinterinfo_p.h>
QCocoaPrinterSupport::QCocoaPrinterSupport()
@@ -69,107 +69,37 @@ QPaintEngine *QCocoaPrinterSupport::createPaintEngine(QPrintEngine *printEngine,
return static_cast<QMacPrintEngine *>(printEngine);
}
-QList<QPrinter::PaperSize> QCocoaPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const
+QPrintDevice QCocoaPrinterSupport::createPrintDevice(const QString &id)
{
- QList<QPrinter::PaperSize> returnValue;
- if (printerInfo.isNull())
- return returnValue;
-
- PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName()));
- if (!printer)
- return returnValue;
-
- CFArrayRef array;
- if (PMPrinterGetPaperList(printer, &array) != noErr) {
- PMRelease(printer);
- return returnValue;
- }
-
- CFIndex count = CFArrayGetCount(array);
- for (CFIndex i = 0; i < count; ++i) {
- PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i)));
- double width, height;
- if (PMPaperGetWidth(paper, &width) == noErr
- && PMPaperGetHeight(paper, &height) == noErr) {
- // width and height are in points, convertQSizeFToPaperSize() expects millimeters
- static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4;
- QSizeF size(width * OnePointInMillimeters, height * OnePointInMillimeters);
- returnValue += QPlatformPrinterSupport::convertQSizeFToPaperSize(size);
- }
- }
-
- PMRelease(printer);
-
- return returnValue;
+ return QPlatformPrinterSupport::createPrintDevice(new QCocoaPrintDevice(id));
}
-QList<QPrinterInfo> QCocoaPrinterSupport::availablePrinters()
+QStringList QCocoaPrinterSupport::availablePrintDeviceIds() const
{
- QList<QPrinterInfo> returnValue;
+ QStringList list;
QCFType<CFArrayRef> printerList;
if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) {
CFIndex count = CFArrayGetCount(printerList);
for (CFIndex i = 0; i < count; ++i) {
PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i)));
- returnValue += printerInfoFromPMPrinter(printer);
+ list.append(QCFString::toQString(PMPrinterGetID(printer)));
}
}
- return returnValue;
-}
-
-QPrinterInfo QCocoaPrinterSupport::printerInfo(const QString &printerName)
-{
- PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerName));
- QPrinterInfo pi = printerInfoFromPMPrinter(printer);
- PMRelease(printer);
- return pi;
-}
-
-QPrinterInfo QCocoaPrinterSupport::printerInfoFromPMPrinter(const PMPrinter &printer)
-{
- if (!printer)
- return QPrinterInfo();
-
- QString name = QCFString::toQString(PMPrinterGetID(printer));
- QString description = QCFString::toQString(PMPrinterGetName(printer));
- QString location = QCFString::toQString(PMPrinterGetLocation(printer));
- CFStringRef cfMakeAndModel;
- PMPrinterGetMakeAndModelName(printer, &cfMakeAndModel);
- QString makeAndModel = QCFString::toQString(cfMakeAndModel);
- bool isDefault = PMPrinterIsDefault(printer);
-
- return createPrinterInfo(name, description, location, makeAndModel, isDefault, 0);
+ return list;
}
-QList<QPair<QString, QSizeF> > QCocoaPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const
+QString QCocoaPrinterSupport::defaultPrintDeviceId() const
{
- QList<QPair<QString, QSizeF> > returnValue;
- if (printerInfo.isNull())
- return returnValue;
-
- PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName()));
- if (!printer)
- return returnValue;
-
- CFArrayRef array;
- if (PMPrinterGetPaperList(printer, &array) != noErr) {
- PMRelease(printer);
- return returnValue;
- }
-
- int count = CFArrayGetCount(array);
- for (int i = 0; i < count; ++i) {
- PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i)));
- double width, height;
- if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) {
- static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4;
- QCFString paperName;
- if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr)
- returnValue.append(qMakePair(QString(paperName), QSizeF(width * OnePointInMillimeters, height * OnePointInMillimeters)));
+ QCFType<CFArrayRef> printerList;
+ if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) {
+ CFIndex count = CFArrayGetCount(printerList);
+ for (CFIndex i = 0; i < count; ++i) {
+ PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i)));
+ if (PMPrinterIsDefault(printer))
+ return QCFString::toQString(PMPrinterGetID(printer));
}
}
- PMRelease(printer);
- return returnValue;
+ return QString();
}
#endif //QT_NO_PRINTER
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index 1c08d4bcb7..f18be8b69c 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -161,7 +161,7 @@ static QMacPaletteMap mac_widget_colors[] = {
QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive),
- QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
+ QMacPaletteMap(QPlatformTheme::MessageBoxLabelPalette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
@@ -191,6 +191,8 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
}
if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette) {
+ qc = qt_mac_colorForTheme(kThemeBrushMenuBackground);
+ pal.setBrush(QPalette::Background, qc);
qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemActive);
pal.setBrush(QPalette::ButtonText, qc);
qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 67cac41383..6e1f00eebe 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -80,6 +80,7 @@ typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow;
- (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow;
- (void)handleWindowEvent:(NSEvent *)theEvent;
+- (void) clearWindow;
@end
@@ -141,6 +142,7 @@ public:
~QCocoaWindow();
void setGeometry(const QRect &rect);
+ QRect geometry() const;
void setCocoaGeometry(const QRect &rect);
void clipChildWindows();
void clipWindow(const NSRect &clipRect);
@@ -189,6 +191,7 @@ public:
NSInteger windowLevel(Qt::WindowFlags flags);
NSUInteger windowStyleMask(Qt::WindowFlags flags);
void setWindowShadow(Qt::WindowFlags flags);
+ void setWindowZoomButton(Qt::WindowFlags flags);
void setCurrentContext(QCocoaGLContext *context);
QCocoaGLContext *currentContext() const;
@@ -206,6 +209,8 @@ public:
void registerTouch(bool enable);
void setContentBorderThickness(int topThickness, int bottomThickness);
+ void registerContentBorderArea(quintptr identifier, int upper, int lower);
+ void enableContentBorderArea(bool enable);
void applyContentBorderThickness(NSWindow *window);
void updateNSToolbar();
@@ -280,6 +285,16 @@ public: // for QNSView
QRect m_normalGeometry;
Qt::WindowFlags m_oldWindowFlags;
NSApplicationPresentationOptions m_presentationOptions;
+
+ struct BorderRange {
+ BorderRange(int u, int l) : upper(u), lower(l) { }
+ int upper;
+ int lower;
+ bool operator<(BorderRange const& right) const {
+ return upper < right.upper;
+ }
+ };
+ QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index f1f88a13dd..c7fba4eef0 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -155,7 +155,14 @@ static bool isMouseEvent(NSEvent *ev)
}
}
+ // The call to -[NSWindow sendEvent] may result in the window being deleted
+ // (e.g., when closing the window by pressing the title bar close button).
+ [self retain];
[self.window superSendEvent:theEvent];
+ bool windowStillAlive = self.window != nil; // We need to read before releasing
+ [self release];
+ if (!windowStillAlive)
+ return;
if (!self.window.delegate)
return; // Already detached, pending NSAppKitDefined event
@@ -179,6 +186,11 @@ static bool isMouseEvent(NSEvent *ev)
self.window.delegate = nil;
}
+- (void)clearWindow
+{
+ _window = nil;
+}
+
- (void)dealloc
{
_window = nil;
@@ -259,6 +271,7 @@ static bool isMouseEvent(NSEvent *ev)
- (void)dealloc
{
+ [_helper clearWindow];
[_helper release];
_helper = nil;
[super dealloc];
@@ -319,6 +332,7 @@ static bool isMouseEvent(NSEvent *ev)
- (void)dealloc
{
+ [_helper clearWindow];
[_helper release];
_helper = nil;
[super dealloc];
@@ -378,7 +392,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
// problem, except if the appilcation wants to have a "custom" viewport.
// (like the hellogl example)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7
- && tlw->surfaceType() == QSurface::OpenGLSurface) {
+ && tlw->supportsOpenGL()) {
BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface",
"QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
[m_contentView setWantsBestResolutionOpenGLSurface:enable];
@@ -448,6 +462,22 @@ void QCocoaWindow::setGeometry(const QRect &rectIn)
setCocoaGeometry(rect);
}
+QRect QCocoaWindow::geometry() const
+{
+ // QWindows that are embedded in a NSView hiearchy may be considered
+ // top-level from Qt's point of view but are not from Cocoa's point
+ // of view. Embedded QWindows get global (screen) geometry.
+ if (m_contentViewIsEmbedded) {
+ NSPoint windowPoint = [m_contentView convertPoint:NSMakePoint(0, 0) toView:nil];
+ NSPoint screenPoint = [[m_contentView window] convertBaseToScreen:windowPoint]; // ### use convertRectToScreen after 10.6 removal
+ QPoint position = qt_mac_flipPoint(screenPoint).toPoint();
+ QSize size = qt_mac_toQRect([m_contentView bounds]).size();
+ return QRect(position, size);
+ }
+
+ return QPlatformWindow::geometry();
+}
+
void QCocoaWindow::setCocoaGeometry(const QRect &rect)
{
QCocoaAutoReleasePool pool;
@@ -791,6 +821,18 @@ void QCocoaWindow::setWindowShadow(Qt::WindowFlags flags)
[m_nsWindow setHasShadow:(keepShadow ? YES : NO)];
}
+void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
+{
+ // Disable the zoom (maximize) button for fixed-sized windows and customized
+ // no-WindowMaximizeButtonHint windows. From a Qt perspective it migth be expected
+ // that the button would be removed in the latter case, but disabling it is more
+ // in line with the platform style guidelines.
+ bool fixedSizeNoZoom = (window()->minimumSize().isValid() && window()->maximumSize().isValid()
+ && window()->minimumSize() == window()->maximumSize());
+ bool customizeNoZoom = ((flags & Qt::CustomizeWindowHint) && !(flags & Qt::WindowMaximizeButtonHint));
+ [[m_nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)];
+}
+
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{
if (m_nsWindow && !m_isNSWindowChild) {
@@ -816,6 +858,7 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
}
}
#endif
+ setWindowZoomButton(flags);
}
m_windowFlags = flags;
@@ -908,6 +951,9 @@ void QCocoaWindow::raise()
[parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
} else {
[m_nsWindow orderFront: m_nsWindow];
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+ SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
}
}
}
@@ -979,6 +1025,9 @@ void QCocoaWindow::propagateSizeHints()
const QSize maximumSize = window()->maximumSize();
[m_nsWindow setContentMaxSize : NSMakeSize(maximumSize.width(), maximumSize.height())];
+ // The window may end up with a fixed size; in this case the zoom button should be disabled.
+ setWindowZoomButton(m_windowFlags);
+
// sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be
// resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case.
if (!window()->sizeIncrement().isEmpty())
@@ -1080,7 +1129,9 @@ NSWindow *QCocoaWindow::nativeWindow() const
void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
{
m_contentViewIsToBeEmbedded = embedded;
- recreateWindow(0); // destroy what was already created
+ // Release any previosly created NSWindow.
+ [m_nsWindow closeAndRelease];
+ m_nsWindow = 0;
}
void QCocoaWindow::windowWillMove()
@@ -1505,15 +1556,46 @@ void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickne
applyContentBorderThickness(m_nsWindow);
}
+void QCocoaWindow::registerContentBorderArea(quintptr identifier, int upper, int lower)
+{
+ m_contentBorderAreas.insert(identifier, BorderRange(upper, lower));
+
+ // Find consecutive registered border areas, starting from the top.
+ QList<BorderRange> ranges = m_contentBorderAreas.values();
+ std::sort(ranges.begin(), ranges.end());
+ m_topContentBorderThickness = 0;
+ foreach (BorderRange range, ranges) {
+ // Is this sub-range adjacent to or overlaping the
+ // existing total border area range? If so merge
+ // it into the total range,
+ if (range.upper <= (m_topContentBorderThickness + 1))
+ m_topContentBorderThickness = qMax(m_topContentBorderThickness, range.lower);
+ else
+ break;
+ }
+
+ m_bottomContentBorderThickness = 0; // (not supported)
+ if (m_drawContentBorderGradient)
+ applyContentBorderThickness(m_nsWindow);
+}
+
+void QCocoaWindow::enableContentBorderArea(bool enable)
+{
+ m_drawContentBorderGradient = enable;
+ applyContentBorderThickness(m_nsWindow);
+}
+
void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
{
if (!window)
return;
- if (m_drawContentBorderGradient)
- [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
- else
+ if (!m_drawContentBorderGradient) {
[window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask];
+ return;
+ }
+
+ [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
if (m_topContentBorderThickness > 0) {
[window setContentBorderThickness:m_topContentBorderThickness forEdge:NSMaxYEdge];
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 90d56bc3f3..47081ab890 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -562,9 +562,11 @@ static QTouchDevice *touchDevice = 0;
QPointF qtWindowPoint;
QPointF qtScreenPoint;
QNSView *targetView = self;
- if (m_platformWindow && m_platformWindow->m_forwardWindow
- && (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)) {
- targetView = m_platformWindow->m_forwardWindow->m_qtView;
+ if (m_platformWindow && m_platformWindow->m_forwardWindow) {
+ if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)
+ targetView = m_platformWindow->m_forwardWindow->m_qtView;
+ else
+ m_platformWindow->m_forwardWindow = 0;
}
[targetView convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
@@ -650,7 +652,7 @@ static QTouchDevice *touchDevice = 0;
{
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseDragged:theEvent];
- if (!(m_buttons & Qt::LeftButton))
+ if (!(m_buttons & (m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton)))
qWarning("QNSView mouseDragged: Internal mouse button tracking invalid (missing Qt::LeftButton)");
[self handleMouseEvent:theEvent];
}
@@ -1719,7 +1721,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
// keep our state, and QGuiApplication state (buttons member) in-sync,
// or future mouse events will be processed incorrectly
- m_buttons &= ~Qt::LeftButton;
+ m_buttons &= ~(m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton);
NSPoint windowPoint = [self convertPoint: point fromView: nil];
QPoint qtWindowPoint(windowPoint.x, windowPoint.y);
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index 61fbe3a61f..ef67d1166f 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -979,43 +979,6 @@ static void drawImageReleaseData (void *info, const void *, size_t)
delete static_cast<QImage *>(info);
}
-CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0)
-{
- QImage *image;
- if (img.depth() != 32)
- image = new QImage(img.convertToFormat(QImage::Format_ARGB32_Premultiplied));
- else
- image = new QImage(img);
-
- uint cgflags = kCGImageAlphaNone;
- switch (image->format()) {
- case QImage::Format_ARGB32_Premultiplied:
- cgflags = kCGImageAlphaPremultipliedFirst;
- break;
- case QImage::Format_ARGB32:
- cgflags = kCGImageAlphaFirst;
- break;
- case QImage::Format_RGB32:
- cgflags = kCGImageAlphaNoneSkipFirst;
- default:
- break;
- }
-#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version
- cgflags |= kCGBitmapByteOrder32Host;
-#endif
- QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image,
- static_cast<const QImage *>(image)->bits(),
- image->byteCount(),
- drawImageReleaseData);
- if (imagePtr)
- *imagePtr = image;
- return CGImageCreate(image->width(), image->height(), 8, 32,
- image->bytesPerLine(),
- QCoreGraphicsPaintEngine::macGenericColorSpace(),
- cgflags, dataProvider, 0, false, kCGRenderingIntentDefault);
-
-}
-
void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
Qt::ImageConversionFlags flags)
{
@@ -1026,8 +989,7 @@ void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, con
if (img.isNull() || state->compositionMode() == QPainter::CompositionMode_Destination)
return;
- const QImage *image;
- QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image);
+ QCFType<CGImageRef> cgimage = qt_mac_toCGImage(img);
CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
if (QRectF(0, 0, img.width(), img.height()) != sr)
cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(),
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index 3e92a45a62..fb968f31e9 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -40,9 +40,11 @@
****************************************************************************/
#include "qprintengine_mac_p.h"
+#include "qcocoaprintersupport.h"
#include <quuid.h>
+#include <QtGui/qpagelayout.h>
#include <QtCore/qcoreapplication.h>
-#include <qpa/qplatformprintersupport.h>
+#include <QtCore/qdebug.h>
#include "qcocoaautoreleasepool.h"
@@ -50,10 +52,14 @@
QT_BEGIN_NAMESPACE
+extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
+
QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(new QMacPrintEnginePrivate))
{
Q_D(QMacPrintEngine);
d->mode = mode;
+ d->m_printDevice = new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId());
+ d->m_pageLayout.setPageSize(d->m_printDevice->defaultPageSize());
d->initialize();
}
@@ -137,126 +143,6 @@ QMacPrintEnginePrivate::~QMacPrintEnginePrivate()
delete paintEngine;
}
-void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps)
-{
- Q_Q(QMacPrintEngine);
- if (hasCustomPaperSize) {
- PMRelease(customPaper);
- customPaper = 0;
- }
- hasCustomPaperSize = (ps == QPrinter::Custom);
- PMPrinter printer;
- if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) {
- if (ps != QPrinter::Custom) {
- QSizeF newSize = QPlatformPrinterSupport::convertPaperSizeToQSizeF(ps);
- QCFType<CFArrayRef> formats;
- if (PMSessionCreatePageFormatList(session(), printer, &formats) == noErr) {
- CFIndex total = CFArrayGetCount(formats);
- PMPageFormat tmp;
- PMRect paper;
- for (CFIndex idx = 0; idx < total; ++idx) {
- tmp = static_cast<PMPageFormat>(const_cast<void *>(CFArrayGetValueAtIndex(formats, idx)));
- PMGetUnadjustedPaperRect(tmp, &paper);
- int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5);
- int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5);
- if (newSize.width() == wMM && newSize.height() == hMM) {
- PMCopyPageFormat(tmp, format());
- // reset the orientation and resolution as they are lost in the copy.
- q->setProperty(QPrintEngine::PPK_Orientation, orient);
- if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) {
- // Don't know, warn for the moment.
- qWarning("QMacPrintEngine, problem setting format and resolution for this page size");
- }
- break;
- }
- }
- }
- } else {
- QCFString paperId = QCFString::toCFStringRef(QUuid::createUuid().toString());
- PMPaperMargins paperMargins;
- paperMargins.left = leftMargin;
- paperMargins.top = topMargin;
- paperMargins.right = rightMargin;
- paperMargins.bottom = bottomMargin;
- PMPaperCreateCustom(printer, paperId, QCFString("Custom size"), customSize.width(), customSize.height(), &paperMargins, &customPaper);
- PMPageFormat tmp;
- PMCreatePageFormatWithPMPaper(&tmp, customPaper);
- PMCopyPageFormat(tmp, format());
- if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) {
- // Don't know, warn for the moment.
- qWarning("QMacPrintEngine, problem setting paper name");
- }
- }
- }
-}
-
-QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const
-{
- if (hasCustomPaperSize)
- return QPrinter::Custom;
- PMRect paper;
- PMGetUnadjustedPaperRect(format(), &paper);
- QSizeF sizef((paper.right - paper.left) / 72.0 * 25.4, (paper.bottom - paper.top) / 72.0 * 25.4);
- return QPlatformPrinterSupport::convertQSizeFToPaperSize(sizef);
-}
-
-void QMacPrintEnginePrivate::setPaperName(const QString &name)
-{
- Q_Q(QMacPrintEngine);
- if (hasCustomPaperSize) {
- PMRelease(customPaper);
- customPaper = 0;
- hasCustomPaperSize = false;
- }
- PMPrinter printer;
-
- if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) {
- CFArrayRef array;
- if (PMPrinterGetPaperList(printer, &array) != noErr)
- return;
- int count = CFArrayGetCount(array);
- for (int i = 0; i < count; ++i) {
- PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i)));
- QCFString paperName;
- if (PMPaperCreateLocalizedName(paper, printer, &paperName) == noErr) {
- if (QString(paperName) == name) {
- PMPageFormat tmp;
- PMCreatePageFormatWithPMPaper(&tmp, paper);
- PMCopyPageFormat(tmp, format());
- q->setProperty(QPrintEngine::PPK_Orientation, orient);
- if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) {
- // Don't know, warn for the moment.
- qWarning("QMacPrintEngine, problem setting paper name");
- }
- }
- }
- }
- }
-}
-
-QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const
-{
- Q_ASSERT_X(printInfo, "QMacPrinterEngine::supportedResolutions",
- "must have a valid printer session");
- UInt32 resCount;
- QList<QVariant> resolutions;
- PMPrinter printer;
- if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) {
- PMResolution res;
- OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount);
- if (status == noErr) {
- // According to the docs, index start at 1.
- for (UInt32 i = 1; i <= resCount; ++i) {
- if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr)
- resolutions.append(QVariant(int(res.hRes)));
- }
- } else {
- qWarning("QMacPrintEngine::supportedResolutions: Unexpected error: %ld", long(status));
- }
- }
- return resolutions;
-}
-
QPrinter::PrinterState QMacPrintEngine::printerState() const
{
return d_func()->state;
@@ -291,77 +177,22 @@ bool QMacPrintEngine::abort()
return ret;
}
-static inline int qt_get_PDMWidth(PMPageFormat pformat, bool fullPage,
- const PMResolution &resolution)
-{
- int val = 0;
- PMRect r;
- qreal hRatio = resolution.hRes / 72;
- if (fullPage) {
- if (PMGetAdjustedPaperRect(pformat, &r) == noErr)
- val = qRound((r.right - r.left) * hRatio);
- } else {
- if (PMGetAdjustedPageRect(pformat, &r) == noErr)
- val = qRound((r.right - r.left) * hRatio);
- }
- return val;
-}
-
-static inline int qt_get_PDMHeight(PMPageFormat pformat, bool fullPage,
- const PMResolution &resolution)
-{
- int val = 0;
- PMRect r;
- qreal vRatio = resolution.vRes / 72;
- if (fullPage) {
- if (PMGetAdjustedPaperRect(pformat, &r) == noErr)
- val = qRound((r.bottom - r.top) * vRatio);
- } else {
- if (PMGetAdjustedPageRect(pformat, &r) == noErr)
- val = qRound((r.bottom - r.top) * vRatio);
- }
- return val;
-}
-
-
int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
{
Q_D(const QMacPrintEngine);
int val = 1;
switch (m) {
case QPaintDevice::PdmWidth:
- if (d->hasCustomPaperSize) {
- val = qRound(d->customSize.width());
- if (d->hasCustomPageMargins) {
- val -= qRound(d->leftMargin + d->rightMargin);
- } else {
- QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList();
- val -= qRound(margins.at(0).toDouble() + margins.at(2).toDouble());
- }
- } else {
- val = qt_get_PDMWidth(d->format(), property(PPK_FullPage).toBool(), d->resolution);
- }
+ val = d->m_pageLayout.paintRectPixels(d->resolution.hRes).width();
break;
case QPaintDevice::PdmHeight:
- if (d->hasCustomPaperSize) {
- val = qRound(d->customSize.height());
- if (d->hasCustomPageMargins) {
- val -= qRound(d->topMargin + d->bottomMargin);
- } else {
- QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList();
- val -= qRound(margins.at(1).toDouble() + margins.at(3).toDouble());
- }
- } else {
- val = qt_get_PDMHeight(d->format(), property(PPK_FullPage).toBool(), d->resolution);
- }
+ val = d->m_pageLayout.paintRectPixels(d->resolution.hRes).height();
break;
case QPaintDevice::PdmWidthMM:
- val = metric(QPaintDevice::PdmWidth);
- val = int((val * 254 + 5 * d->resolution.hRes) / (10 * d->resolution.hRes));
+ val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).width());
break;
case QPaintDevice::PdmHeightMM:
- val = metric(QPaintDevice::PdmHeight);
- val = int((val * 254 + 5 * d->resolution.vRes) / (10 * d->resolution.vRes));
+ val = qRound(d->m_pageLayout.paintRect(QPageLayout::Millimeter).height());
break;
case QPaintDevice::PdmPhysicalDpiX:
case QPaintDevice::PdmPhysicalDpiY: {
@@ -407,33 +238,24 @@ void QMacPrintEnginePrivate::initialize()
q->gccaps = paintEngine->gccaps;
- fullPage = false;
-
QCocoaAutoReleasePool pool;
printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]];
- PMPrinter printer;
- if (printInfo && PMSessionGetCurrentPrinter(session(), &printer) == noErr) {
- QList<QVariant> resolutions = supportedResolutions();
- if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) {
- if (resolutions.count() > 1 && mode == QPrinter::HighResolution) {
- int max = 0;
- for (int i = 0; i < resolutions.count(); ++i) {
- int value = resolutions.at(i).toInt();
- if (value > max)
- max = value;
- }
- resolution.hRes = resolution.vRes = max;
- } else {
- resolution.hRes = resolution.vRes = resolutions.at(0).toInt();
- }
- if (resolution.hRes == 0)
- resolution.hRes = resolution.vRes = 600;
- } else {
- resolution.hRes = resolution.vRes = qt_defaultDpi();
- }
+ QList<int> resolutions = m_printDevice->supportedResolutions();
+ if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) {
+ qSort(resolutions);
+ if (resolutions.count() > 1 && mode == QPrinter::HighResolution)
+ resolution.hRes = resolution.vRes = resolutions.last();
+ else
+ resolution.hRes = resolution.vRes = resolutions.first();
+ if (resolution.hRes == 0)
+ resolution.hRes = resolution.vRes = 600;
+ } else {
+ resolution.hRes = resolution.vRes = qt_defaultDpi();
}
+ setPageSize(m_pageLayout.pageSize());
+
QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant>::const_iterator propC;
for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) {
q->setProperty(propC.key(), propC.value());
@@ -444,8 +266,6 @@ void QMacPrintEnginePrivate::releaseSession()
{
PMSessionEndPageNoDialog(session());
PMSessionEndDocumentNoDialog(session());
- if (hasCustomPaperSize)
- PMRelease(customPaper);
[printInfo release];
printInfo = 0;
}
@@ -473,8 +293,8 @@ bool QMacPrintEnginePrivate::newPage_helper()
return false;
}
- QRect page = q->property(QPrintEngine::PPK_PageRect).toRect();
- QRect paper = q->property(QPrintEngine::PPK_PaperRect).toRect();
+ QRect page = m_pageLayout.paintRectPixels(resolution.hRes);
+ QRect paper = m_pageLayout.fullRectPixels(resolution.hRes);
CGContextRef cgContext;
OSStatus err = noErr;
@@ -491,7 +311,7 @@ bool QMacPrintEnginePrivate::newPage_helper()
CGContextScaleCTM(cgContext, 1, -1);
CGContextTranslateCTM(cgContext, 0, -paper.height());
- if (!fullPage)
+ if (m_pageLayout.mode() != QPageLayout::FullPageMode)
CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y());
cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext);
cgEngine->d_func()->setClip(0);
@@ -505,6 +325,34 @@ bool QMacPrintEnginePrivate::newPage_helper()
return true;
}
+void QMacPrintEnginePrivate::setPageSize(const QPageSize &pageSize)
+{
+ if (!pageSize.isValid())
+ return;
+
+ // Get the matching printer paper
+ QPageSize printerPageSize = m_printDevice->supportedPageSize(pageSize);
+ QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
+
+ // Get the PMPaper and check it is valid
+ PMPaper macPaper = m_printDevice->macPaper(usePageSize);
+ if (macPaper == 0) {
+ qWarning() << "QMacPrintEngine: Invalid PMPaper returned for " << pageSize;
+ return;
+ }
+
+ QMarginsF printable = m_printDevice->printableMargins(usePageSize, m_pageLayout.orientation(), resolution.hRes);
+ m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));
+
+ // You cannot set the page size on a PMPageFormat, you must create a new PMPageFormat
+ PMPageFormat pageFormat;
+ PMCreatePageFormatWithPMPaper(&pageFormat, macPaper);
+ PMSetOrientation(pageFormat, m_pageLayout.orientation() == QPageLayout::Landscape ? kPMLandscape : kPMPortrait, kPMUnlocked);
+ PMCopyPageFormat(pageFormat, format());
+ if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr)
+ qWarning("QMacPrintEngine: Invalid page format");
+ PMRelease(pageFormat);
+}
void QMacPrintEngine::updateState(const QPaintEngineState &state)
{
@@ -624,32 +472,22 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
break;
case PPK_SelectionOption:
break;
- case PPK_WindowsPageSize:
- break;
// The following keys are properties and settings that are supported by the Mac PrintEngine
case PPK_Resolution: {
- PMPrinter printer;
- UInt32 count;
- if (PMSessionGetCurrentPrinter(d->session(), &printer) != noErr)
- break;
- if (PMPrinterGetPrinterResolutionCount(printer, &count) != noErr)
- break;
- PMResolution resolution = { 0.0, 0.0 };
- PMResolution bestResolution = { 0.0, 0.0 };
+ // TODO It appears the old code didn't actually set the resolution??? Can we delete all this???
+ int bestResolution = 0;
int dpi = value.toInt();
int bestDistance = INT_MAX;
- for (UInt32 i = 1; i <= count; ++i) { // Yes, it starts at 1
- if (PMPrinterGetIndexedPrinterResolution(printer, i, &resolution) == noErr) {
- if (dpi == int(resolution.hRes)) {
+ foreach (int resolution, d->m_printDevice->supportedResolutions()) {
+ if (dpi == resolution) {
+ bestResolution = resolution;
+ break;
+ } else {
+ int distance = qAbs(dpi - resolution);
+ if (distance < bestDistance) {
+ bestDistance = distance;
bestResolution = resolution;
- break;
- } else {
- int distance = qAbs(dpi - int(resolution.hRes));
- if (distance < bestDistance) {
- bestDistance = distance;
- bestResolution = resolution;
- }
}
}
}
@@ -666,75 +504,80 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString()));
break;
case PPK_FullPage:
- d->fullPage = value.toBool();
+ if (value.toBool())
+ d->m_pageLayout.setMode(QPageLayout::FullPageMode);
+ else
+ d->m_pageLayout.setMode(QPageLayout::StandardMode);
break;
case PPK_CopyCount: // fallthrough
case PPK_NumberOfCopies:
PMSetCopies(d->settings(), value.toInt(), false);
break;
case PPK_Orientation: {
- QPrinter::Orientation newOrientation = QPrinter::Orientation(value.toInt());
- if (d->hasCustomPaperSize && (d->orient != newOrientation))
- d->customSize = QSizeF(d->customSize.height(), d->customSize.width());
- d->orient = newOrientation;
- PMOrientation o = d->orient == QPrinter::Portrait ? kPMPortrait : kPMLandscape;
- PMSetOrientation(d->format(), o, false);
+ // First try set the Mac format orientation, then set our orientation to match result
+ QPageLayout::Orientation newOrientation = QPageLayout::Orientation(value.toInt());
+ PMOrientation macOrientation = (newOrientation == QPageLayout::Landscape) ? kPMLandscape : kPMPortrait;
+ PMSetOrientation(d->format(), macOrientation, kPMUnlocked);
PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean);
+ PMGetOrientation(d->format(), &macOrientation);
+ d->m_pageLayout.setOrientation(macOrientation == kPMLandscape ? QPageLayout::Landscape : QPageLayout::Portrait);
break;
}
case PPK_OutputFileName:
d->outputFilename = value.toString();
break;
- case PPK_PaperSize:
- d->setPaperSize(QPrinter::PaperSize(value.toInt()));
+ case PPK_PageSize:
+ d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt())));
break;
case PPK_PaperName:
- d->setPaperName(value.toString());
+ // Get the named page size from the printer if supported
+ d->setPageSize(d->m_printDevice->supportedPageSize(value.toString()));
+ break;
+ case PPK_WindowsPageSize:
+ d->setPageSize(QPageSize(QPageSize::id(value.toInt())));
break;
case PPK_PrinterName: {
- bool printerNameSet = false;
- OSStatus status = noErr;
- QCFType<CFArrayRef> printerList;
- status = PMServerCreatePrinterList(kPMServerLocal, &printerList);
- if (status == noErr) {
- CFIndex count = CFArrayGetCount(printerList);
- for (CFIndex i=0; i<count; ++i) {
- PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i)));
- QString name = QCFString::toQString(PMPrinterGetID(printer));
- if (name == value.toString()) {
- status = PMSessionSetCurrentPMPrinter(d->session(), printer);
- printerNameSet = true;
- break;
- }
- }
- }
- if (status != noErr)
- qWarning("QMacPrintEngine::setPrinterName: Error setting printer: %ld", long(status));
- if (!printerNameSet) {
- qWarning("QMacPrintEngine::setPrinterName: Failed to set printer named '%s'.", qPrintable(value.toString()));
- d->releaseSession();
- d->state = QPrinter::Idle;
- }
- break; }
- case PPK_CustomPaperSize:
- {
- PMOrientation orientation;
- PMGetOrientation(d->format(), &orientation);
- d->customSize = value.toSizeF();
- if (orientation != kPMPortrait)
- d->customSize = QSizeF(d->customSize.height(), d->customSize.width());
- d->setPaperSize(QPrinter::Custom);
+ QString id = value.toString();
+ if (id.isEmpty())
+ id = QCocoaPrinterSupport().defaultPrintDeviceId();
+ else if (!QCocoaPrinterSupport().availablePrintDeviceIds().contains(id))
+ break;
+ d->m_printDevice = new QCocoaPrintDevice(id);
+ PMPrinter printer = d->m_printDevice->macPrinter();
+ PMRetain(printer);
+ PMSessionSetCurrentPMPrinter(d->session(), printer);
+ // TODO Do we need to check if the page size, etc, are valid on new printer?
break;
}
+ case PPK_CustomPaperSize:
+ d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
+ break;
case PPK_PageMargins:
{
QList<QVariant> margins(value.toList());
Q_ASSERT(margins.size() == 4);
- d->leftMargin = margins.at(0).toDouble();
- d->topMargin = margins.at(1).toDouble();
- d->rightMargin = margins.at(2).toDouble();
- d->bottomMargin = margins.at(3).toDouble();
- d->hasCustomPageMargins = true;
+ d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(),
+ margins.at(2).toReal(), margins.at(3).toReal()));
+ break;
+ }
+ case PPK_QPageSize:
+ d->setPageSize(value.value<QPageSize>());
+ break;
+ case PPK_QPageMargins: {
+ QPair<QMarginsF, QPageLayout::Unit> pair = value.value<QPair<QMarginsF, QPageLayout::Unit> >();
+ d->m_pageLayout.setUnits(pair.second);
+ d->m_pageLayout.setMargins(pair.first);
+ break;
+ }
+ case PPK_QPageLayout: {
+ QPageLayout pageLayout = value.value<QPageLayout>();
+ if (pageLayout.isValid() && d->m_printDevice->isValidPageLayout(pageLayout, d->resolution.hRes)) {
+ setProperty(PPK_QPageSize, QVariant::fromValue(pageLayout.pageSize()));
+ setProperty(PPK_FullPage, pageLayout.mode() == QPageLayout::FullPageMode);
+ setProperty(PPK_Orientation, QVariant::fromValue(pageLayout.orientation()));
+ d->m_pageLayout.setUnits(pageLayout.units());
+ d->m_pageLayout.setMargins(pageLayout.margins());
+ }
break;
}
// No default so that compiler will complain if new keys added and not handled in this engine
@@ -787,9 +630,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_SelectionOption:
ret = QString();
break;
- case PPK_WindowsPageSize:
- // Special case, leave null
- break;
// The following keys are properties and settings that are supported by the Mac PrintEngine
case PPK_CollateCopies: {
@@ -808,7 +648,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
break;
}
case PPK_FullPage:
- ret = d->fullPage;
+ ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
break;
case PPK_NumberOfCopies:
ret = 1;
@@ -823,107 +663,62 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
ret = true;
break;
case PPK_Orientation:
- PMOrientation orientation;
- PMGetOrientation(d->format(), &orientation);
- ret = orientation == kPMPortrait ? QPrinter::Portrait : QPrinter::Landscape;
+ ret = d->m_pageLayout.orientation();
break;
case PPK_OutputFileName:
ret = d->outputFilename;
break;
- case PPK_PageRect: {
+ case PPK_PageRect:
// PageRect is returned in device pixels
- QRect r;
- PMRect macrect, macpaper;
- qreal hRatio = d->resolution.hRes / 72;
- qreal vRatio = d->resolution.vRes / 72;
- if (d->hasCustomPaperSize) {
- r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio));
- if (d->hasCustomPageMargins) {
- r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio),
- -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio));
- } else {
- QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList();
- r.adjust(qRound(margins.at(0).toDouble() * hRatio),
- qRound(margins.at(1).toDouble() * vRatio),
- -qRound(margins.at(2).toDouble() * hRatio),
- -qRound(margins.at(3).toDouble()) * vRatio);
- }
- } else if (PMGetAdjustedPageRect(d->format(), &macrect) == noErr
- && PMGetAdjustedPaperRect(d->format(), &macpaper) == noErr)
- {
- if (d->fullPage || d->hasCustomPageMargins) {
- r.setCoords(int(macpaper.left * hRatio), int(macpaper.top * vRatio),
- int(macpaper.right * hRatio), int(macpaper.bottom * vRatio));
- r.translate(-r.x(), -r.y());
- if (d->hasCustomPageMargins) {
- r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio),
- -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio));
- }
- } else {
- r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio),
- int(macrect.right * hRatio), int(macrect.bottom * vRatio));
- r.translate(int(-macpaper.left * hRatio), int(-macpaper.top * vRatio));
- }
- }
- ret = r;
- break; }
- case PPK_PaperSize:
- ret = d->paperSize();
+ ret = d->m_pageLayout.paintRectPixels(d->resolution.hRes);
+ break;
+ case PPK_PageSize:
+ ret = d->m_pageLayout.pageSize().id();
break;
case PPK_PaperName:
- ret = QCFString::toQString([d->printInfo localizedPaperName]);
- break;
- case PPK_PaperRect: {
- QRect r;
- PMRect macrect;
- qreal hRatio = d->resolution.hRes / 72;
- qreal vRatio = d->resolution.vRes / 72;
- if (d->hasCustomPaperSize) {
- r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio));
- } else if (PMGetAdjustedPaperRect(d->format(), &macrect) == noErr) {
- r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio),
- int(macrect.right * hRatio), int(macrect.bottom * vRatio));
- r.translate(-r.x(), -r.y());
- }
- ret = r;
- break; }
- case PPK_PrinterName: {
- PMPrinter printer;
- OSStatus status = PMSessionGetCurrentPrinter(d->session(), &printer);
- if (status != noErr)
- qWarning("QMacPrintEngine::printerName: Failed getting current PMPrinter: %ld", long(status));
- if (printer)
- ret = QCFString::toQString(PMPrinterGetID(printer));
- break; }
+ ret = d->m_pageLayout.pageSize().name();
+ break;
+ case PPK_WindowsPageSize:
+ ret = d->m_pageLayout.pageSize().windowsId();
+ break;
+ case PPK_PaperRect:
+ // PaperRect is returned in device pixels
+ ret = d->m_pageLayout.fullRectPixels(d->resolution.hRes);
+ break;
+ case PPK_PrinterName:
+ return d->m_printDevice->id();
+ break;
case PPK_Resolution: {
ret = d->resolution.hRes;
break;
}
- case PPK_SupportedResolutions:
- ret = d->supportedResolutions();
+ case PPK_SupportedResolutions: {
+ QList<QVariant> list;
+ foreach (int resolution, d->m_printDevice->supportedResolutions())
+ list << resolution;
+ ret = list;
break;
+ }
case PPK_CustomPaperSize:
- ret = d->customSize;
+ ret = d->m_pageLayout.fullRectPoints().size();
break;
- case PPK_PageMargins:
- {
- QList<QVariant> margins;
- if (d->hasCustomPageMargins) {
- margins << d->leftMargin << d->topMargin
- << d->rightMargin << d->bottomMargin;
- } else if (!d->hasCustomPaperSize) {
- PMPaperMargins paperMargins;
- PMPaper paper;
- PMGetPageFormatPaper(d->format(), &paper);
- PMPaperGetMargins(paper, &paperMargins);
- margins << paperMargins.left << paperMargins.top
- << paperMargins.right << paperMargins.bottom;
- } else {
- margins << 0 << 0 << 0 << 0;
- }
- ret = margins;
+ case PPK_PageMargins: {
+ QList<QVariant> list;
+ QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point);
+ list << margins.left() << margins.top() << margins.right() << margins.bottom();
+ ret = list;
+ break;
+ }
+ case PPK_QPageSize:
+ ret.setValue(d->m_pageLayout.pageSize());
+ break;
+ case PPK_QPageMargins: {
+ QPair<QMarginsF, QPageLayout::Unit> pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units());
+ ret.setValue(pair);
break;
}
+ case PPK_QPageLayout:
+ ret.setValue(d->m_pageLayout);
// No default so that compiler will complain if new keys added and not handled in this engine
}
return ret;
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
index e3a8520811..12a87b35e9 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
@@ -60,6 +60,9 @@
#include <QtPrintSupport/qprinter.h>
#include <QtPrintSupport/qprintengine.h>
#include <QtGui/private/qpainter_p.h>
+#include <QtGui/qpagelayout.h>
+
+#include "qcocoaprintdevice.h"
#include "qpaintengine_mac_p.h"
@@ -121,33 +124,24 @@ class QMacPrintEnginePrivate : public QPaintEnginePrivate
public:
QPrinter::PrinterMode mode;
QPrinter::PrinterState state;
- QPrinter::Orientation orient;
+ QSharedDataPointer<QCocoaPrintDevice> m_printDevice;
+ QPageLayout m_pageLayout;
NSPrintInfo *printInfo;
PMResolution resolution;
QString outputFilename;
QString m_creator;
- bool fullPage;
QPaintEngine *paintEngine;
- bool hasCustomPaperSize;
- QSizeF customSize;
- bool hasCustomPageMargins;
- qreal leftMargin;
- qreal topMargin;
- qreal rightMargin;
- qreal bottomMargin;
QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant> valueCache;
- PMPaper customPaper;
+
QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle),
- orient(QPrinter::Portrait), printInfo(0), paintEngine(0),
- hasCustomPaperSize(false), hasCustomPageMargins(false) {}
+ m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))),
+ printInfo(0), paintEngine(0) {}
~QMacPrintEnginePrivate();
+
void initialize();
void releaseSession();
bool newPage_helper();
- void setPaperSize(QPrinter::PaperSize ps);
- QPrinter::PaperSize paperSize() const;
- void setPaperName(const QString &name);
- QList<QVariant> supportedResolutions() const;
+ void setPageSize(const QPageSize &pageSize);
inline bool isPrintSessionInitialized() const
{
return printInfo != 0;
diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h
index 581157c2e1..7d38b08d84 100644
--- a/src/plugins/platforms/cocoa/qt_mac_p.h
+++ b/src/plugins/platforms/cocoa/qt_mac_p.h
@@ -194,8 +194,6 @@ extern QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt)
QFont qfontForThemeFont(ThemeFontID themeID);
-QColor qcolorForTheme(ThemeBrush brush);
-
QColor qcolorForThemeTextColor(ThemeTextColor themeColor);
struct QMacDndAnswerRecord {
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index e19a6be47b..d8f34fc3ed 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -77,6 +77,12 @@ enum {
D2DDebugDrawStaticTextItemTag,
D2DDebugDrawTextItemTag
};
+
+//Clipping flags
+enum {
+ UserClip = 0x1,
+ SimpleSystemClip = 0x2
+};
#define D2D_TAG(tag) d->dc()->SetTags(tag, tag)
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
@@ -286,7 +292,7 @@ class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate
public:
QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm)
: bitmap(bm)
- , clipPushed(false)
+ , clipFlags(0)
{
pen.reset();
brush.reset();
@@ -297,7 +303,7 @@ public:
QWindowsDirect2DBitmap *bitmap;
QPainterPath clipPath;
- bool clipPushed;
+ unsigned int clipFlags;
QPointF currentBrushOrigin;
@@ -381,14 +387,14 @@ public:
NULL,
D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND),
NULL);
- clipPushed = true;
+ clipFlags |= UserClip;
}
void popClip()
{
- if (clipPushed) {
+ if (clipFlags & UserClip) {
dc()->PopLayer();
- clipPushed = false;
+ clipFlags &= ~UserClip;
}
}
@@ -397,7 +403,7 @@ public:
Q_Q(const QWindowsDirect2DPaintEngine);
if (!q->state()->clipEnabled)
popClip();
- else if (!clipPushed)
+ else if (!(clipFlags & UserClip))
pushClip();
}
@@ -729,11 +735,29 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev)
d->bitmap->deviceContext()->begin();
d->dc()->SetTransform(D2D1::Matrix3x2F::Identity());
- QRect clip(0, 0, pdev->width(), pdev->height());
- if (!systemClip().isEmpty())
- clip &= systemClip().boundingRect();
+ if (systemClip().rectCount() > 1) {
+ QPainterPath p;
+ p.addRegion(systemClip());
- d->dc()->PushAxisAlignedClip(to_d2d_rect_f(clip), D2D1_ANTIALIAS_MODE_ALIASED);
+ ComPtr<ID2D1PathGeometry1> geometry = painterPathToPathGeometry(p);
+ if (!geometry)
+ return false;
+
+ d->dc()->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(),
+ geometry.Get(),
+ d->antialiasMode(),
+ D2D1::IdentityMatrix(),
+ 1.0,
+ NULL,
+ D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND),
+ NULL);
+ } else {
+ QRect clip(0, 0, pdev->width(), pdev->height());
+ if (!systemClip().isEmpty())
+ clip &= systemClip().boundingRect();
+ d->dc()->PushAxisAlignedClip(to_d2d_rect_f(clip), D2D1_ANTIALIAS_MODE_ALIASED);
+ d->clipFlags |= SimpleSystemClip;
+ }
D2D_TAG(D2DDebugDrawInitialStateTag);
@@ -746,7 +770,12 @@ bool QWindowsDirect2DPaintEngine::end()
// First pop any user-applied clipping
d->popClip();
// Now the system clip from begin() above
- d->dc()->PopAxisAlignedClip();
+ if (d->clipFlags & SimpleSystemClip) {
+ d->dc()->PopAxisAlignedClip();
+ d->clipFlags &= ~SimpleSystemClip;
+ } else {
+ d->dc()->PopLayer();
+ }
return d->bitmap->deviceContext()->end();
}
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 4fe2cae15e..13a0b46745 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -39,13 +39,16 @@
**
****************************************************************************/
-#include "qiosglobal.h"
#include "qiosinputcontext.h"
+
+#import <UIKit/UIGestureRecognizerSubclass.h>
+
+#include "qiosglobal.h"
#include "qioswindow.h"
#include "quiview.h"
#include <QGuiApplication>
-@interface QIOSKeyboardListener : NSObject {
+@interface QIOSKeyboardListener : UIGestureRecognizer {
@public
QIOSInputContext *m_context;
BOOL m_keyboardVisible;
@@ -63,7 +66,7 @@
- (id)initWithQIOSInputContext:(QIOSInputContext *)context
{
- self = [super init];
+ self = [super initWithTarget:self action:@selector(gestureTriggered)];
if (self) {
m_context = context;
m_keyboardVisible = NO;
@@ -82,6 +85,14 @@
}
}
Q_ASSERT(m_viewController);
+
+ // Attach 'hide keyboard' gesture to the window, but keep it disabled when the
+ // keyboard is not visible. Note that we never trigger the gesture the way it is intended
+ // since we don't want to cancel touch events and interrupt flicking etc. Instead we use
+ // the gesture framework more as an event filter and hide the keyboard silently.
+ self.enabled = NO;
+ self.delaysTouchesEnded = NO;
+ [m_viewController.view.window addGestureRecognizer:self];
}
[[NSNotificationCenter defaultCenter]
@@ -102,7 +113,9 @@
- (void) dealloc
{
+ [m_viewController.view.window removeGestureRecognizer:self];
[m_viewController release];
+
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:@"UIKeyboardWillShowNotification" object:nil];
@@ -131,16 +144,11 @@
- (void) keyboardDidChangeFrame:(NSNotification *)notification
{
+ Q_UNUSED(notification);
if (m_ignoreKeyboardChanges)
return;
- m_keyboardRect = [self getKeyboardRect:notification];
- m_context->emitKeyboardRectChanged();
- BOOL visible = m_keyboardRect.intersects(fromCGRect([UIScreen mainScreen].bounds));
- if (m_keyboardVisible != visible) {
- m_keyboardVisible = visible;
- m_context->emitInputPanelVisibleChanged();
- }
+ [self handleKeyboardRectChanged];
// If the keyboard was visible and docked from before, this is just a geometry
// change (normally caused by an orientation change). In that case, update scroll:
@@ -155,6 +163,7 @@
// Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked.
m_keyboardVisibleAndDocked = YES;
m_keyboardEndRect = [self getKeyboardRect:notification];
+ self.enabled = YES;
if (!m_duration) {
m_duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16);
@@ -169,9 +178,35 @@
// Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked.
m_keyboardVisibleAndDocked = NO;
m_keyboardEndRect = [self getKeyboardRect:notification];
+ self.enabled = NO;
m_context->scroll(0);
}
+- (void) handleKeyboardRectChanged
+{
+ QRectF rect = m_keyboardEndRect;
+ rect.moveTop(rect.y() + m_viewController.view.bounds.origin.y);
+ if (m_keyboardRect != rect) {
+ m_keyboardRect = rect;
+ m_context->emitKeyboardRectChanged();
+ }
+
+ BOOL visible = m_keyboardEndRect.intersects(fromCGRect([UIScreen mainScreen].bounds));
+ if (m_keyboardVisible != visible) {
+ m_keyboardVisible = visible;
+ m_context->emitInputPanelVisibleChanged();
+ }
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ QPointF p = fromCGPoint([[touches anyObject] locationInView:m_viewController.view]);
+ if (m_keyboardRect.contains(p))
+ m_context->hideInputPanel();
+
+ [super touchesMoved:touches withEvent:event];
+}
+
@end
QIOSInputContext::QIOSInputContext()
@@ -295,10 +330,15 @@ void QIOSInputContext::scroll(int y)
CGRect newBounds = view.bounds;
newBounds.origin.y = y;
+ QPointer<QIOSInputContext> self = this;
[UIView animateWithDuration:m_keyboardListener->m_duration delay:0
options:m_keyboardListener->m_curve
animations:^{ view.bounds = newBounds; }
- completion:0];
+ completion:^(BOOL){
+ if (self)
+ [m_keyboardListener handleKeyboardRectChanged];
+ }
+ ];
}
void QIOSInputContext::update(Qt::InputMethodQueries query)
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 96410952f9..5331d05ae9 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -120,7 +120,9 @@ static QString deviceModelIdentifier()
QIOSScreen::QIOSScreen(unsigned int screenIndex)
: QPlatformScreen()
- , m_uiScreen([[UIScreen screens] objectAtIndex:qMin(NSUInteger(screenIndex), [[UIScreen screens] count] - 1)])
+ , m_uiScreen([[UIScreen screens] count] > screenIndex
+ ? [[UIScreen screens] objectAtIndex:screenIndex]
+ : [UIScreen mainScreen])
, m_orientationListener(0)
{
QString deviceIdentifier = deviceModelIdentifier();
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index d0088d415a..28fb23d57b 100644
--- a/src/plugins/platforms/ios/quiview_textinput.mm
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -492,8 +492,17 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables);
if (!focusObject)
return;
- if ([text isEqualToString:@"\n"] && self.returnKeyType == UIReturnKeyDone)
- [self resignFirstResponder];
+ if ([text isEqualToString:@"\n"]) {
+ QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
+ QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier);
+ [self sendEventToFocusObject:press];
+ [self sendEventToFocusObject:release];
+
+ if (self.returnKeyType == UIReturnKeyDone)
+ [self resignFirstResponder];
+
+ return;
+ }
QInputMethodEvent e;
e.setCommitString(QString::fromNSString(text));
diff --git a/src/plugins/platforms/qnx/qblackberrytheme.cpp b/src/plugins/platforms/qnx/qblackberrytheme.cpp
index a0f334d909..46ab4d7033 100644
--- a/src/plugins/platforms/qnx/qblackberrytheme.cpp
+++ b/src/plugins/platforms/qnx/qblackberrytheme.cpp
@@ -60,9 +60,11 @@ QBlackberryTheme::QBlackberryTheme(const QQnxIntegration *integration) : m_integ
m_defaultPalette.setBrush(QPalette::Disabled, QPalette::WindowText, color);
m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Text, color);
- m_defaultPalette.setColor(QPalette::Window, QColor(18, 18, 18));
- m_defaultPalette.setColor(QPalette::Base, QColor(18, 18, 18));
+ color.setRgb(18, 18, 18);
+ m_defaultPalette.setColor(QPalette::Window, color);
+ m_defaultPalette.setColor(QPalette::Base, color);
m_defaultPalette.setColor(QPalette::AlternateBase, QColor(50, 50, 50));
+ m_defaultPalette.setColor(QPalette::Button, color);
m_defaultPalette.setBrush(QPalette::Highlight, QColor(0, 168, 223));
m_defaultPalette.setBrush(QPalette::HighlightedText, QColor(250, 250,250));
diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
index 3c08cc9f82..f1f9f5469c 100644
--- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
@@ -70,8 +70,7 @@ QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool nee
if (result != 0)
qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno);
- m_requestedBufferSize = screen()->rootWindow() == this ?
- screen()->geometry().size() : window->geometry().size();
+ m_requestedBufferSize = shouldMakeFullScreen() ? screen()->geometry().size() : window->geometry().size();
}
QQnxEglWindow::~QQnxEglWindow()
@@ -156,7 +155,7 @@ EGLSurface QQnxEglWindow::getSurface()
void QQnxEglWindow::setGeometry(const QRect &rect)
{
//If this is the root window, it has to be shown fullscreen
- const QRect &newGeometry = screen()->rootWindow() == this ? screen()->geometry() : rect;
+ const QRect &newGeometry = shouldMakeFullScreen() ? screen()->geometry() : rect;
//We need to request that the GL context updates
// the EGLsurface on which it is rendering.
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index 178ea121e6..5724fbd92a 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -457,7 +457,7 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0] - (touchArea[0]>>1),
w->geometry().top() + windowPos[1] - (touchArea[1]>>1),
- 0.0, 0.0);
+ (touchArea[0]>>1), (touchArea[1]>>1));
QWindow *parent = w->parent();
while (parent) {
m_touchPoints[touchId].area.translate(parent->geometry().topLeft());
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
index 156ba8a780..b66de3cac5 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
@@ -103,10 +103,10 @@ void QQnxScreenEventThread::run()
Q_SCREEN_CHECKERROR(screen_create_event(&event), "Failed to create screen event");
// block until screen event is available
- const int result = screen_get_event(m_screenContext, event, -1);
- Q_SCREEN_CRITICALERROR(result, "Failed to get screen event");
+ const int error = screen_get_event(m_screenContext, event, -1);
+ Q_SCREEN_CRITICALERROR(error, "Failed to get screen event");
// Only allow 50 consecutive errors before we exit the thread
- if (!result) {
+ if (error) {
errorCounter++;
if (errorCounter > 50)
m_quit = true;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 9ae2d01ab4..f11a009bca 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -242,19 +242,14 @@ QQnxWindow::~QQnxWindow()
void QQnxWindow::setGeometry(const QRect &rect)
{
QRect newGeometry = rect;
- if (screen()->rootWindow() == this) //If this is the root window, it has to be shown fullscreen
+ if (shouldMakeFullScreen())
newGeometry = screen()->geometry();
setGeometryHelper(newGeometry);
- // Send a geometry change event to Qt (triggers resizeEvent() in QWindow/QWidget).
-
- // Calling flushWindowSystemEvents() here would flush input events which
- // could result in re-entering QQnxWindow::setGeometry() again.
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(true);
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
- QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(false);
+ if (isExposed())
+ QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
}
void QQnxWindow::setGeometryHelper(const QRect &rect)
@@ -714,7 +709,7 @@ void QQnxWindow::initWindow()
if (window()->parent() && window()->parent()->handle())
setParent(window()->parent()->handle());
- if (screen()->rootWindow() == this) {
+ if (shouldMakeFullScreen()) {
setGeometryHelper(screen()->geometry());
QWindowSystemInterface::handleGeometryChange(window(), screen()->geometry());
} else {
@@ -817,4 +812,9 @@ void QQnxWindow::windowPosted()
qqnxLgmonFramePosted(m_cover); // for performance measurements
}
+bool QQnxWindow::shouldMakeFullScreen() const
+{
+ return ((screen()->rootWindow() == this) && (QQnxIntegration::options() & QQnxIntegration::FullScreenApplication));
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index e97e941a08..9a2006396f 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -112,6 +112,8 @@ public:
QByteArray groupName() const { return m_windowGroupName; }
void joinWindowGroup(const QByteArray &groupName);
+ bool shouldMakeFullScreen() const;
+
protected:
virtual int pixelFormat() const = 0;
virtual void resetBuffers() = 0;
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index b6ff3dc3ce..f70b5b4e2b 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -1195,7 +1195,7 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters,
const QRegExp filterSeparatorRE(QStringLiteral("[;\\s]+"));
const QString separator = QStringLiteral(";");
Q_ASSERT(filterSeparatorRE.isValid());
- // Split filter specification as 'Texts (*.txt[;] *.doc)'
+ // Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc'
// into description and filters specification as '*.txt;*.doc'
foreach (const QString &filterString, filters) {
const int openingParenPos = filterString.lastIndexOf(QLatin1Char('('));
@@ -1203,8 +1203,10 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters,
filterString.indexOf(QLatin1Char(')'), openingParenPos + 1) : -1;
FilterSpec filterSpec;
filterSpec.filter = closingParenPos == -1 ?
- QString(QLatin1Char('*')) :
+ filterString :
filterString.mid(openingParenPos + 1, closingParenPos - openingParenPos - 1).trimmed();
+ if (filterSpec.filter.isEmpty())
+ filterSpec.filter += QLatin1Char('*');
filterSpec.filter.replace(filterSeparatorRE, separator);
filterSpec.description = filterString;
if (hideFilterDetails && openingParenPos != -1) { // Do not show pattern in description
@@ -1559,7 +1561,7 @@ public:
QWindowsFileDialogHelper() {}
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return false; }
virtual bool defaultNameFilterDisables() const
- { return true; }
+ { return false; }
virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
virtual QUrl directory() const Q_DECL_OVERRIDE;
virtual void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index c45c34ae4d..e7e4028079 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -387,7 +387,12 @@ static int choosePixelFormat(HDC hdc,
iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB;
iAttributes[i++] = TRUE;
iAttributes[i++] = WGL_COLOR_BITS_ARB;
- iAttributes[i++] = 24;
+
+ iAttributes[i++] = (format.redBufferSize() > 0)
+ && (format.greenBufferSize() > 0)
+ && (format.blueBufferSize() > 0) ?
+ format.redBufferSize() + format.greenBufferSize() + format.blueBufferSize() :
+ 24;
switch (format.swapBehavior()) {
case QSurfaceFormat::SingleBuffer:
iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index e0e8753e14..de34663286 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -83,6 +83,7 @@
# include "qwindowssessionmanager.h"
#endif
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
#include <QtCore/private/qeventdispatcher_win_p.h>
#include <QtCore/QDebug>
@@ -158,7 +159,7 @@ struct QWindowsIntegrationPrivate
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
QOpenGLStaticContextPtr m_staticOpenGLContext;
#endif
- QWindowsInputContext m_inputContext;
+ QScopedPointer<QPlatformInputContext> m_inputContext;
#ifndef QT_NO_ACCESSIBILITY
QWindowsAccessibility m_accessibility;
#endif
@@ -224,6 +225,14 @@ QWindowsIntegration::~QWindowsIntegration()
{
}
+void QWindowsIntegration::initialize()
+{
+ if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create())
+ d->m_inputContext.reset(pluginContext);
+ else
+ d->m_inputContext.reset(new QWindowsInputContext);
+}
+
bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
@@ -441,7 +450,7 @@ QPlatformDrag *QWindowsIntegration::drag() const
QPlatformInputContext * QWindowsIntegration::inputContext() const
{
- return &d->m_inputContext;
+ return d->m_inputContext.data();
}
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 2202ebd39e..0f417c8239 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -76,6 +76,7 @@ public:
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
#endif
virtual QAbstractEventDispatcher *createEventDispatcher() const;
+ void initialize() Q_DECL_OVERRIDE;
#ifndef QT_NO_CLIPBOARD
virtual QPlatformClipboard *clipboard() const;
# ifndef QT_NO_DRAGANDDROP
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
index 10136dbead..9b623048af 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
@@ -207,14 +207,24 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
, m_fbo(0)
, m_texture(0)
, m_screen(static_cast<QWinRTScreen*>(window->screen()->handle()))
+ , m_initialized(false)
{
window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap
+}
- m_context->setFormat(window->requestedFormat());
- m_context->setScreen(window->screen());
- m_context->create();
+bool QWinRTBackingStore::initialize()
+{
+ if (m_initialized)
+ return true;
+
+ m_context->setFormat(window()->requestedFormat());
+ m_context->setScreen(window()->screen());
+ if (!m_context->create())
+ return false;
+
+ if (!m_context->makeCurrent(window()))
+ return false;
- m_context->makeCurrent(window);
glGenFramebuffers(1, &m_fbo);
glGenRenderbuffers(1, &m_rbo);
glGenTextures(1, &m_texture);
@@ -258,11 +268,14 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size());
#endif
m_context->doneCurrent();
- resize(window->size(), QRegion());
+ m_initialized = true;
+ return true;
}
QWinRTBackingStore::~QWinRTBackingStore()
{
+ if (!m_initialized)
+ return;
glDeleteBuffers(1, &m_fbo);
glDeleteRenderbuffers(1, &m_rbo);
glDeleteTextures(1, &m_texture);
@@ -277,6 +290,8 @@ QPaintDevice *QWinRTBackingStore::paintDevice()
void QWinRTBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(offset)
+ if (m_size.isEmpty())
+ return;
const QImage *image = static_cast<QImage *>(m_paintDevice.data());
@@ -334,10 +349,16 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion &region, const QPo
void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents)
+ if (!initialize())
+ return;
+
if (m_size == size)
return;
m_size = size;
+ if (m_size.isEmpty())
+ return;
+
m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied));
m_context->makeCurrent(window());
@@ -360,6 +381,7 @@ void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents
void QWinRTBackingStore::beginPaint(const QRegion &region)
{
Q_UNUSED(region)
+ resize(window()->size(), QRegion());
}
void QWinRTBackingStore::endPaint()
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h
index 8be549b441..726f7c838f 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.h
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h
@@ -62,6 +62,8 @@ public:
void resize(const QSize &size, const QRegion &staticContents);
private:
+ bool initialize();
+ bool m_initialized;
QSize m_size;
QScopedPointer<QPaintDevice> m_paintDevice;
QScopedPointer<QOpenGLContext> m_context;
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
index c7fa339fad..3da87de708 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
@@ -44,6 +44,14 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QFile>
+#ifndef Q_OS_WINPHONE
+#include <QtCore/QUuid>
+#include <QtGui/private/qfontengine_ft_p.h>
+#include <dwrite_1.h>
+#include <wrl.h>
+using namespace Microsoft::WRL;
+#endif // !Q_OS_WINPHONE
+
QT_BEGIN_NAMESPACE
QString QWinRTFontDatabase::fontDir() const
@@ -54,11 +62,315 @@ QString QWinRTFontDatabase::fontDir() const
const QString applicationDirPath = QCoreApplication::applicationDirPath();
fontDirectory = applicationDirPath + QLatin1String("/fonts");
if (!QFile::exists(fontDirectory)) {
- qWarning("No fonts directory found in application package.");
+#ifndef Q_OS_WINPHONE
+ if (m_fonts.isEmpty())
+#endif
+ qWarning("No fonts directory found in application package.");
fontDirectory = applicationDirPath;
}
}
return fontDirectory;
}
+#ifndef Q_OS_WINPHONE
+
+QWinRTFontDatabase::~QWinRTFontDatabase()
+{
+ foreach (IDWriteFontFile *fontFile, m_fonts.keys())
+ fontFile->Release();
+}
+
+QFont QWinRTFontDatabase::defaultFont() const
+{
+ return QFont(QStringLiteral("Segoe UI"));
+}
+
+void QWinRTFontDatabase::populateFontDatabase()
+{
+ ComPtr<IDWriteFactory1> factory;
+ HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory);
+ if (FAILED(hr)) {
+ qWarning("Failed to create DirectWrite factory: %s", qPrintable(qt_error_string(hr)));
+ QBasicFontDatabase::populateFontDatabase();
+ return;
+ }
+
+ ComPtr<IDWriteFontCollection> fontCollection;
+ hr = factory->GetSystemFontCollection(&fontCollection);
+ if (FAILED(hr)) {
+ qWarning("Failed to open system font collection: %s", qPrintable(qt_error_string(hr)));
+ QBasicFontDatabase::populateFontDatabase();
+ return;
+ }
+
+ int fontFamilyCount = fontCollection->GetFontFamilyCount();
+ for (int i = 0; i < fontFamilyCount; ++i) {
+ ComPtr<IDWriteFontFamily> fontFamily;
+ hr = fontCollection->GetFontFamily(i, &fontFamily);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font family: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+
+ ComPtr<IDWriteLocalizedStrings> names;
+ hr = fontFamily->GetFamilyNames(&names);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font family names: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ quint32 familyNameLength;
+ hr = names->GetStringLength(0, &familyNameLength);
+ if (FAILED(hr)) {
+ qWarning("Unable to get family name length: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ QVector<wchar_t> familyBuffer(familyNameLength + 1);
+ hr = names->GetString(0, familyBuffer.data(), familyBuffer.size());
+ if (FAILED(hr)) {
+ qWarning("Unable to create font family name: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ QString familyName = QString::fromWCharArray(familyBuffer.data(), familyNameLength);
+
+ int fontCount = fontFamily->GetFontCount();
+ for (int j = 0; j < fontCount; ++j) {
+ ComPtr<IDWriteFont> font;
+ hr = fontFamily->GetFont(j, &font);
+ if (FAILED(hr)) {
+ qWarning("Unable to get base font: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+
+ ComPtr<IDWriteFontFace> baseFontFace;
+ hr = font->CreateFontFace(&baseFontFace);
+ if (FAILED(hr)) {
+ qWarning("Unable to create base font face: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ ComPtr<IDWriteFontFace1> fontFace;
+ hr = baseFontFace.As(&fontFace);
+ if (FAILED(hr)) {
+ qWarning("Unable to create font face: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+
+ // Only try to load true-type fonts
+ DWRITE_FONT_FACE_TYPE type = fontFace->GetType();
+ if (!(type == DWRITE_FONT_FACE_TYPE_TRUETYPE
+ || type == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)) {
+ continue;
+ }
+
+ // We can't deal with multi-file fonts
+ quint32 fileCount;
+ hr = fontFace->GetFiles(&fileCount, NULL);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ if (fileCount != 1) // Should not happen as we only look at TT fonts
+ continue;
+
+ ComPtr<IDWriteLocalizedStrings> informationalStrings;
+ BOOL exists;
+ hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_MANUFACTURER,
+ &informationalStrings, &exists);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font foundry: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ QString foundryName;
+ if (exists) {
+ quint32 length;
+ hr = informationalStrings->GetStringLength(0, &length);
+ if (FAILED(hr))
+ qWarning("Unable to get foundry name length: %s", qPrintable(qt_error_string(hr)));
+ if (SUCCEEDED(hr)) {
+ QVector<wchar_t> buffer(length + 1);
+ hr = informationalStrings->GetString(0, buffer.data(), buffer.size());
+ if (FAILED(hr))
+ qWarning("Unable to get foundry name: %s", qPrintable(qt_error_string(hr)));
+ if (SUCCEEDED(hr))
+ foundryName = QString::fromWCharArray(buffer.data(), length);
+ }
+ }
+
+ QFont::Weight weight;
+ switch (font->GetWeight()) {
+ case DWRITE_FONT_WEIGHT_THIN:
+ case DWRITE_FONT_WEIGHT_EXTRA_LIGHT:
+ case DWRITE_FONT_WEIGHT_LIGHT:
+ case DWRITE_FONT_WEIGHT_SEMI_LIGHT:
+ weight = QFont::Light;
+ break;
+ default:
+ case DWRITE_FONT_WEIGHT_NORMAL:
+ case DWRITE_FONT_WEIGHT_MEDIUM:
+ weight = QFont::Normal;
+ break;
+ case DWRITE_FONT_WEIGHT_DEMI_BOLD:
+ weight = QFont::DemiBold;
+ break;
+ case DWRITE_FONT_WEIGHT_BOLD:
+ case DWRITE_FONT_WEIGHT_EXTRA_BOLD:
+ weight = QFont::Bold;
+ break;
+ case DWRITE_FONT_WEIGHT_BLACK:
+ case DWRITE_FONT_WEIGHT_EXTRA_BLACK:
+ weight = QFont::Black;
+ break;
+ }
+
+ QFont::Style style;
+ switch (font->GetStyle()) {
+ default:
+ case DWRITE_FONT_STYLE_NORMAL:
+ style = QFont::StyleNormal;
+ break;
+ case DWRITE_FONT_STYLE_OBLIQUE:
+ style = QFont::StyleOblique;
+ break;
+ case DWRITE_FONT_STYLE_ITALIC:
+ style = QFont::StyleItalic;
+ break;
+ }
+
+ QFont::Stretch stretch;
+ switch (font->GetStretch()) {
+ default:
+ case DWRITE_FONT_STRETCH_UNDEFINED:
+ case DWRITE_FONT_STRETCH_NORMAL:
+ stretch = QFont::Unstretched;
+ break;
+ case DWRITE_FONT_STRETCH_ULTRA_CONDENSED:
+ stretch = QFont::UltraCondensed;
+ break;
+ case DWRITE_FONT_STRETCH_EXTRA_CONDENSED:
+ stretch = QFont::ExtraCondensed;
+ break;
+ case DWRITE_FONT_STRETCH_CONDENSED:
+ stretch = QFont::Condensed;
+ break;
+ case DWRITE_FONT_STRETCH_SEMI_CONDENSED:
+ stretch = QFont::SemiCondensed;
+ break;
+ case DWRITE_FONT_STRETCH_SEMI_EXPANDED:
+ stretch = QFont::SemiExpanded;
+ break;
+ case DWRITE_FONT_STRETCH_EXPANDED:
+ stretch = QFont::Expanded;
+ break;
+ case DWRITE_FONT_STRETCH_EXTRA_EXPANDED:
+ stretch = QFont::ExtraExpanded;
+ break;
+ case DWRITE_FONT_STRETCH_ULTRA_EXPANDED:
+ stretch = QFont::UltraExpanded;
+ break;
+ }
+
+ const bool fixedPitch = fontFace->IsMonospacedFont();
+
+ quint32 unicodeRange[4];
+ quint32 actualRangeCount;
+ hr = fontFace->GetUnicodeRanges(
+ 2, reinterpret_cast<DWRITE_UNICODE_RANGE *>(unicodeRange), &actualRangeCount);
+ if (FAILED(hr) && hr != E_NOT_SUFFICIENT_BUFFER) { // Ignore insufficient buffer; we only need 4 indices
+ qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+ quint32 codePageRange[2] = { 0, 0 };
+ QSupportedWritingSystems writingSystems =
+ QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+
+ IDWriteFontFile *fontFile;
+ hr = fontFace->GetFiles(&fileCount, &fontFile);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file: %s", qPrintable(qt_error_string(hr)));
+ continue;
+ }
+
+ FontDescription description = { fontFace->GetIndex(), QUuid::createUuid().toByteArray() };
+ m_fonts.insert(fontFile, description);
+ registerFont(familyName, QString(), foundryName, weight, style, stretch,
+ true, true, 0, fixedPitch, writingSystems, fontFile);
+ }
+ }
+
+ QBasicFontDatabase::populateFontDatabase();
+}
+
+QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
+{
+ IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle);
+ if (!m_fonts.contains(fontFile))
+ return QBasicFontDatabase::fontEngine(fontDef, handle);
+
+ const void *referenceKey;
+ quint32 referenceKeySize;
+ HRESULT hr = fontFile->GetReferenceKey(&referenceKey, &referenceKeySize);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file reference key: %s", qPrintable(qt_error_string(hr)));
+ return 0;
+ }
+
+ ComPtr<IDWriteFontFileLoader> loader;
+ hr = fontFile->GetLoader(&loader);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file loader: %s", qPrintable(qt_error_string(hr)));
+ return 0;
+ }
+
+ ComPtr<IDWriteFontFileStream> stream;
+ hr =loader->CreateStreamFromKey(referenceKey, referenceKeySize, &stream);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file stream: %s", qPrintable(qt_error_string(hr)));
+ return 0;
+ }
+
+ quint64 fileSize;
+ hr = stream->GetFileSize(&fileSize);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file size: %s", qPrintable(qt_error_string(hr)));
+ return 0;
+ }
+
+ const void *data;
+ void *context;
+ hr = stream->ReadFileFragment(&data, 0, fileSize, &context);
+ if (FAILED(hr)) {
+ qWarning("Unable to get font file data: %s", qPrintable(qt_error_string(hr)));
+ return 0;
+ }
+ const QByteArray fontData((const char *)data, fileSize);
+ stream->ReleaseFileFragment(context);
+
+ QFontEngine::FaceId faceId;
+ const FontDescription description = m_fonts.value(fontFile);
+ faceId.uuid = description.uuid;
+ faceId.index = description.index;
+ const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
+ QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono;
+ QFontEngineFT *engine = new QFontEngineFT(fontDef);
+ if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) {
+ delete engine;
+ return 0;
+ }
+
+ return engine;
+}
+
+void QWinRTFontDatabase::releaseHandle(void *handle)
+{
+ IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle);
+ if (m_fonts.contains(fontFile)) {
+ m_fonts.remove(fontFile);
+ fontFile->Release();
+ return;
+ }
+
+ QBasicFontDatabase::releaseHandle(handle);
+}
+
+#endif // !Q_OS_WINPHONE
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
index 49e32470c2..6f194a10cc 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
@@ -46,10 +46,29 @@
QT_BEGIN_NAMESPACE
+#ifndef Q_OS_WINPHONE
+struct IDWriteFontFile;
+
+struct FontDescription
+{
+ quint32 index;
+ QByteArray uuid;
+};
+#endif
+
class QWinRTFontDatabase : public QBasicFontDatabase
{
public:
QString fontDir() const;
+#ifndef Q_OS_WINPHONE
+ ~QWinRTFontDatabase();
+ QFont defaultFont() const Q_DECL_OVERRIDE;
+ void populateFontDatabase() Q_DECL_OVERRIDE;
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
+ void releaseHandle(void *handle) Q_DECL_OVERRIDE;
+private:
+ QHash<IDWriteFontFile *, FontDescription> m_fonts;
+#endif // !Q_OS_WINPHONE
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp
index 8f0a1d55bb..73c090351b 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.cpp
+++ b/src/plugins/platforms/winrt/qwinrtservices.cpp
@@ -106,8 +106,7 @@ bool QWinRTServices::openDocument(const QUrl &url)
if (!(m_fileFactory && m_launcher))
return QPlatformServices::openDocument(url);
- QString pathString = QDir::toNativeSeparators(
- QDir::cleanPath(qApp->applicationDirPath().append(url.toString(QUrl::RemoveScheme))));
+ const QString pathString = QDir::toNativeSeparators(url.toLocalFile());
HSTRING_HEADER header; HSTRING path;
WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path);
IAsyncOperation<StorageFile*> *fileOp;
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 6e3cfb1d20..306bbc8174 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -11,6 +11,11 @@ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES
LIBS += $$QMAKE_LIBS_CORE
+!winphone {
+ LIBS += -ldwrite
+ INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include
+}
+
SOURCES = \
main.cpp \
qwinrtbackingstore.cpp \
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index eaa4d05311..c183deb3b8 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -130,7 +130,7 @@ static void updateFormatFromContext(QSurfaceFormat &format)
}
format.setProfile(QSurfaceFormat::NoProfile);
- format.setOption(QSurfaceFormat::FormatOptions());
+ format.setOptions(QSurfaceFormat::FormatOptions());
if (format.renderableType() == QSurfaceFormat::OpenGL) {
if (format.version() < qMakePair(3, 0)) {
@@ -211,7 +211,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
// Don't bother with versions below ES 2.0
glVersions << 30 << 20;
// ES does not support any format option
- m_format.setOption(QSurfaceFormat::FormatOptions());
+ m_format.setOptions(QSurfaceFormat::FormatOptions());
}
Q_ASSERT(glVersions.count() > 0);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 030090d98d..a68ae8cf71 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -144,23 +144,23 @@ void QXcbConnection::updateScreens()
xcb_generic_error_t *error = NULL;
xcb_randr_get_output_primary_cookie_t primaryCookie =
xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
- xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
- xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root);
+ xcb_randr_get_screen_resources_cookie_t resourcesCookie =
+ xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root);
xcb_randr_get_output_primary_reply_t *primary =
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error);
if (!primary || error) {
qWarning("QXcbConnection: Failed to get the primary output of the screen");
free(error);
} else {
- xcb_randr_get_screen_resources_current_reply_t *resources =
- xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error);
+ xcb_randr_get_screen_resources_reply_t *resources =
+ xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error);
if (!resources || error) {
qWarning("QXcbConnection: Failed to get the screen resources");
free(error);
} else {
xcb_timestamp_t timestamp = resources->config_timestamp;
- outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources);
- xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(resources);
+ outputCount = xcb_randr_get_screen_resources_outputs_length(resources);
+ xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources);
for (int i = 0; i < outputCount; i++) {
xcb_randr_get_output_info_reply_t *output =
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 6042ec0f87..bcadcd1f02 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -872,7 +872,6 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event)
}
QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction);
- updateAction(Qt::IgnoreAction);
xdnd_dragsource = 0;
xdnd_types.clear();
@@ -1045,7 +1044,8 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
- showing dialog box on drop event where user's response takes more time than XdndDropTransactionTimeout (QTBUG-14493)
- dnd takes unusually long time to process data
*/
- t.drag->deleteLater();
+ if (t.drag)
+ t.drag->deleteLater();
transactions.removeAt(i--);
} else {
stopTimer = false;
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index 537898db48..7b0d337e7c 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -156,7 +156,7 @@ private:
xcb_window_t proxy_target;
QWindow *targetWindow;
// QWidget *embedding_widget;
- QDrag *drag;
+ QPointer<QDrag> drag;
QTime time;
};
QVector<Transaction> transactions;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index aaa2e81c40..0bab341914 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -396,7 +396,6 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
case QPlatformIntegration::CursorFlashTime:
case QPlatformIntegration::KeyboardInputInterval:
case QPlatformIntegration::MouseDoubleClickInterval:
- case QPlatformIntegration::StartDragDistance:
case QPlatformIntegration::StartDragTime:
case QPlatformIntegration::KeyboardAutoRepeatRate:
case QPlatformIntegration::PasswordMaskDelay:
@@ -406,6 +405,20 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
case QPlatformIntegration::PasswordMaskCharacter:
// TODO using various xcb, gnome or KDE settings
break; // Not implemented, use defaults
+ case QPlatformIntegration::StartDragDistance: {
+ // The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
+ // on a high-resolution screen it makes sense to increase it.
+ const QList<QXcbScreen *> &screens = defaultConnection()->screens();
+ qreal dpi = 100.0;
+ if (screens.length() > 0) {
+ const QXcbScreen *screen = screens.at(defaultConnection()->primaryScreen());
+ if (screen->logicalDpi().first > dpi)
+ dpi = screen->logicalDpi().first;
+ if (screen->logicalDpi().second > dpi)
+ dpi = screen->logicalDpi().second;
+ }
+ return 10.0 * dpi / 100.0;
+ }
case QPlatformIntegration::ShowIsFullScreen:
// X11 always has support for windows, but the
// window manager could prevent it (e.g. matchbox)
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 966090dbd5..0a52640c9a 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -53,10 +53,6 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformcursor.h>
-#ifdef XKBCOMMON_0_2_0
-#include <xkbcommon_workaround.h>
-#endif
-
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
@@ -1398,23 +1394,7 @@ QString QXcbKeyboard::keysymToUnicode(xcb_keysym_t sym) const
QByteArray chars;
int bytes;
chars.resize(7);
-
-#ifdef XKBCOMMON_0_2_0
- if (needWorkaround(sym)) {
- quint32 codepoint;
- if (sym == XKB_KEY_KP_Space)
- codepoint = XKB_KEY_space & 0x7f;
- else
- codepoint = sym & 0x7f;
-
- bytes = utf32_to_utf8(codepoint, chars.data());
- } else {
- bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
- }
-#else
bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
-#endif
-
if (bytes == -1)
qWarning("QXcbKeyboard::handleKeyEvent - buffer too small");
chars.resize(bytes-1);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index b1ef3182ba..9f19841437 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -371,7 +371,6 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
}
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry());
- QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
QDpi ldpi = logicalDpi();
@@ -409,6 +408,8 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
m_availableGeometry = m_geometry & virtualAvailableGeometry;
}
free(workArea);
+
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), m_availableGeometry);
}
void QXcbScreen::updateRefreshRate()
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index aabcb84a08..d890398416 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1823,23 +1823,21 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
- const xcb_atom_t netWmStateAtom = atom(QXcbAtom::_NET_WM_STATE);
- const xcb_atom_t wmStateAtom = atom(QXcbAtom::WM_STATE);
- if (event->atom == netWmStateAtom || event->atom == wmStateAtom) {
+ if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted)
return;
Qt::WindowState newState = Qt::WindowNoState;
- if (event->atom == wmStateAtom) { // WM_STATE: Quick check for 'Minimize'.
+ if (event->atom == atom(QXcbAtom::_NET_WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
const xcb_get_property_cookie_t get_cookie =
- xcb_get_property(xcb_connection(), 0, m_window, wmStateAtom,
+ xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
XCB_ATOM_ANY, 0, 1024);
xcb_get_property_reply_t *reply =
xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
- if (reply && reply->format == 32 && reply->type == wmStateAtom) {
+ if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::_NET_WM_STATE)) {
const quint32 *data = (const quint32 *)xcb_get_property_value(reply);
if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0])
newState = Qt::WindowMinimized;
@@ -1860,6 +1858,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
m_windowState = newState;
}
return;
+ } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && event->window == m_screen->root()) {
+ m_screen->updateGeometry(event->time);
}
}
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index bfbec91e3c..e19bb921e1 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -131,12 +131,9 @@ contains(QT_CONFIG, xcb-qt) {
# libxkbcommon
contains(QT_CONFIG, xkbcommon-qt): {
+ QT_CONFIG += use-xkbcommon-x11support
include(../../../3rdparty/xkbcommon.pri)
} else {
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
- equals(QMAKE_VERSION_XKBCOMMON, "0.2.0") {
- DEFINES += XKBCOMMON_0_2_0
- INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/
- }
}