diff options
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r-- | src/plugins/platforms/cocoa/cocoa.pro | 12 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 8 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 18 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm | 16 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoahelpers.mm | 41 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.mm | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoakeymapper.h | 111 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoakeymapper.mm | 468 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasystemsettings.mm | 32 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 13 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 35 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsviewaccessibility.mm | 2 |
16 files changed, 718 insertions, 61 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 78fcf20afc..83e2a88e6a 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -1,6 +1,7 @@ TARGET = qcocoa PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QCocoaIntegrationPlugin load(qt_plugin) OBJECTIVE_SOURCES += main.mm \ @@ -38,6 +39,7 @@ OBJECTIVE_SOURCES += main.mm \ qcocoaservices.mm \ qcocoasystemtrayicon.mm \ qcocoaintrospection.mm \ + qcocoakeymapper.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -72,6 +74,7 @@ HEADERS += qcocoaintegration.h \ qcocoaservices.h \ qcocoasystemtrayicon.h \ qcocoaintrospection.h \ + qcocoakeymapper.h \ RESOURCES += qcocoaresources.qrc @@ -79,7 +82,7 @@ LIBS += -framework Cocoa -framework IOKit QT += core-private gui-private platformsupport-private -!contains(QT_CONFIG, no-widgets) { +qtHaveModule(widgets) { OBJECTIVE_SOURCES += \ qpaintengine_mac.mm \ qprintengine_mac.mm \ @@ -95,13 +98,6 @@ QT += core-private gui-private platformsupport-private OTHER_FILES += cocoa.json -# Build the release libqcocoa.dylib only, skip the debug version. -# The Qt plugin loader will dlopen both if found, causing duplicate -# Objective-c class definitions for the classes defined in the plugin. -contains(QT_CONFIG,release):CONFIG -= debug -contains(QT_CONFIG,debug_and_release):CONFIG -= debug_and_release -contains(QT_CONFIG,build_all):CONFIG -= build_all - # Acccessibility debug support # DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR # include ($$PWD/../../../../util/accessibilityinspector/accessibilityinspector.pri) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index df6b64443d..d5841c1983 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -122,7 +122,7 @@ static QAccessibleInterface *acast(void *ptr) [attributes addObject : NSAccessibilityValueAttribute]; } - return attributes; + return [attributes autorelease]; } - (id)accessibilityAttributeValue:(NSString *)attribute { @@ -139,7 +139,7 @@ static QAccessibleInterface *acast(void *ptr) [kids addObject:[QCocoaAccessibleElement elementWithInterface:(void*)childInterface parent:self]]; } - return NSAccessibilityUnignoredChildren(kids); + return kids; } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { // Just check if the app thinks we're focused. id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute]; @@ -239,6 +239,10 @@ static QAccessibleInterface *acast(void *ptr) if (!accessibleInterface) return NSAccessibilityUnignoredAncestor(self); + + if (!acast(accessibleInterface)->isValid()) + return NSAccessibilityUnignoredAncestor(self); + QAccessibleInterface *childInterface = acast(accessibleInterface)->childAt(point.x, qt_mac_flipYCoordinate(point.y)); // No child found, meaning we hit this element. diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 7aa365df67..80c9e227d2 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -510,14 +510,16 @@ static bool IsMouseOrKeyEvent( NSEvent* event ) static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRunLoopMode) { - // If no event exist in the cocoa event que, wait - // (and free up cpu time) until at least one event occur. - // This implementation is a bit on the edge, but seems to - // work fine: - [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:runLoopMode - dequeue:NO]; + // If no event exist in the cocoa event que, wait (and free up cpu time) until + // at least one event occur. Setting 'dequeuing' to 'no' in the following call + // causes it to hang under certain circumstances (QTBUG-28283), so we tell it + // to dequeue instead, just to repost the event again: + NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantFuture] + inMode:runLoopMode + dequeue:YES]; + if (event) + [NSApp postEvent:event atStart:YES]; } bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index f9122f56d1..5747cc01e9 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -223,7 +223,7 @@ static QString strippedText(QString s) - (void)showModelessPanel { if (mOpenPanel){ - QFileInfo info(*mCurrentSelection); + QFileInfo info(!mCurrentSelection->isEmpty() ? *mCurrentSelection : QT_PREPEND_NAMESPACE(QCFString::toQString)(mCurrentDir)); NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath()); bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:nil shouldShowFilename:filepath]; @@ -241,7 +241,7 @@ static QString strippedText(QString s) - (BOOL)runApplicationModalPanel { - QFileInfo info(*mCurrentSelection); + QFileInfo info(!mCurrentSelection->isEmpty() ? *mCurrentSelection : QT_PREPEND_NAMESPACE(QCFString::toQString)(mCurrentDir)); NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath()); bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:nil shouldShowFilename:filepath]; @@ -266,7 +266,7 @@ static QString strippedText(QString s) - (void)showWindowModalSheet:(QWindow *)parent { - QFileInfo info(*mCurrentSelection); + QFileInfo info(!mCurrentSelection->isEmpty() ? *mCurrentSelection : QT_PREPEND_NAMESPACE(QCFString::toQString)(mCurrentDir)); NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath()); bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:nil shouldShowFilename:filepath]; diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 5ccd019a9b..ff3ba63931 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -92,20 +92,16 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) QFont newFont; if (cocoaFont) { int pSize = qRound([cocoaFont pointSize]); - QString family(QCFString::toQString([cocoaFont familyName])); - QString typeface(QCFString::toQString([cocoaFont fontName])); - - int hyphenPos = typeface.indexOf(QLatin1Char('-')); - if (hyphenPos != -1) { - typeface.remove(0, hyphenPos + 1); - } else { - typeface = QLatin1String("Normal"); - } + CTFontDescriptorRef font = CTFontCopyFontDescriptor((CTFontRef)cocoaFont); + // QCoreTextFontDatabase::populateFontDatabase() is using localized names + QString family = QCFString::toQString((CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL)); + QString style = QCFString::toQString((CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL)); - newFont = QFontDatabase().font(family, typeface, pSize); + newFont = QFontDatabase().font(family, style, pSize); newFont.setUnderline(resolveFont.underline()); newFont.setStrikeOut(resolveFont.strikeOut()); + CFRelease(font); } return newFont; } diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 9783899742..31a56b9d66 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -138,6 +138,8 @@ NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image) NSImage *qt_mac_create_nsimage(const QPixmap &pm) { + if (pm.isNull()) + return 0; QImage image = pm.toImage(); CGImageRef cgImage = qt_mac_image_to_cgimage(image); NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); @@ -784,14 +786,49 @@ CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy) NULL, false); } else { - CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB(); + // Try get a device color space. Using the device color space means + // that the CGImage can be drawn to screen without per-pixel color + // space conversion, at the cost of less color accuracy. + CGColorSpaceRef cgColourSpaceRef = 0; + CMProfileRef sysProfile; + if (CMGetSystemProfile(&sysProfile) == noErr) + { + cgColourSpaceRef = CGColorSpaceCreateWithPlatformColorSpace(sysProfile); + CMCloseProfile(sysProfile); + } + + // Fall back to Generic RGB if a profile was not found. + if (!cgColourSpaceRef) + cgColourSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + + // Create a CGBitmapInfo contiaining the image format. + // Support the 8-bit per component (A)RGB formats. + CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little; + switch (qImage.format()) { + case QImage::Format_ARGB32_Premultiplied : + bitmapInfo |= kCGImageAlphaPremultipliedFirst; + break; + case QImage::Format_ARGB32 : + bitmapInfo |= kCGImageAlphaFirst; + break; + case QImage::Format_RGB32 : + bitmapInfo |= kCGImageAlphaNoneSkipFirst; + break; + case QImage::Format_RGB888 : + bitmapInfo |= kCGImageAlphaNone; + break; + default: + qWarning() << "qt_mac_toCGImage: Unsupported image format" << qImage.format(); + break; + } + cgImage = CGImageCreate(width, height, colorBufferSize, bitDepth, bytesPrLine, cgColourSpaceRef, - kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, + bitmapInfo, cgDataProviderRef, NULL, false, diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 1bb46ea3ea..e455a3552e 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -49,6 +49,7 @@ #include "qcocoaclipboard.h" #include "qcocoadrag.h" #include "qcocoaservices.h" +#include "qcocoakeymapper.h" #include <QtCore/QScopedPointer> #include <qpa/qplatformintegration.h> @@ -121,6 +122,8 @@ public: QPlatformServices *services() const; QVariant styleHint(StyleHint hint) const; + QList<int> possibleKeys(const QKeyEvent *event) const; + void updateScreens(); private: @@ -138,6 +141,7 @@ private: QScopedPointer<QCocoaDrag> mCocoaDrag; QScopedPointer<QPlatformNativeInterface> mNativeInterface; QScopedPointer<QCocoaServices> mServices; + QScopedPointer<QCocoaKeyMapper> mKeyboardMapper; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 393c471c25..e096096e99 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -199,6 +199,7 @@ QCocoaIntegration::QCocoaIntegration() , mCocoaDrag(new QCocoaDrag) , mNativeInterface(new QCocoaNativeInterface) , mServices(new QCocoaServices) + , mKeyboardMapper(new QCocoaKeyMapper) { initResources(); QCocoaAutoReleasePool pool; @@ -414,4 +415,9 @@ QVariant QCocoaIntegration::styleHint(StyleHint hint) const return QPlatformIntegration::styleHint(hint); } +QList<int> QCocoaIntegration::possibleKeys(const QKeyEvent *event) const +{ + return mKeyboardMapper->possibleKeys(event); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.h b/src/plugins/platforms/cocoa/qcocoakeymapper.h new file mode 100644 index 0000000000..693539dd4e --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** 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 QCOCOAKEYMAPPER_H +#define QCOCOAKEYMAPPER_H + +#include <qcocoahelpers.h> + +#include <Cocoa/Cocoa.h> +#include <Carbon/Carbon.h> + +#include <QtCore/QList> +#include <QtGui/QKeyEvent> + +QT_BEGIN_NAMESPACE + +/* + \internal + A Mac KeyboardLayoutItem has 8 possible states: + 1. Unmodified + 2. Shift + 3. Control + 4. Control + Shift + 5. Alt + 6. Alt + Shift + 7. Alt + Control + 8. Alt + Control + Shift + 9. Meta + 10. Meta + Shift + 11. Meta + Control + 12. Meta + Control + Shift + 13. Meta + Alt + 14. Meta + Alt + Shift + 15. Meta + Alt + Control + 16. Meta + Alt + Control + Shift +*/ +struct KeyboardLayoutItem { + bool dirty; + quint32 qtKey[16]; // Can by any Qt::Key_<foo>, or unicode character +}; + + +class QCocoaKeyMapper +{ +public: + QCocoaKeyMapper(); + ~QCocoaKeyMapper(); + QList<int> possibleKeys(const QKeyEvent *event) const; + bool updateKeyboard(); + void deleteLayouts(); + void updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey); + void clearMappings(); + +private: + QCFType<TISInputSourceRef> currentInputSource; + + QLocale keyboardInputLocale; + Qt::LayoutDirection keyboardInputDirection; + enum { NullMode, UnicodeMode, OtherMode } keyboard_mode; + union { + const UCKeyboardLayout *unicode; + void *other; + } keyboard_layout_format; + KeyboardLayoutRef currentKeyboardLayout; + KeyboardLayoutKind keyboard_kind; + UInt32 keyboard_dead; + KeyboardLayoutItem *keyLayout[256]; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm new file mode 100644 index 0000000000..6df0466355 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm @@ -0,0 +1,468 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** 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 "qcocoakeymapper.h" + +#include <QtCore/QDebug> +#include <QtGui/QGuiApplication> + +QT_BEGIN_NAMESPACE + +// QCocoaKeyMapper debug facilities +//#define DEBUG_KEY_BINDINGS +//#define DEBUG_KEY_BINDINGS_MODIFIERS +//#define DEBUG_KEY_MAPS + +// Possible modifier states. +// NOTE: The order of these states match the order in updatePossibleKeyCodes()! +static const Qt::KeyboardModifiers ModsTbl[] = { + Qt::NoModifier, // 0 + Qt::ShiftModifier, // 1 + Qt::ControlModifier, // 2 + Qt::ControlModifier | Qt::ShiftModifier, // 3 + Qt::AltModifier, // 4 + Qt::AltModifier | Qt::ShiftModifier, // 5 + Qt::AltModifier | Qt::ControlModifier, // 6 + Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 + Qt::MetaModifier, // 8 + Qt::MetaModifier | Qt::ShiftModifier, // 9 + Qt::MetaModifier | Qt::ControlModifier, // 10 + Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11 + Qt::MetaModifier | Qt::AltModifier, // 12 + Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13 + Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14 + Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15 +}; + +bool qt_mac_eat_unicode_key = false; + +Q_GUI_EXPORT void qt_mac_secure_keyboard(bool b) +{ + static bool secure = false; + if (b != secure){ + b ? EnableSecureEventInput() : DisableSecureEventInput(); + secure = b; + } +} + +/* key maps */ +struct qt_mac_enum_mapper +{ + int mac_code; + int qt_code; +#if defined(DEBUG_KEY_BINDINGS) +# define QT_MAC_MAP_ENUM(x) x, #x + const char *desc; +#else +# define QT_MAC_MAP_ENUM(x) x +#endif +}; + +//modifiers +static qt_mac_enum_mapper qt_mac_modifier_symbols[] = { + { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, + { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, + { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, + { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, + { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) }, + { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, + { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, + { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) }, + { 0, QT_MAC_MAP_ENUM(0) } +}; +Qt::KeyboardModifiers qt_mac_get_modifiers(int keys) +{ +#ifdef DEBUG_KEY_BINDINGS_MODIFIERS + qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys); +#endif + Qt::KeyboardModifiers ret = Qt::NoModifier; + for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { + if (keys & qt_mac_modifier_symbols[i].mac_code) { +#ifdef DEBUG_KEY_BINDINGS_MODIFIERS + qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); +#endif + ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code); + } + } + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + Qt::KeyboardModifiers oldModifiers = ret; + ret &= ~(Qt::MetaModifier | Qt::ControlModifier); + if (oldModifiers & Qt::ControlModifier) + ret |= Qt::MetaModifier; + if (oldModifiers & Qt::MetaModifier) + ret |= Qt::ControlModifier; + } + return ret; +} +static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys) +{ +#ifdef DEBUG_KEY_BINDINGS_MODIFIERS + qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys); +#endif + int ret = 0; + for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { + if (keys & qt_mac_modifier_symbols[i].qt_code) { +#ifdef DEBUG_KEY_BINDINGS_MODIFIERS + qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); +#endif + ret |= qt_mac_modifier_symbols[i].mac_code; + } + } + + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + int oldModifiers = ret; + ret &= ~(controlKeyBit | cmdKeyBit); + if (oldModifiers & controlKeyBit) + ret |= cmdKeyBit; + if (oldModifiers & cmdKeyBit) + ret |= controlKeyBit; + } + return ret; +} + +//keyboard keys (non-modifiers) +static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = { + { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) }, + { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) }, + { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) }, + { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) }, + { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) }, + { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, + { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, + { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) }, + { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) }, + { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) }, + { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) }, + { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) }, + { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) }, + { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) }, + { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, +//ascii maps, for debug + { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) }, + { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) }, + { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) }, + { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) }, + { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) }, + { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) }, + { '@', QT_MAC_MAP_ENUM(Qt::Key_At) }, + { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) }, + { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) }, + { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) }, + { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) }, + { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) }, + { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) }, + { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) }, + { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) }, + { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) }, + { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) }, + { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) }, + { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) }, + { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) }, + { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) }, + { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) }, + { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) }, + { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) }, + { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) }, + { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) }, + { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) }, + { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) }, + { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) }, + { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) }, + { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) }, + { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) }, + { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) }, + { 0, QT_MAC_MAP_ENUM(0) } +}; + +static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes + { 122, QT_MAC_MAP_ENUM(Qt::Key_F1) }, + { 120, QT_MAC_MAP_ENUM(Qt::Key_F2) }, + { 99, QT_MAC_MAP_ENUM(Qt::Key_F3) }, + { 118, QT_MAC_MAP_ENUM(Qt::Key_F4) }, + { 96, QT_MAC_MAP_ENUM(Qt::Key_F5) }, + { 97, QT_MAC_MAP_ENUM(Qt::Key_F6) }, + { 98, QT_MAC_MAP_ENUM(Qt::Key_F7) }, + { 100, QT_MAC_MAP_ENUM(Qt::Key_F8) }, + { 101, QT_MAC_MAP_ENUM(Qt::Key_F9) }, + { 109, QT_MAC_MAP_ENUM(Qt::Key_F10) }, + { 103, QT_MAC_MAP_ENUM(Qt::Key_F11) }, + { 111, QT_MAC_MAP_ENUM(Qt::Key_F12) }, + { 105, QT_MAC_MAP_ENUM(Qt::Key_F13) }, + { 107, QT_MAC_MAP_ENUM(Qt::Key_F14) }, + { 113, QT_MAC_MAP_ENUM(Qt::Key_F15) }, + { 106, QT_MAC_MAP_ENUM(Qt::Key_F16) }, + { 0, QT_MAC_MAP_ENUM(0) } +}; + +static qt_mac_enum_mapper qt_mac_private_unicode[] = { + { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey + { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey + { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey + { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey + { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey + { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey + { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey + { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey + { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey + { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey + { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey + { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey + { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey + { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey + { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintFunctionKey + { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey + { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey + { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey + { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey + { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey + { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey + { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey + { 0, QT_MAC_MAP_ENUM(0) } +}; + +static int qt_mac_get_key(int modif, const QChar &key, int virtualKey) +{ +#ifdef DEBUG_KEY_BINDINGS + qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey); +#endif + + if (key == kClearCharCode && virtualKey == 0x47) + return Qt::Key_Clear; + + if (key.isDigit()) { +#ifdef DEBUG_KEY_BINDINGS + qDebug("%d: got key: %d", __LINE__, key.digitValue()); +#endif + return key.digitValue() + Qt::Key_0; + } + + if (key.isLetter()) { +#ifdef DEBUG_KEY_BINDINGS + qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A')); +#endif + return (key.toUpper().unicode() - 'A') + Qt::Key_A; + } + if (key.isSymbol()) { +#ifdef DEBUG_KEY_BINDINGS + qDebug("%d: got key: %d", __LINE__, (key.unicode())); +#endif + return key.unicode(); + } + + for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) { + if (qt_mac_keyboard_symbols[i].mac_code == key) { + /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */ + if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) { +#ifdef DEBUG_KEY_BINDINGS + qDebug("%d: got key: Qt::Key_Backtab", __LINE__); +#endif + return Qt::Key_Backtab; + } + +#ifdef DEBUG_KEY_BINDINGS + qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc); +#endif + return qt_mac_keyboard_symbols[i].qt_code; + } + } + + //last ditch try to match the scan code + for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) { + if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) { +#ifdef DEBUG_KEY_BINDINGS + qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc); +#endif + return qt_mac_keyvkey_symbols[i].qt_code; + } + } + + // check if they belong to key codes in private unicode range + if (key >= 0xf700 && key <= 0xf747) { + if (key >= 0xf704 && key <= 0xf726) { + return Qt::Key_F1 + (key.unicode() - 0xf704) ; + } + for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) { + if (qt_mac_private_unicode[i].mac_code == key) { + return qt_mac_private_unicode[i].qt_code; + } + } + + } + + //oh well +#ifdef DEBUG_KEY_BINDINGS + qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey); +#endif + return Qt::Key_unknown; +} + +QCocoaKeyMapper::QCocoaKeyMapper() +{ + memset(keyLayout, 0, sizeof(keyLayout)); + keyboard_layout_format.unicode = 0; + currentInputSource = 0; +} + +QCocoaKeyMapper::~QCocoaKeyMapper() +{ + deleteLayouts(); +} + +bool QCocoaKeyMapper::updateKeyboard() +{ + const UCKeyboardLayout *uchrData = 0; + QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource(); + if (keyboard_mode != NullMode && source == currentInputSource) { + return false; + } + Q_ASSERT(source != 0); + CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source, + kTISPropertyUnicodeKeyLayoutData)); + uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0; + + keyboard_kind = LMGetKbdType(); + if (uchrData) { + keyboard_layout_format.unicode = uchrData; + keyboard_mode = UnicodeMode; + } + currentInputSource = source; + keyboard_dead = 0; + CFStringRef iso639Code; + + CFArrayRef array = static_cast<CFArrayRef>(TISGetInputSourceProperty(currentInputSource, kTISPropertyInputSourceLanguages)); + iso639Code = static_cast<CFStringRef>(CFArrayGetValueAtIndex(array, 0)); // Actually a RFC3066bis, but it's close enough + + if (iso639Code) { + keyboardInputLocale = QLocale(QCFString::toQString(iso639Code)); + keyboardInputDirection = keyboardInputLocale.textDirection(); + } else { + keyboardInputLocale = QLocale::c(); + keyboardInputDirection = Qt::LeftToRight; + } + return true; +} + +void QCocoaKeyMapper::deleteLayouts() +{ + keyboard_mode = NullMode; + for (int i = 0; i < 255; ++i) { + if (keyLayout[i]) { + delete keyLayout[i]; + keyLayout[i] = 0; + } + } +} + +void QCocoaKeyMapper::clearMappings() +{ + deleteLayouts(); + updateKeyboard(); +} + +void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey) +{ + if (updateKeyboard()) { + // ### Qt 4 did this: + // QKeyMapper::changeKeyboard(); + } + if (keyLayout[macVirtualKey]) + return; + + UniCharCount buffer_size = 10; + UniChar buffer[buffer_size]; + keyLayout[macVirtualKey] = new KeyboardLayoutItem; + for (int i = 0; i < 16; ++i) { + UniCharCount out_buffer_size = 0; + keyLayout[macVirtualKey]->qtKey[i] = 0; + + const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF); + OSStatus err = UCKeyTranslate(keyboard_layout_format.unicode, macVirtualKey, kUCKeyActionDown, keyModifier, + keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer); + if (err == noErr && out_buffer_size) { + const QChar unicode(buffer[0]); + int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); + if (qtkey == Qt::Key_unknown) + qtkey = unicode.unicode(); + keyLayout[macVirtualKey]->qtKey[i] = qtkey; + } else { + int qtkey = qt_mac_get_key(keyModifier, unicodeKey, macVirtualKey); + if (qtkey == Qt::Key_unknown) + qtkey = unicodeKey.unicode(); + keyLayout[macVirtualKey]->qtKey[i] = qtkey; + } + } +#ifdef DEBUG_KEY_MAPS + qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey); + for (int i = 0; i < 16; ++i) { + qDebug(" [%d] (%d,0x%02x,'%c')", i, + keyLayout[macVirtualKey]->qtKey[i], + keyLayout[macVirtualKey]->qtKey[i], + keyLayout[macVirtualKey]->qtKey[i]); + } +#endif +} + +QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const +{ + QList<int> ret; + const_cast<QCocoaKeyMapper *>(this)->updateKeyMap(event->nativeVirtualKey(), QChar(event->key())); + + KeyboardLayoutItem *kbItem = keyLayout[event->nativeVirtualKey()]; + + if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard) + return ret; + + int baseKey = kbItem->qtKey[0]; + Qt::KeyboardModifiers keyMods = event->modifiers(); + + ret << int(baseKey + keyMods); // The base key is _always_ valid, of course + + for (int i = 1; i < 8; ++i) { + Qt::KeyboardModifiers neededMods = ModsTbl[i]; + int key = kbItem->qtKey[i]; + if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) { + ret << int(key + (keyMods & ~neededMods)); + } + } + return ret; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index f0b1bd330a..271c9d2894 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -107,8 +107,10 @@ QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport() void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine) { #ifndef QT_NO_WIDGETS - QMacPrintEngine *macPrintEngine = static_cast<QMacPrintEngine *>(printEngine); - return macPrintEngine->d_func()->printInfo; + QMacPrintEnginePrivate *macPrintEnginePriv = static_cast<QMacPrintEngine *>(printEngine)->d_func(); + if (macPrintEnginePriv->state == QPrinter::Idle && !macPrintEnginePriv->isPrintSessionInitialized()) + macPrintEnginePriv->initialize(); + return macPrintEnginePriv->printInfo; #else qFatal("Printing is not supported when Qt is configured with -no-widgets"); return 0; diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index aacf47ec43..692e504432 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -96,6 +96,8 @@ QColor qt_mac_colorForThemeTextColor(ThemeTextColor themeColor) case kThemeTextColorTabFrontInactive: case kThemeTextColorBevelButtonInactive: return QColor(127, 127, 127, 255); + case kThemeTextColorMenuItemSelected: + return Qt::white; default: return QColor(0, 0, 0, 255); // ### TODO: Sample color like Qt 4. } @@ -153,21 +155,19 @@ struct QMacPaletteMap { }; static QMacPaletteMap mac_widget_colors[] = { -// TODO (msorvig): Fix/match palette behavior with Qt 4 and enable. -// -// QMacPaletteMap(QPlatformTheme::ToolButtonPalette, kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive), -// QMacPaletteMap(QPlatformTheme::ButtonPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), -// QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), -// QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive), -// QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive), -// QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive), -// QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive), -// QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), -// QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), -// QMacPaletteMap(QPlatformTheme::MenuPalette, kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive), -// ### TODO: The zeros below gives white-on-black text. -// QMacPaletteMap(QPlatformTheme::TextEditPalette, 0, 0), -// QMacPaletteMap(QPlatformTheme::TextLineEditPalette, 0, 0), + QMacPaletteMap(QPlatformTheme::ToolButtonPalette, kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive), + QMacPaletteMap(QPlatformTheme::ButtonPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), + QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), + QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive), + QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive), + QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive), + QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive), + QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), + QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), + QMacPaletteMap(QPlatformTheme::MenuPalette, kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive), + //### TODO: The zeros below gives white-on-black text. + QMacPaletteMap(QPlatformTheme::TextEditPalette, 0, 0), + QMacPaletteMap(QPlatformTheme::TextLineEditPalette, 0, 0), QMacPaletteMap(QPlatformTheme::NPalettes, 0, 0) }; QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() @@ -175,7 +175,7 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() QHash<QPlatformTheme::Palette, QPalette*> palettes; QColor qc; for (int i = 0; mac_widget_colors[i].paletteRole != QPlatformTheme::NPalettes; i++) { - QPalette pal; + QPalette pal = *qt_mac_createSystemPalette(); if (mac_widget_colors[i].active != 0) { qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].active); pal.setColor(QPalette::Active, QPalette::Text, qc); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index f786e6969f..b545844a24 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -49,6 +49,7 @@ #include <QtCore/qfileinfo.h> #include <QtCore/private/qcore_mac_p.h> #include <qwindow.h> +#include <private/qwindow_p.h> #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformscreen.h> @@ -372,9 +373,9 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) if (flags == Qt::Window) { styleMask = (NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask); } else if ((flags & Qt::Dialog) && (window()->modality() != Qt::NonModal)) { - styleMask = NSTitledWindowMask; + styleMask = NSResizableWindowMask | NSTitledWindowMask; } else if (!(flags & Qt::FramelessWindowHint)) { - if (flags & Qt::WindowMaximizeButtonHint) + if ((flags & Qt::Dialog) || (flags & Qt::WindowMaximizeButtonHint)) styleMask |= NSResizableWindowMask; if (flags & Qt::WindowTitleHint) styleMask |= NSTitledWindowMask; @@ -590,9 +591,7 @@ void QCocoaWindow::windowDidResize() if (!m_nsWindow) return; - NSRect rect = [[m_nsWindow contentView]frame]; - // Call setFrameSize which will trigger a frameDidChangeNotification on QNSView. - [[m_nsWindow contentView] setFrameSize:rect.size]; + [m_contentView updateGeometry]; } void QCocoaWindow::windowWillClose() @@ -651,6 +650,10 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); [m_contentView setFrame:frame]; } + + const qreal opacity = qt_window_private(window())->opacity; + if (!qFuzzyCompare(opacity, qreal(1.0))) + setOpacity(opacity); } NSWindow * QCocoaWindow::createNSWindow() diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index f93fd86205..9cdfe6f5bb 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -66,6 +66,7 @@ QT_END_NAMESPACE QString m_composingText; bool m_sendKeyEvent; QStringList *currentCustomDragTypes; + bool m_sendUpAsRightButton; Qt::KeyboardModifiers currentWheelModifiers; bool m_subscribesForGlobalFrameNotifications; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index b608989e43..678f88baa0 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -84,6 +84,7 @@ static QTouchDevice *touchDevice = 0; m_sendKeyEvent = false; m_subscribesForGlobalFrameNotifications = false; currentCustomDragTypes = 0; + m_sendUpAsRightButton = false; if (!touchDevice) { touchDevice = new QTouchDevice; @@ -184,6 +185,9 @@ static QTouchDevice *touchDevice = 0; geometry = qt_mac_toQRect([self frame]); } + if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry()) + return; + #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QNSView::udpateGeometry" << m_platformWindow << geometry; #endif @@ -312,6 +316,7 @@ static QTouchDevice *touchDevice = 0; ); CGImageRef bsCGImage = m_backingStore->getBackingStoreCGImage(); CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect); + CGContextSetBlendMode(cgContext, kCGBlendModeCopy); CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg); // Clean-up: @@ -427,6 +432,7 @@ static QTouchDevice *touchDevice = 0; - (void)mouseDown:(NSEvent *)theEvent { + m_sendUpAsRightButton = false; if (m_platformWindow->m_activePopupWindow) { QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow); QWindowSystemInterface::flushWindowSystemEvents(); @@ -438,7 +444,12 @@ static QTouchDevice *touchDevice = 0; [inputManager handleMouseEvent:theEvent]; } } else { - m_buttons |= Qt::LeftButton; + if ([self convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { + m_buttons |= Qt::RightButton; + m_sendUpAsRightButton = true; + } else { + m_buttons |= Qt::LeftButton; + } [self handleMouseEvent:theEvent]; } } @@ -452,7 +463,12 @@ static QTouchDevice *touchDevice = 0; - (void)mouseUp:(NSEvent *)theEvent { - m_buttons &= QFlag(~int(Qt::LeftButton)); + if (m_sendUpAsRightButton) { + m_buttons &= QFlag(~int(Qt::RightButton)); + m_sendUpAsRightButton = false; + } else { + m_buttons &= QFlag(~int(Qt::LeftButton)); + } [self handleMouseEvent:theEvent]; } @@ -740,9 +756,19 @@ static QTouchDevice *touchDevice = 0; - (void)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType { ulong timestamp = [nsevent timestamp] * 1000; - Qt::KeyboardModifiers modifiers = [self convertKeyModifiers:[nsevent modifierFlags]]; + ulong nativeModifiers = [nsevent modifierFlags]; + Qt::KeyboardModifiers modifiers = [self convertKeyModifiers: nativeModifiers]; NSString *charactersIgnoringModifiers = [nsevent charactersIgnoringModifiers]; + // [from Qt 4 impl] There is no way to get the scan code from carbon. But we cannot + // use the value 0, since it indicates that the event originates from somewhere + // else than the keyboard. + quint32 nativeScanCode = 1; + + UInt32 nativeVirtualKey = 0; + EventRef eventRef = EventRef([nsevent eventRef]); + GetEventParameter(eventRef, kEventParamKeyCode, typeUInt32, 0, sizeof(nativeVirtualKey), 0, &nativeVirtualKey); + QChar ch; int keyCode; if ([charactersIgnoringModifiers length] > 0) { @@ -783,7 +809,8 @@ static QTouchDevice *touchDevice = 0; } if (m_sendKeyEvent && m_composingText.isEmpty()) - QWindowSystemInterface::handleKeyEvent(m_window, timestamp, QEvent::Type(eventType), keyCode, modifiers, text); + QWindowSystemInterface::handleExtendedKeyEvent(m_window, timestamp, QEvent::Type(eventType), keyCode, modifiers, + nativeScanCode, nativeVirtualKey, nativeModifiers, text); m_sendKeyEvent = false; } diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm index 6824f19489..da714d3326 100644 --- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm +++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm @@ -80,7 +80,7 @@ [kids addObject:[QCocoaAccessibleElement elementWithInterface: m_accessibleRoot->child(i) parent:self ]]; } - return NSAccessibilityUnignoredChildren(kids); + return kids; } else { return [super accessibilityAttributeValue:attribute]; } |