182 extern bool qt_tab_all_widgets; // from qapplication.cpp |
182 extern bool qt_tab_all_widgets; // from qapplication.cpp |
183 bool qt_mac_app_fullscreen = false; |
183 bool qt_mac_app_fullscreen = false; |
184 bool qt_scrollbar_jump_to_pos = false; |
184 bool qt_scrollbar_jump_to_pos = false; |
185 static bool qt_mac_collapse_on_dblclick = true; |
185 static bool qt_mac_collapse_on_dblclick = true; |
186 extern int qt_antialiasing_threshold; // from qapplication.cpp |
186 extern int qt_antialiasing_threshold; // from qapplication.cpp |
187 QPointer<QWidget> qt_button_down; // widget got last button-down |
187 QWidget * qt_button_down; // widget got last button-down |
|
188 QPointer<QWidget> qt_last_mouse_receiver; |
188 #ifndef QT_MAC_USE_COCOA |
189 #ifndef QT_MAC_USE_COCOA |
189 static bool qt_button_down_in_content; // whether the button_down was in the content area. |
190 static bool qt_button_down_in_content; // whether the button_down was in the content area. |
190 static bool qt_mac_previous_press_in_popup_mode = false; |
191 static bool qt_mac_previous_press_in_popup_mode = false; |
191 static bool qt_mac_no_click_through_mode = false; |
192 static bool qt_mac_no_click_through_mode = false; |
192 static int tablet_button_state = 0; |
193 static int tablet_button_state = 0; |
1218 app_proc_handlerUPP = NewEventHandlerUPP(QApplicationPrivate::globalEventProcessor); |
1219 app_proc_handlerUPP = NewEventHandlerUPP(QApplicationPrivate::globalEventProcessor); |
1219 qt_init_app_proc_handler(); |
1220 qt_init_app_proc_handler(); |
1220 } |
1221 } |
1221 |
1222 |
1222 #endif |
1223 #endif |
1223 if (!app_proc_ae_handlerUPP) { |
1224 if (!app_proc_ae_handlerUPP && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) { |
1224 app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor); |
1225 app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor); |
1225 for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) |
1226 for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) { |
1226 AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, |
1227 // Install apple event handler, but avoid overwriting an already |
1227 app_proc_ae_handlerUPP, SRefCon(qApp), false); |
1228 // existing handler (it means a 3rd party application has installed one): |
|
1229 SRefCon refCon = 0; |
|
1230 AEEventHandlerUPP current_handler = NULL; |
|
1231 AEGetEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, ¤t_handler, &refCon, false); |
|
1232 if (!current_handler) |
|
1233 AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, |
|
1234 app_proc_ae_handlerUPP, SRefCon(qApp), false); |
|
1235 } |
1228 } |
1236 } |
1229 |
1237 |
1230 if (QApplicationPrivate::app_style) { |
1238 if (QApplicationPrivate::app_style) { |
1231 QEvent ev(QEvent::Style); |
1239 QEvent ev(QEvent::Style); |
1232 qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); |
1240 qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); |
1235 if (QApplication::desktopSettingsAware()) |
1243 if (QApplication::desktopSettingsAware()) |
1236 QApplicationPrivate::qt_mac_apply_settings(); |
1244 QApplicationPrivate::qt_mac_apply_settings(); |
1237 |
1245 |
1238 // Cocoa application delegate |
1246 // Cocoa application delegate |
1239 #ifdef QT_MAC_USE_COCOA |
1247 #ifdef QT_MAC_USE_COCOA |
1240 NSApplication *cocoaApp = [NSApplication sharedApplication]; |
1248 NSApplication *cocoaApp = [QNSApplication sharedApplication]; |
1241 QMacCocoaAutoReleasePool pool; |
1249 QMacCocoaAutoReleasePool pool; |
1242 NSObject *oldDelegate = [cocoaApp delegate]; |
1250 NSObject *oldDelegate = [cocoaApp delegate]; |
1243 QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; |
1251 QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; |
1244 Q_ASSERT(newDelegate); |
1252 Q_ASSERT(newDelegate); |
1245 [newDelegate setQtPrivate:priv]; |
1253 [newDelegate setQtPrivate:priv]; |
1256 } |
1264 } |
1257 |
1265 |
1258 [cocoaApp setMenu:[qtMenuLoader menu]]; |
1266 [cocoaApp setMenu:[qtMenuLoader menu]]; |
1259 [newDelegate setMenuLoader:qtMenuLoader]; |
1267 [newDelegate setMenuLoader:qtMenuLoader]; |
1260 [qtMenuLoader release]; |
1268 [qtMenuLoader release]; |
1261 |
|
1262 NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager]; |
|
1263 [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:) |
|
1264 forEventClass:kInternetEventClass andEventID:kAEGetURL]; |
|
1265 } |
1269 } |
1266 #endif |
1270 #endif |
1267 // Register for Carbon tablet proximity events on the event monitor target. |
1271 // Register for Carbon tablet proximity events on the event monitor target. |
1268 // This means that we should receive proximity events even when we aren't the active application. |
1272 // This means that we should receive proximity events even when we aren't the active application. |
1269 if (!tablet_proximity_handler) { |
1273 if (!tablet_proximity_handler) { |
1359 #ifndef QT_NO_CURSOR |
1363 #ifndef QT_NO_CURSOR |
1360 |
1364 |
1361 /***************************************************************************** |
1365 /***************************************************************************** |
1362 QApplication cursor stack |
1366 QApplication cursor stack |
1363 *****************************************************************************/ |
1367 *****************************************************************************/ |
|
1368 #ifdef QT_MAC_USE_COCOA |
|
1369 void QApplicationPrivate::disableUsageOfCursorRects(bool disable) |
|
1370 { |
|
1371 // In Cocoa there are two competing ways of setting the cursor; either |
|
1372 // by using cursor rects (see qcocoaview_mac.mm), or by pushing/popping |
|
1373 // the cursor manually. When we use override cursors, it makes most sense |
|
1374 // to use the latter. But then we need to tell cocoa to stop using the |
|
1375 // first approach so it doesn't change the cursor back when hovering over |
|
1376 // a cursor rect: |
|
1377 QWidgetList topLevels = qApp->topLevelWidgets(); |
|
1378 for (int i=0; i<topLevels.size(); ++i) { |
|
1379 if (NSWindow *window = qt_mac_window_for(topLevels.at(i))) |
|
1380 disable ? [window disableCursorRects] : [window enableCursorRects]; |
|
1381 } |
|
1382 } |
|
1383 |
|
1384 void QApplicationPrivate::updateOverrideCursor() |
|
1385 { |
|
1386 // Sometimes Cocoa forgets that we have set a Cursor |
|
1387 // manually. In those cases, remind it again: |
|
1388 if (QCursor *override = qApp->overrideCursor()) |
|
1389 [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(*override)) set]; |
|
1390 } |
|
1391 #endif |
|
1392 |
1364 void QApplication::setOverrideCursor(const QCursor &cursor) |
1393 void QApplication::setOverrideCursor(const QCursor &cursor) |
1365 { |
1394 { |
1366 qApp->d_func()->cursor_list.prepend(cursor); |
1395 qApp->d_func()->cursor_list.prepend(cursor); |
1367 |
1396 |
1368 #ifdef QT_MAC_USE_COCOA |
1397 #ifdef QT_MAC_USE_COCOA |
1369 QMacCocoaAutoReleasePool pool; |
1398 QMacCocoaAutoReleasePool pool; |
|
1399 if (qApp->d_func()->cursor_list.size() == 1) |
|
1400 qApp->d_func()->disableUsageOfCursorRects(true); |
1370 [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) push]; |
1401 [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) push]; |
1371 #else |
1402 #else |
1372 if (qApp && qApp->activeWindow()) |
1403 if (qApp && qApp->activeWindow()) |
1373 qt_mac_set_cursor(&qApp->d_func()->cursor_list.first(), QCursor::pos()); |
1404 qt_mac_set_cursor(&qApp->d_func()->cursor_list.first(), QCursor::pos()); |
1374 #endif |
1405 #endif |
1381 qApp->d_func()->cursor_list.removeFirst(); |
1412 qApp->d_func()->cursor_list.removeFirst(); |
1382 |
1413 |
1383 #ifdef QT_MAC_USE_COCOA |
1414 #ifdef QT_MAC_USE_COCOA |
1384 QMacCocoaAutoReleasePool pool; |
1415 QMacCocoaAutoReleasePool pool; |
1385 [NSCursor pop]; |
1416 [NSCursor pop]; |
|
1417 if (qApp->d_func()->cursor_list.isEmpty()) |
|
1418 qApp->d_func()->disableUsageOfCursorRects(false); |
1386 #else |
1419 #else |
1387 if (qApp && qApp->activeWindow()) { |
1420 if (qApp && qApp->activeWindow()) { |
1388 const QCursor def(Qt::ArrowCursor); |
1421 const QCursor def(Qt::ArrowCursor); |
1389 qt_mac_set_cursor(qApp->d_func()->cursor_list.isEmpty() ? &def : &qApp->d_func()->cursor_list.first(), QCursor::pos()); |
1422 qt_mac_set_cursor(qApp->d_func()->cursor_list.isEmpty() ? &def : &qApp->d_func()->cursor_list.first(), QCursor::pos()); |
1390 } |
1423 } |
1724 // compatibility with older applications, carbon will also send us |
1757 // compatibility with older applications, carbon will also send us |
1725 // kEventMouseWheelMoved events if we dont eat this event |
1758 // kEventMouseWheelMoved events if we dont eat this event |
1726 // (actually two events; one for horizontal and one for vertical). |
1759 // (actually two events; one for horizontal and one for vertical). |
1727 // As a results of this, and to make sure we dont't receive duplicate events, |
1760 // As a results of this, and to make sure we dont't receive duplicate events, |
1728 // we try to detect when this happend by checking the 'compatibilityEvent'. |
1761 // we try to detect when this happend by checking the 'compatibilityEvent'. |
|
1762 // Since delta is delivered as pixels rather than degrees, we need to |
|
1763 // convert from pixels to degrees in a sensible manner. |
|
1764 // It looks like 1/4 degrees per pixel behaves most native. |
|
1765 // (NB: Qt expects the unit for delta to be 8 per degree): |
|
1766 const int pixelsToDegrees = 2; |
1729 SInt32 mdelt = 0; |
1767 SInt32 mdelt = 0; |
1730 GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, |
1768 GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, |
1731 sizeof(mdelt), 0, &mdelt); |
1769 sizeof(mdelt), 0, &mdelt); |
1732 wheel_deltaX = mdelt; |
1770 wheel_deltaX = mdelt * pixelsToDegrees; |
1733 mdelt = 0; |
1771 mdelt = 0; |
1734 GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, |
1772 GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, |
1735 sizeof(mdelt), 0, &mdelt); |
1773 sizeof(mdelt), 0, &mdelt); |
1736 wheel_deltaY = mdelt; |
1774 wheel_deltaY = mdelt * pixelsToDegrees; |
1737 GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, |
1775 GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, |
1738 sizeof(compatibilityEvent), 0, &compatibilityEvent); |
1776 sizeof(compatibilityEvent), 0, &compatibilityEvent); |
1739 } else if (ekind == kEventMouseWheelMoved) { |
1777 } else if (ekind == kEventMouseWheelMoved) { |
1740 if (event != compatibilityEvent) { |
1778 if (event != compatibilityEvent) { |
1741 compatibilityEvent = 0; |
1779 compatibilityEvent = 0; |
2406 if(SendEventToMenu(copy, copy_cmd.menu.menuRef) == noErr) |
2444 if(SendEventToMenu(copy, copy_cmd.menu.menuRef) == noErr) |
2407 handled_event = true; |
2445 handled_event = true; |
2408 } |
2446 } |
2409 if(!handled_event) { |
2447 if(!handled_event) { |
2410 if(cmd.commandID == kHICommandQuit) { |
2448 if(cmd.commandID == kHICommandQuit) { |
2411 handled_event = true; |
2449 // Quitting the application is not Qt's responsibility if |
2412 HiliteMenu(0); |
2450 // used in a plugin or just embedded into a native application. |
2413 bool handle_quit = true; |
2451 // In that case, let the event pass down to the native apps event handler. |
2414 if(QApplicationPrivate::modalState()) { |
2452 if (!QApplication::testAttribute(Qt::AA_MacPluginApplication)) { |
2415 int visible = 0; |
2453 handled_event = true; |
2416 const QWidgetList tlws = QApplication::topLevelWidgets(); |
2454 HiliteMenu(0); |
2417 for(int i = 0; i < tlws.size(); ++i) { |
2455 bool handle_quit = true; |
2418 if(tlws.at(i)->isVisible()) |
2456 if(QApplicationPrivate::modalState()) { |
2419 ++visible; |
2457 int visible = 0; |
|
2458 const QWidgetList tlws = QApplication::topLevelWidgets(); |
|
2459 for(int i = 0; i < tlws.size(); ++i) { |
|
2460 if(tlws.at(i)->isVisible()) |
|
2461 ++visible; |
|
2462 } |
|
2463 handle_quit = (visible <= 1); |
2420 } |
2464 } |
2421 handle_quit = (visible <= 1); |
2465 if(handle_quit) { |
2422 } |
2466 QCloseEvent ev; |
2423 if(handle_quit) { |
2467 QApplication::sendSpontaneousEvent(app, &ev); |
2424 QCloseEvent ev; |
2468 if(ev.isAccepted()) |
2425 QApplication::sendSpontaneousEvent(app, &ev); |
2469 app->quit(); |
2426 if(ev.isAccepted()) |
2470 } else { |
2427 app->quit(); |
2471 QApplication::beep(); |
2428 } else { |
2472 } |
2429 QApplication::beep(); |
|
2430 } |
2473 } |
2431 } else if(cmd.commandID == kHICommandSelectWindow) { |
2474 } else if(cmd.commandID == kHICommandSelectWindow) { |
2432 if((GetCurrentKeyModifiers() & cmdKey)) |
2475 if((GetCurrentKeyModifiers() & cmdKey)) |
2433 handled_event = true; |
2476 handled_event = true; |
2434 } else if(cmd.commandID == kHICommandAbout) { |
2477 } else if(cmd.commandID == kHICommandAbout) { |
2454 Q_UNUSED(event); |
2497 Q_UNUSED(event); |
2455 Q_UNUSED(data); |
2498 Q_UNUSED(data); |
2456 return eventNotHandledErr; |
2499 return eventNotHandledErr; |
2457 #endif |
2500 #endif |
2458 } |
2501 } |
|
2502 |
|
2503 #ifdef QT_MAC_USE_COCOA |
|
2504 void QApplicationPrivate::qt_initAfterNSAppStarted() |
|
2505 { |
|
2506 setupAppleEvents(); |
|
2507 updateOverrideCursor(); |
|
2508 } |
|
2509 |
|
2510 void QApplicationPrivate::setupAppleEvents() |
|
2511 { |
|
2512 // This function is called from the event dispatcher when NSApplication has |
|
2513 // finished initialization, which appears to be just after [NSApplication run] has |
|
2514 // started to execute. By setting up our apple events handlers this late, we override |
|
2515 // the ones set up by NSApplication. |
|
2516 |
|
2517 // If Qt is used as a plugin, we let the 3rd party application handle events |
|
2518 // like quit and open file events. Otherwise, if we install our own handlers, we |
|
2519 // easily end up breaking functionallity the 3rd party application depend on: |
|
2520 if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) |
|
2521 return; |
|
2522 |
|
2523 QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; |
|
2524 NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager]; |
|
2525 [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:) |
|
2526 forEventClass:kCoreEventClass andEventID:kAEQuitApplication]; |
|
2527 [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:) |
|
2528 forEventClass:kInternetEventClass andEventID:kAEGetURL]; |
|
2529 } |
|
2530 #endif |
2459 |
2531 |
2460 // In Carbon this is your one stop for apple events. |
2532 // In Carbon this is your one stop for apple events. |
2461 // In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists |
2533 // In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists |
2462 // for the time between instantiating the NSApplication, but before the |
2534 // for the time between instantiating the NSApplication, but before the |
2463 // NSApplication has installed it's OWN Apple Event handler. When Cocoa has |
2535 // NSApplication has installed it's OWN Apple Event handler. When Cocoa has |