source: trunk/src/gui/widgets/qcocoamenu_mac.mm

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 8.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qmacdefines_mac.h"
43#include "qapplication.h"
44#ifdef QT_MAC_USE_COCOA
45#import <private/qcocoamenu_mac_p.h>
46#import <private/qcocoamenuloader_mac_p.h>
47#include <private/qt_cocoa_helpers_mac_p.h>
48#include <private/qapplication_p.h>
49#include <private/qaction_p.h>
50
51#include <QtGui/QMenu>
52
53QT_FORWARD_DECLARE_CLASS(QAction)
54QT_FORWARD_DECLARE_CLASS(QWidget)
55QT_FORWARD_DECLARE_CLASS(QApplication)
56QT_FORWARD_DECLARE_CLASS(QCoreApplication)
57QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
58QT_FORWARD_DECLARE_CLASS(QKeyEvent)
59QT_FORWARD_DECLARE_CLASS(QEvent)
60
61QT_BEGIN_NAMESPACE
62extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication.cpp
63QT_END_NAMESPACE
64
65QT_USE_NAMESPACE
66
67@implementation QT_MANGLE_NAMESPACE(QCocoaMenu)
68
69- (id)initWithQMenu:(QMenu*)menu
70{
71 self = [super init];
72 if (self) {
73 qmenu = menu;
74 previousAction = 0;
75 [self setAutoenablesItems:NO];
76 [self setDelegate:self];
77 }
78 return self;
79}
80
81- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item;
82{
83 Q_UNUSED(menu);
84
85 if (!item) {
86 if (previousAction) {
87 qt_mac_clear_status_text(previousAction);
88 previousAction = 0;
89 }
90 return;
91 }
92
93 if (QAction *action = reinterpret_cast<QAction *>([item tag])) {
94 QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
95 previousAction = action;
96 action->activate(QAction::Hover);
97 qt_mac_menu_emit_hovered(qtmenu, action);
98 action->showStatusText(0); // 0 widget -> action's parent
99 }
100}
101
102- (void)menuWillOpen:(NSMenu*)menu;
103{
104 while (QWidget *popup
105 = QApplication::activePopupWidget())
106 popup->close();
107 QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
108 qt_mac_emit_menuSignals(qtmenu, true);
109 qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
110}
111
112- (void)menuDidClose:(NSMenu*)menu;
113{
114 qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, false);
115 if (previousAction) {
116 qt_mac_clear_status_text(previousAction);
117 previousAction = 0;
118 }
119}
120
121- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
122 whichItem:(NSMenuItem**)outItem
123{
124 for (NSMenuItem *item in [menu itemArray]) {
125 if (![item isEnabled] || [item isHidden] || [item isSeparatorItem])
126 continue;
127 if ([item hasSubmenu]) {
128 if ([self hasShortcut:[item submenu]
129 forKey:key
130 forModifiers:modifier whichItem:outItem]) {
131 if (outItem)
132 *outItem = item;
133 return YES;
134 }
135 }
136 NSString *menuKey = [item keyEquivalent];
137 if (menuKey && NSOrderedSame == [menuKey compare:key]
138 && (modifier == [item keyEquivalentModifierMask])) {
139 if (outItem)
140 *outItem = item;
141 return YES;
142 }
143 }
144 if (outItem)
145 *outItem = 0;
146 return NO;
147}
148
149- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
150{
151 // Check if the menu actually has a keysequence defined for this key event.
152 // If it does, then we will first send the key sequence to the QWidget that has focus
153 // since (in Qt's eyes) it needs to a chance at the key event first. If the widget
154 // accepts the key event, we then return YES, but set the target and action to be nil,
155 // which means that the action should not be triggered, and instead dispatch the event ourselves.
156 // In every other case we return NO, which means that Cocoa can do as it pleases
157 // (i.e., fire the menu action).
158 NSMenuItem *whichItem;
159 if ([self hasShortcut:menu
160 forKey:[event characters]
161 forModifiers:([event modifierFlags] & NSDeviceIndependentModifierFlagsMask)
162 whichItem:&whichItem]) {
163 QWidget *widget = 0;
164 QAction *qaction = 0;
165 if (whichItem && [whichItem tag]) {
166 qaction = reinterpret_cast<QAction *>([whichItem tag]);
167 }
168 if (qApp->activePopupWidget())
169 widget = (qApp->activePopupWidget()->focusWidget() ?
170 qApp->activePopupWidget()->focusWidget() : qApp->activePopupWidget());
171 else if (QApplicationPrivate::focus_widget)
172 widget = QApplicationPrivate::focus_widget;
173 if (qaction && widget) {
174 int key = qaction->shortcut();
175 QKeyEvent accel_ev(QEvent::ShortcutOverride, (key & (~Qt::KeyboardModifierMask)),
176 Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask));
177 accel_ev.ignore();
178 qt_sendSpontaneousEvent(widget, &accel_ev);
179 if (accel_ev.isAccepted()) {
180 if (qt_dispatchKeyEvent(event, widget)) {
181 *target = nil;
182 *action = nil;
183 return YES;
184 }
185 }
186 }
187 }
188 return NO;
189}
190
191- (NSInteger)indexOfItemWithTarget:(id)anObject andAction:(SEL)actionSelector
192{
193 NSInteger index = [super indexOfItemWithTarget:anObject andAction:actionSelector];
194 static SEL selForOFCP = NSSelectorFromString(@"orderFrontCharacterPalette:");
195 if (index == -1 && selForOFCP == actionSelector) {
196 // Check if the 'orderFrontCharacterPalette' SEL exists for QCocoaMenuLoader object
197 QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)];
198 return [super indexOfItemWithTarget:loader andAction:actionSelector];
199 }
200 return index;
201}
202
203@end
204
205QT_BEGIN_NAMESPACE
206extern int qt_mac_menus_open_count; // qmenu_mac.mm
207
208void qt_mac_emit_menuSignals(QMenu *menu, bool show)
209{
210 if (!menu)
211 return;
212 int delta;
213 if (show) {
214 emit menu->aboutToShow();
215 delta = 1;
216 } else {
217 emit menu->aboutToHide();
218 delta = -1;
219 }
220 qt_mac_menus_open_count += delta;
221}
222
223void qt_mac_clear_status_text(QAction *action)
224{
225 action->d_func()->showStatusText(0, QString());
226}
227
228void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action)
229{
230 emit menu->hovered(action);
231}
232
233
234QT_END_NAMESPACE
235
236#endif
Note: See TracBrowser for help on using the repository browser.