src/gui/kernel/qcocoaview_mac.mm
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #import <private/qcocoaview_mac_p.h>
       
    43 #ifdef QT_MAC_USE_COCOA
       
    44 
       
    45 #include <private/qwidget_p.h>
       
    46 #include <private/qt_mac_p.h>
       
    47 #include <private/qapplication_p.h>
       
    48 #include <private/qabstractscrollarea_p.h>
       
    49 #include <private/qt_cocoa_helpers_mac_p.h>
       
    50 #include <private/qdnd_p.h>
       
    51 #include <private/qmacinputcontext_p.h>
       
    52 #include <private/qmultitouch_mac_p.h>
       
    53 #include <private/qevent_p.h>
       
    54 #include <private/qbackingstore_p.h>
       
    55 
       
    56 #include <qscrollarea.h>
       
    57 #include <qhash.h>
       
    58 #include <qtextformat.h>
       
    59 #include <qpaintengine.h>
       
    60 #include <QUrl>
       
    61 #include <QAccessible>
       
    62 #include <QFileInfo>
       
    63 #include <QFile>
       
    64 
       
    65 #include <qdebug.h>
       
    66 
       
    67 @interface NSEvent (DeviceDelta)
       
    68   - (CGFloat)deviceDeltaX;
       
    69   - (CGFloat)deviceDeltaY;
       
    70   - (CGFloat)deviceDeltaZ;
       
    71 @end
       
    72 
       
    73 QT_BEGIN_NAMESPACE
       
    74 
       
    75 Q_GLOBAL_STATIC(DnDParams, qMacDnDParams);
       
    76 
       
    77 extern void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos); // qcursor_mac.mm
       
    78 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp
       
    79 extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm
       
    80 extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp
       
    81 extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm
       
    82 
       
    83 Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
       
    84 {
       
    85     if (buttonNum == 0)
       
    86         return Qt::LeftButton;
       
    87     if (buttonNum == 1)
       
    88         return Qt::RightButton;
       
    89     if (buttonNum == 2)
       
    90         return Qt::MidButton;
       
    91     if (buttonNum == 3)
       
    92         return Qt::XButton1;
       
    93     if (buttonNum == 4)
       
    94         return Qt::XButton2;
       
    95     return Qt::NoButton;
       
    96 }
       
    97 
       
    98 struct dndenum_mapper
       
    99 {
       
   100     NSDragOperation mac_code;
       
   101     Qt::DropAction qt_code;
       
   102     bool Qt2Mac;
       
   103 };
       
   104 
       
   105 static dndenum_mapper dnd_enums[] = {
       
   106     { NSDragOperationLink,  Qt::LinkAction, true },
       
   107     { NSDragOperationMove,  Qt::MoveAction, true },
       
   108     { NSDragOperationCopy,  Qt::CopyAction, true },
       
   109     { NSDragOperationGeneric,  Qt::CopyAction, false },
       
   110     { NSDragOperationEvery, Qt::ActionMask, false },
       
   111     { NSDragOperationNone, Qt::IgnoreAction, false }
       
   112 };
       
   113 
       
   114 static NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
       
   115 {
       
   116     for (int i=0; dnd_enums[i].qt_code; i++) {
       
   117         if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) {
       
   118             return dnd_enums[i].mac_code;
       
   119         }
       
   120     }
       
   121     return NSDragOperationNone;
       
   122 }
       
   123 
       
   124 static NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
       
   125 {
       
   126     NSDragOperation nsActions = NSDragOperationNone;
       
   127     for (int i=0; dnd_enums[i].qt_code; i++) {
       
   128         if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code))
       
   129             nsActions |= dnd_enums[i].mac_code;
       
   130     }
       
   131     return nsActions;
       
   132 }
       
   133 
       
   134 static Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
       
   135 {
       
   136     Qt::DropAction action = Qt::IgnoreAction;
       
   137     for (int i=0; dnd_enums[i].mac_code; i++) {
       
   138         if (nsActions & dnd_enums[i].mac_code)
       
   139             return dnd_enums[i].qt_code;
       
   140     }
       
   141     return action;
       
   142 }
       
   143 
       
   144 static Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
       
   145 {
       
   146     Qt::DropActions actions = Qt::IgnoreAction;
       
   147     for (int i=0; dnd_enums[i].mac_code; i++) {
       
   148         if (nsActions & dnd_enums[i].mac_code)
       
   149             actions |= dnd_enums[i].qt_code;
       
   150     }
       
   151     return actions;
       
   152 }
       
   153 
       
   154 static QColor colorFrom(NSColor *color)
       
   155 {
       
   156     QColor qtColor;
       
   157     NSString *colorSpace = [color colorSpaceName];
       
   158     if (colorSpace == NSDeviceCMYKColorSpace) {
       
   159         CGFloat cyan, magenta, yellow, black, alpha;
       
   160         [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha];
       
   161         qtColor.setCmykF(cyan, magenta, yellow, black, alpha);
       
   162     } else {
       
   163         NSColor *tmpColor;
       
   164         tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
       
   165         CGFloat red, green, blue, alpha;
       
   166         [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
       
   167         qtColor.setRgbF(red, green, blue, alpha);
       
   168     }
       
   169     return qtColor;
       
   170 }
       
   171 
       
   172 QT_END_NAMESPACE
       
   173 
       
   174 QT_FORWARD_DECLARE_CLASS(QMacCocoaAutoReleasePool)
       
   175 QT_FORWARD_DECLARE_CLASS(QCFString)
       
   176 QT_FORWARD_DECLARE_CLASS(QDragManager)
       
   177 QT_FORWARD_DECLARE_CLASS(QMimeData)
       
   178 QT_FORWARD_DECLARE_CLASS(QPoint)
       
   179 QT_FORWARD_DECLARE_CLASS(QApplication)
       
   180 QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
       
   181 QT_FORWARD_DECLARE_CLASS(QDragEnterEvent)
       
   182 QT_FORWARD_DECLARE_CLASS(QDragMoveEvent)
       
   183 QT_FORWARD_DECLARE_CLASS(QStringList)
       
   184 QT_FORWARD_DECLARE_CLASS(QString)
       
   185 QT_FORWARD_DECLARE_CLASS(QRect)
       
   186 QT_FORWARD_DECLARE_CLASS(QRegion)
       
   187 QT_FORWARD_DECLARE_CLASS(QAbstractScrollArea)
       
   188 QT_FORWARD_DECLARE_CLASS(QAbstractScrollAreaPrivate)
       
   189 QT_FORWARD_DECLARE_CLASS(QPaintEvent)
       
   190 QT_FORWARD_DECLARE_CLASS(QPainter)
       
   191 QT_FORWARD_DECLARE_CLASS(QHoverEvent)
       
   192 QT_FORWARD_DECLARE_CLASS(QCursor)
       
   193 QT_USE_NAMESPACE
       
   194 extern "C" {
       
   195     extern NSString *NSTextInputReplacementRangeAttributeName;
       
   196 }
       
   197 
       
   198 
       
   199 @implementation QT_MANGLE_NAMESPACE(QCocoaView)
       
   200 
       
   201 - (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate
       
   202 {
       
   203     self = [super init];
       
   204     if (self) {
       
   205         [self finishInitWithQWidget:widget widgetPrivate:widgetprivate];
       
   206     }
       
   207     composingText = new QString();
       
   208     composing = false;
       
   209     sendKeyEvents = true;
       
   210     currentCustomTypes = 0;
       
   211     [self setHidden:YES];
       
   212     return self;
       
   213 }
       
   214 
       
   215 - (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate
       
   216 {
       
   217     qwidget = widget;
       
   218     qwidgetprivate = widgetprivate;
       
   219     [[NSNotificationCenter defaultCenter] addObserver:self
       
   220                                              selector:@selector(frameDidChange:)
       
   221                                                  name:@"NSViewFrameDidChangeNotification"
       
   222                                                object:self];
       
   223 }
       
   224 
       
   225 -(void)registerDragTypes
       
   226 {
       
   227     QMacCocoaAutoReleasePool pool;
       
   228     // Calling registerForDraggedTypes is slow, so only do it once for each widget
       
   229     // or when the custom types change.
       
   230     const QStringList& customTypes = qEnabledDraggedTypes();
       
   231     if (currentCustomTypes == 0 || *currentCustomTypes != customTypes) {
       
   232         if (currentCustomTypes == 0)
       
   233             currentCustomTypes = new QStringList();
       
   234         *currentCustomTypes = customTypes;
       
   235         const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
       
   236 	NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
       
   237                                    NSFilenamesPboardType, NSStringPboardType,
       
   238                                    NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
       
   239                                    NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
       
   240                                    NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
       
   241                                    NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
       
   242                                    NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
       
   243                                    NSFilesPromisePboardType, NSInkTextPboardType,
       
   244                                    NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
       
   245         // Add custom types supported by the application.
       
   246         for (int i = 0; i < customTypes.size(); i++) {
       
   247            [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))];
       
   248         }
       
   249         [self registerForDraggedTypes:supportedTypes];
       
   250     }
       
   251 }
       
   252 
       
   253 - (void)resetCursorRects
       
   254 {
       
   255     QWidget *cursorWidget = qwidget;
       
   256 
       
   257     if (cursorWidget->testAttribute(Qt::WA_TransparentForMouseEvents))
       
   258         cursorWidget = QApplication::widgetAt(qwidget->mapToGlobal(qwidget->rect().center()));
       
   259 
       
   260     if (cursorWidget == 0)
       
   261         return;
       
   262 
       
   263     if (!cursorWidget->testAttribute(Qt::WA_SetCursor)) {
       
   264         [super resetCursorRects];
       
   265         return;
       
   266     }
       
   267 
       
   268     QRegion mask = qt_widget_private(cursorWidget)->extra->mask;
       
   269     NSCursor *nscursor = static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursorWidget->cursor()));
       
   270     if (mask.isEmpty()) {
       
   271         [self addCursorRect:[qt_mac_nativeview_for(cursorWidget) visibleRect] cursor:nscursor];
       
   272     } else {
       
   273         const QVector<QRect> &rects = mask.rects();
       
   274         for (int i = 0; i < rects.size(); ++i) {
       
   275             const QRect &rect = rects.at(i);
       
   276             [self addCursorRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()) cursor:nscursor];
       
   277         }
       
   278     }
       
   279 }
       
   280 
       
   281 - (void)removeDropData
       
   282 {
       
   283     if (dropData) {
       
   284         delete dropData;
       
   285         dropData = 0;
       
   286     }
       
   287 }
       
   288 
       
   289 - (void)addDropData:(id <NSDraggingInfo>)sender
       
   290 {
       
   291     [self removeDropData];
       
   292     CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name];
       
   293     dropData = new QCocoaDropData(dropPasteboard);
       
   294 }
       
   295 
       
   296 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
       
   297 {
       
   298     if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false)
       
   299         return NSDragOperationNone;
       
   300     NSPoint windowPoint = [sender draggingLocation];
       
   301     if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
       
   302         // pass the drag enter event to the view underneath.
       
   303         NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
       
   304         if (candidateView && candidateView != self)
       
   305             return [candidateView draggingEntered:sender];
       
   306     }
       
   307     dragEnterSequence = [sender draggingSequenceNumber];
       
   308     [self addDropData:sender];
       
   309     QMimeData *mimeData = dropData;
       
   310     if (QDragManager::self()->source())
       
   311         mimeData = QDragManager::self()->dragPrivate()->data;
       
   312     NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
       
   313     NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
       
   314     QPoint posDrag(localPoint.x, localPoint.y);
       
   315     NSDragOperation nsActions = [sender draggingSourceOperationMask];
       
   316     Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions);
       
   317     QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions;
       
   318     Qt::KeyboardModifiers modifiers  = Qt::NoModifier;
       
   319     if ([sender draggingSource] != nil) {
       
   320         // modifier flags might have changed, update it here since we don't send any input events.
       
   321         QApplicationPrivate::modifier_buttons = qt_cocoaModifiers2QtModifiers([[NSApp currentEvent] modifierFlags]);
       
   322         modifiers = QApplication::keyboardModifiers();
       
   323     } else {
       
   324         // when the source is from another application the above technique will not work.
       
   325         modifiers = qt_cocoaDragOperation2QtModifiers(nsActions);
       
   326     }
       
   327     // send the drag enter event to the widget.
       
   328     QDragEnterEvent qDEEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers);
       
   329     QApplication::sendEvent(qwidget, &qDEEvent);
       
   330     if (!qDEEvent.isAccepted()) {
       
   331         // widget is not interested in this drag, so ignore this drop data.
       
   332         [self removeDropData];
       
   333         return NSDragOperationNone;
       
   334     } else {
       
   335         // save the mouse position, used by draggingExited handler.
       
   336         DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
       
   337         dndParams->activeDragEnterPos = windowPoint;
       
   338         // send a drag move event immediately after a drag enter event (as per documentation).
       
   339         QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers);
       
   340         qDMEvent.setDropAction(qDEEvent.dropAction());
       
   341         qDMEvent.accept(); // accept by default, since enter event was accepted.
       
   342         QApplication::sendEvent(qwidget, &qDMEvent);
       
   343         if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) {
       
   344             // since we accepted the drag enter event, the widget expects
       
   345             // future drage move events.
       
   346             // ### check if we need to treat this like the drag enter event.
       
   347             nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDEEvent.dropAction());
       
   348         } else {
       
   349             nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDMEvent.dropAction());
       
   350         }
       
   351         QT_PREPEND_NAMESPACE(qt_mac_copy_answer_rect)(qDMEvent);
       
   352         return nsActions;
       
   353     }
       
   354  }
       
   355 
       
   356 - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
       
   357 {
       
   358     NSPoint windowPoint = [sender draggingLocation];
       
   359     if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
       
   360         // pass the drag move event to the view underneath.
       
   361         NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
       
   362         if (candidateView && candidateView != self)
       
   363             return [candidateView draggingUpdated:sender];
       
   364     }
       
   365     // in cases like QFocusFrame, the view under the mouse might
       
   366     // not have received the drag enter. Generate a synthetic
       
   367     // drag enter event for that view.
       
   368     if (dragEnterSequence != [sender draggingSequenceNumber])
       
   369         [self draggingEntered:sender];
       
   370     // drag enter event was rejected, so ignore the move event.
       
   371     if (dropData == 0)
       
   372         return NSDragOperationNone;
       
   373     // return last value, if we are still in the answerRect.
       
   374     NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
       
   375     NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
       
   376     NSDragOperation nsActions = [sender draggingSourceOperationMask];
       
   377     QPoint posDrag(localPoint.x, localPoint.y);
       
   378     if (qt_mac_mouse_inside_answer_rect(posDrag)
       
   379         && QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) == nsActions)
       
   380         return QT_PREPEND_NAMESPACE(qt_mac_mapDropActions)(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastAction));
       
   381     // send drag move event to the widget
       
   382     QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions;
       
   383     Qt::DropActions qtAllowed = QT_PREPEND_NAMESPACE(qt_mac_mapNSDragOperations)(nsActions);
       
   384     Qt::KeyboardModifiers modifiers  = Qt::NoModifier;
       
   385     if ([sender draggingSource] != nil) {
       
   386         // modifier flags might have changed, update it here since we don't send any input events.
       
   387         QApplicationPrivate::modifier_buttons = qt_cocoaModifiers2QtModifiers([[NSApp currentEvent] modifierFlags]);
       
   388         modifiers = QApplication::keyboardModifiers();
       
   389     } else {
       
   390         // when the source is from another application the above technique will not work.
       
   391         modifiers = qt_cocoaDragOperation2QtModifiers(nsActions);
       
   392     }
       
   393     QMimeData *mimeData = dropData;
       
   394     if (QDragManager::self()->source())
       
   395         mimeData = QDragManager::self()->dragPrivate()->data;
       
   396     QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers);
       
   397     qDMEvent.setDropAction(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).lastAction);
       
   398     qDMEvent.accept();
       
   399     QApplication::sendEvent(qwidget, &qDMEvent);
       
   400     qt_mac_copy_answer_rect(qDMEvent);
       
   401 
       
   402     NSDragOperation operation = qt_mac_mapDropAction(qDMEvent.dropAction());
       
   403     if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) {
       
   404         // ignore this event (we will still receive further notifications)
       
   405         operation = NSDragOperationNone;
       
   406     }
       
   407     return operation;
       
   408 }
       
   409 
       
   410 - (void)draggingExited:(id < NSDraggingInfo >)sender
       
   411 {
       
   412     dragEnterSequence = -1;
       
   413     if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
       
   414         // try sending the leave event to the last view which accepted drag enter.
       
   415         DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
       
   416         NSView *candidateView = [[[self window] contentView] hitTest:dndParams->activeDragEnterPos];
       
   417         if (candidateView && candidateView != self)
       
   418             return [candidateView draggingExited:sender];
       
   419     }
       
   420     // drag enter event was rejected, so ignore the move event.
       
   421     if (dropData) {
       
   422         QDragLeaveEvent de;
       
   423         QApplication::sendEvent(qwidget, &de);
       
   424         [self removeDropData];
       
   425     }
       
   426 }
       
   427 
       
   428 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
       
   429 {
       
   430     NSPoint windowPoint = [sender draggingLocation];
       
   431     dragEnterSequence = -1;
       
   432     if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
       
   433         // pass the drop event to the view underneath.
       
   434         NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
       
   435         if (candidateView && candidateView != self)
       
   436             return [candidateView performDragOperation:sender];
       
   437     }
       
   438     [self addDropData:sender];
       
   439 
       
   440     NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
       
   441     NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
       
   442     QPoint posDrop(localPoint.x, localPoint.y);
       
   443 
       
   444     NSDragOperation nsActions = [sender draggingSourceOperationMask];
       
   445     Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions);
       
   446     QMimeData *mimeData = dropData;
       
   447     if (QDragManager::self()->source())
       
   448         mimeData = QDragManager::self()->dragPrivate()->data;
       
   449     // send the drop event to the widget.
       
   450     QDropEvent de(posDrop, qtAllowed, mimeData,
       
   451                   QApplication::mouseButtons(), QApplication::keyboardModifiers());
       
   452     if (QDragManager::self()->object)
       
   453         QDragManager::self()->dragPrivate()->target = qwidget;
       
   454     QApplication::sendEvent(qwidget, &de);
       
   455     if (QDragManager::self()->object)
       
   456         QDragManager::self()->dragPrivate()->executed_action = de.dropAction();
       
   457     if (!de.isAccepted())
       
   458         return NO;
       
   459     else
       
   460         return YES;
       
   461 }
       
   462 
       
   463 - (void)dealloc
       
   464 {
       
   465     delete composingText;
       
   466     [[NSNotificationCenter defaultCenter] removeObserver:self];
       
   467     delete currentCustomTypes;
       
   468     [self unregisterDraggedTypes];
       
   469     [super dealloc];
       
   470 }
       
   471 
       
   472 - (BOOL)isOpaque;
       
   473 {
       
   474     return qwidgetprivate->isOpaque;
       
   475 }
       
   476 
       
   477 - (BOOL)isFlipped;
       
   478 {
       
   479     return YES;
       
   480 }
       
   481 
       
   482 - (BOOL) preservesContentDuringLiveResize;
       
   483 {
       
   484     return qwidget->testAttribute(Qt::WA_StaticContents);
       
   485 }
       
   486 
       
   487 - (void) setFrameSize:(NSSize)newSize
       
   488 {
       
   489     [super setFrameSize:newSize];
       
   490 
       
   491     // A change in size has required the view to be invalidated.
       
   492     if ([self inLiveResize]) {
       
   493         NSRect rects[4];
       
   494         NSInteger count;
       
   495         [self getRectsExposedDuringLiveResize:rects count:&count];
       
   496         while (count-- > 0)
       
   497         {
       
   498             [self setNeedsDisplayInRect:rects[count]];
       
   499         }
       
   500     } else {
       
   501         [self setNeedsDisplay:YES];
       
   502     }
       
   503 }
       
   504 
       
   505 - (void)drawRect:(NSRect)aRect
       
   506 {
       
   507     if (QApplicationPrivate::graphicsSystem() != 0) {
       
   508         if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore())
       
   509             bs->markDirty(qwidget->rect(), qwidget);
       
   510         qwidgetprivate->syncBackingStore(qwidget->rect());
       
   511         return;
       
   512     }
       
   513     CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
       
   514     qwidgetprivate->hd = cg;
       
   515     CGContextSaveGState(cg);
       
   516 
       
   517     if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event.
       
   518         if (qwidget->testAttribute(Qt::WA_WState_InPaintEvent))
       
   519             qWarning("QWidget::repaint: Recursive repaint detected");
       
   520 
       
   521         const QRect qrect = QRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);
       
   522         QRegion qrgn(qrect);
       
   523 
       
   524         if (!qwidget->isWindow() && !qobject_cast<QAbstractScrollArea *>(qwidget->parent())) {
       
   525             const QRegion &parentMask = qwidget->window()->mask();
       
   526             if (!parentMask.isEmpty()) {
       
   527                 const QPoint mappedPoint = qwidget->mapTo(qwidget->window(), qrect.topLeft());
       
   528                 qrgn.translate(mappedPoint);
       
   529                 qrgn &= parentMask;
       
   530                 qrgn.translate(-mappedPoint.x(), -mappedPoint.y());
       
   531             }
       
   532         }
       
   533 
       
   534         QPoint redirectionOffset(0, 0);
       
   535         //setup the context
       
   536         qwidget->setAttribute(Qt::WA_WState_InPaintEvent);
       
   537         QPaintEngine *engine = qwidget->paintEngine();
       
   538         if (engine)
       
   539             engine->setSystemClip(qrgn);
       
   540         if (qwidgetprivate->extra && qwidgetprivate->extra->hasMask) {
       
   541             CGRect widgetRect = CGRectMake(0, 0, qwidget->width(), qwidget->height());
       
   542             CGContextTranslateCTM (cg, 0, widgetRect.size.height);
       
   543             CGContextScaleCTM(cg, 1, -1);
       
   544             if (qwidget->isWindow())
       
   545                 CGContextClearRect(cg, widgetRect);
       
   546             CGContextClipToMask(cg, widgetRect, qwidgetprivate->extra->imageMask);
       
   547             CGContextScaleCTM(cg, 1, -1);
       
   548             CGContextTranslateCTM (cg, 0, -widgetRect.size.height);
       
   549         }
       
   550 
       
   551         if (qwidget->isWindow() && !qwidgetprivate->isOpaque
       
   552                 && !qwidget->testAttribute(Qt::WA_MacBrushedMetal)) {
       
   553             CGContextClearRect(cg, NSRectToCGRect(aRect));
       
   554         }
       
   555 
       
   556         if (engine && !qwidget->testAttribute(Qt::WA_NoSystemBackground)
       
   557             && (qwidget->isWindow() || qwidget->autoFillBackground())
       
   558                 || qwidget->testAttribute(Qt::WA_TintedBackground)
       
   559                 || qwidget->testAttribute(Qt::WA_StyledBackground)) {
       
   560 #ifdef DEBUG_WIDGET_PAINT
       
   561             if(doDebug)
       
   562                 qDebug(" Handling erase for [%s::%s]", qwidget->metaObject()->className(),
       
   563                        qwidget->objectName().local8Bit().data());
       
   564 #endif
       
   565             QPainter p(qwidget);
       
   566             qwidgetprivate->paintBackground(&p, qrgn,
       
   567                                             qwidget->isWindow() ? QWidgetPrivate::DrawAsRoot : 0);
       
   568             p.end();
       
   569         }
       
   570         QPaintEvent e(qrgn);
       
   571 #ifdef QT3_SUPPORT
       
   572         e.setErased(true);
       
   573 #endif
       
   574         qt_sendSpontaneousEvent(qwidget, &e);
       
   575         if (!redirectionOffset.isNull())
       
   576             QPainter::restoreRedirected(qwidget);
       
   577         if (engine)
       
   578             engine->setSystemClip(QRegion());
       
   579         qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false);
       
   580         if(!qwidget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && qwidget->paintingActive())
       
   581             qWarning("QWidget: It is dangerous to leave painters active on a"
       
   582                      " widget outside of the PaintEvent");
       
   583     }
       
   584     qwidgetprivate->hd = 0;
       
   585     CGContextRestoreGState(cg);
       
   586 }
       
   587 
       
   588 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
       
   589 {
       
   590     Q_UNUSED(theEvent);
       
   591     return !qwidget->testAttribute(Qt::WA_MacNoClickThrough);
       
   592 }
       
   593 
       
   594 - (NSView *)hitTest:(NSPoint)aPoint
       
   595 {
       
   596     if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents))
       
   597         return nil; // You cannot hit a transparent for mouse event widget.
       
   598     return [super hitTest:aPoint];
       
   599 }
       
   600 
       
   601 - (void)updateTrackingAreas
       
   602 {
       
   603     QMacCocoaAutoReleasePool pool;
       
   604     if (NSArray *trackingArray = [self trackingAreas]) {
       
   605         NSUInteger size = [trackingArray count];
       
   606         for (NSUInteger i = 0; i < size; ++i) {
       
   607             NSTrackingArea *t = [trackingArray objectAtIndex:i];
       
   608             [self removeTrackingArea:t];
       
   609         }
       
   610     }
       
   611 
       
   612     // Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should
       
   613     // only be turned on if mouseTracking, hover is on or a tool tip is set.
       
   614     // Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to
       
   615     // turn it on in ALL case. That means EVERY QCocoaView gets to pay the cost of
       
   616     // mouse moves delivered to it (Apple recommends keeping it OFF because there
       
   617     // is a performance hit). So it goes.
       
   618     NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
       
   619                                  | NSTrackingInVisibleRect | NSTrackingMouseMoved;
       
   620     NSTrackingArea *ta = [[NSTrackingArea alloc] initWithRect:NSMakeRect(0, 0,
       
   621                                                                          qwidget->width(),
       
   622                                                                          qwidget->height())
       
   623                                                       options:trackingOptions
       
   624                                                         owner:self
       
   625                                                      userInfo:nil];
       
   626     [self addTrackingArea:ta];
       
   627     [ta release];
       
   628 }
       
   629 
       
   630 - (void)mouseEntered:(NSEvent *)event
       
   631 {
       
   632     QEvent enterEvent(QEvent::Enter);
       
   633     NSPoint windowPoint = [event locationInWindow];
       
   634     NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint];
       
   635     NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil];
       
   636     if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
       
   637         QApplication::sendEvent(qwidget, &enterEvent);
       
   638         qt_mouseover = qwidget;
       
   639 
       
   640         // Update cursor and dispatch hover events.
       
   641         qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint());
       
   642         if (qwidget->testAttribute(Qt::WA_Hover) &&
       
   643             (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window())) {
       
   644             QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1));
       
   645             QApplicationPrivate::instance()->notify_helper(qwidget, &he);
       
   646         }
       
   647     }
       
   648 }
       
   649 
       
   650 - (void)mouseExited:(NSEvent *)event
       
   651 {
       
   652     QEvent leaveEvent(QEvent::Leave);
       
   653     NSPoint globalPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
       
   654     if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
       
   655         QApplication::sendEvent(qwidget, &leaveEvent);
       
   656 
       
   657         // ### Think about if it is necessary to update the cursor, should only be for a few cases.
       
   658         qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint());
       
   659         if (qwidget->testAttribute(Qt::WA_Hover)
       
   660             && (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window())) {
       
   661             QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1),
       
   662                            qwidget->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos));
       
   663             QApplicationPrivate::instance()->notify_helper(qwidget, &he);
       
   664         }
       
   665     }
       
   666 }
       
   667 
       
   668 - (void)flagsChanged:(NSEvent *)theEvent
       
   669 {
       
   670     QWidget *widgetToGetKey = qwidget;
       
   671 
       
   672     QWidget *popup = qAppInstance()->activePopupWidget();
       
   673     if (popup && popup != qwidget->window())
       
   674         widgetToGetKey = popup->focusWidget() ? popup->focusWidget() : popup;
       
   675     qt_dispatchModifiersChanged(theEvent, widgetToGetKey);
       
   676     [super flagsChanged:theEvent];
       
   677 }
       
   678 
       
   679 - (void)mouseMoved:(NSEvent *)theEvent
       
   680 {
       
   681     // We always enable mouse tracking for all QCocoaView-s. In cases where we have
       
   682     // child views, we will receive mouseMoved for both parent & the child (if
       
   683     // mouse is over the child). We need to ignore the parent mouseMoved in such
       
   684     // cases.
       
   685     NSPoint windowPoint = [theEvent locationInWindow];
       
   686     NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
       
   687     if (candidateView && candidateView == self) {
       
   688         qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton);
       
   689     }
       
   690 }
       
   691 
       
   692 - (void)mouseDown:(NSEvent *)theEvent
       
   693 {
       
   694     qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::LeftButton);
       
   695     // Don't call super here. This prevents us from getting the mouseUp event,
       
   696     // which we need to send even if the mouseDown event was not accepted.
       
   697     // (this is standard Qt behavior.)
       
   698 }
       
   699 
       
   700 
       
   701 - (void)mouseUp:(NSEvent *)theEvent
       
   702 {
       
   703     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::LeftButton);
       
   704 
       
   705     if (!mouseOK)
       
   706         [super mouseUp:theEvent];
       
   707 }
       
   708 
       
   709 - (void)rightMouseDown:(NSEvent *)theEvent
       
   710 {
       
   711     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton);
       
   712 
       
   713     if (!mouseOK)
       
   714         [super rightMouseDown:theEvent];
       
   715 }
       
   716 
       
   717 - (void)rightMouseUp:(NSEvent *)theEvent
       
   718 {
       
   719     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::RightButton);
       
   720 
       
   721     if (!mouseOK)
       
   722         [super rightMouseUp:theEvent];
       
   723 }
       
   724 
       
   725 - (void)otherMouseDown:(NSEvent *)theEvent
       
   726 {
       
   727     Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]);
       
   728     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, mouseButton);
       
   729 
       
   730     if (!mouseOK)
       
   731         [super otherMouseDown:theEvent];
       
   732 }
       
   733 
       
   734 - (void)otherMouseUp:(NSEvent *)theEvent
       
   735 {
       
   736     Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]);
       
   737     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent,  QEvent::MouseButtonRelease, mouseButton);
       
   738 
       
   739     if (!mouseOK)
       
   740         [super otherMouseUp:theEvent];
       
   741 
       
   742 }
       
   743 
       
   744 - (void)mouseDragged:(NSEvent *)theEvent
       
   745 {
       
   746     qMacDnDParams()->view = self;
       
   747     qMacDnDParams()->theEvent = theEvent;
       
   748     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::LeftButton);
       
   749 
       
   750     if (!mouseOK)
       
   751         [super mouseDragged:theEvent];
       
   752 }
       
   753 
       
   754 - (void)rightMouseDragged:(NSEvent *)theEvent
       
   755 {
       
   756     qMacDnDParams()->view = self;
       
   757     qMacDnDParams()->theEvent = theEvent;
       
   758     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::RightButton);
       
   759 
       
   760     if (!mouseOK)
       
   761         [super rightMouseDragged:theEvent];
       
   762 }
       
   763 
       
   764 - (void)otherMouseDragged:(NSEvent *)theEvent
       
   765 {
       
   766     qMacDnDParams()->view = self;
       
   767     qMacDnDParams()->theEvent = theEvent;
       
   768     Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]);
       
   769     bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, mouseButton);
       
   770 
       
   771     if (!mouseOK)
       
   772         [super otherMouseDragged:theEvent];
       
   773 }
       
   774 
       
   775 - (void)scrollWheel:(NSEvent *)theEvent
       
   776 {
       
   777     // Give the Input Manager a chance to process the wheel event.
       
   778     NSInputManager *currentIManager = [NSInputManager currentInputManager];
       
   779     if (currentIManager && [currentIManager wantsToHandleMouseEvents]) {
       
   780         [currentIManager handleMouseEvent:theEvent];
       
   781     }
       
   782 
       
   783     NSPoint windowPoint = [theEvent locationInWindow];
       
   784     NSPoint globalPoint = [[theEvent window] convertBaseToScreen:windowPoint];
       
   785     NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
       
   786     QPoint qlocal = QPoint(localPoint.x, localPoint.y);
       
   787     QPoint qglobal = QPoint(globalPoint.x, globalPoint.y);
       
   788     Qt::MouseButton buttons = cocoaButton2QtButton([theEvent buttonNumber]);
       
   789     bool wheelOK = false;
       
   790     Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]);
       
   791     QWidget *widgetToGetMouse = qwidget;
       
   792     int deltaX = 0;
       
   793     int deltaY = 0;
       
   794     int deltaZ = 0;
       
   795 
       
   796     const EventRef carbonEvent = (EventRef)[theEvent eventRef];
       
   797     const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0;
       
   798     if (carbonEventKind == kEventMouseScroll) {
       
   799         // The mouse device containts pixel scroll wheel support (Mighty Mouse, Trackpad).
       
   800         // Since deviceDelta is delivered as pixels rather than degrees, we need to
       
   801         // convert from pixels to degrees in a sensible manner.
       
   802         // It looks like four degrees per pixel behaves most native.
       
   803         // Qt expects the unit for delta to be 1/8 of a degree:
       
   804         const int scrollFactor = 4 * 8;
       
   805         deltaX = (int)[theEvent deviceDeltaX] * scrollFactor;
       
   806         deltaY = (int)[theEvent deviceDeltaY] * scrollFactor;
       
   807         deltaZ = (int)[theEvent deviceDeltaZ] * scrollFactor;
       
   808     } else { // carbonEventKind == kEventMouseWheelMoved
       
   809         // Mouse wheel deltas seem to tick in at increments of 0.1.
       
   810         // Qt widgets expect the delta to be a multiple of 120.
       
   811         const int scrollFactor = 10 * 120;
       
   812         deltaX = [theEvent deltaX] * scrollFactor;
       
   813         deltaY = [theEvent deltaY] * scrollFactor;
       
   814         deltaZ = [theEvent deltaZ] * scrollFactor;
       
   815     }
       
   816 
       
   817     if (deltaX != 0) {
       
   818         QWheelEvent qwe(qlocal, qglobal, deltaX, buttons, keyMods, Qt::Horizontal);
       
   819         qt_sendSpontaneousEvent(widgetToGetMouse, &qwe);
       
   820         wheelOK = qwe.isAccepted();
       
   821         if (!wheelOK && QApplicationPrivate::focus_widget
       
   822             && QApplicationPrivate::focus_widget != widgetToGetMouse) {
       
   823             QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal,
       
   824                              deltaX, buttons, keyMods, Qt::Horizontal);
       
   825             qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
       
   826             wheelOK = qwe2.isAccepted();
       
   827         }
       
   828     }
       
   829 
       
   830     if (deltaY) {
       
   831         QWheelEvent qwe(qlocal, qglobal, deltaY, buttons, keyMods, Qt::Vertical);
       
   832         qt_sendSpontaneousEvent(widgetToGetMouse, &qwe);
       
   833         wheelOK = qwe.isAccepted();
       
   834         if (!wheelOK && QApplicationPrivate::focus_widget
       
   835             && QApplicationPrivate::focus_widget != widgetToGetMouse) {
       
   836             QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal,
       
   837                              deltaY, buttons, keyMods, Qt::Vertical);
       
   838             qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
       
   839             wheelOK = qwe2.isAccepted();
       
   840         }
       
   841     }
       
   842 
       
   843     if (deltaZ) {
       
   844         // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to
       
   845         // try to be ahead of the pack, I'm adding this extra value.
       
   846         QWheelEvent qwe(qlocal, qglobal, deltaZ, buttons, keyMods, (Qt::Orientation)3);
       
   847         qt_sendSpontaneousEvent(widgetToGetMouse, &qwe);
       
   848         wheelOK = qwe.isAccepted();
       
   849         if (!wheelOK && QApplicationPrivate::focus_widget
       
   850             && QApplicationPrivate::focus_widget != widgetToGetMouse) {
       
   851             QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal,
       
   852                              deltaZ, buttons, keyMods, (Qt::Orientation)3);
       
   853             qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
       
   854             wheelOK = qwe2.isAccepted();
       
   855         }
       
   856     }
       
   857     if (!wheelOK) {
       
   858         return [super scrollWheel:theEvent];
       
   859     }
       
   860 }
       
   861 
       
   862 - (void)tabletProximity:(NSEvent *)tabletEvent
       
   863 {
       
   864     qt_dispatchTabletProximityEvent(tabletEvent);
       
   865 }
       
   866 
       
   867 - (void)tabletPoint:(NSEvent *)tabletEvent
       
   868 {
       
   869     if (!qt_mac_handleTabletEvent(self, tabletEvent))
       
   870         [super tabletPoint:tabletEvent];
       
   871 }
       
   872 
       
   873 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
       
   874 - (void)touchesBeganWithEvent:(NSEvent *)event;
       
   875 {
       
   876     bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
       
   877     qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
       
   878 }
       
   879 
       
   880 - (void)touchesMovedWithEvent:(NSEvent *)event;
       
   881 {
       
   882     bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
       
   883     qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
       
   884 }
       
   885 
       
   886 - (void)touchesEndedWithEvent:(NSEvent *)event;
       
   887 {
       
   888     bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
       
   889     qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
       
   890 }
       
   891 
       
   892 - (void)touchesCancelledWithEvent:(NSEvent *)event;
       
   893 {
       
   894     bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
       
   895     qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
       
   896 }
       
   897 
       
   898 - (void)magnifyWithEvent:(NSEvent *)event;
       
   899 {
       
   900     if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
       
   901         return;
       
   902 
       
   903     QNativeGestureEvent qNGEvent;
       
   904     qNGEvent.gestureType = QNativeGestureEvent::Zoom;
       
   905     NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
       
   906     qNGEvent.position = flipPoint(p).toPoint();
       
   907     qNGEvent.percentage = [event magnification];
       
   908     qt_sendSpontaneousEvent(qwidget, &qNGEvent);
       
   909 }
       
   910 
       
   911 - (void)rotateWithEvent:(NSEvent *)event;
       
   912 {
       
   913     if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
       
   914         return;
       
   915 
       
   916     QNativeGestureEvent qNGEvent;
       
   917     qNGEvent.gestureType = QNativeGestureEvent::Rotate;
       
   918     NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
       
   919     qNGEvent.position = flipPoint(p).toPoint();
       
   920     qNGEvent.percentage = -[event rotation];
       
   921     qt_sendSpontaneousEvent(qwidget, &qNGEvent);
       
   922 }
       
   923 
       
   924 - (void)swipeWithEvent:(NSEvent *)event;
       
   925 {
       
   926     if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
       
   927         return;
       
   928 
       
   929     QNativeGestureEvent qNGEvent;
       
   930     qNGEvent.gestureType = QNativeGestureEvent::Swipe;
       
   931     NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
       
   932     qNGEvent.position = flipPoint(p).toPoint();
       
   933     if ([event deltaX] == 1)
       
   934         qNGEvent.angle = 180.0f;
       
   935     else if ([event deltaX] == -1)
       
   936         qNGEvent.angle = 0.0f;
       
   937     else if ([event deltaY] == 1)
       
   938         qNGEvent.angle = 90.0f;
       
   939     else if ([event deltaY] == -1)
       
   940         qNGEvent.angle = 270.0f;
       
   941     qt_sendSpontaneousEvent(qwidget, &qNGEvent);
       
   942 }
       
   943 
       
   944 - (void)beginGestureWithEvent:(NSEvent *)event;
       
   945 {
       
   946     if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
       
   947         return;
       
   948 
       
   949     QNativeGestureEvent qNGEvent;
       
   950     qNGEvent.gestureType = QNativeGestureEvent::GestureBegin;
       
   951     NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
       
   952     qNGEvent.position = flipPoint(p).toPoint();
       
   953     qt_sendSpontaneousEvent(qwidget, &qNGEvent);
       
   954 }
       
   955 
       
   956 - (void)endGestureWithEvent:(NSEvent *)event;
       
   957 {
       
   958     if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
       
   959         return;
       
   960 
       
   961     QNativeGestureEvent qNGEvent;
       
   962     qNGEvent.gestureType = QNativeGestureEvent::GestureEnd;
       
   963     NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
       
   964     qNGEvent.position = flipPoint(p).toPoint();
       
   965     qt_sendSpontaneousEvent(qwidget, &qNGEvent);
       
   966 }
       
   967 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
       
   968 
       
   969 - (void)frameDidChange:(NSNotification *)note
       
   970 {
       
   971     Q_UNUSED(note);
       
   972     if (qwidget->isWindow())
       
   973         return;
       
   974     NSRect newFrame = [self frame];
       
   975     QRect newGeo(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height);
       
   976     bool moved = qwidget->testAttribute(Qt::WA_Moved);
       
   977     bool resized = qwidget->testAttribute(Qt::WA_Resized);
       
   978     qwidget->setGeometry(newGeo);
       
   979     qwidget->setAttribute(Qt::WA_Moved, moved);
       
   980     qwidget->setAttribute(Qt::WA_Resized, resized);
       
   981     qwidgetprivate->syncCocoaMask();
       
   982 }
       
   983 
       
   984 - (BOOL)isEnabled
       
   985 {
       
   986     if (!qwidget)
       
   987         return [super isEnabled];
       
   988     return [super isEnabled] && qwidget->isEnabled();
       
   989 }
       
   990 
       
   991 - (void)setEnabled:(BOOL)flag
       
   992 {
       
   993     QMacCocoaAutoReleasePool pool;
       
   994     [super setEnabled:flag];
       
   995     if (qwidget->isEnabled() != flag)
       
   996         qwidget->setEnabled(flag);
       
   997 }
       
   998 
       
   999 + (Class)cellClass
       
  1000 {
       
  1001     return [NSActionCell class];
       
  1002 }
       
  1003 
       
  1004 - (BOOL)acceptsFirstResponder
       
  1005 {
       
  1006     if (qwidget->isWindow())
       
  1007         return YES;  // Always do it, so that windows can accept key press events.
       
  1008     return qwidget->focusPolicy() != Qt::NoFocus;
       
  1009 }
       
  1010 
       
  1011 - (BOOL)resignFirstResponder
       
  1012 {
       
  1013     // Seems like the following test only triggers if this
       
  1014     // view is inside a QMacNativeWidget:
       
  1015     if (qwidget == QApplication::focusWidget())
       
  1016         QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
       
  1017     return YES;
       
  1018 }
       
  1019 
       
  1020 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
       
  1021 {
       
  1022     Q_UNUSED(isLocal);
       
  1023     return supportedActions;
       
  1024 }
       
  1025 
       
  1026 - (void)setSupportedActions:(NSDragOperation)actions
       
  1027 {
       
  1028     supportedActions = actions;
       
  1029 }
       
  1030 
       
  1031 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
       
  1032 {
       
  1033     Q_UNUSED(anImage);
       
  1034     Q_UNUSED(aPoint);
       
  1035     qMacDnDParams()->performedAction = operation;
       
  1036     if (QDragManager::self()->object
       
  1037         && QDragManager::self()->dragPrivate()->executed_action != Qt::ActionMask) {
       
  1038         qMacDnDParams()->performedAction =
       
  1039                 qt_mac_mapDropAction(QDragManager::self()->dragPrivate()->executed_action);
       
  1040     }
       
  1041 }
       
  1042 
       
  1043 - (QWidget *)qt_qwidget
       
  1044 {
       
  1045     return qwidget;
       
  1046 }
       
  1047 
       
  1048 - (BOOL)qt_leftButtonIsRightButton
       
  1049 {
       
  1050     return leftButtonIsRightButton;
       
  1051 }
       
  1052 
       
  1053 - (void)qt_setLeftButtonIsRightButton:(BOOL)isSwapped
       
  1054 {
       
  1055     leftButtonIsRightButton = isSwapped;
       
  1056 }
       
  1057 
       
  1058 + (DnDParams*)currentMouseEvent
       
  1059 {
       
  1060     return qMacDnDParams();
       
  1061 }
       
  1062 
       
  1063 - (void)keyDown:(NSEvent *)theEvent
       
  1064 {
       
  1065     sendKeyEvents = true;
       
  1066 
       
  1067     QWidget *widgetToGetKey = qwidget;
       
  1068 
       
  1069     QWidget *popup = qAppInstance()->activePopupWidget();
       
  1070     bool sendToPopup = false;
       
  1071     if (popup && popup != qwidget->window()) {
       
  1072         widgetToGetKey = popup->focusWidget() ? popup->focusWidget() : popup;
       
  1073         sendToPopup = true;
       
  1074     }
       
  1075 
       
  1076     if (widgetToGetKey->testAttribute(Qt::WA_InputMethodEnabled)
       
  1077             && !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly
       
  1078                  || widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly
       
  1079                  || widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) {
       
  1080         [qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]];
       
  1081     }
       
  1082     if (sendKeyEvents && !composing) {
       
  1083         bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey);
       
  1084         if (!keyOK && !sendToPopup)
       
  1085             [super keyDown:theEvent];
       
  1086     }
       
  1087 }
       
  1088 
       
  1089 
       
  1090 - (void)keyUp:(NSEvent *)theEvent
       
  1091 {
       
  1092     if (sendKeyEvents) {
       
  1093         bool keyOK = qt_dispatchKeyEvent(theEvent, qwidget);
       
  1094         if (!keyOK)
       
  1095             [super keyUp:theEvent];
       
  1096     }
       
  1097 }
       
  1098 
       
  1099 - (void)viewWillMoveToWindow:(NSWindow *)window
       
  1100 {
       
  1101     if (qwidget->windowFlags() & Qt::MSWindowsOwnDC
       
  1102           && (window != [self window])) { // OpenGL Widget
       
  1103         // Create a stupid ClearDrawable Event
       
  1104         QEvent event(QEvent::MacGLClearDrawable);
       
  1105         qApp->sendEvent(qwidget, &event);
       
  1106     }
       
  1107 }
       
  1108 
       
  1109 - (void)viewDidMoveToWindow
       
  1110 {
       
  1111     if (qwidget->windowFlags() & Qt::MSWindowsOwnDC && [self window]) {
       
  1112         // call update paint event
       
  1113         qwidgetprivate->needWindowChange = true;
       
  1114         QEvent event(QEvent::MacGLWindowChange);
       
  1115         qApp->sendEvent(qwidget, &event);
       
  1116     }
       
  1117 }
       
  1118 
       
  1119 
       
  1120 // NSTextInput Protocol implementation
       
  1121 
       
  1122 - (void) insertText:(id)aString
       
  1123 {
       
  1124     QString commitText;
       
  1125     if ([aString length]) {
       
  1126         if ([aString isKindOfClass:[NSAttributedString class]]) {
       
  1127             commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string]));
       
  1128         } else {
       
  1129             commitText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString));
       
  1130         };
       
  1131     }
       
  1132 
       
  1133     if ([aString length] && composing) {
       
  1134         // Send the commit string to the widget.
       
  1135         composing = false;
       
  1136         sendKeyEvents = false;
       
  1137         QInputMethodEvent e;
       
  1138         e.setCommitString(commitText);
       
  1139         qt_sendSpontaneousEvent(qwidget, &e);
       
  1140     } else {
       
  1141         // The key sequence "`q" on a French Keyboard will generate two calls to insertText before
       
  1142         // it returns from interpretKeyEvents. The first call will turn off 'composing' and accept
       
  1143         // the "`" key. The last keyDown event needs to be processed by the widget to get the
       
  1144         // character "q". The string parameter is ignored for the second call.
       
  1145         sendKeyEvents = true;
       
  1146     }
       
  1147 
       
  1148     composingText->clear();
       
  1149 }
       
  1150 
       
  1151 - (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange
       
  1152 {
       
  1153     // Generate the QInputMethodEvent with preedit string and the attributes
       
  1154     // for rendering it. The attributes handled here are 'underline',
       
  1155     // 'underline color' and 'cursor position'.
       
  1156     sendKeyEvents = false;
       
  1157     composing = true;
       
  1158     QString qtText;
       
  1159     // Cursor position is retrived from the range.
       
  1160     QList<QInputMethodEvent::Attribute> attrs;
       
  1161     attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location, 1, QVariant());
       
  1162     if ([aString isKindOfClass:[NSAttributedString class]]) {
       
  1163         qtText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string]));
       
  1164         composingLength = qtText.length();
       
  1165         int index = 0;
       
  1166         // Create attributes for individual sections of preedit text
       
  1167         while (index < composingLength) {
       
  1168             NSRange effectiveRange;
       
  1169             NSRange range = NSMakeRange(index, composingLength-index);
       
  1170             NSDictionary *attributes = [aString attributesAtIndex:index
       
  1171                                             longestEffectiveRange:&effectiveRange
       
  1172                                                           inRange:range];
       
  1173             NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName];
       
  1174             if (underlineStyle) {
       
  1175                 QColor clr (Qt::black);
       
  1176                 NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName];
       
  1177                 if (color) {
       
  1178                     clr = colorFrom(color);
       
  1179                 }
       
  1180                 QTextCharFormat format;
       
  1181                 format.setFontUnderline(true);
       
  1182                 format.setUnderlineColor(clr);
       
  1183                 attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
       
  1184                                                     effectiveRange.location,
       
  1185                                                     effectiveRange.length,
       
  1186                                                     format);
       
  1187             }
       
  1188             index = effectiveRange.location + effectiveRange.length;
       
  1189         }
       
  1190     } else {
       
  1191         // No attributes specified, take only the preedit text.
       
  1192         qtText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString));
       
  1193         composingLength = qtText.length();
       
  1194     }
       
  1195     // Make sure that we have at least one text format.
       
  1196     if (attrs.size() <= 1) {
       
  1197         QTextCharFormat format;
       
  1198         format.setFontUnderline(true);
       
  1199         attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
       
  1200                                             0, composingLength, format);
       
  1201     }
       
  1202     *composingText = qtText;
       
  1203     QInputMethodEvent e(qtText, attrs);
       
  1204     qt_sendSpontaneousEvent(qwidget, &e);
       
  1205     if (!composingLength)
       
  1206         composing = false;
       
  1207 }
       
  1208 
       
  1209 - (void) unmarkText
       
  1210 {
       
  1211     if (composing) {
       
  1212         QInputMethodEvent e;
       
  1213         e.setCommitString(*composingText);
       
  1214         qt_sendSpontaneousEvent(qwidget, &e);
       
  1215     }
       
  1216     composingText->clear();
       
  1217     composing = false;
       
  1218 }
       
  1219 
       
  1220 - (BOOL) hasMarkedText
       
  1221 {
       
  1222     return (composing ? YES: NO);
       
  1223 }
       
  1224 
       
  1225 - (void) doCommandBySelector:(SEL)aSelector
       
  1226 {
       
  1227     Q_UNUSED(aSelector);
       
  1228 }
       
  1229 
       
  1230 - (BOOL)isComposing
       
  1231 {
       
  1232     return composing;
       
  1233 }
       
  1234 
       
  1235 - (NSInteger) conversationIdentifier
       
  1236 {
       
  1237     // Return a unique identifier fot this ime conversation
       
  1238     return (NSInteger)self;
       
  1239 }
       
  1240 
       
  1241 - (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange
       
  1242 {
       
  1243     QString selectedText(qwidget->inputMethodQuery(Qt::ImCurrentSelection).toString());
       
  1244     if (!selectedText.isEmpty()) {
       
  1245         QCFString string(selectedText.mid(theRange.location, theRange.length));
       
  1246         const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
       
  1247         return [[[NSAttributedString alloc]  initWithString:tmpString] autorelease];
       
  1248     } else {
       
  1249         return nil;
       
  1250     }
       
  1251 }
       
  1252 
       
  1253 - (NSRange) markedRange
       
  1254 {
       
  1255     NSRange range;
       
  1256     if (composing) {
       
  1257         range.location = 0;
       
  1258         range.length = composingLength;
       
  1259     } else {
       
  1260         range.location = NSNotFound;
       
  1261         range.length = 0;
       
  1262     }
       
  1263     return range;
       
  1264 }
       
  1265 
       
  1266 - (NSRange) selectedRange
       
  1267 {
       
  1268     NSRange selRange;
       
  1269     QString selectedText(qwidget->inputMethodQuery(Qt::ImCurrentSelection).toString());
       
  1270     if (!selectedText.isEmpty()) {
       
  1271         // Consider only the selected text.
       
  1272         selRange.location = 0;
       
  1273         selRange.length = selectedText.length();
       
  1274     } else {
       
  1275         // No selected text.
       
  1276         selRange.location = NSNotFound;
       
  1277         selRange.length = 0;
       
  1278     }
       
  1279     return selRange;
       
  1280 
       
  1281 }
       
  1282 
       
  1283 - (NSRect) firstRectForCharacterRange:(NSRange)theRange
       
  1284 {
       
  1285     Q_UNUSED(theRange);
       
  1286     // The returned rect is always based on the internal cursor.
       
  1287     QRect mr(qwidget->inputMethodQuery(Qt::ImMicroFocus).toRect());
       
  1288     QPoint mp(qwidget->mapToGlobal(QPoint(mr.bottomLeft())));
       
  1289     NSRect rect ;
       
  1290     rect.origin.x = mp.x();
       
  1291     rect.origin.y = flipYCoordinate(mp.y());
       
  1292     rect.size.width = mr.width();
       
  1293     rect.size.height = mr.height();
       
  1294     return rect;
       
  1295 }
       
  1296 
       
  1297 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
       
  1298 {
       
  1299     // We dont support cursor movements using mouse while composing.
       
  1300     Q_UNUSED(thePoint);
       
  1301     return NSNotFound;
       
  1302 }
       
  1303 
       
  1304 - (NSArray*) validAttributesForMarkedText
       
  1305 {
       
  1306     if (!qwidget->testAttribute(Qt::WA_InputMethodEnabled))
       
  1307         return nil;  // Not sure if that's correct, but it's saves a malloc.
       
  1308 
       
  1309     // Support only underline color/style.
       
  1310     return [NSArray arrayWithObjects:NSUnderlineColorAttributeName,
       
  1311                                      NSUnderlineStyleAttributeName, nil];
       
  1312 }
       
  1313 @end
       
  1314 
       
  1315 QT_BEGIN_NAMESPACE
       
  1316 void QMacInputContext::reset()
       
  1317 {
       
  1318     QWidget *w = QInputContext::focusWidget();
       
  1319     if (w) {
       
  1320         NSView *view = qt_mac_nativeview_for(w);
       
  1321         if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
       
  1322             QMacCocoaAutoReleasePool pool;
       
  1323             QT_MANGLE_NAMESPACE(QCocoaView) *qc = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view);
       
  1324             NSInputManager *currentIManager = [NSInputManager currentInputManager];
       
  1325             if (currentIManager) {
       
  1326                 [currentIManager markedTextAbandoned:view];
       
  1327                 [qc unmarkText];
       
  1328             }
       
  1329         }
       
  1330     }
       
  1331 }
       
  1332 
       
  1333 bool QMacInputContext::isComposing() const
       
  1334 {
       
  1335     QWidget *w = QInputContext::focusWidget();
       
  1336     if (w) {
       
  1337         NSView *view = qt_mac_nativeview_for(w);
       
  1338         if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
       
  1339             return [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) isComposing];
       
  1340         }
       
  1341     }
       
  1342     return false;
       
  1343 }
       
  1344 
       
  1345 extern bool qt_mac_in_drag;
       
  1346 void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm);
       
  1347 static const int default_pm_hotx = -2;
       
  1348 static const int default_pm_hoty = -16;
       
  1349 static const char* default_pm[] = {
       
  1350     "13 9 3 1",
       
  1351     ".      c None",
       
  1352     "       c #000000",
       
  1353     "X      c #FFFFFF",
       
  1354     "X X X X X X X",
       
  1355     " X X X X X X ",
       
  1356     "X ......... X",
       
  1357     " X.........X ",
       
  1358     "X ......... X",
       
  1359     " X.........X ",
       
  1360     "X ......... X",
       
  1361     " X X X X X X ",
       
  1362     "X X X X X X X",
       
  1363 };
       
  1364 
       
  1365 Qt::DropAction QDragManager::drag(QDrag *o)
       
  1366 {
       
  1367     if(qt_mac_in_drag) {     //just make sure..
       
  1368         qWarning("Qt: Internal error: WH0A, unexpected condition reached");
       
  1369         return Qt::IgnoreAction;
       
  1370     }
       
  1371     if(object == o)
       
  1372         return Qt::IgnoreAction;
       
  1373     /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button
       
  1374      so we just bail early to prevent it */
       
  1375     if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary))
       
  1376         return Qt::IgnoreAction;
       
  1377 
       
  1378     if(object) {
       
  1379         dragPrivate()->source->removeEventFilter(this);
       
  1380         cancel();
       
  1381         beingCancelled = false;
       
  1382     }
       
  1383 
       
  1384     object = o;
       
  1385     dragPrivate()->target = 0;
       
  1386 
       
  1387 #ifndef QT_NO_ACCESSIBILITY
       
  1388     QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart);
       
  1389 #endif
       
  1390 
       
  1391     // setup the data
       
  1392     QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND);
       
  1393     dragPrivate()->data->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray());
       
  1394     dragBoard.setMimeData(dragPrivate()->data);
       
  1395 
       
  1396     // create the image
       
  1397     QPoint hotspot;
       
  1398     QPixmap pix = dragPrivate()->pixmap;
       
  1399     if(pix.isNull()) {
       
  1400         if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) {
       
  1401             // get the string
       
  1402             QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text()
       
  1403             : dragPrivate()->data->urls().first().toString();
       
  1404             if(s.length() > 26)
       
  1405                 s = s.left(23) + QChar(0x2026);
       
  1406             if(!s.isEmpty()) {
       
  1407                 // draw it
       
  1408                 QFont f(qApp->font());
       
  1409                 f.setPointSize(12);
       
  1410                 QFontMetrics fm(f);
       
  1411                 QPixmap tmp(fm.width(s), fm.height());
       
  1412                 if(!tmp.isNull()) {
       
  1413                     QPainter p(&tmp);
       
  1414                     p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0);
       
  1415                     p.setPen(Qt::color1);
       
  1416                     p.setFont(f);
       
  1417                     p.drawText(0, fm.ascent(), s);
       
  1418                     // save it
       
  1419                     pix = tmp;
       
  1420                     hotspot = QPoint(tmp.width() / 2, tmp.height() / 2);
       
  1421                 }
       
  1422             }
       
  1423         } else {
       
  1424             pix = QPixmap(default_pm);
       
  1425             hotspot = QPoint(default_pm_hotx, default_pm_hoty);
       
  1426         }
       
  1427     } else {
       
  1428         hotspot = dragPrivate()->hotspot;
       
  1429     }
       
  1430     // convert the image to NSImage.
       
  1431     NSImage *image = (NSImage *)qt_mac_create_nsimage(pix);
       
  1432     [image retain];
       
  1433     DnDParams dndParams = *[QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
       
  1434     // save supported actions
       
  1435     [dndParams.view setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)];
       
  1436     NSPoint imageLoc = {dndParams.localPoint.x - hotspot.x(),
       
  1437                         dndParams.localPoint.y + pix.height() - hotspot.y()};
       
  1438     NSSize mouseOffset = {0.0, 0.0};
       
  1439     NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
       
  1440     NSPoint windowPoint = [dndParams.theEvent locationInWindow];
       
  1441     dragPrivate()->executed_action = Qt::ActionMask;
       
  1442     // do the drag
       
  1443     [dndParams.view retain];
       
  1444     [dndParams.view dragImage:image
       
  1445                             at:imageLoc
       
  1446                         offset:mouseOffset
       
  1447                          event:dndParams.theEvent
       
  1448                     pasteboard:pboard
       
  1449                         source:dndParams.view
       
  1450                      slideBack:YES];
       
  1451     [dndParams.view release];
       
  1452     [image release];
       
  1453     dragPrivate()->executed_action = Qt::IgnoreAction;
       
  1454     object = 0;
       
  1455     Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams.performedAction));
       
  1456     // do post drag processing, if required.
       
  1457     if(performedAction != Qt::IgnoreAction) {
       
  1458         // check if the receiver points us to a file location.
       
  1459         // if so, we need to do the file copy/move ourselves.
       
  1460         QCFType<CFURLRef> pasteLocation = 0;
       
  1461         PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation);
       
  1462         if (pasteLocation) {
       
  1463             QList<QUrl> urls = o->mimeData()->urls();
       
  1464             for (int i = 0; i < urls.size(); ++i) {
       
  1465                 QUrl fromUrl = urls.at(i);
       
  1466                 QString filename = QFileInfo(fromUrl.path()).fileName();
       
  1467                 QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename);
       
  1468                 if (performedAction == Qt::MoveAction)
       
  1469                     QFile::rename(fromUrl.path(), toUrl.path());
       
  1470                 else if (performedAction == Qt::CopyAction)
       
  1471                     QFile::copy(fromUrl.path(), toUrl.path());
       
  1472             }
       
  1473         }
       
  1474     }
       
  1475     return performedAction;
       
  1476 }
       
  1477 
       
  1478 QT_END_NAMESPACE
       
  1479 
       
  1480 #endif // QT_MAC_USE_COCOA