From f67b8df3ebdba2d398b9cce686b7c644adffff08 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 00:02:01 +0200 Subject: library split --- src/gui/widgets/qmenu_mac.mm | 2217 ------------------------------------------ 1 file changed, 2217 deletions(-) delete mode 100644 src/gui/widgets/qmenu_mac.mm (limited to 'src/gui/widgets/qmenu_mac.mm') diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm deleted file mode 100644 index 2977558a75..0000000000 --- a/src/gui/widgets/qmenu_mac.mm +++ /dev/null @@ -1,2217 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmenu.h" -#include "qhash.h" -#include -#include "qapplication.h" -#include -#include "qregexp.h" -#include "qmainwindow.h" -#include "qdockwidget.h" -#include "qtoolbar.h" -#include "qevent.h" -#include "qstyle.h" -#include "qwidgetaction.h" -#include "qmacnativewidget_mac.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - QMenu debug facilities - *****************************************************************************/ - -/***************************************************************************** - QMenu globals - *****************************************************************************/ -bool qt_mac_no_menubar_merge = false; -bool qt_mac_quit_menu_item_enabled = true; -int qt_mac_menus_open_count = 0; - -static OSMenuRef qt_mac_create_menu(QWidget *w); - -#ifndef QT_MAC_USE_COCOA -static uint qt_mac_menu_static_cmd_id = 'QT00'; -const UInt32 kMenuCreatorQt = 'cute'; -enum { - kMenuPropertyQAction = 'QAcT', - kMenuPropertyQWidget = 'QWId', - kMenuPropertyCausedQWidget = 'QCAU', - kMenuPropertyMergeMenu = 'QApP', - kMenuPropertyMergeList = 'QAmL', - kMenuPropertyWidgetActionWidget = 'QWid', - kMenuPropertyWidgetMenu = 'QWMe', - - kHICommandAboutQt = 'AOQT', - kHICommandCustomMerge = 'AQt0' -}; -#endif - -static struct { - QPointer qmenubar; - bool modal; -} qt_mac_current_menubar = { 0, false }; - - - - -/***************************************************************************** - Externals - *****************************************************************************/ -extern OSViewRef qt_mac_hiview_for(const QWidget *w); //qwidget_mac.cpp -extern HIViewRef qt_mac_hiview_for(OSWindowRef w); //qwidget_mac.cpp -extern IconRef qt_mac_create_iconref(const QPixmap &px); //qpixmap_mac.cpp -extern QWidget * mac_keyboard_grabber; //qwidget_mac.cpp -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication_xxx.cpp -RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp -void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp - -/***************************************************************************** - QMenu utility functions - *****************************************************************************/ -bool qt_mac_watchingAboutToShow(QMenu *menu) -{ - return menu && menu->receivers(SIGNAL(aboutToShow())); -} - -static int qt_mac_CountMenuItems(OSMenuRef menu) -{ - if (menu) { -#ifndef QT_MAC_USE_COCOA - int ret = 0; - const int items = CountMenuItems(menu); - for(int i = 0; i < items; i++) { - MenuItemAttributes attr; - if (GetMenuItemAttributes(menu, i+1, &attr) == noErr && - attr & kMenuItemAttrHidden) - continue; - ++ret; - } - return ret; -#else - return [menu numberOfItems]; -#endif - } - return 0; -} - -static quint32 constructModifierMask(quint32 accel_key) -{ - quint32 ret = 0; - const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta); -#ifndef QT_MAC_USE_COCOA - if ((accel_key & Qt::ALT) == Qt::ALT) - ret |= kMenuOptionModifier; - if ((accel_key & Qt::SHIFT) == Qt::SHIFT) - ret |= kMenuShiftModifier; - if (dontSwap) { - if ((accel_key & Qt::META) != Qt::META) - ret |= kMenuNoCommandModifier; - if ((accel_key & Qt::CTRL) == Qt::CTRL) - ret |= kMenuControlModifier; - } else { - if ((accel_key & Qt::CTRL) != Qt::CTRL) - ret |= kMenuNoCommandModifier; - if ((accel_key & Qt::META) == Qt::META) - ret |= kMenuControlModifier; - } -#else - if ((accel_key & Qt::CTRL) == Qt::CTRL) - ret |= (dontSwap ? NSControlKeyMask : NSCommandKeyMask); - if ((accel_key & Qt::META) == Qt::META) - ret |= (dontSwap ? NSCommandKeyMask : NSControlKeyMask); - if ((accel_key & Qt::ALT) == Qt::ALT) - ret |= NSAlternateKeyMask; - if ((accel_key & Qt::SHIFT) == Qt::SHIFT) - ret |= NSShiftKeyMask; -#endif - return ret; -} - -static void cancelAllMenuTracking() -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - NSMenu *mainMenu = [NSApp mainMenu]; - [mainMenu cancelTracking]; - for (NSMenuItem *item in [mainMenu itemArray]) { - if ([item submenu]) { - [[item submenu] cancelTracking]; - } - } -#else - CancelMenuTracking(AcquireRootMenu(), true, 0); -#endif -} - -static bool actualMenuItemVisibility(const QMenuBarPrivate::QMacMenuBarPrivate *mbp, - const QMacMenuAction *action) -{ - bool visible = action->action->isVisible(); - if (visible && action->action->text() == QString(QChar(0x14))) - return false; - if (visible && action->action->menu() && !action->action->menu()->actions().isEmpty() && - !qt_mac_CountMenuItems(action->action->menu()->macMenu(mbp->apple_menu)) && - !qt_mac_watchingAboutToShow(action->action->menu())) { - return false; - } - return visible; -} - -#ifndef QT_MAC_USE_COCOA -bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent action_e, bool by_accel) -{ - //fire event - QMacMenuAction *action = 0; - if (GetMenuCommandProperty(menu, command, kMenuCreatorQt, kMenuPropertyQAction, sizeof(action), 0, &action) != noErr) { - QMenuMergeList *list = 0; - GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list); - if (!list && qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) { - MenuRef apple_menu = qt_mac_current_menubar.qmenubar->d_func()->mac_menubar->apple_menu; - GetMenuItemProperty(apple_menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, sizeof(list), 0, &list); - if (list) - menu = apple_menu; - } - if (list) { - for(int i = 0; i < list->size(); ++i) { - QMenuMergeItem item = list->at(i); - if (item.command == command && item.action) { - action = item.action; - break; - } - } - } - if (!action) - return false; - } - - if (action_e == QAction::Trigger && by_accel && action->ignore_accel) //no, not a real accel (ie tab) - return false; - - // Unhighlight the highlighted menu item before triggering the action to - // prevent items from staying highlighted while a modal dialog is shown. - // This also fixed the problem that parentless modal dialogs leave - // the menu item highlighted (since the menu bar is cleared for these types of dialogs). - if (action_e == QAction::Trigger) - HiliteMenu(0); - - action->action->activate(action_e); - - //now walk up firing for each "caused" widget (like in the platform independent menu) - QWidget *caused = 0; - if (action_e == QAction::Hover && GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), 0, &caused) == noErr) { - MenuRef caused_menu = 0; - if (QMenu *qmenu2 = qobject_cast(caused)) - caused_menu = qmenu2->macMenu(); - else if (QMenuBar *qmenubar2 = qobject_cast(caused)) - caused_menu = qmenubar2->macMenu(); - else - caused_menu = 0; - while(caused_menu) { - //fire - QWidget *widget = 0; - GetMenuItemProperty(caused_menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(widget), 0, &widget); - if (QMenu *qmenu = qobject_cast(widget)) { - action->action->showStatusText(widget); - emit qmenu->hovered(action->action); - } else if (QMenuBar *qmenubar = qobject_cast(widget)) { - action->action->showStatusText(widget); - emit qmenubar->hovered(action->action); - break; //nothing more.. - } - - //walk up - if (GetMenuItemProperty(caused_menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, - sizeof(caused), 0, &caused) != noErr) - break; - if (QMenu *qmenu2 = qobject_cast(caused)) - caused_menu = qmenu2->macMenu(); - else if (QMenuBar *qmenubar2 = qobject_cast(caused)) - caused_menu = qmenubar2->macMenu(); - else - caused_menu = 0; - } - } - return true; -} - -//lookup a QMacMenuAction in a menu -static int qt_mac_menu_find_action(MenuRef menu, MenuCommand cmd) -{ - MenuItemIndex ret_idx; - MenuRef ret_menu; - if (GetIndMenuItemWithCommandID(menu, cmd, 1, &ret_menu, &ret_idx) == noErr) { - if (ret_menu == menu) - return (int)ret_idx; - } - return -1; -} -static int qt_mac_menu_find_action(MenuRef menu, QMacMenuAction *action) -{ - return qt_mac_menu_find_action(menu, action->command); -} - -typedef QMultiHash EventHandlerHash; -Q_GLOBAL_STATIC(EventHandlerHash, menu_eventHandlers_hash) - -static EventTypeSpec widget_in_menu_events[] = { - { kEventClassMenu, kEventMenuMeasureItemWidth }, - { kEventClassMenu, kEventMenuMeasureItemHeight }, - { kEventClassMenu, kEventMenuDrawItem }, - { kEventClassMenu, kEventMenuCalculateSize } -}; - -static OSStatus qt_mac_widget_in_menu_eventHandler(EventHandlerCallRef er, EventRef event, void *) -{ - UInt32 ekind = GetEventKind(event); - UInt32 eclass = GetEventClass(event); - OSStatus result = eventNotHandledErr; - switch (eclass) { - case kEventClassMenu: - switch (ekind) { - default: - break; - case kEventMenuMeasureItemWidth: { - MenuItemIndex item; - GetEventParameter(event, kEventParamMenuItemIndex, typeMenuItemIndex, - 0, sizeof(item), 0, &item); - OSMenuRef menu; - GetEventParameter(event, kEventParamDirectObject, typeMenuRef, 0, sizeof(menu), 0, &menu); - QWidget *widget; - if (GetMenuItemProperty(menu, item, kMenuCreatorQt, kMenuPropertyWidgetActionWidget, - sizeof(widget), 0, &widget) == noErr) { - short width = short(widget->sizeHint().width()); - SetEventParameter(event, kEventParamMenuItemWidth, typeSInt16, - sizeof(short), &width); - result = noErr; - } - break; } - case kEventMenuMeasureItemHeight: { - MenuItemIndex item; - GetEventParameter(event, kEventParamMenuItemIndex, typeMenuItemIndex, - 0, sizeof(item), 0, &item); - OSMenuRef menu; - GetEventParameter(event, kEventParamDirectObject, typeMenuRef, 0, sizeof(menu), 0, &menu); - QWidget *widget; - if (GetMenuItemProperty(menu, item, kMenuCreatorQt, kMenuPropertyWidgetActionWidget, - sizeof(widget), 0, &widget) == noErr && widget) { - short height = short(widget->sizeHint().height()); - SetEventParameter(event, kEventParamMenuItemHeight, typeSInt16, - sizeof(short), &height); - result = noErr; - } - break; } - case kEventMenuDrawItem: - result = noErr; - break; - case kEventMenuCalculateSize: { - result = CallNextEventHandler(er, event); - if (result == noErr) { - OSMenuRef menu; - GetEventParameter(event, kEventParamDirectObject, typeMenuRef, 0, sizeof(menu), 0, &menu); - HIViewRef content; - HIMenuGetContentView(menu, kThemeMenuTypePullDown, &content); - UInt16 count = CountMenuItems(menu); - for (MenuItemIndex i = 1; i <= count; ++i) { - QWidget *widget; - if (GetMenuItemProperty(menu, i, kMenuCreatorQt, kMenuPropertyWidgetActionWidget, - sizeof(widget), 0, &widget) == noErr && widget) { - RgnHandle itemRgn = qt_mac_get_rgn(); - GetControlRegion(content, i, itemRgn); - - Rect bounds; - GetRegionBounds( itemRgn, &bounds ); - qt_mac_dispose_rgn(itemRgn); - widget->setGeometry(bounds.left, bounds.top, - bounds.right - bounds.left, bounds.bottom - bounds.top); - } - } - } - break; } - } - } - return result; -} - -//handling of events for menurefs created by Qt.. -static EventTypeSpec menu_events[] = { - { kEventClassCommand, kEventCommandProcess }, - { kEventClassMenu, kEventMenuTargetItem }, - { kEventClassMenu, kEventMenuOpening }, - { kEventClassMenu, kEventMenuClosed } -}; - -// Special case for kEventMenuMatchKey, see qt_mac_create_menu below. -static EventTypeSpec menu_menu_events[] = { - { kEventClassMenu, kEventMenuMatchKey } -}; - -OSStatus qt_mac_menu_event(EventHandlerCallRef er, EventRef event, void *) -{ - QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); - - bool handled_event = true; - UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); - switch(eclass) { - case kEventClassCommand: - if (ekind == kEventCommandProcess) { - UInt32 context; - GetEventParameter(event, kEventParamMenuContext, typeUInt32, - 0, sizeof(context), 0, &context); - HICommand cmd; - GetEventParameter(event, kEventParamDirectObject, typeHICommand, - 0, sizeof(cmd), 0, &cmd); - if (!mac_keyboard_grabber && (context & kMenuContextKeyMatching)) { - QMacMenuAction *action = 0; - if (GetMenuCommandProperty(cmd.menu.menuRef, cmd.commandID, kMenuCreatorQt, - kMenuPropertyQAction, sizeof(action), 0, &action) == noErr) { - QWidget *widget = 0; - if (qApp->activePopupWidget()) - widget = (qApp->activePopupWidget()->focusWidget() ? - qApp->activePopupWidget()->focusWidget() : qApp->activePopupWidget()); - else if (QApplicationPrivate::focus_widget) - widget = QApplicationPrivate::focus_widget; - if (widget) { - int key = action->action->shortcut(); - QKeyEvent accel_ev(QEvent::ShortcutOverride, (key & (~Qt::KeyboardModifierMask)), - Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask)); - accel_ev.ignore(); - qt_sendSpontaneousEvent(widget, &accel_ev); - if (accel_ev.isAccepted()) { - handled_event = false; - break; - } - } - } - } - handled_event = qt_mac_activate_action(cmd.menu.menuRef, cmd.commandID, - QAction::Trigger, context & kMenuContextKeyMatching); - } - break; - case kEventClassMenu: { - MenuRef menu; - GetEventParameter(event, kEventParamDirectObject, typeMenuRef, NULL, sizeof(menu), NULL, &menu); - if (ekind == kEventMenuMatchKey) { - // Don't activate any actions if we are showing a native modal dialog, - // the key events should go to the dialog in this case. - if (QApplicationPrivate::native_modal_dialog_active) - return menuItemNotFoundErr; - - handled_event = false; - } else if (ekind == kEventMenuTargetItem) { - MenuCommand command; - GetEventParameter(event, kEventParamMenuCommand, typeMenuCommand, - 0, sizeof(command), 0, &command); - handled_event = qt_mac_activate_action(menu, command, QAction::Hover, false); - } else if (ekind == kEventMenuOpening || ekind == kEventMenuClosed) { - qt_mac_menus_open_count += (ekind == kEventMenuOpening) ? 1 : -1; - MenuRef mr; - GetEventParameter(event, kEventParamDirectObject, typeMenuRef, - 0, sizeof(mr), 0, &mr); - - QWidget *widget = 0; - if (GetMenuItemProperty(mr, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(widget), 0, &widget) == noErr) { - if (QMenu *qmenu = qobject_cast(widget)) { - handled_event = true; - if (ekind == kEventMenuOpening) { - emit qmenu->aboutToShow(); - - int merged = 0; - const QMenuPrivate::QMacMenuPrivate *mac_menu = qmenu->d_func()->mac_menu; - const int ActionItemsCount = mac_menu->actionItems.size(); - for(int i = 0; i < ActionItemsCount; ++i) { - QMacMenuAction *action = mac_menu->actionItems.at(i); - if (action->action->isSeparator()) { - bool hide = false; - if(!action->action->isVisible()) { - hide = true; - } else if (merged && merged == i) { - hide = true; - } else { - for(int l = i+1; l < mac_menu->actionItems.size(); ++l) { - QMacMenuAction *action = mac_menu->actionItems.at(l); - if (action->merged) { - hide = true; - } else if (action->action->isSeparator()) { - if (hide) - break; - } else if (!action->merged) { - hide = false; - break; - } - } - } - - const int index = qt_mac_menu_find_action(mr, action); - if (hide) { - ++merged; - ChangeMenuItemAttributes(mr, index, kMenuItemAttrHidden, 0); - } else { - ChangeMenuItemAttributes(mr, index, 0, kMenuItemAttrHidden); - } - } else if (action->merged) { - ++merged; - } - } - } else { - emit qmenu->aboutToHide(); - } - } - } - } else { - handled_event = false; - } - break; } - default: - handled_event = false; - break; - } - if (!handled_event) //let the event go through - return CallNextEventHandler(er, event); - return noErr; //we eat the event -} -static EventHandlerRef mac_menu_event_handler = 0; -static EventHandlerUPP mac_menu_eventUPP = 0; -static void qt_mac_cleanup_menu_event() -{ - if (mac_menu_event_handler) { - RemoveEventHandler(mac_menu_event_handler); - mac_menu_event_handler = 0; - } - if (mac_menu_eventUPP) { - DisposeEventHandlerUPP(mac_menu_eventUPP); - mac_menu_eventUPP = 0; - } -} -static inline void qt_mac_create_menu_event_handler() -{ - if (!mac_menu_event_handler) { - mac_menu_eventUPP = NewEventHandlerUPP(qt_mac_menu_event); - InstallEventHandler(GetApplicationEventTarget(), mac_menu_eventUPP, - GetEventTypeCount(menu_events), menu_events, 0, - &mac_menu_event_handler); - qAddPostRoutine(qt_mac_cleanup_menu_event); - } -} - - -//enabling of commands -static void qt_mac_command_set_enabled(MenuRef menu, UInt32 cmd, bool b) -{ - if (cmd == kHICommandQuit) - qt_mac_quit_menu_item_enabled = b; - - if (b) { - EnableMenuCommand(menu, cmd); - if (MenuRef dock_menu = GetApplicationDockTileMenu()) - EnableMenuCommand(dock_menu, cmd); - } else { - DisableMenuCommand(menu, cmd); - if (MenuRef dock_menu = GetApplicationDockTileMenu()) - DisableMenuCommand(dock_menu, cmd); - } -} - -static bool qt_mac_auto_apple_menu(MenuCommand cmd) -{ - return (cmd == kHICommandPreferences || cmd == kHICommandQuit); -} - -static void qt_mac_get_accel(quint32 accel_key, quint32 *modif, quint32 *key) { - if (modif) { - *modif = constructModifierMask(accel_key); - } - - accel_key &= ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL); - if (key) { - *key = 0; - if (accel_key == Qt::Key_Return) - *key = kMenuReturnGlyph; - else if (accel_key == Qt::Key_Enter) - *key = kMenuEnterGlyph; - else if (accel_key == Qt::Key_Tab) - *key = kMenuTabRightGlyph; - else if (accel_key == Qt::Key_Backspace) - *key = kMenuDeleteLeftGlyph; - else if (accel_key == Qt::Key_Delete) - *key = kMenuDeleteRightGlyph; - else if (accel_key == Qt::Key_Escape) - *key = kMenuEscapeGlyph; - else if (accel_key == Qt::Key_PageUp) - *key = kMenuPageUpGlyph; - else if (accel_key == Qt::Key_PageDown) - *key = kMenuPageDownGlyph; - else if (accel_key == Qt::Key_Up) - *key = kMenuUpArrowGlyph; - else if (accel_key == Qt::Key_Down) - *key = kMenuDownArrowGlyph; - else if (accel_key == Qt::Key_Left) - *key = kMenuLeftArrowGlyph; - else if (accel_key == Qt::Key_Right) - *key = kMenuRightArrowGlyph; - else if (accel_key == Qt::Key_CapsLock) - *key = kMenuCapsLockGlyph; - else if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15) - *key = (accel_key - Qt::Key_F1) + kMenuF1Glyph; - else if (accel_key == Qt::Key_Home) - *key = kMenuNorthwestArrowGlyph; - else if (accel_key == Qt::Key_End) - *key = kMenuSoutheastArrowGlyph; - } -} -#else // Cocoa -static inline void syncNSMenuItemVisiblity(NSMenuItem *menuItem, bool actionVisibility) -{ - [menuItem setHidden:NO]; - [menuItem setHidden:YES]; - [menuItem setHidden:!actionVisibility]; -} - -static inline void syncNSMenuItemEnabled(NSMenuItem *menuItem, bool enabled) -{ - [menuItem setEnabled:NO]; - [menuItem setEnabled:YES]; - [menuItem setEnabled:enabled]; -} - -static inline void syncMenuBarItemsVisiblity(const QMenuBarPrivate::QMacMenuBarPrivate *mac_menubar) -{ - const QList &menubarActions = mac_menubar->actionItems; - for (int i = 0; i < menubarActions.size(); ++i) { - const QMacMenuAction *action = menubarActions.at(i); - syncNSMenuItemVisiblity(action->menuItem, actualMenuItemVisibility(mac_menubar, action)); - } -} - -static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader() -{ - return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)]; -} - -static NSMenuItem *createNSMenuItem(const QString &title) -{ - NSMenuItem *item = [[NSMenuItem alloc] - initWithTitle:qt_mac_QStringToNSString(title) - action:@selector(qtDispatcherToQAction:) keyEquivalent:@""]; - [item setTarget:nil]; - return item; -} -#endif - - - -// helper that recurses into a menu structure and en/dis-ables them -void qt_mac_set_modal_state_helper_recursive(OSMenuRef menu, OSMenuRef merge, bool on) -{ -#ifndef QT_MAC_USE_COCOA - for (int i = 0; i < CountMenuItems(menu); i++) { - OSMenuRef submenu; - GetMenuItemHierarchicalMenu(menu, i+1, &submenu); - if (submenu != merge) { - if (submenu) - qt_mac_set_modal_state_helper_recursive(submenu, merge, on); - if (on) - DisableMenuItem(submenu, 0); - else - EnableMenuItem(submenu, 0); - } - } -#else - bool modalWindowOnScreen = qApp->activeModalWidget() != 0; - for (NSMenuItem *item in [menu itemArray]) { - OSMenuRef submenu = [item submenu]; - if (submenu != merge) { - if (submenu) - qt_mac_set_modal_state_helper_recursive(submenu, merge, on); - if (!on) { - // The item should follow what the QAction has. - if ([item tag]) { - QAction *action = reinterpret_cast([item tag]); - syncNSMenuItemEnabled(item, action->isEnabled()); - } else { - syncNSMenuItemEnabled(item, YES); - } - // We sneak in some extra code here to handle a menu problem: - // If there is no window on screen, we cannot set 'nil' as - // menu item target, because then cocoa will disable the item - // (guess it assumes that there will be no first responder to - // catch the trigger anyway?) OTOH, If we have a modal window, - // then setting the menu loader as target will make cocoa not - // deliver the trigger because the loader is then seen as modally - // shaddowed). So either way there are shortcomings. Instead, we - // decide the target as late as possible: - [item setTarget:modalWindowOnScreen ? nil : getMenuLoader()]; - } else { - syncNSMenuItemEnabled(item, NO); - } - } - } -#endif -} - -//toggling of modal state -static void qt_mac_set_modal_state(OSMenuRef menu, bool on) -{ -#ifndef QT_MAC_USE_COCOA - OSMenuRef merge = 0; - GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyMergeMenu, - sizeof(merge), 0, &merge); - - qt_mac_set_modal_state_helper_recursive(menu, merge, on); - - UInt32 commands[] = { kHICommandQuit, kHICommandPreferences, kHICommandAbout, kHICommandAboutQt, 0 }; - for(int c = 0; commands[c]; c++) { - bool enabled = !on; - if (enabled) { - QMacMenuAction *action = 0; - GetMenuCommandProperty(menu, commands[c], kMenuCreatorQt, kMenuPropertyQAction, - sizeof(action), 0, &action); - if (!action && merge) { - GetMenuCommandProperty(merge, commands[c], kMenuCreatorQt, kMenuPropertyQAction, - sizeof(action), 0, &action); - if (!action) { - QMenuMergeList *list = 0; - GetMenuItemProperty(merge, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list); - for(int i = 0; list && i < list->size(); ++i) { - QMenuMergeItem item = list->at(i); - if (item.command == commands[c] && item.action) { - action = item.action; - break; - } - } - } - } - - if (!action) { - if (commands[c] != kHICommandQuit) - enabled = false; - } else { - enabled = action->action ? action->action->isEnabled() : 0; - } - } - qt_mac_command_set_enabled(menu, commands[c], enabled); - } -#else - OSMenuRef merge = QMenuPrivate::mergeMenuHash.value(menu); - qt_mac_set_modal_state_helper_recursive(menu, merge, on); - // I'm ignoring the special items now, since they should get handled via a syncAction() -#endif -} - -bool qt_mac_menubar_is_open() -{ - return qt_mac_menus_open_count > 0; -} - -QMacMenuAction::~QMacMenuAction() -{ -#ifdef QT_MAC_USE_COCOA - [menu release]; - // Update the menu item if this action still owns it. For some items - // (like 'Quit') ownership will be transferred between all menu bars... - if (action && action.data() == reinterpret_cast([menuItem tag])) { - QAction::MenuRole role = action->menuRole(); - // Check if the item is owned by Qt, and should be hidden to keep it from causing - // problems. Do it for everything but the quit menu item since that should always - // be visible. - if (role > QAction::ApplicationSpecificRole && role < QAction::QuitRole) { - [menuItem setHidden:YES]; - } else if (role == QAction::TextHeuristicRole - && menuItem != [getMenuLoader() quitMenuItem]) { - [menuItem setHidden:YES]; - } - [menuItem setTag:nil]; - } - [menuItem release]; -#endif -} - -#ifndef QT_MAC_USE_COCOA -static MenuCommand qt_mac_menu_merge_action(MenuRef merge, QMacMenuAction *action) -#else -static NSMenuItem *qt_mac_menu_merge_action(OSMenuRef merge, QMacMenuAction *action) -#endif -{ - if (qt_mac_no_menubar_merge || action->action->menu() || action->action->isSeparator() - || action->action->menuRole() == QAction::NoRole) - return 0; - - QString t = qt_mac_removeMnemonics(action->action->text().toLower()); - int st = t.lastIndexOf(QLatin1Char('\t')); - if (st != -1) - t.remove(st, t.length()-st); - t.replace(QRegExp(QString::fromLatin1("\\.*$")), QLatin1String("")); //no ellipses - //now the fun part -#ifndef QT_MAC_USE_COCOA - MenuCommand ret = 0; -#else - NSMenuItem *ret = 0; - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); -#endif - switch (action->action->menuRole()) { - case QAction::NoRole: - ret = 0; - break; - case QAction::ApplicationSpecificRole: -#ifndef QT_MAC_USE_COCOA - { - QMenuMergeList *list = 0; - if (GetMenuItemProperty(merge, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list) == noErr && list) { - MenuCommand lastCustom = kHICommandCustomMerge; - for(int i = 0; i < list->size(); ++i) { - QMenuMergeItem item = list->at(i); - if (item.command == lastCustom) - ++lastCustom; - } - ret = lastCustom; - } else { - // The list hasn't been created, so, must be the first one. - ret = kHICommandCustomMerge; - } - } -#else - ret = [loader appSpecificMenuItem]; -#endif - break; - case QAction::AboutRole: -#ifndef QT_MAC_USE_COCOA - ret = kHICommandAbout; -#else - ret = [loader aboutMenuItem]; -#endif - break; - case QAction::AboutQtRole: -#ifndef QT_MAC_USE_COCOA - ret = kHICommandAboutQt; -#else - ret = [loader aboutQtMenuItem]; -#endif - break; - case QAction::QuitRole: -#ifndef QT_MAC_USE_COCOA - ret = kHICommandQuit; -#else - ret = [loader quitMenuItem]; -#endif - break; - case QAction::PreferencesRole: -#ifndef QT_MAC_USE_COCOA - ret = kHICommandPreferences; -#else - ret = [loader preferencesMenuItem]; -#endif - break; - case QAction::TextHeuristicRole: { - QString aboutString = QMenuBar::tr("About").toLower(); - if (t.startsWith(aboutString) || t.endsWith(aboutString)) { - if (t.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1) { -#ifndef QT_MAC_USE_COCOA - ret = kHICommandAbout; -#else - ret = [loader aboutMenuItem]; -#endif - } else { -#ifndef QT_MAC_USE_COCOA - ret = kHICommandAboutQt; -#else - ret = [loader aboutQtMenuItem]; -#endif - } - } else if (t.startsWith(QMenuBar::tr("Config").toLower()) - || t.startsWith(QMenuBar::tr("Preference").toLower()) - || t.startsWith(QMenuBar::tr("Options").toLower()) - || t.startsWith(QMenuBar::tr("Setting").toLower()) - || t.startsWith(QMenuBar::tr("Setup").toLower())) { -#ifndef QT_MAC_USE_COCOA - ret = kHICommandPreferences; -#else - ret = [loader preferencesMenuItem]; -#endif - } else if (t.startsWith(QMenuBar::tr("Quit").toLower()) - || t.startsWith(QMenuBar::tr("Exit").toLower())) { -#ifndef QT_MAC_USE_COCOA - ret = kHICommandQuit; -#else - ret = [loader quitMenuItem]; -#endif - } - } - break; - } - -#ifndef QT_MAC_USE_COCOA - QMenuMergeList *list = 0; - if (GetMenuItemProperty(merge, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list) == noErr && list) { - for(int i = 0; i < list->size(); ++i) { - QMenuMergeItem item = list->at(i); - if (item.command == ret && item.action) - return 0; - } - } - - QAction *cmd_action = 0; - if (GetMenuCommandProperty(merge, ret, kMenuCreatorQt, kMenuPropertyQAction, - sizeof(cmd_action), 0, &cmd_action) == noErr && cmd_action) - return 0; //already taken -#else - if (QMenuMergeList *list = QMenuPrivate::mergeMenuItemsHash.value(merge)) { - for(int i = 0; i < list->size(); ++i) { - const QMenuMergeItem &item = list->at(i); - if (item.menuItem == ret && item.action) - return 0; - } - } - -#endif - return ret; -} - -static QString qt_mac_menu_merge_text(QMacMenuAction *action) -{ - QString ret; - extern QString qt_mac_applicationmenu_string(int type); -#ifdef QT_MAC_USE_COCOA - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); -#endif - if (action->action->menuRole() == QAction::ApplicationSpecificRole) - ret = action->action->text(); -#ifndef QT_MAC_USE_COCOA - else if (action->command == kHICommandAbout) - ret = qt_mac_applicationmenu_string(6).arg(qAppName()); - else if (action->command == kHICommandAboutQt) - ret = QMenuBar::tr("About Qt"); - else if (action->command == kHICommandPreferences) - ret = qt_mac_applicationmenu_string(4); - else if (action->command == kHICommandQuit) - ret = qt_mac_applicationmenu_string(5).arg(qAppName()); -#else - else if (action->menuItem == [loader aboutMenuItem]) { - ret = qt_mac_applicationmenu_string(6).arg(qAppName()); - } else if (action->menuItem == [loader aboutQtMenuItem]) { - if (action->action->text() == QString("About Qt")) - ret = QMenuBar::tr("About Qt"); - else - ret = action->action->text(); - } else if (action->menuItem == [loader preferencesMenuItem]) { - ret = qt_mac_applicationmenu_string(4); - } else if (action->menuItem == [loader quitMenuItem]) { - ret = qt_mac_applicationmenu_string(5).arg(qAppName()); - } -#endif - return ret; -} - -static QKeySequence qt_mac_menu_merge_accel(QMacMenuAction *action) -{ - QKeySequence ret; -#ifdef QT_MAC_USE_COCOA - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); -#endif - if (action->action->menuRole() == QAction::ApplicationSpecificRole) - ret = action->action->shortcut(); -#ifndef QT_MAC_USE_COCOA - else if (action->command == kHICommandPreferences) - ret = QKeySequence(QKeySequence::Preferences); - else if (action->command == kHICommandQuit) - ret = QKeySequence(QKeySequence::Quit); -#else - else if (action->menuItem == [loader preferencesMenuItem]) - ret = QKeySequence(QKeySequence::Preferences); - else if (action->menuItem == [loader quitMenuItem]) - ret = QKeySequence(QKeySequence::Quit); -#endif - return ret; -} - -void Q_GUI_EXPORT qt_mac_set_menubar_icons(bool b) -{ QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus, !b); } -void Q_GUI_EXPORT qt_mac_set_native_menubar(bool b) -{ QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, !b); } -void Q_GUI_EXPORT qt_mac_set_menubar_merge(bool b) { qt_mac_no_menubar_merge = !b; } - -/***************************************************************************** - QMenu bindings - *****************************************************************************/ -QMenuPrivate::QMacMenuPrivate::QMacMenuPrivate() : menu(0) -{ -} - -QMenuPrivate::QMacMenuPrivate::~QMacMenuPrivate() -{ -#ifndef QT_MAC_USE_COCOA - for(QList::Iterator it = actionItems.begin(); it != actionItems.end(); ++it) { - QMacMenuAction *action = (*it); - RemoveMenuCommandProperty(action->menu, action->command, kMenuCreatorQt, kMenuPropertyQAction); - if (action->merged) { - QMenuMergeList *list = 0; - GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list); - for(int i = 0; list && i < list->size(); ) { - QMenuMergeItem item = list->at(i); - if (item.action == action) - list->removeAt(i); - else - ++i; - } - } - delete action; - } - if (menu) { - EventHandlerHash::iterator it = menu_eventHandlers_hash()->find(menu); - while (it != menu_eventHandlers_hash()->end() && it.key() == menu) { - RemoveEventHandler(it.value()); - ++it; - } - menu_eventHandlers_hash()->remove(menu); - ReleaseMenu(menu); - } -#else - QMacCocoaAutoReleasePool pool; - while (actionItems.size()) { - QMacMenuAction *action = actionItems.takeFirst(); - if (QMenuMergeList *list = mergeMenuItemsHash.value(action->menu)) { - int i = 0; - while (i < list->size()) { - const QMenuMergeItem &item = list->at(i); - if (item.action == action) - list->removeAt(i); - else - ++i; - } - } - delete action; - } - mergeMenuHash.remove(menu); - mergeMenuItemsHash.remove(menu); - [menu release]; -#endif -} - -void -QMenuPrivate::QMacMenuPrivate::addAction(QAction *a, QMacMenuAction *before, QMenuPrivate *qmenu) -{ - QMacMenuAction *action = new QMacMenuAction; - action->action = a; - action->ignore_accel = 0; - action->merged = 0; - action->menu = 0; -#ifndef QT_MAC_USE_COCOA - action->command = qt_mac_menu_static_cmd_id++; -#endif - addAction(action, before, qmenu); -} - -void -QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction *before, QMenuPrivate *qmenu) -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - Q_UNUSED(qmenu); -#endif - if (!action) - return; - int before_index = actionItems.indexOf(before); - if (before_index < 0) { - before = 0; - before_index = actionItems.size(); - } - actionItems.insert(before_index, action); - -#ifndef QT_MAC_USE_COCOA - int index = qt_mac_menu_find_action(menu, action); -#else - [menu retain]; - [action->menu release]; -#endif - action->menu = menu; - - /* When the action is considered a mergable action it - will stay that way, until removed.. */ - if (!qt_mac_no_menubar_merge) { -#ifndef QT_MAC_USE_COCOA - MenuRef merge = 0; - GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyMergeMenu, - sizeof(merge), 0, &merge); -#else - OSMenuRef merge = QMenuPrivate::mergeMenuHash.value(menu); -#endif - if (merge) { -#ifndef QT_MAC_USE_COCOA - if (MenuCommand cmd = qt_mac_menu_merge_action(merge, action)) { - action->merged = 1; - action->menu = merge; - action->command = cmd; - if (qt_mac_auto_apple_menu(cmd)) - index = 0; //no need - - QMenuMergeList *list = 0; - if (GetMenuItemProperty(merge, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list) != noErr || !list) { - list = new QMenuMergeList; - SetMenuItemProperty(merge, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), &list); - } - list->append(QMenuMergeItem(cmd, action)); - } -#else - if (NSMenuItem *cmd = qt_mac_menu_merge_action(merge, action)) { - action->merged = 1; - [merge retain]; - [action->menu release]; - action->menu = merge; - [cmd retain]; - [cmd setAction:@selector(qtDispatcherToQAction:)]; - [cmd setTarget:nil]; - [action->menuItem release]; - action->menuItem = cmd; - QMenuMergeList *list = QMenuPrivate::mergeMenuItemsHash.value(merge); - if (!list) { - list = new QMenuMergeList; - QMenuPrivate::mergeMenuItemsHash.insert(merge, list); - } - list->append(QMenuMergeItem(cmd, action)); - } -#endif - } - } - -#ifdef QT_MAC_USE_COCOA - NSMenuItem *newItem = action->menuItem; -#endif - if ( -#ifndef QT_MAC_USE_COCOA - index == -1 -#else - newItem == 0 -#endif - ) { -#ifndef QT_MAC_USE_COCOA - index = before_index; - MenuItemAttributes attr = kMenuItemAttrAutoRepeat; -#else - newItem = createNSMenuItem(action->action->text()); - action->menuItem = newItem; -#endif - if (before) { -#ifndef QT_MAC_USE_COCOA - InsertMenuItemTextWithCFString(action->menu, 0, qMax(before_index, 0), attr, action->command); -#else - [menu insertItem:newItem atIndex:qMax(before_index, 0)]; -#endif - } else { -#ifndef QT_MAC_USE_COCOA - // Append the menu item to the menu. If it is a kHICommandAbout or a kHICommandAboutQt append - // a separator also (to get a separator above "Preferences"), but make sure that we don't - // add separators between two "about" items. - - // Build a set of all commands that could possibly be before the separator. - QSet mergedItems; - mergedItems.insert(kHICommandAbout); - mergedItems.insert(kHICommandAboutQt); - mergedItems.insert(kHICommandCustomMerge); - - QMenuMergeList *list = 0; - if (GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list) == noErr && list) { - for (int i = 0; i < list->size(); ++i) { - MenuCommand command = list->at(i).command; - if (command > kHICommandCustomMerge) { - mergedItems.insert(command); - } - } - } - - const int itemCount = CountMenuItems(action->menu); - MenuItemAttributes testattr; - GetMenuItemAttributes(action->menu, itemCount , &testattr); - if (mergedItems.contains(action->command) - && (testattr & kMenuItemAttrSeparator)) { - InsertMenuItemTextWithCFString(action->menu, 0, qMax(itemCount - 1, 0), attr, action->command); - index = itemCount; - } else { - MenuItemIndex tmpIndex; - AppendMenuItemTextWithCFString(action->menu, 0, attr, action->command, &tmpIndex); - index = tmpIndex; - if (mergedItems.contains(action->command)) - AppendMenuItemTextWithCFString(action->menu, 0, kMenuItemAttrSeparator, 0, &tmpIndex); - } -#else - [menu addItem:newItem]; -#endif - } - - QWidget *widget = qmenu ? qmenu->widgetItems.value(action->action) : 0; - if (widget) { -#ifndef QT_MAC_USE_COCOA - ChangeMenuAttributes(action->menu, kMenuAttrDoNotCacheImage, 0); - attr = kMenuItemAttrCustomDraw; - SetMenuItemProperty(action->menu, index, kMenuCreatorQt, kMenuPropertyWidgetActionWidget, - sizeof(QWidget *), &widget); - HIViewRef content; - HIMenuGetContentView(action->menu, kThemeMenuTypePullDown, &content); - - EventHandlerRef eventHandlerRef; - InstallMenuEventHandler(action->menu, qt_mac_widget_in_menu_eventHandler, - GetEventTypeCount(widget_in_menu_events), - widget_in_menu_events, 0, &eventHandlerRef); - menu_eventHandlers_hash()->insert(action->menu, eventHandlerRef); - - QWidget *menuWidget = 0; - GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyWidgetMenu, - sizeof(menuWidget), 0, &menuWidget); - if(!menuWidget) { - menuWidget = new QMacNativeWidget(content); - SetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyWidgetMenu, - sizeof(menuWidget), &menuWidget); - menuWidget->show(); - } - widget->setParent(menuWidget); -#else - QMacNativeWidget *container = new QMacNativeWidget(0); - container->resize(widget->sizeHint()); - widget->setAttribute(Qt::WA_LayoutUsesWidgetRect); - widget->setParent(container); - - NSView *containerView = qt_mac_nativeview_for(container); - [containerView setAutoresizesSubviews:YES]; - [containerView setAutoresizingMask:NSViewWidthSizable]; - [qt_mac_nativeview_for(widget) setAutoresizingMask:NSViewWidthSizable]; - - [newItem setView:containerView]; - container->show(); -#endif - widget->show(); - } - - } else { -#ifndef QT_MAC_USE_COCOA - qt_mac_command_set_enabled(action->menu, action->command, !QApplicationPrivate::modalState()); -#else - [newItem setEnabled:!QApplicationPrivate::modalState()]; -#endif - } -#ifndef QT_MAC_USE_COCOA - SetMenuCommandProperty(action->menu, action->command, kMenuCreatorQt, kMenuPropertyQAction, - sizeof(action), &action); -#else - [newItem setTag:long(static_cast(action->action))]; -#endif - syncAction(action); -} - -// return an autoreleased string given a QKeySequence (currently only looks at the first one). -NSString *keySequenceToKeyEqivalent(const QKeySequence &accel) -{ - quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL)); - extern QChar qtKey2CocoaKey(Qt::Key key); - QChar cocoa_key = qtKey2CocoaKey(Qt::Key(accel_key)); - if (cocoa_key.isNull()) - cocoa_key = QChar(accel_key).toLower().unicode(); - return [NSString stringWithCharacters:&cocoa_key.unicode() length:1]; -} - -// return the cocoa modifier mask for the QKeySequence (currently only looks at the first one). -NSUInteger keySequenceModifierMask(const QKeySequence &accel) -{ - return constructModifierMask(accel[0]); -} - -void -QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action) -{ - if (!action) - return; - -#ifndef QT_MAC_USE_COCOA - const int index = qt_mac_menu_find_action(action->menu, action); - if (index == -1) - return; -#else - NSMenuItem *item = action->menuItem; - if (!item) - return; -#endif - -#ifndef QT_MAC_USE_COCOA - if (!action->action->isVisible()) { - ChangeMenuItemAttributes(action->menu, index, kMenuItemAttrHidden, 0); - return; - } - ChangeMenuItemAttributes(action->menu, index, 0, kMenuItemAttrHidden); -#else - QMacCocoaAutoReleasePool pool; - NSMenu *menu = [item menu]; - bool actionVisible = action->action->isVisible(); - [item setHidden:!actionVisible]; - if (!actionVisible) - return; -#endif - -#ifndef QT_MAC_USE_COCOA - if (action->action->isSeparator()) { - ChangeMenuItemAttributes(action->menu, index, kMenuItemAttrSeparator, 0); - return; - } - ChangeMenuItemAttributes(action->menu, index, 0, kMenuItemAttrSeparator); -#else - int itemIndex = [menu indexOfItem:item]; - Q_ASSERT(itemIndex != -1); - if (action->action->isSeparator()) { - action->menuItem = [NSMenuItem separatorItem]; - [action->menuItem retain]; - [menu insertItem: action->menuItem atIndex:itemIndex]; - [menu removeItem:item]; - [item release]; - item = action->menuItem; - return; - } else if ([item isSeparatorItem]) { - // I'm no longer a separator... - action->menuItem = createNSMenuItem(action->action->text()); - [menu insertItem:action->menuItem atIndex:itemIndex]; - [menu removeItem:item]; - [item release]; - item = action->menuItem; - } -#endif - - //find text (and accel) - action->ignore_accel = 0; - QString text = action->action->text(); - QKeySequence accel = action->action->shortcut(); - { - int st = text.lastIndexOf(QLatin1Char('\t')); - if (st != -1) { - action->ignore_accel = 1; - accel = QKeySequence(text.right(text.length()-(st+1))); - text.remove(st, text.length()-st); - } - } - { - QString cmd_text = qt_mac_menu_merge_text(action); - if (!cmd_text.isEmpty()) { - text = cmd_text; - accel = qt_mac_menu_merge_accel(action); - } - } - // Show multiple key sequences as part of the menu text. - if (accel.count() > 1) - text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")"); - - QString finalString = qt_mac_removeMnemonics(text); - -#ifndef QT_MAC_USE_COCOA - MenuItemDataRec data; - memset(&data, '\0', sizeof(data)); - - //Carbon text - data.whichData |= kMenuItemDataCFString; - QCFString cfstring(finalString); // Hold the reference to the end of the function. - data.cfText = cfstring; - - // Carbon enabled - data.whichData |= kMenuItemDataEnabled; - data.enabled = action->action->isEnabled(); - // Carbon icon - data.whichData |= kMenuItemDataIconHandle; - if (!action->action->icon().isNull() - && action->action->isIconVisibleInMenu()) { - data.iconType = kMenuIconRefType; - data.iconHandle = (Handle)qt_mac_create_iconref(action->action->icon().pixmap(16, QIcon::Normal)); - } else { - data.iconType = kMenuNoIcon; - } - if (action->action->font().resolve()) { // Carbon font - if (action->action->font().bold()) - data.style |= bold; - if (action->action->font().underline()) - data.style |= underline; - if (action->action->font().italic()) - data.style |= italic; - if (data.style) - data.whichData |= kMenuItemDataStyle; - data.whichData |= kMenuItemDataFontID; - data.fontID = action->action->font().macFontID(); - } -#else - // Cocoa Font and title - if (action->action->font().resolve()) { - const QFont &actionFont = action->action->font(); - NSFont *customMenuFont = [NSFont fontWithName:qt_mac_QStringToNSString(actionFont.family()) - size:actionFont.pointSize()]; - NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil]; - NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil]; - NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; - NSAttributedString *str = [[[NSAttributedString alloc] initWithString:qt_mac_QStringToNSString(finalString) - attributes:attributes] autorelease]; - [item setAttributedTitle: str]; - } else { - [item setTitle: qt_mac_QStringToNSString(finalString)]; - } - - if (action->action->menuRole() == QAction::AboutRole || action->action->menuRole() == QAction::QuitRole) - [item setTitle:qt_mac_QStringToNSString(text)]; - else - [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))]; - - // Cocoa Enabled - [item setEnabled: action->action->isEnabled()]; - - // Cocoa icon - NSImage *nsimage = 0; - if (!action->action->icon().isNull() && action->action->isIconVisibleInMenu()) { - nsimage = static_cast(qt_mac_create_nsimage(action->action->icon().pixmap(16, QIcon::Normal))); - } - [item setImage:nsimage]; - [nsimage release]; -#endif - - if (action->action->menu()) { //submenu -#ifndef QT_MAC_USE_COCOA - data.whichData |= kMenuItemDataSubmenuHandle; - data.submenuHandle = action->action->menu()->macMenu(); - QWidget *caused = 0; - GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(caused), 0, &caused); - SetMenuItemProperty(data.submenuHandle, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), &caused); -#else - NSMenu *subMenu = static_cast(action->action->menu()->macMenu()); - if ([subMenu supermenu] && [subMenu supermenu] != [item menu]) { - // The menu is already a sub-menu of another one. Cocoa will throw an exception, - // in such cases. For the time being, a new QMenu with same set of actions is the - // only workaround. - action->action->setEnabled(false); - } else { - [item setSubmenu:subMenu]; - } -#endif - } else { //respect some other items -#ifndef QT_MAC_USE_COCOA - //shortcuts (say we are setting them all so that we can also clear them). - data.whichData |= kMenuItemDataCmdKey; - data.whichData |= kMenuItemDataCmdKeyModifiers; - data.whichData |= kMenuItemDataCmdKeyGlyph; - if (accel.count() == 1) { - qt_mac_get_accel(accel[0], (quint32*)&data.cmdKeyModifiers, (quint32*)&data.cmdKeyGlyph); - if (data.cmdKeyGlyph == 0) - data.cmdKey = (UniChar)accel[0]; - } -#else - [item setSubmenu:0]; - // No key equivalent set for multiple key QKeySequence. - if (accel.count() == 1) { - [item setKeyEquivalent:keySequenceToKeyEqivalent(accel)]; - [item setKeyEquivalentModifierMask:keySequenceModifierMask(accel)]; - } else { - [item setKeyEquivalent:@""]; - [item setKeyEquivalentModifierMask:NSCommandKeyMask]; - } -#endif - } -#ifndef QT_MAC_USE_COCOA - //mark glyph - data.whichData |= kMenuItemDataMark; - if (action->action->isChecked()) { -#if 0 - if (action->action->actionGroup() && - action->action->actionGroup()->isExclusive()) - data.mark = diamondMark; - else -#endif - data.mark = checkMark; - } else { - data.mark = noMark; - } - - //actually set it - SetMenuItemData(action->menu, action->command, true, &data); - - // Free up memory - if (data.iconHandle) - ReleaseIconRef(IconRef(data.iconHandle)); -#else - //mark glyph - [item setState:action->action->isChecked() ? NSOnState : NSOffState]; -#endif -} - -void -QMenuPrivate::QMacMenuPrivate::removeAction(QMacMenuAction *action) -{ - if (!action) - return; -#ifndef QT_MAC_USE_COCOA - if (action->command == kHICommandQuit || action->command == kHICommandPreferences) - qt_mac_command_set_enabled(action->menu, action->command, false); - else - DeleteMenuItem(action->menu, qt_mac_menu_find_action(action->menu, action)); -#else - QMacCocoaAutoReleasePool pool; - if (action->merged) { - if (reinterpret_cast([action->menuItem tag]) == action->action) { - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); - [action->menuItem setEnabled:false]; - if (action->menuItem != [loader quitMenuItem] - && action->menuItem != [loader preferencesMenuItem]) { - [[action->menuItem menu] removeItem:action->menuItem]; - } - } - } else { - [[action->menuItem menu] removeItem:action->menuItem]; - } -#endif - actionItems.removeAll(action); -} - -OSMenuRef -QMenuPrivate::macMenu(OSMenuRef merge) -{ - Q_UNUSED(merge); - Q_Q(QMenu); - if (mac_menu && mac_menu->menu) - return mac_menu->menu; - if (!mac_menu) - mac_menu = new QMacMenuPrivate; - mac_menu->menu = qt_mac_create_menu(q); - if (merge) { -#ifndef QT_MAC_USE_COCOA - SetMenuItemProperty(mac_menu->menu, 0, kMenuCreatorQt, kMenuPropertyMergeMenu, sizeof(merge), &merge); -#else - mergeMenuHash.insert(mac_menu->menu, merge); -#endif - } - QList items = q->actions(); - for(int i = 0; i < items.count(); i++) - mac_menu->addAction(items[i], 0, this); - syncSeparatorsCollapsible(collapsibleSeparators); - return mac_menu->menu; -} - -/*! - \internal -*/ -void -QMenuPrivate::syncSeparatorsCollapsible(bool collapse) -{ -#ifndef QT_MAC_USE_COCOA - if (collapse) - ChangeMenuAttributes(mac_menu->menu, kMenuAttrCondenseSeparators, 0); - else - ChangeMenuAttributes(mac_menu->menu, 0, kMenuAttrCondenseSeparators); -#else - qt_mac_menu_collapseSeparators(mac_menu->menu, collapse); -#endif -} - - - -/*! - \internal -*/ -void QMenuPrivate::setMacMenuEnabled(bool enable) -{ - if (!macMenu(0)) - return; - - QMacCocoaAutoReleasePool pool; - if (enable) { - for (int i = 0; i < mac_menu->actionItems.count(); ++i) { - QMacMenuAction *menuItem = mac_menu->actionItems.at(i); - if (menuItem && menuItem->action && menuItem->action->isEnabled()) { -#ifndef QT_MAC_USE_COCOA - // Only enable those items which contains an enabled QAction. - // i == 0 -> the menu itself, hence i + 1 for items. - EnableMenuItem(mac_menu->menu, i + 1); -#else - [menuItem->menuItem setEnabled:true]; -#endif - } - } - } else { -#ifndef QT_MAC_USE_COCOA - DisableAllMenuItems(mac_menu->menu); -#else - NSMenu *menu = mac_menu->menu; - for (NSMenuItem *item in [menu itemArray]) { - [item setEnabled:false]; - } -#endif - } -} - -/*! - \internal - - This function will return the OSMenuRef used to create the native menu bar - bindings. - - If Qt is built against Carbon, the OSMenuRef is a MenuRef that can be used - with Carbon's Menu Manager API. - - If Qt is built against Cocoa, the OSMenuRef is a NSMenu pointer. - - \warning This function is not portable. - - \sa QMenuBar::macMenu() -*/ -OSMenuRef QMenu::macMenu(OSMenuRef merge) { return d_func()->macMenu(merge); } - -/***************************************************************************** - QMenuBar bindings - *****************************************************************************/ -typedef QHash MenuBarHash; -Q_GLOBAL_STATIC(MenuBarHash, menubars) -static QMenuBar *fallback = 0; -QMenuBarPrivate::QMacMenuBarPrivate::QMacMenuBarPrivate() : menu(0), apple_menu(0) -{ -} - -QMenuBarPrivate::QMacMenuBarPrivate::~QMacMenuBarPrivate() -{ - for(QList::Iterator it = actionItems.begin(); it != actionItems.end(); ++it) - delete (*it); -#ifndef QT_MAC_USE_COCOA - if (apple_menu) { - QMenuMergeList *list = 0; - GetMenuItemProperty(apple_menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list); - if (list) { - RemoveMenuItemProperty(apple_menu, 0, kMenuCreatorQt, kMenuPropertyMergeList); - delete list; - } - ReleaseMenu(apple_menu); - } - if (menu) - ReleaseMenu(menu); -#else - [apple_menu release]; - [menu release]; -#endif -} - -void -QMenuBarPrivate::QMacMenuBarPrivate::addAction(QAction *a, QMacMenuAction *before) -{ - if (a->isSeparator() || !menu) - return; - QMacMenuAction *action = new QMacMenuAction; - action->action = a; - action->ignore_accel = 1; -#ifndef QT_MAC_USE_COCOA - action->command = qt_mac_menu_static_cmd_id++; -#endif - addAction(action, before); -} - -void -QMenuBarPrivate::QMacMenuBarPrivate::addAction(QMacMenuAction *action, QMacMenuAction *before) -{ - if (!action || !menu) - return; - - int before_index = actionItems.indexOf(before); - if (before_index < 0) { - before = 0; - before_index = actionItems.size(); - } - actionItems.insert(before_index, action); - - MenuItemIndex index = actionItems.size()-1; - - action->menu = menu; -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - [action->menu retain]; - NSMenuItem *newItem = createNSMenuItem(action->action->text()); - action->menuItem = newItem; -#endif - if (before) { -#ifndef QT_MAC_USE_COCOA - InsertMenuItemTextWithCFString(action->menu, 0, qMax(1, before_index+1), 0, action->command); -#else - [menu insertItem:newItem atIndex:qMax(1, before_index + 1)]; -#endif - index = before_index; - } else { -#ifndef QT_MAC_USE_COCOA - AppendMenuItemTextWithCFString(action->menu, 0, 0, action->command, &index); -#else - [menu addItem:newItem]; -#endif - } -#ifndef QT_MAC_USE_COCOA - SetMenuItemProperty(action->menu, index, kMenuCreatorQt, kMenuPropertyQAction, sizeof(action), - &action); -#else - [newItem setTag:long(static_cast(action->action))]; -#endif - syncAction(action); -} - -void -QMenuBarPrivate::QMacMenuBarPrivate::syncAction(QMacMenuAction *action) -{ - if (!action || !menu) - return; -#ifndef QT_MAC_USE_COCOA - const int index = qt_mac_menu_find_action(action->menu, action); -#else - QMacCocoaAutoReleasePool pool; - NSMenuItem *item = action->menuItem; -#endif - - OSMenuRef submenu = 0; - bool release_submenu = false; - if (action->action->menu()) { - if ((submenu = action->action->menu()->macMenu(apple_menu))) { -#ifndef QT_MAC_USE_COCOA - QWidget *caused = 0; - GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(caused), 0, &caused); - SetMenuItemProperty(submenu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), &caused); -#else - if ([submenu supermenu] && [submenu supermenu] != [item menu]) - return; - else - [item setSubmenu:submenu]; -#endif - } -#ifndef QT_MAC_USE_COCOA - } else { // create a submenu to act as menu - release_submenu = true; - CreateNewMenu(0, 0, &submenu); -#endif - } - - if (submenu) { - bool visible = actualMenuItemVisibility(this, action); -#ifndef QT_MAC_USE_COCOA - SetMenuItemHierarchicalMenu(action->menu, index, submenu); - SetMenuTitleWithCFString(submenu, QCFString(qt_mac_removeMnemonics(action->action->text()))); - if (visible) - ChangeMenuAttributes(submenu, 0, kMenuAttrHidden); - else - ChangeMenuAttributes(submenu, kMenuAttrHidden, 0); -#else - [item setSubmenu: submenu]; - [submenu setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(action->action->text()))]; - syncNSMenuItemVisiblity(item, visible); -#endif - if (release_submenu) { //no pointers to it -#ifndef QT_MAC_USE_COCOA - ReleaseMenu(submenu); -#else - [submenu release]; -#endif - } - } else { - qWarning("QMenu: No OSMenuRef created for popup menu"); - } -} - -void -QMenuBarPrivate::QMacMenuBarPrivate::removeAction(QMacMenuAction *action) -{ - if (!action || !menu) - return; -#ifndef QT_MAC_USE_COCOA - DeleteMenuItem(action->menu, qt_mac_menu_find_action(action->menu, action)); -#else - QMacCocoaAutoReleasePool pool; - [action->menu removeItem:action->menuItem]; -#endif - actionItems.removeAll(action); -} - -bool QMenuBarPrivate::macWidgetHasNativeMenubar(QWidget *widget) -{ - // This function is different from q->isNativeMenuBar(), as - // it returns true only if a native menu bar is actually - // _created_. - if (!widget) - return false; - return menubars()->contains(widget->window()); -} - -void -QMenuBarPrivate::macCreateMenuBar(QWidget *parent) -{ - Q_Q(QMenuBar); - static int dontUseNativeMenuBar = -1; - // We call the isNativeMenuBar function here - // because that will make sure that local overrides - // are dealt with correctly. q->isNativeMenuBar() will, if not - // overridden, depend on the attribute Qt::AA_DontUseNativeMenuBar: - bool qt_mac_no_native_menubar = !q->isNativeMenuBar(); - if (qt_mac_no_native_menubar == false && dontUseNativeMenuBar < 0) { - // The menubar is set to be native. Let's check (one time only - // for all menubars) if this is OK with the rest of the environment. - // As a result, Qt::AA_DontUseNativeMenuBar is set. NB: the application - // might still choose to not respect, or change, this flag. - bool isPlugin = QApplication::testAttribute(Qt::AA_MacPluginApplication); - bool environmentSaysNo = !qgetenv("QT_MAC_NO_NATIVE_MENUBAR").isEmpty(); - dontUseNativeMenuBar = isPlugin || environmentSaysNo; - QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, dontUseNativeMenuBar); - qt_mac_no_native_menubar = !q->isNativeMenuBar(); - } - if (qt_mac_no_native_menubar == false) { - // INVARIANT: Use native menubar. - extern void qt_event_request_menubarupdate(); //qapplication_mac.cpp - qt_event_request_menubarupdate(); - if (!parent && !fallback) { - fallback = q; - mac_menubar = new QMacMenuBarPrivate; - } else if (parent && parent->isWindow()) { - menubars()->insert(q->window(), q); - mac_menubar = new QMacMenuBarPrivate; - } - } -} - -void QMenuBarPrivate::macDestroyMenuBar() -{ - Q_Q(QMenuBar); - QMacCocoaAutoReleasePool pool; - if (fallback == q) - fallback = 0; - delete mac_menubar; - QWidget *tlw = q->window(); - menubars()->remove(tlw); - mac_menubar = 0; - - if (!qt_mac_current_menubar.qmenubar || qt_mac_current_menubar.qmenubar == q) { -#ifdef QT_MAC_USE_COCOA - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); - [loader removeActionsFromAppMenu]; -#else - cancelAllMenuTracking(); -#endif - extern void qt_event_request_menubarupdate(); //qapplication_mac.cpp - qt_event_request_menubarupdate(); - } -} - -OSMenuRef QMenuBarPrivate::macMenu() -{ - Q_Q(QMenuBar); - if (!q->isNativeMenuBar() || !mac_menubar) { - return 0; - } else if (!mac_menubar->menu) { - mac_menubar->menu = qt_mac_create_menu(q); - ProcessSerialNumber mine, front; - if (GetCurrentProcess(&mine) == noErr && GetFrontProcess(&front) == noErr) { - if (!qt_mac_no_menubar_merge && !mac_menubar->apple_menu) { - mac_menubar->apple_menu = qt_mac_create_menu(q); -#ifndef QT_MAC_USE_COCOA - MenuItemIndex index; - AppendMenuItemTextWithCFString(mac_menubar->menu, 0, 0, 0, &index); - - SetMenuTitleWithCFString(mac_menubar->apple_menu, QCFString(QString(QChar(0x14)))); - SetMenuItemHierarchicalMenu(mac_menubar->menu, index, mac_menubar->apple_menu); - SetMenuItemProperty(mac_menubar->apple_menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(q), &q); -#else - [mac_menubar->apple_menu setTitle:qt_mac_QStringToNSString(QString(QChar(0x14)))]; - NSMenuItem *apple_menuItem = [[NSMenuItem alloc] init]; - [apple_menuItem setSubmenu:mac_menubar->menu]; - [mac_menubar->apple_menu addItem:apple_menuItem]; - [apple_menuItem release]; -#endif - } - if (mac_menubar->apple_menu) { -#ifndef QT_MAC_USE_COCOA - SetMenuItemProperty(mac_menubar->menu, 0, kMenuCreatorQt, kMenuPropertyMergeMenu, - sizeof(mac_menubar->apple_menu), &mac_menubar->apple_menu); -#else - QMenuPrivate::mergeMenuHash.insert(mac_menubar->menu, mac_menubar->apple_menu); -#endif - } - QList items = q->actions(); - for(int i = 0; i < items.count(); i++) - mac_menubar->addAction(items[i]); - } - } - return mac_menubar->menu; -} - -/*! - \internal - - This function will return the OSMenuRef used to create the native menu bar - bindings. This OSMenuRef is then set as the root menu for the Menu - Manager. - - \warning This function is not portable. - - \sa QMenu::macMenu() -*/ -OSMenuRef QMenuBar::macMenu() { return d_func()->macMenu(); } - -/* ! - \internal - Ancestor function that crosses windows (QWidget::isAncestorOf - only considers widgets within the same window). -*/ -static bool qt_mac_is_ancestor(QWidget* possibleAncestor, QWidget *child) -{ - if (!possibleAncestor) - return false; - - QWidget * current = child->parentWidget(); - while (current != 0) { - if (current == possibleAncestor) - return true; - current = current->parentWidget(); - } - return false; -} - -/* ! - \internal - Returns true if the entries of menuBar should be disabled, - based on the modality type of modalWidget. -*/ -static bool qt_mac_should_disable_menu(QMenuBar *menuBar) -{ - QWidget *modalWidget = qApp->activeModalWidget(); - if (!modalWidget) - return false; - - if (menuBar && menuBar == menubars()->value(modalWidget)) - // The menu bar is owned by the modal widget. - // In that case we should enable it: - return false; - - // When there is an application modal window on screen, the entries of - // the menubar should be disabled. The exception in Qt is that if the - // modal window is the only window on screen, then we enable the menu bar. - QWidget *w = modalWidget; - QWidgetList topLevelWidgets = QApplication::topLevelWidgets(); - while (w) { - if (w->isVisible() && w->windowModality() == Qt::ApplicationModal) { - for (int i=0; iisVisible()) { - // INVARIANT: we found another visible window - // on screen other than our modalWidget. We therefore - // disable the menu bar to follow normal modality logic: - return true; - } - } - // INVARIANT: We have only one window on screen that happends - // to be application modal. We choose to enable the menu bar - // in that case to e.g. enable the quit menu item. - return false; - } - w = w->parentWidget(); - } - - // INVARIANT: modalWidget is window modal. Disable menu entries - // if the menu bar belongs to an ancestor of modalWidget. If menuBar - // is nil, we understand it as the default menu bar set by the nib: - return menuBar ? qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget) : false; -} - -static QWidget *findWindowThatShouldDisplayMenubar() -{ - QWidget *w = qApp->activeWindow(); - if (!w) { - // We have no active window on screen. Try to - // find a window from the list of top levels: - QWidgetList tlws = QApplication::topLevelWidgets(); - for(int i = 0; i < tlws.size(); ++i) { - QWidget *tlw = tlws.at(i); - if ((tlw->isVisible() && tlw->windowType() != Qt::Tool && - tlw->windowType() != Qt::Popup)) { - w = tlw; - break; - } - } - } - return w; -} - -static QMenuBar *findMenubarForWindow(QWidget *w) -{ - QMenuBar *mb = 0; - if (w) { - mb = menubars()->value(w); -#ifndef QT_NO_MAINWINDOW - QDockWidget *dw = qobject_cast(w); - if (!mb && dw) { - QMainWindow *mw = qobject_cast(dw->parentWidget()); - if (mw && (mb = menubars()->value(mw))) - w = mw; - } -#endif - while(w && !mb) - mb = menubars()->value((w = w->parentWidget())); - } - - if (!mb) { - // We could not find a menu bar for the window. Lets - // check if we have a global (parentless) menu bar instead: - mb = fallback; - } - - return mb; -} - -void qt_mac_clear_menubar() -{ - if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) - return; - -#ifndef QT_MAC_USE_COCOA - MenuRef clear_menu = 0; - if (CreateNewMenu(0, 0, &clear_menu) == noErr) { - SetRootMenu(clear_menu); - ReleaseMenu(clear_menu); - } else { - qWarning("QMenu: Internal error at %s:%d", __FILE__, __LINE__); - } - ClearMenuBar(); - qt_mac_command_set_enabled(0, kHICommandPreferences, false); - InvalMenuBar(); -#else - QMacCocoaAutoReleasePool pool; - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); - NSMenu *menu = [loader menu]; - [loader ensureAppMenuInMenu:menu]; - [NSApp setMainMenu:menu]; - const bool modal = qt_mac_should_disable_menu(0); - if (qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal) - qt_mac_set_modal_state(menu, modal); - qt_mac_current_menubar.qmenubar = 0; - qt_mac_current_menubar.modal = modal; -#endif -} - -/*! - \internal - - This function will update the current menu bar and set it as the - active menu bar in the Menu Manager. - - \warning This function is not portable. - - \sa QMenu::macMenu(), QMenuBar::macMenu() -*/ -bool QMenuBar::macUpdateMenuBar() -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar)); - return true; -#else - return QMenuBarPrivate::macUpdateMenuBarImmediatly(); -#endif -} - -bool QMenuBarPrivate::macUpdateMenuBarImmediatly() -{ - bool ret = false; - cancelAllMenuTracking(); - QWidget *w = findWindowThatShouldDisplayMenubar(); - QMenuBar *mb = findMenubarForWindow(w); - extern bool qt_mac_app_fullscreen; //qapplication_mac.mm - - // We need to see if we are in full screen mode, if so we need to - // switch the full screen mode to be able to show or hide the menubar. - if(w && mb) { - // This case means we are creating a menubar, check if full screen - if(w->isFullScreen()) { - // Ok, switch to showing the menubar when hovering over it. - SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); - qt_mac_app_fullscreen = true; - } - } else if(w) { - // Removing a menubar - if(w->isFullScreen()) { - // Ok, switch to not showing the menubar when hovering on it - SetSystemUIMode(kUIModeAllHidden, 0); - qt_mac_app_fullscreen = true; - } - } - - if (mb && mb->isNativeMenuBar()) { - bool modal = QApplicationPrivate::modalState(); -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; -#endif - if (OSMenuRef menu = mb->macMenu()) { -#ifndef QT_MAC_USE_COCOA - SetRootMenu(menu); -#else - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); - [loader ensureAppMenuInMenu:menu]; - [NSApp setMainMenu:menu]; - syncMenuBarItemsVisiblity(mb->d_func()->mac_menubar); - - if (OSMenuRef tmpMerge = QMenuPrivate::mergeMenuHash.value(menu)) { - if (QMenuMergeList *mergeList - = QMenuPrivate::mergeMenuItemsHash.value(tmpMerge)) { - const int mergeListSize = mergeList->size(); - - for (int i = 0; i < mergeListSize; ++i) { - const QMenuMergeItem &mergeItem = mergeList->at(i); - // Ideally we would call QMenuPrivate::syncAction, but that requires finding - // the original QMen and likely doing more work than we need. - // For example, enabled is handled below. - [mergeItem.menuItem setTag:reinterpret_cast( - static_cast(mergeItem.action->action))]; - [mergeItem.menuItem setHidden:!(mergeItem.action->action->isVisible())]; - } - } - } -#endif - // Check if menu is modally shaddowed and should be disabled: - modal = qt_mac_should_disable_menu(mb); - if (mb != qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal) - qt_mac_set_modal_state(menu, modal); - } - qt_mac_current_menubar.qmenubar = mb; - qt_mac_current_menubar.modal = modal; - ret = true; - } else if (qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) { - // INVARIANT: The currently active menu bar (if any) is not native. But we do have a - // native menu bar from before. So we need to decide whether or not is should be enabled: - const bool modal = qt_mac_should_disable_menu(qt_mac_current_menubar.qmenubar); - if (modal != qt_mac_current_menubar.modal) { - ret = true; - if (OSMenuRef menu = qt_mac_current_menubar.qmenubar->macMenu()) { -#ifndef QT_MAC_USE_COCOA - SetRootMenu(menu); -#else - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader(); - [loader ensureAppMenuInMenu:menu]; - [NSApp setMainMenu:menu]; - syncMenuBarItemsVisiblity(qt_mac_current_menubar.qmenubar->d_func()->mac_menubar); -#endif - qt_mac_set_modal_state(menu, modal); - } - qt_mac_current_menubar.modal = modal; - } - } - - if (!ret) { - qt_mac_clear_menubar(); - } - return ret; -} - -QHash QMenuPrivate::mergeMenuHash; -QHash QMenuPrivate::mergeMenuItemsHash; - -bool QMenuPrivate::QMacMenuPrivate::merged(const QAction *action) const -{ -#ifndef QT_MAC_USE_COCOA - MenuRef merge = 0; - GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyMergeMenu, - sizeof(merge), 0, &merge); - if (merge) { - QMenuMergeList *list = 0; - if (GetMenuItemProperty(merge, 0, kMenuCreatorQt, kMenuPropertyMergeList, - sizeof(list), 0, &list) == noErr && list) { - for(int i = 0; i < list->size(); ++i) { - QMenuMergeItem item = list->at(i); - if (item.action->action == action) - return true; - } - } - } -#else - if (OSMenuRef merge = mergeMenuHash.value(menu)) { - if (QMenuMergeList *list = mergeMenuItemsHash.value(merge)) { - for(int i = 0; i < list->size(); ++i) { - const QMenuMergeItem &item = list->at(i); - if (item.action->action == action) - return true; - } - } - } -#endif - return false; -} - -//creation of the OSMenuRef -static OSMenuRef qt_mac_create_menu(QWidget *w) -{ - OSMenuRef ret; -#ifndef QT_MAC_USE_COCOA - ret = 0; - if (CreateNewMenu(0, 0, &ret) == noErr) { - qt_mac_create_menu_event_handler(); - SetMenuItemProperty(ret, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(w), &w); - - // kEventMenuMatchKey is only sent to the menu itself and not to - // the application, install a separate handler for that event. - EventHandlerRef eventHandlerRef; - InstallMenuEventHandler(ret, qt_mac_menu_event, - GetEventTypeCount(menu_menu_events), - menu_menu_events, 0, &eventHandlerRef); - menu_eventHandlers_hash()->insert(ret, eventHandlerRef); - } else { - qWarning("QMenu: Internal error"); - } -#else - if (QMenu *qmenu = qobject_cast(w)){ - ret = [[QT_MANGLE_NAMESPACE(QCocoaMenu) alloc] initWithQMenu:qmenu]; - } else { - ret = [[NSMenu alloc] init]; - } -#endif - return ret; -} - - - -QT_END_NAMESPACE - -- cgit v1.2.3