diff options
-rw-r--r-- | src/gui/kernel/qcocoapanel_mac_p.h | 6 | ||||
-rw-r--r-- | src/gui/kernel/qcocoasharedwindowmethods_mac_p.h | 126 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaview_mac.mm | 68 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaview_mac_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qcocoawindow_mac_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qnsthemeframe_mac_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_mac.mm | 9 |
7 files changed, 151 insertions, 65 deletions
diff --git a/src/gui/kernel/qcocoapanel_mac_p.h b/src/gui/kernel/qcocoapanel_mac_p.h index 69dca1e..f35d9fb 100644 --- a/src/gui/kernel/qcocoapanel_mac_p.h +++ b/src/gui/kernel/qcocoapanel_mac_p.h @@ -54,10 +54,16 @@ #ifdef QT_MAC_USE_COCOA #import <Cocoa/Cocoa.h> +QT_FORWARD_DECLARE_CLASS(QStringList); + @interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel { bool leftButtonIsRightButton; + QStringList *currentCustomDragTypes; } + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; +- (void)registerDragTypes; + @end #endif + diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index f347240..8dd03aa 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -54,8 +54,31 @@ QT_BEGIN_NAMESPACE extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp +extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp + +Q_GLOBAL_STATIC(QPointer<QWidget>, currentDragTarget); + QT_END_NAMESPACE +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(NSUInteger)windowStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)deferCreation +{ + self = [super initWithContentRect:contentRect styleMask:windowStyle + backing:bufferingType defer:deferCreation]; + if (self) { + currentCustomDragTypes = 0; + } + return self; +} + +- (void)dealloc +{ + delete currentCustomDragTypes; + [super dealloc]; +} + - (BOOL)canBecomeKeyWindow { QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; @@ -185,3 +208,106 @@ QT_END_NAMESPACE return [super frameViewClassForStyleMask:styleMask]; } +-(void)registerDragTypes +{ + // Calling registerForDraggedTypes below is slow, so only do + // it once for each window, or when the custom types change. + QMacCocoaAutoReleasePool pool; + const QStringList& customTypes = qEnabledDraggedTypes(); + if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) { + if (currentCustomDragTypes == 0) + currentCustomDragTypes = new QStringList(); + *currentCustomDragTypes = customTypes; + const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName"; + NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType, + NSFilenamesPboardType, NSStringPboardType, + NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType, + NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType, + NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType, + NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType, + NSURLPboardType, NSPDFPboardType, NSVCardPboardType, + NSFilesPromisePboardType, NSInkTextPboardType, + NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil]; + // Add custom types supported by the application. + for (int i = 0; i < customTypes.size(); i++) { + [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))]; + } + [self registerForDraggedTypes:supportedTypes]; + } +} + +- (QWidget *)dragTargetHitTest:(id <NSDraggingInfo>)sender +{ + // Do a hittest to find the NSView under the + // mouse, and return the corresponding QWidget: + NSPoint windowPoint = [sender draggingLocation]; + NSView *candidateView = [[self contentView] hitTest:windowPoint]; + if (![candidateView isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) + return 0; + return [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(candidateView) qt_qwidget]; +} + +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender +{ + // The user dragged something into the window. Send a draggingEntered message + // to the QWidget under the mouse. As the drag moves over the window, and over + // different widgets, we will handle enter and leave events from within + // draggingUpdated below. The reason why we handle this ourselves rather than + // subscribing for drag events directly in QCocoaView is that calling + // registerForDraggedTypes on the views will severly degrade initialization time + // for an application that uses a lot of drag subscribing widgets. + + QWidget *target = [self dragTargetHitTest:sender]; + if (!target) + return [super draggingEntered:sender]; + if (target->testAttribute(Qt::WA_DropSiteRegistered) == false) + return NSDragOperationNone; + + *currentDragTarget() = target; + return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingEntered:sender]; + } + +- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender +{ + QWidget *target = [self dragTargetHitTest:sender]; + if (!target) + return [super draggingUpdated:sender]; + + if (target == *currentDragTarget()) { + // The drag continues to move over the widget that we have sendt + // a draggingEntered message to. So just update the view: + return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingUpdated:sender]; + } else { + // The widget under the mouse has changed. + // So we need to fake enter/leave events: + if (*currentDragTarget()) + [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingExited:sender]; + if (target->testAttribute(Qt::WA_DropSiteRegistered) == false) { + *currentDragTarget() = 0; + return NSDragOperationNone; + } + *currentDragTarget() = target; + return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingEntered:sender]; + } +} + +- (void)draggingExited:(id < NSDraggingInfo >)sender +{ + if (*currentDragTarget()) + [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingExited:sender]; + else + [super draggingExited:sender]; + *currentDragTarget() = 0; +} + +- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender +{ + BOOL dropAccepted = NO; + if (*currentDragTarget()) + dropAccepted = [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) performDragOperation:sender]; + else + return [super performDragOperation:sender]; + *currentDragTarget() = 0; + return dropAccepted; +} + diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index ddd8ca6..212684b 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -81,7 +81,6 @@ Q_GLOBAL_STATIC(DnDParams, qMacDnDParams); extern void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos); // qcursor_mac.mm extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm -extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp @@ -212,7 +211,6 @@ extern "C" { composingText = new QString(); composing = false; sendKeyEvents = true; - currentCustomTypes = 0; [self setHidden:YES]; return self; } @@ -227,34 +225,6 @@ extern "C" { object:self]; } --(void)registerDragTypes -{ - QMacCocoaAutoReleasePool pool; - // Calling registerForDraggedTypes is slow, so only do it once for each widget - // or when the custom types change. - const QStringList& customTypes = qEnabledDraggedTypes(); - if (currentCustomTypes == 0 || *currentCustomTypes != customTypes) { - if (currentCustomTypes == 0) - currentCustomTypes = new QStringList(); - *currentCustomTypes = customTypes; - const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName"; - NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType, - NSFilenamesPboardType, NSStringPboardType, - NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType, - NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType, - NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType, - NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType, - NSURLPboardType, NSPDFPboardType, NSVCardPboardType, - NSFilesPromisePboardType, NSInkTextPboardType, - NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil]; - // Add custom types supported by the application. - for (int i = 0; i < customTypes.size(); i++) { - [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))]; - } - [self registerForDraggedTypes:supportedTypes]; - } -} - - (void)resetCursorRects { QWidget *cursorWidget = qwidget; @@ -300,15 +270,9 @@ extern "C" { - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender { - if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false) - return NSDragOperationNone; + // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly + // from Cocoa. They modify the drag target, and might fake enter/leave events. NSPoint windowPoint = [sender draggingLocation]; - if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // pass the drag enter event to the view underneath. - NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; - if (candidateView && candidateView != self) - return [candidateView draggingEntered:sender]; - } dragEnterSequence = [sender draggingSequenceNumber]; [self addDropData:sender]; QMimeData *mimeData = dropData; @@ -360,13 +324,9 @@ extern "C" { - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { + // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly + // from Cocoa. They modify the drag target, and might fake enter/leave events. NSPoint windowPoint = [sender draggingLocation]; - if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // pass the drag move event to the view underneath. - NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; - if (candidateView && candidateView != self) - return [candidateView draggingUpdated:sender]; - } // in cases like QFocusFrame, the view under the mouse might // not have received the drag enter. Generate a synthetic // drag enter event for that view. @@ -414,14 +374,10 @@ extern "C" { - (void)draggingExited:(id < NSDraggingInfo >)sender { + // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly + // from Cocoa. They modify the drag target, and might fake enter/leave events. + Q_UNUSED(sender); dragEnterSequence = -1; - if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // try sending the leave event to the last view which accepted drag enter. - DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]; - NSView *candidateView = [[[self window] contentView] hitTest:dndParams->activeDragEnterPos]; - if (candidateView && candidateView != self) - return [candidateView draggingExited:sender]; - } // drag enter event was rejected, so ignore the move event. if (dropData) { QDragLeaveEvent de; @@ -432,14 +388,10 @@ extern "C" { - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender { + // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly + // from Cocoa. They modify the drag target, and might fake enter/leave events. NSPoint windowPoint = [sender draggingLocation]; dragEnterSequence = -1; - if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // pass the drop event to the view underneath. - NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; - if (candidateView && candidateView != self) - return [candidateView performDragOperation:sender]; - } [self addDropData:sender]; NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; @@ -469,8 +421,6 @@ extern "C" { { delete composingText; [[NSNotificationCenter defaultCenter] removeObserver:self]; - delete currentCustomTypes; - [self unregisterDraggedTypes]; [super dealloc]; } diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index d549177..e6ff423 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -87,7 +87,6 @@ Q_GUI_EXPORT int composingLength; bool sendKeyEvents; QString *composingText; - QStringList *currentCustomTypes; NSInteger dragEnterSequence; } - (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; @@ -97,7 +96,6 @@ Q_GUI_EXPORT - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender; - (void)draggingExited:(id < NSDraggingInfo >)sender; - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender; -- (void)registerDragTypes; - (void)removeDropData; - (void)addDropData:(id <NSDraggingInfo>)sender; - (void)setSupportedActions:(NSDragOperation)actions; diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h index 91c5d4e..ea3461c 100644 --- a/src/gui/kernel/qcocoawindow_mac_p.h +++ b/src/gui/kernel/qcocoawindow_mac_p.h @@ -70,9 +70,12 @@ QT_FORWARD_DECLARE_CLASS(QStringList); @interface QT_MANGLE_NAMESPACE(QCocoaWindow) : NSWindow { bool leftButtonIsRightButton; + QStringList *currentCustomDragTypes; } + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; +- (void)registerDragTypes; + @end #endif diff --git a/src/gui/kernel/qnsthemeframe_mac_p.h b/src/gui/kernel/qnsthemeframe_mac_p.h index af1406b..c8c7f4a 100644 --- a/src/gui/kernel/qnsthemeframe_mac_p.h +++ b/src/gui/kernel/qnsthemeframe_mac_p.h @@ -157,7 +157,7 @@ - (void)resetCursorRects; - (char)shouldBeTreatedAsInkEvent:fp8; - (char)_shouldBeTreatedAsInkEventInInactiveWindow:fp8; -- hitTest:(struct _NSPoint)fp8; +//- hitTest:(struct _NSPoint)fp8; // collides with hittest in qcocoasharedwindowmethods_mac_p.h - (NSRect)_leftGroupRect; - (NSRect)_rightGroupRect; - (void)_updateWidgets; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1907cca..c75358d 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4554,9 +4554,12 @@ void QWidgetPrivate::registerDropSite(bool on) #ifndef QT_MAC_USE_COCOA SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on); #else - NSView *view = qt_mac_nativeview_for(q); - if (on && [view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) { - [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) registerDragTypes]; + NSWindow *win = qt_mac_window_for(q); + if (on) { + if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaWindow) class]]) + [static_cast<QT_MANGLE_NAMESPACE(QCocoaWindow) *>(win) registerDragTypes]; + else if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaPanel) class]]) + [static_cast<QT_MANGLE_NAMESPACE(QCocoaPanel) *>(win) registerDragTypes]; } #endif } |