src/gui/kernel/qapplication_mac.mm
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   102 #include "qwidget.h"
   102 #include "qwidget.h"
   103 #include "qcolormap.h"
   103 #include "qcolormap.h"
   104 #include "qdir.h"
   104 #include "qdir.h"
   105 #include "qdebug.h"
   105 #include "qdebug.h"
   106 #include "qtimer.h"
   106 #include "qtimer.h"
       
   107 #include "qurl.h"
   107 #include "private/qmacinputcontext_p.h"
   108 #include "private/qmacinputcontext_p.h"
   108 #include "private/qpaintengine_mac_p.h"
   109 #include "private/qpaintengine_mac_p.h"
   109 #include "private/qcursor_p.h"
   110 #include "private/qcursor_p.h"
   110 #include "private/qapplication_p.h"
   111 #include "private/qapplication_p.h"
   111 #include "private/qcolor_p.h"
   112 #include "private/qcolor_p.h"
   964 struct QMacAppleEventTypeSpec {
   965 struct QMacAppleEventTypeSpec {
   965     AEEventClass mac_class;
   966     AEEventClass mac_class;
   966     AEEventID mac_id;
   967     AEEventID mac_id;
   967 } app_apple_events[] = {
   968 } app_apple_events[] = {
   968     { kCoreEventClass, kAEQuitApplication },
   969     { kCoreEventClass, kAEQuitApplication },
   969     { kCoreEventClass, kAEOpenDocuments }
   970     { kCoreEventClass, kAEOpenDocuments },
       
   971     { kInternetEventClass, kAEGetURL },
   970 };
   972 };
   971 
   973 
   972 #ifndef QT_MAC_USE_COCOA
   974 #ifndef QT_MAC_USE_COCOA
   973 
   975 
   974 #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
   976 #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
  1199 #endif
  1201 #endif
  1200         if (!app_proc_ae_handlerUPP) {
  1202         if (!app_proc_ae_handlerUPP) {
  1201             app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
  1203             app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
  1202             for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
  1204             for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
  1203                 AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
  1205                 AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
  1204                         app_proc_ae_handlerUPP, SRefCon(qApp), true);
  1206                         app_proc_ae_handlerUPP, SRefCon(qApp), false);
  1205         }
  1207         }
  1206 
  1208 
  1207         if (QApplicationPrivate::app_style) {
  1209         if (QApplicationPrivate::app_style) {
  1208             QEvent ev(QEvent::Style);
  1210             QEvent ev(QEvent::Style);
  1209             qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
  1211             qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
  1235         }
  1237         }
  1236 
  1238 
  1237         [cocoaApp setMenu:[qtMenuLoader menu]];
  1239         [cocoaApp setMenu:[qtMenuLoader menu]];
  1238         [newDelegate setMenuLoader:qtMenuLoader];
  1240         [newDelegate setMenuLoader:qtMenuLoader];
  1239         [qtMenuLoader release];
  1241         [qtMenuLoader release];
       
  1242 
       
  1243         NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
       
  1244         [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
       
  1245           forEventClass:kInternetEventClass andEventID:kAEGetURL];
  1240     }
  1246     }
  1241 #endif
  1247 #endif
  1242     // Register for Carbon tablet proximity events on the event monitor target.
  1248     // Register for Carbon tablet proximity events on the event monitor target.
  1243     // This means that we should receive proximity events even when we aren't the active application.
  1249     // This means that we should receive proximity events even when we aren't the active application.
  1244     if (!tablet_proximity_handler) {
  1250     if (!tablet_proximity_handler) {
  1679         Qt::MouseButtons buttons;
  1685         Qt::MouseButtons buttons;
  1680         {
  1686         {
  1681             UInt32 mac_buttons = 0;
  1687             UInt32 mac_buttons = 0;
  1682             GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0,
  1688             GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0,
  1683                               sizeof(mac_buttons), 0, &mac_buttons);
  1689                               sizeof(mac_buttons), 0, &mac_buttons);
  1684             buttons = qt_mac_get_buttons(mac_buttons);
  1690             if (ekind != kEventMouseWheelMoved)
       
  1691                 buttons = qt_mac_get_buttons(mac_buttons);
       
  1692             else
       
  1693                 buttons = QApplication::mouseButtons();
  1685         }
  1694         }
  1686 
  1695 
  1687         int wheel_deltaX = 0;
  1696         int wheel_deltaX = 0;
  1688         int wheel_deltaY = 0;
  1697         int wheel_deltaY = 0;
  1689         static EventRef compatibilityEvent = 0;
  1698         static EventRef compatibilityEvent = 0;
  1695             // compatibility with older applications, carbon will also send us
  1704             // compatibility with older applications, carbon will also send us
  1696             // kEventMouseWheelMoved events if we dont eat this event
  1705             // kEventMouseWheelMoved events if we dont eat this event
  1697             // (actually two events; one for horizontal and one for vertical).
  1706             // (actually two events; one for horizontal and one for vertical).
  1698             // As a results of this, and to make sure we dont't receive duplicate events,
  1707             // As a results of this, and to make sure we dont't receive duplicate events,
  1699             // we try to detect when this happend by checking the 'compatibilityEvent'. 
  1708             // we try to detect when this happend by checking the 'compatibilityEvent'. 
  1700             const int scrollFactor = 4 * 8;
       
  1701             SInt32 mdelt = 0;
  1709             SInt32 mdelt = 0;
  1702             GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0,
  1710             GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0,
  1703                               sizeof(mdelt), 0, &mdelt);
  1711                               sizeof(mdelt), 0, &mdelt);
  1704             wheel_deltaX = mdelt * scrollFactor;
  1712             wheel_deltaX = mdelt;
  1705             mdelt = 0;
  1713             mdelt = 0;
  1706             GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0,
  1714             GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0,
  1707                               sizeof(mdelt), 0, &mdelt);
  1715                               sizeof(mdelt), 0, &mdelt);
  1708             wheel_deltaY = mdelt * scrollFactor;
  1716             wheel_deltaY = mdelt;
  1709             GetEventParameter(event, kEventParamEventRef, typeEventRef, 0,
  1717             GetEventParameter(event, kEventParamEventRef, typeEventRef, 0,
  1710                               sizeof(compatibilityEvent), 0, &compatibilityEvent);
  1718                               sizeof(compatibilityEvent), 0, &compatibilityEvent);
  1711         } else if (ekind == kEventMouseWheelMoved) {
  1719         } else if (ekind == kEventMouseWheelMoved) {
  1712             if (event != compatibilityEvent) {
  1720             if (event != compatibilityEvent) {
  1713                 compatibilityEvent = 0;
  1721                 compatibilityEvent = 0;
  1716                         sizeof(mdelt), 0, &mdelt);
  1724                         sizeof(mdelt), 0, &mdelt);
  1717                 EventMouseWheelAxis axis;
  1725                 EventMouseWheelAxis axis;
  1718                 GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0,
  1726                 GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0,
  1719                         sizeof(axis), 0, &axis);
  1727                         sizeof(axis), 0, &axis);
  1720 
  1728 
  1721                 // The 'new' event has acceleration applied by the OS, while the old (on
  1729                 // Remove acceleration, and use either -120 or 120 as delta:
  1722                 // Carbon only), has not. So we introduce acceleration here to be consistent.
       
  1723                 // The acceleration is trying to respect both pixel based and line scrolling,
       
  1724                 // which turns out to be rather difficult.
       
  1725                 int linesToScroll = mdelt > 0 ? 1 : -1;
       
  1726                 static QTime t;
       
  1727                 int elapsed = t.elapsed();
       
  1728                 t.restart();
       
  1729                 if (elapsed < 20)
       
  1730                     linesToScroll *= 120;
       
  1731                 else if (elapsed < 30)
       
  1732                     linesToScroll *= 60;
       
  1733                 else if (elapsed < 50)
       
  1734                     linesToScroll *= 30;
       
  1735                 else if (elapsed < 100)
       
  1736                     linesToScroll *= 6;
       
  1737                 else if (elapsed < 200)
       
  1738                     linesToScroll *= 3;
       
  1739                 else if (elapsed < 300)
       
  1740                     linesToScroll *= 2;
       
  1741 
       
  1742                 if (axis == kEventMouseWheelAxisX)
  1730                 if (axis == kEventMouseWheelAxisX)
  1743                     wheel_deltaX = linesToScroll * 120;
  1731                     wheel_deltaX = qBound(-120, int(mdelt * 10000), 120);
  1744                 else
  1732                 else
  1745                     wheel_deltaY = linesToScroll * 120;
  1733                     wheel_deltaY = qBound(-120, int(mdelt * 10000), 120);
  1746             }
  1734             }
  1747         }
  1735         }
  1748 
  1736 
  1749         Qt::MouseButton button = Qt::NoButton;
  1737         Qt::MouseButton button = Qt::NoButton;
  1750         if(ekind == kEventMouseDown || ekind == kEventMouseUp) {
  1738         if(ekind == kEventMouseDown || ekind == kEventMouseUp) {
  2462     AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
  2450     AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
  2463     if(aeClass == kCoreEventClass) {
  2451     if(aeClass == kCoreEventClass) {
  2464         switch(aeID) {
  2452         switch(aeID) {
  2465         case kAEQuitApplication: {
  2453         case kAEQuitApplication: {
  2466             extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp
  2454             extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp
  2467             if(!QApplicationPrivate::modalState() && qt_mac_quit_menu_item_enabled) {
  2455             if (qt_mac_quit_menu_item_enabled) {
  2468                 QCloseEvent ev;
  2456                 QCloseEvent ev;
  2469                 QApplication::sendSpontaneousEvent(app, &ev);
  2457                 QApplication::sendSpontaneousEvent(app, &ev);
  2470                 if(ev.isAccepted()) {
  2458                 if(ev.isAccepted()) {
  2471                     handled_event = true;
  2459                     handled_event = true;
  2472                     app->quit();
  2460                     app->quit();
  2493                 }
  2481                 }
  2494                 if(str_buffer)
  2482                 if(str_buffer)
  2495                     free(str_buffer);
  2483                     free(str_buffer);
  2496             }
  2484             }
  2497             break; }
  2485             break; }
       
  2486         default:
       
  2487             break;
       
  2488         }
       
  2489     } else if (aeClass == kInternetEventClass) {
       
  2490         switch (aeID) {
       
  2491         case kAEGetURL: {
       
  2492             char urlData[1024];
       
  2493             Size actualSize;
       
  2494             if (AEGetParamPtr(ae, keyDirectObject, typeChar, 0, urlData,
       
  2495                     sizeof(urlData) - 1, &actualSize) == noErr) {
       
  2496                 urlData[actualSize] = 0;
       
  2497                 QFileOpenEvent ev(QUrl(QString::fromUtf8(urlData)));
       
  2498                 QApplication::sendSpontaneousEvent(app, &ev);
       
  2499             }
       
  2500             break;
       
  2501         }
  2498         default:
  2502         default:
  2499             break;
  2503             break;
  2500         }
  2504         }
  2501     }
  2505     }
  2502 #ifdef DEBUG_EVENTS
  2506 #ifdef DEBUG_EVENTS
  2693     return QApplicationPrivate::keyboard_input_time;
  2697     return QApplicationPrivate::keyboard_input_time;
  2694 }
  2698 }
  2695 
  2699 
  2696 void QApplication::setWheelScrollLines(int n)
  2700 void QApplication::setWheelScrollLines(int n)
  2697 {
  2701 {
  2698     Q_UNUSED(n);
  2702     QApplicationPrivate::wheel_scroll_lines = n;
  2699     // On Mac, acceleration is handled by the OS. Multiplying wheel scroll
       
  2700     // deltas with n will not be as cross platform as one might think! So
       
  2701     // we choose to go native in this case (and let wheel_scroll_lines == 1).
       
  2702     //    QApplicationPrivate::wheel_scroll_lines = n;
       
  2703 }
  2703 }
  2704 
  2704 
  2705 int QApplication::wheelScrollLines()
  2705 int QApplication::wheelScrollLines()
  2706 {
  2706 {
  2707     return QApplicationPrivate::wheel_scroll_lines;
  2707     return QApplicationPrivate::wheel_scroll_lines;