8007267: [macosx] com.apple.eawt.Application.setDefaultMenuBar is not working
Reviewed-by: anthony, serb
--- a/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Wed Jul 24 17:14:45 2013 +0400
+++ b/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Fri Jul 26 16:22:29 2013 +0400
@@ -31,6 +31,7 @@
import javax.swing.*;
import javax.swing.plaf.MenuBarUI;
+import com.apple.laf.ScreenMenuBar;
import sun.lwawt.macosx.CMenuBar;
import com.apple.laf.AquaMenuBarUI;
@@ -72,12 +73,15 @@
// scan the current frames, and see if any are foreground
final Frame[] frames = Frame.getFrames();
for (final Frame frame : frames) {
- if (frame.isVisible() && !isFrameMinimized(frame)) return;
+ if (frame.isVisible() && !isFrameMinimized(frame)) {
+ return;
+ }
}
// if we have no foreground frames, then we have to "kick" the menubar
final JFrame pingFrame = new JFrame();
pingFrame.getRootPane().putClientProperty("Window.alpha", new Float(0.0f));
+ pingFrame.setUndecorated(true);
pingFrame.setVisible(true);
pingFrame.toFront();
pingFrame.setVisible(false);
@@ -101,7 +105,6 @@
// Aqua was not installed
throw new IllegalStateException("Application.setDefaultMenuBar() only works with the Aqua Look and Feel");
}
-/* TODO: disabled until ScreenMenuBar is working
final AquaMenuBarUI aquaUI = (AquaMenuBarUI)ui;
final ScreenMenuBar screenMenuBar = aquaUI.getScreenMenuBar();
@@ -118,8 +121,7 @@
}
// grab the pointer to the CMenuBar, and retain it in native
- nativeSetDefaultMenuBar(((CMenuBar)peer).getNativeMenuBarPeer());
-*/
+ nativeSetDefaultMenuBar(((CMenuBar)peer).getModel());
}
void setAboutMenuItemVisible(final boolean present) {
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Wed Jul 24 17:14:45 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Fri Jul 26 16:22:29 2013 +0400
@@ -43,7 +43,7 @@
return target;
}
- long getModel() {
+ public long getModel() {
return modelPtr;
}
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Jul 24 17:14:45 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Fri Jul 26 16:22:29 2013 +0400
@@ -30,6 +30,7 @@
#import "sun_lwawt_macosx_CPlatformWindow.h"
#import "com_apple_eawt_event_GestureHandler.h"
#import "com_apple_eawt_FullScreenHandler.h"
+#import "ApplicationDelegate.h"
#import "AWTWindow.h"
#import "AWTView.h"
@@ -55,7 +56,7 @@
// doesn't provide information about "opposite" window, so we
// have to do a bit of tracking. This variable points to a window
// which had been the key window just before a new key window
-// was set. It would be nil if the new key window isn't an AWT
+// was set. It would be nil if the new key window isn't an AWT
// window or the app currently has no key window.
static AWTWindow* lastKeyWindow = nil;
@@ -542,17 +543,26 @@
AWT_ASSERT_APPKIT_THREAD;
[AWTToolkit eventCountPlusPlus];
AWTWindow *opposite = [AWTWindow lastKeyWindow];
-
+
// Finds appropriate menubar in our hierarchy,
AWTWindow *awtWindow = self;
while (awtWindow.ownerWindow != nil) {
awtWindow = awtWindow.ownerWindow;
}
+
CMenuBar *menuBar = nil;
+ BOOL isDisabled = NO;
if ([awtWindow.nsWindow isVisible]){
menuBar = awtWindow.javaMenuBar;
+ isDisabled = !awtWindow.isEnabled;
}
- [CMenuBar activate:menuBar modallyDisabled:!awtWindow.isEnabled];
+
+ if (menuBar == nil) {
+ menuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
+ isDisabled = NO;
+ }
+
+ [CMenuBar activate:menuBar modallyDisabled:isDisabled];
[AWTWindow setLastKeyWindow:nil];
@@ -565,6 +575,14 @@
[AWTToolkit eventCountPlusPlus];
[self.javaMenuBar deactivate];
+ // In theory, this might cause flickering if the window gaining focus
+ // has its own menu. However, I couldn't reproduce it on practice, so
+ // perhaps this is a non issue.
+ CMenuBar* defaultMenu = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
+ if (defaultMenu != nil) {
+ [CMenuBar activate:defaultMenu modallyDisabled:NO];
+ }
+
// the new key window
NSWindow *keyWindow = [NSApp keyWindow];
AWTWindow *opposite = nil;
@@ -829,11 +847,19 @@
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
- if ([nsWindow isKeyWindow]) [window.javaMenuBar deactivate];
+ if ([nsWindow isKeyWindow]) {
+ [window.javaMenuBar deactivate];
+ }
+
window.javaMenuBar = menuBar;
+ CMenuBar* actualMenuBar = menuBar;
+ if (actualMenuBar == nil) {
+ actualMenuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
+ }
+
if ([nsWindow isKeyWindow]) {
- [CMenuBar activate:window.javaMenuBar modallyDisabled:NO];
+ [CMenuBar activate:actualMenuBar modallyDisabled:NO];
}
}];
--- a/jdk/src/macosx/native/sun/awt/CMenuItem.m Wed Jul 24 17:14:45 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/CMenuItem.m Fri Jul 26 16:22:29 2013 +0400
@@ -70,9 +70,15 @@
JNIEnv *env = [ThreadUtilities getJNIEnv];
JNF_COCOA_ENTER(env);
- // If we are called as a result of user pressing a shorcut, do nothing,
+ // If we are called as a result of user pressing a shortcut, do nothing,
// because AVTView has already sent corresponding key event to the Java
- // layer from performKeyEquivalent
+ // layer from performKeyEquivalent.
+ // There is an exception from the rule above, though: if a window with
+ // a menu gets minimized by user and there are no other windows to take
+ // focus, the window's menu won't be removed from the global menu bar.
+ // However, the Java layer won't handle invocation by a shortcut coming
+ // from this "frameless" menu, because there are no active windows. This
+ // means we have to handle it here.
NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
if ([currEvent type] == NSKeyDown) {
NSString *menuKey = [sender keyEquivalent];
@@ -91,7 +97,8 @@
eventKey = [NSString stringWithCharacters: &newChar length: 1];
}
- if ([menuKey isEqualToString:eventKey]) {
+ NSWindow *keyWindow = [NSApp keyWindow];
+ if ([menuKey isEqualToString:eventKey] && keyWindow != nil) {
return;
}
}