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

Last change on this file since 792 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 6.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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 [email protected].
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
50#include <QtGui/QMenu>
51
52QT_FORWARD_DECLARE_CLASS(QAction)
53QT_FORWARD_DECLARE_CLASS(QWidget)
54QT_FORWARD_DECLARE_CLASS(QApplication)
55QT_FORWARD_DECLARE_CLASS(QCoreApplication)
56QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
57QT_FORWARD_DECLARE_CLASS(QKeyEvent)
58QT_FORWARD_DECLARE_CLASS(QEvent)
59
60QT_BEGIN_NAMESPACE
61extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication.cpp
62QT_END_NAMESPACE
63
64QT_USE_NAMESPACE
65
66@implementation QT_MANGLE_NAMESPACE(QCocoaMenu)
67
68- (id)initWithQMenu:(QMenu*)menu
69{
70 self = [super init];
71 if (self) {
72 qmenu = menu;
73 [self setAutoenablesItems:NO];
74 [self setDelegate:self];
75 }
76 return self;
77}
78
79- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item;
80{
81 Q_UNUSED(menu);
82
83 if (!item) {
84 // ### According to the docs everything will be highlighted. Not sure what we should do in
85 // Qt, so just return.
86 return;
87 }
88
89 if (QAction *action = reinterpret_cast<QAction *>([item tag]))
90 action->activate(QAction::Hover);
91}
92
93- (void)menuWillOpen:(NSMenu*)menu;
94{
95 while (QWidget *popup
96 = QApplication::activePopupWidget())
97 popup->close();
98 QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
99 qt_mac_emit_menuSignals(qtmenu, true);
100 qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
101}
102
103- (void)menuWillClose:(NSMenu*)menu;
104{
105 qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, false);
106}
107
108- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
109 whichItem:(NSMenuItem**)outItem
110{
111 for (NSMenuItem *item in [menu itemArray]) {
112 if (![item isEnabled] || [item isHidden] || [item isSeparatorItem])
113 continue;
114 if ([item hasSubmenu]) {
115 if ([self hasShortcut:[item submenu]
116 forKey:key
117 forModifiers:modifier whichItem:outItem]) {
118 if (outItem)
119 *outItem = item;
120 return YES;
121 }
122 }
123 NSString *menuKey = [item keyEquivalent];
124 if (menuKey && NSOrderedSame == [menuKey compare:key]
125 && (modifier == [item keyEquivalentModifierMask])) {
126 if (outItem)
127 *outItem = item;
128 return YES;
129 }
130 }
131 if (outItem)
132 *outItem = 0;
133 return NO;
134}
135
136- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
137{
138 // Check if the menu actually has a keysequence defined for this key event.
139 // If it does, then we will first send the key sequence to the QWidget that has focus
140 // since (in Qt's eyes) it needs to a chance at the key event first. If the widget
141 // accepts the key event, we then return YES, but set the target and action to be nil,
142 // which means that the action should not be triggered, and instead dispatch the event ourselves.
143 // In every other case we return NO, which means that Cocoa can do as it pleases
144 // (i.e., fire the menu action).
145 NSMenuItem *whichItem;
146 if ([self hasShortcut:menu
147 forKey:[event characters]
148 forModifiers:([event modifierFlags] & NSDeviceIndependentModifierFlagsMask)
149 whichItem:&whichItem]) {
150 QWidget *widget = 0;
151 QAction *qaction = 0;
152 if (whichItem && [whichItem tag]) {
153 qaction = reinterpret_cast<QAction *>([whichItem tag]);
154 }
155 if (qApp->activePopupWidget())
156 widget = (qApp->activePopupWidget()->focusWidget() ?
157 qApp->activePopupWidget()->focusWidget() : qApp->activePopupWidget());
158 else if (QApplicationPrivate::focus_widget)
159 widget = QApplicationPrivate::focus_widget;
160 if (qaction && widget) {
161 int key = qaction->shortcut();
162 QKeyEvent accel_ev(QEvent::ShortcutOverride, (key & (~Qt::KeyboardModifierMask)),
163 Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask));
164 accel_ev.ignore();
165 qt_sendSpontaneousEvent(widget, &accel_ev);
166 if (accel_ev.isAccepted()) {
167 if (qt_dispatchKeyEvent(event, widget)) {
168 *target = nil;
169 *action = nil;
170 return YES;
171 }
172 }
173 }
174 }
175 return NO;
176}
177
178@end
179
180QT_BEGIN_NAMESPACE
181extern int qt_mac_menus_open_count; // qmenu_mac.mm
182
183void qt_mac_emit_menuSignals(QMenu *menu, bool show)
184{
185 if (!menu)
186 return;
187 int delta;
188 if (show) {
189 emit menu->aboutToShow();
190 delta = 1;
191 } else {
192 emit menu->aboutToHide();
193 delta = -1;
194 }
195 qt_mac_menus_open_count += delta;
196}
197QT_END_NAMESPACE
198
199#endif
Note: See TracBrowser for help on using the repository browser.