8013581: [macosx] Key Bindings break with awt GraphicsEnvironment setFullScreenWindow
Reviewed-by: anthony, serb
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java Wed Oct 30 20:54:42 2013 +0400
@@ -54,14 +54,6 @@
}
@Override
- public void enterFullScreenMode() {
- }
-
- @Override
- public void exitFullScreenMode() {
- }
-
- @Override
public SurfaceData replaceSurfaceData() {
return null;
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Wed Oct 30 20:54:42 2013 +0400
@@ -96,14 +96,6 @@
return peer;
}
- public void enterFullScreenMode() {
- CWrapper.NSView.enterFullScreenMode(ptr);
- }
-
- public void exitFullScreenMode() {
- CWrapper.NSView.exitFullScreenMode(ptr);
- }
-
public void setToolTip(String msg) {
CWrapper.NSView.setToolTip(ptr, msg);
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Oct 30 20:54:42 2013 +0400
@@ -63,6 +63,8 @@
private static native void nativeSynthesizeMouseEnteredExitedEvents();
private static native void nativeDispose(long nsWindowPtr);
private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
+ private static native void nativeEnterFullScreenMode(long nsWindowPtr);
+ private static native void nativeExitFullScreenMode(long nsWindowPtr);
// Loger to report issues happened during execution but that do not affect functionality
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
@@ -440,10 +442,7 @@
@Override // PlatformWindow
public Insets getInsets() {
- if (!isFullScreenMode) {
- return nativeGetNSWindowInsets(getNSWindowPtr());
- }
- return new Insets(0, 0, 0, 0);
+ return nativeGetNSWindowInsets(getNSWindowPtr());
}
@Override // PlatformWindow
@@ -764,18 +763,12 @@
@Override
public void enterFullScreenMode() {
isFullScreenMode = true;
- contentView.enterFullScreenMode();
- // the move/size notification from the underlying system comes
- // but it contains a bounds smaller than the whole screen
- // and therefore we need to create the synthetic notifications
- Rectangle screenBounds = getPeer().getGraphicsConfiguration().getBounds();
- peer.notifyReshape(screenBounds.x, screenBounds.y, screenBounds.width,
- screenBounds.height);
+ nativeEnterFullScreenMode(getNSWindowPtr());
}
@Override
public void exitFullScreenMode() {
- contentView.exitFullScreenMode();
+ nativeExitFullScreenMode(getNSWindowPtr());
isFullScreenMode = false;
}
@@ -933,14 +926,6 @@
protected void deliverMoveResizeEvent(int x, int y, int width, int height,
boolean byUser) {
- // when the content view enters the full-screen mode, the native
- // move/resize notifications contain a bounds smaller than
- // the whole screen and therefore we ignore the native notifications
- // and the content view itself creates correct synthetic notifications
- if (isFullScreenMode) {
- return;
- }
-
checkZoom();
final Rectangle oldB = nativeBounds;
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java Wed Oct 30 20:54:42 2013 +0400
@@ -82,9 +82,6 @@
public static native Rectangle2D frame(long view);
public static native long window(long view);
- public static native void enterFullScreenMode(long view);
- public static native void exitFullScreenMode(long view);
-
public static native void setHidden(long view, boolean hidden);
public static native void setToolTip(long view, String msg);
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.h Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.h Wed Oct 30 20:54:42 2013 +0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
BOOL isEnabled;
NSWindow *nsWindow;
AWTWindow *ownerWindow;
+ jint preFullScreenLevel;
}
// An instance of either AWTWindow_Normal or AWTWindow_Panel
@@ -57,6 +58,7 @@
@property (nonatomic) NSSize javaMaxSize;
@property (nonatomic) jint styleBits;
@property (nonatomic) BOOL isEnabled;
+@property (nonatomic) jint preFullScreenLevel;
- (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)javaPlatformWindow
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Oct 30 20:54:42 2013 +0400
@@ -122,6 +122,7 @@
@synthesize styleBits;
@synthesize isEnabled;
@synthesize ownerWindow;
+@synthesize preFullScreenLevel;
- (void) updateMinMaxSize:(BOOL)resizable {
if (resizable) {
@@ -1212,3 +1213,58 @@
JNF_COCOA_EXIT(env);
}
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeEnterFullScreenMode
+(JNIEnv *env, jclass clazz, jlong windowPtr)
+{
+JNF_COCOA_ENTER(env);
+
+ NSWindow *nsWindow = OBJC(windowPtr);
+ [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
+ AWTWindow *window = (AWTWindow*)[nsWindow delegate];
+ NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
+ CGDirectDisplayID aID = [screenID intValue];
+
+ if (CGDisplayCapture(aID) == kCGErrorSuccess) {
+ // remove window decoration
+ NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
+ [nsWindow setStyleMask:(styleMask & ~NSTitledWindowMask) | NSBorderlessWindowMask];
+
+ int shieldLevel = CGShieldingWindowLevel();
+ window.preFullScreenLevel = [nsWindow level];
+ [nsWindow setLevel: shieldLevel];
+
+ NSRect screenRect = [[nsWindow screen] frame];
+ [nsWindow setFrame:screenRect display:YES];
+ } else {
+ [JNFException raise:env as:kRuntimeException reason:"Failed to enter full screen."];
+ }
+ }];
+
+JNF_COCOA_EXIT(env);
+}
+
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeExitFullScreenMode
+(JNIEnv *env, jclass clazz, jlong windowPtr)
+{
+JNF_COCOA_ENTER(env);
+
+ NSWindow *nsWindow = OBJC(windowPtr);
+ [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
+ AWTWindow *window = (AWTWindow*)[nsWindow delegate];
+ NSNumber* screenID = [AWTWindow getNSWindowDisplayID_AppKitThread: nsWindow];
+ CGDirectDisplayID aID = [screenID intValue];
+
+ if (CGDisplayRelease(aID) == kCGErrorSuccess) {
+ NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
+ [nsWindow setStyleMask:styleMask];
+ [nsWindow setLevel: window.preFullScreenLevel];
+
+ // GraphicsDevice takes care of restoring pre full screen bounds
+ } else {
+ [JNFException raise:env as:kRuntimeException reason:"Failed to exit full screen."];
+ }
+ }];
+
+JNF_COCOA_EXIT(env);
+}
+
--- a/jdk/src/macosx/native/sun/awt/CWrapper.m Wed Oct 30 12:00:18 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/CWrapper.m Wed Oct 30 20:54:42 2013 +0400
@@ -587,46 +587,6 @@
/*
* Class: sun_lwawt_macosx_CWrapper$NSView
- * Method: enterFullScreenMode
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_sun_lwawt_macosx_CWrapper_00024NSView_enterFullScreenMode
-(JNIEnv *env, jclass cls, jlong viewPtr)
-{
-JNF_COCOA_ENTER(env);
-
- NSView *view = (NSView *)jlong_to_ptr(viewPtr);
- [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
- NSScreen *screen = [[view window] screen];
- NSDictionary *opts = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], NSFullScreenModeAllScreens, nil];
- [view enterFullScreenMode:screen withOptions:opts];
- }];
-
-JNF_COCOA_EXIT(env);
-}
-
-/*
- * Class: sun_lwawt_macosx_CWrapper$NSView
- * Method: exitFullScreenMode
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_sun_lwawt_macosx_CWrapper_00024NSView_exitFullScreenMode
-(JNIEnv *env, jclass cls, jlong viewPtr)
-{
-JNF_COCOA_ENTER(env);
-
- NSView *view = (NSView *)jlong_to_ptr(viewPtr);
- [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
- [view exitFullScreenModeWithOptions:nil];
- }];
-
-JNF_COCOA_EXIT(env);
-}
-
-/*
- * Class: sun_lwawt_macosx_CWrapper$NSView
* Method: window
* Signature: (J)J
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/8013581/bug8013581.java Wed Oct 30 20:54:42 2013 +0400
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8013581
+ * @summary [macosx] Key Bindings break with awt GraphicsEnvironment setFullScreenWindow
+ * @author leonid.romanov@oracle.com
+ * @run main bug8013581
+ */
+
+import sun.awt.*;
+import java.awt.*;
+import java.awt.event.*;
+
+public class bug8013581 {
+ private static Frame frame;
+ private static volatile int listenerCallCounter = 0;
+
+ public static void main(String[] args) throws Exception {
+ final GraphicsEnvironment ge = GraphicsEnvironment
+ .getLocalGraphicsEnvironment();
+ final GraphicsDevice[] devices = ge.getScreenDevices();
+
+ final SunToolkit toolkit = (SunToolkit)Toolkit.getDefaultToolkit();
+ final Robot robot = new Robot();
+ robot.setAutoDelay(50);
+
+ createAndShowGUI();
+ toolkit.realSync();
+
+ Exception error = null;
+ for (final GraphicsDevice device : devices) {
+ if (!device.isFullScreenSupported()) {
+ continue;
+ }
+
+ device.setFullScreenWindow(frame);
+ sleep();
+
+ robot.keyPress(KeyEvent.VK_A);
+ robot.keyRelease(KeyEvent.VK_A);
+ toolkit.realSync();
+
+ device.setFullScreenWindow(null);
+ sleep();
+
+ if (listenerCallCounter != 2) {
+ error = new Exception("Test failed: KeyListener called " + listenerCallCounter + " times instead of 2!");
+ break;
+ }
+
+ listenerCallCounter = 0;
+ }
+
+ frame.dispose();
+
+ if (error != null) {
+ throw error;
+ }
+ }
+
+ private static void createAndShowGUI() {
+ frame = new Frame("Test");
+ frame.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ listenerCallCounter++;
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ listenerCallCounter++;
+ }
+ });
+
+ frame.setUndecorated(true);
+ frame.setVisible(true);
+ }
+
+ private static void sleep() {
+ ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException ignored) {
+ }
+ }
+}