diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qnsview.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 349 |
1 files changed, 341 insertions, 8 deletions
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9ed3332ba5..a28c5959ce 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -51,6 +51,7 @@ #include "qcocoadrag.h" #include <QtGui/QWindowSystemInterface> +#include <QtGui/QTextFormat> #include <QtCore/QDebug> #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR @@ -94,6 +95,7 @@ static QTouchDevice *touchDevice = 0; m_window = window; m_platformWindow = platformWindow; m_accessibleRoot = 0; + m_keyEventsAccepted = false; #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR // prevent rift in space-time continuum, disable @@ -144,14 +146,27 @@ static QTouchDevice *touchDevice = 0; - (void)windowDidBecomeKey { - QWindowSystemInterface::handleWindowActivated(m_window); +// QWindowSystemInterface::handleWindowActivated(m_window); } - (void)windowDidResignKey { +// QWindowSystemInterface::handleWindowActivated(0); +} + +- (void)windowDidBecomeMain +{ +// qDebug() << "window did become main" << m_window; + QWindowSystemInterface::handleWindowActivated(m_window); +} + +- (void)windowDidResignMain +{ +// qDebug() << "window did resign main" << m_window; QWindowSystemInterface::handleWindowActivated(0); } + - (void) setImage:(QImage *)image { CGImageRelease(m_cgImage); @@ -266,14 +281,24 @@ static QTouchDevice *touchDevice = 0; qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); } ulong timestamp = [theEvent timestamp] * 1000; - QWindowSystemInterface::handleMouseEvent(m_window, timestamp, qtWindowPoint, qtScreenPoint, m_buttons); } - (void)mouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::LeftButton; - [self handleMouseEvent:theEvent]; + if (m_platformWindow->m_activePopupWindow) { + QWindowSystemInterface::handleSynchronousCloseEvent(m_platformWindow->m_activePopupWindow); + m_platformWindow->m_activePopupWindow = 0; + } + if ([self hasMarkedText]) { + NSInputManager* inputManager = [NSInputManager currentInputManager]; + if ([inputManager wantsToHandleMouseEvents]) { + [inputManager handleMouseEvent:theEvent]; + } + } else { + m_buttons |= Qt::LeftButton; + [self handleMouseEvent:theEvent]; + } } - (void)mouseDragged:(NSEvent *)theEvent @@ -327,7 +352,53 @@ static QTouchDevice *touchDevice = 0; - (void)otherMouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::RightButton; + switch ([theEvent buttonNumber]) { + case 3: + m_buttons |= Qt::MiddleButton; + break; + case 4: + m_buttons |= Qt::ExtraButton1; // AKA Qt::BackButton + break; + case 5: + m_buttons |= Qt::ExtraButton2; // AKA Qt::ForwardButton + break; + case 6: + m_buttons |= Qt::ExtraButton3; + break; + case 7: + m_buttons |= Qt::ExtraButton4; + break; + case 8: + m_buttons |= Qt::ExtraButton5; + break; + case 9: + m_buttons |= Qt::ExtraButton6; + break; + case 10: + m_buttons |= Qt::ExtraButton7; + break; + case 11: + m_buttons |= Qt::ExtraButton8; + break; + case 12: + m_buttons |= Qt::ExtraButton9; + break; + case 13: + m_buttons |= Qt::ExtraButton10; + break; + case 14: + m_buttons |= Qt::ExtraButton11; + break; + case 15: + m_buttons |= Qt::ExtraButton12; + break; + case 16: + m_buttons |= Qt::ExtraButton13; + break; + default: + m_buttons |= Qt::MiddleButton; + break; + } [self handleMouseEvent:theEvent]; } @@ -340,7 +411,53 @@ static QTouchDevice *touchDevice = 0; - (void)otherMouseUp:(NSEvent *)theEvent { - m_buttons &= QFlag(~int(Qt::MiddleButton)); + switch ([theEvent buttonNumber]) { + case 3: + m_buttons &= QFlag(~int(Qt::MiddleButton)); + break; + case 4: + m_buttons &= QFlag(~int(Qt::ExtraButton1)); // AKA Qt::BackButton + break; + case 5: + m_buttons &= QFlag(~int(Qt::ExtraButton2)); // AKA Qt::ForwardButton + break; + case 6: + m_buttons &= QFlag(~int(Qt::ExtraButton3)); + break; + case 7: + m_buttons &= QFlag(~int(Qt::ExtraButton4)); + break; + case 8: + m_buttons &= QFlag(~int(Qt::ExtraButton5)); + break; + case 9: + m_buttons &= QFlag(~int(Qt::ExtraButton6)); + break; + case 10: + m_buttons &= QFlag(~int(Qt::ExtraButton7)); + break; + case 11: + m_buttons &= QFlag(~int(Qt::ExtraButton8)); + break; + case 12: + m_buttons &= QFlag(~int(Qt::ExtraButton9)); + break; + case 13: + m_buttons &= QFlag(~int(Qt::ExtraButton10)); + break; + case 14: + m_buttons &= QFlag(~int(Qt::ExtraButton11)); + break; + case 15: + m_buttons &= QFlag(~int(Qt::ExtraButton12)); + break; + case 16: + m_buttons &= QFlag(~int(Qt::ExtraButton13)); + break; + default: + m_buttons &= QFlag(~int(Qt::MiddleButton)); + break; + } [self handleMouseEvent:theEvent]; } @@ -467,12 +584,228 @@ static QTouchDevice *touchDevice = 0; - (void)keyDown:(NSEvent *)theEvent { - [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; + QObject *fo = QGuiApplication::focusObject(); + m_keyEventsAccepted = false; + if (fo) { + QInputMethodQueryEvent queryEvent(Qt::ImHints); + if (QCoreApplication::sendEvent(fo, &queryEvent)) { + Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt()); + if (!(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) { + [self interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; + } + } + } + + if (!m_keyEventsAccepted && m_composingText.isEmpty()) { + [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; + } } - (void)keyUp:(NSEvent *)theEvent { - [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; + if (!m_keyEventsAccepted && m_composingText.isEmpty()) { + [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; + } +} + +- (void) doCommandBySelector:(SEL)aSelector +{ + [self tryToPerform:aSelector with:self]; +} + +- (void) insertText:(id)aString +{ + QString commitString; + if ([aString length]) { + if ([aString isKindOfClass:[NSAttributedString class]]) { + commitString = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); + } else { + commitString = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); + }; + } + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e; + e.setCommitString(commitString); + QCoreApplication::sendEvent(fo, &e); + m_keyEventsAccepted = true; + } + + m_composingText.clear(); + } + +- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange +{ + QString preeditString; + + QList<QInputMethodEvent::Attribute> attrs; + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location + selRange.length, 1, QVariant()); + + if ([aString isKindOfClass:[NSAttributedString class]]) { + // Preedit string has attribution + preeditString = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); + int composingLength = preeditString.length(); + int index = 0; + // Create attributes for individual sections of preedit text + while (index < composingLength) { + NSRange effectiveRange; + NSRange range = NSMakeRange(index, composingLength-index); + NSDictionary *attributes = [aString attributesAtIndex:index + longestEffectiveRange:&effectiveRange + inRange:range]; + NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName]; + if (underlineStyle) { + QColor clr (Qt::black); + NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName]; + if (color) { + clr = qt_mac_toQColor(color); + } + QTextCharFormat format; + format.setFontUnderline(true); + format.setUnderlineColor(clr); + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, + effectiveRange.location, + effectiveRange.length, + format); + } + index = effectiveRange.location + effectiveRange.length; + } + } else { + // No attributes specified, take only the preedit text. + preeditString = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); + } + + if (attrs.isEmpty()) { + QTextCharFormat format; + format.setFontUnderline(true); + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, + 0, preeditString.length(), format); + } + + m_composingText = preeditString; + + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e(preeditString, attrs); + QCoreApplication::sendEvent(fo, &e); + m_keyEventsAccepted = true; + } +} + +- (void) unmarkText +{ + if (!m_composingText.isEmpty()) { + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e; + e.setCommitString(m_composingText); + QCoreApplication::sendEvent(fo, &e); + } + } + m_composingText.clear(); +} + +- (BOOL) hasMarkedText +{ + return (m_composingText.isEmpty() ? NO: YES); +} + +- (NSInteger) conversationIdentifier +{ + return (NSInteger)self; +} + +- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange +{ + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return nil; + QInputMethodQueryEvent queryEvent(Qt::ImCurrentSelection); + if (!QCoreApplication::sendEvent(fo, &queryEvent)) + return nil; + + QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString(); + if (selectedText.isEmpty()) + return nil; + + QCFString string(selectedText.mid(theRange.location, theRange.length)); + const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); + return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease]; +} + +- (NSRange) markedRange +{ + NSRange range; + if (!m_composingText.isEmpty()) { + range.location = 0; + range.length = m_composingText.length(); + } else { + range.location = NSNotFound; + range.length = 0; + } + return range; +} + + +- (NSRange) selectedRange +{ + NSRange selRange = {NSNotFound, 0}; + selRange.location = NSNotFound; + selRange.length = 0; + + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return selRange; + QInputMethodQueryEvent queryEvent(Qt::ImCurrentSelection); + if (!QCoreApplication::sendEvent(fo, &queryEvent)) + return selRange; + QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString(); + + if (!selectedText.isEmpty()) { + selRange.location = 0; + selRange.length = selectedText.length(); + } + return selRange; +} + +- (NSRect) firstRectForCharacterRange:(NSRange)theRange +{ + Q_UNUSED(theRange); + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return NSZeroRect; + + if (!m_window) + return NSZeroRect; + + // The returned rect is always based on the internal cursor. + QRect mr = qApp->inputMethod()->cursorRectangle().toRect(); + QPoint mp = m_window->mapToGlobal(mr.bottomLeft()); + + NSRect rect; + rect.origin.x = mp.x(); + rect.origin.y = qt_mac_flipYCoordinate(mp.y()); + rect.size.width = mr.width(); + rect.size.height = mr.height(); + return rect; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint +{ + // We dont support cursor movements using mouse while composing. + Q_UNUSED(thePoint); + return NSNotFound; +} + +- (NSArray*) validAttributesForMarkedText +{ + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return nil; + + // Support only underline color/style. + return [NSArray arrayWithObjects:NSUnderlineColorAttributeName, + NSUnderlineStyleAttributeName, nil]; } -(void)registerDragTypes |