diff options
author | Richard Moe Gustavsen <richard.gustavsen@nokia.com> | 2010-02-09 09:39:37 (GMT) |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@nokia.com> | 2010-02-10 09:14:33 (GMT) |
commit | 8b112609b7d86572fbb41dc59354da1f958d1910 (patch) | |
tree | 4304da66aef9ab4245decf1009752cff6eac1b9b | |
parent | 2a1bf99770401576f451806b2e2a8c73853ca99b (diff) | |
download | Qt-8b112609b7d86572fbb41dc59354da1f958d1910.zip Qt-8b112609b7d86572fbb41dc59354da1f958d1910.tar.gz Qt-8b112609b7d86572fbb41dc59354da1f958d1910.tar.bz2 |
Cocoa: Menu in menubar stays highlighted
If you use the menu bar for a window to open up
another window woth no menu bar, the first menu bar
stays highlighted once it is set as current again.
The reason is that we remove the first menu bar before
cocoa gets a chance to update it correctly. This patch
implements a system for us to post a message/call to
cocoa, so we delay removing the toolbar until after
cocoa has finished closing it properly.
NB: Rather than posting the call to a window on screen, it
would have been better and safer to post it no window, and
then receive the event in the event handler of NSApplication.
But for the moment, we have decided not to subclass NSApplication...
Rev-By:prasanth
-rw-r--r-- | src/gui/kernel/qcocoamenuloader_mac.mm | 6 | ||||
-rw-r--r-- | src/gui/kernel/qcocoamenuloader_mac_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qcocoasharedwindowmethods_mac_p.h | 18 | ||||
-rw-r--r-- | src/gui/kernel/qeventdispatcher_mac.mm | 3 | ||||
-rw-r--r-- | src/gui/kernel/qt_cocoa_helpers_mac.mm | 24 | ||||
-rw-r--r-- | src/gui/kernel/qt_cocoa_helpers_mac_p.h | 22 | ||||
-rw-r--r-- | src/gui/widgets/qmenu_mac.mm | 15 | ||||
-rw-r--r-- | src/gui/widgets/qmenubar_p.h | 1 |
8 files changed, 87 insertions, 3 deletions
diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index 18b3772..573b763 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -46,6 +46,7 @@ #include <private/qcocoamenuloader_mac_p.h> #include <private/qapplication_p.h> #include <private/qt_mac_p.h> +#include <private/qmenubar_p.h> #include <qmenubar.h> QT_FORWARD_DECLARE_CLASS(QCFString) @@ -208,6 +209,11 @@ QT_USE_NAMESPACE [NSApp hide:sender]; } +- (void)qtUpdateMenubar +{ + QMenuBarPrivate::macUpdateMenuBarImmediatly(); +} + - (IBAction)qtDispatcherToQAction:(id)sender { QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); diff --git a/src/gui/kernel/qcocoamenuloader_mac_p.h b/src/gui/kernel/qcocoamenuloader_mac_p.h index 81c136e..2504b8c 100644 --- a/src/gui/kernel/qcocoamenuloader_mac_p.h +++ b/src/gui/kernel/qcocoamenuloader_mac_p.h @@ -85,6 +85,7 @@ - (IBAction)unhideAllApplications:(id)sender; - (IBAction)hide:(id)sender; - (IBAction)qtDispatcherToQAction:(id)sender; +- (void)qtUpdateMenubar; @end #endif // QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index d8bbcd4..3b92ce2 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -178,8 +178,26 @@ QT_END_NAMESPACE [NSApp terminate:sender]; } +- (void)sendPostedMessage:(NSEvent *)event +{ + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // That is why we need to split the address in two parts: + quint64 lower = [event data1]; + quint64 upper = [event data2]; + QCocoaPostCallArgs *args = reinterpret_cast<QCocoaPostCallArgs *>(lower | (upper << 32)); + if (args != 0) { + [args->target performSelector:args->selector]; + delete args; + } +} + - (void)sendEvent:(NSEvent *)event { + if ([event type] == NSApplicationDefined) { + if ([event subtype] == QtCocoaEventSubTypePostMessage) + [self sendPostedMessage:event]; + return; + } QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; // Cocoa can hold onto the window after we've disavowed its knowledge. So, diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index c7d042d..8a67dee 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -1064,10 +1064,9 @@ void QEventDispatcherMacPrivate::cancelWaitForMoreEvents() // In case the event dispatcher is waiting for more // events somewhere, we post a dummy event to wake it up: QMacCocoaAutoReleasePool pool; - static const short NSAppShouldStopForQt = SHRT_MAX; [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint modifierFlags:0 timestamp:0. windowNumber:0 context:0 - subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO]; + subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO]; } #endif diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 377e5a0..74514a0 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1281,6 +1281,30 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor) } #endif +bool qt_cocoaPostMessage(id target, SEL selector) +{ + if (!target) + return false; + NSWindow *nswin = [NSApp mainWindow]; + if (!nswin) { + nswin = [NSApp keyWindow]; + if (!nswin) + return false; + } + + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // That is why we need to split the address in two parts: + QCocoaPostCallArgs *args = new QCocoaPostCallArgs(target, selector); + quint32 lower = quintptr(args); + quint32 upper = quintptr(args) >> 32; + NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined + location:NSZeroPoint modifierFlags:0 timestamp:0 + windowNumber:[nswin windowNumber] + context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper]; + [NSApp postEvent:e atStart:NO]; + return true; +} + @implementation DebugNSApplication { } - (void)sendEvent:(NSEvent *)event diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index ace8255..0b961b1 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -114,6 +114,12 @@ typedef struct CGPoint NSPoint; #endif QT_BEGIN_NAMESPACE + +enum { + QtCocoaEventSubTypeWakeup = SHRT_MAX, + QtCocoaEventSubTypePostMessage = SHRT_MAX-1 +}; + Qt::MouseButtons qt_mac_get_buttons(int buttons); Qt::MouseButton qt_mac_get_button(EventMouseButton button); void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0.15); @@ -182,6 +188,22 @@ inline QString qt_mac_NSStringToQString(const NSString *nsstr) inline NSString *qt_mac_QStringToNSString(const QString &qstr) { return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; } +class QCocoaPostCallArgs { + public: + id target; + SEL selector; + QCocoaPostCallArgs(id target, SEL selector) : target(target), selector(selector) + { + [target retain]; + } + + ~QCocoaPostCallArgs() + { + [target release]; + } +}; +bool qt_cocoaPostMessage(id target, SEL selector); + @interface DebugNSApplication : NSApplication {} @end diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index 658a020..99c550f 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -2030,6 +2030,18 @@ void qt_mac_clear_menubar() */ bool QMenuBar::macUpdateMenuBar() { +#ifdef QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; + if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar))) + return QMenuBarPrivate::macUpdateMenuBarImmediatly(); + return true; +#else + return QMenuBarPrivate::macUpdateMenuBarImmediatly(); +#endif +} + +bool QMenuBarPrivate::macUpdateMenuBarImmediatly() +{ bool ret = false; cancelAllMenuTracking(); QWidget *w = findWindowThatShouldDisplayMenubar(); @@ -2095,8 +2107,9 @@ bool QMenuBar::macUpdateMenuBar() } } - if(!ret) + if (!ret) { qt_mac_clear_menubar(); + } return ret; } diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h index f2e5357..819aee4 100644 --- a/src/gui/widgets/qmenubar_p.h +++ b/src/gui/widgets/qmenubar_p.h @@ -196,6 +196,7 @@ public: return 0; } } *mac_menubar; + static bool macUpdateMenuBarImmediatly(); bool macWidgetHasNativeMenubar(QWidget *widget); void macCreateMenuBar(QWidget *); void macDestroyMenuBar(); |