-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
8u151
-
x86_64
-
os_x
FULL PRODUCT VERSION :
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Mac OS X El Capitan 10.11.6
A DESCRIPTION OF THE PROBLEM :
A JFrame which has been set to be always on top (using setAlwaysOnTop(true)) disappears after being restored from either 1. being iconified to the OS X dock or 2. the OS X fullscreen effect.
The fullscreen effect requires use of the Apple com.apple.eawt.FullScreenUtilities API, but iconification (minimizing) the frame is a standard JFrame feature so the bug may be present on other operating systems.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Call setAlwaysOnTop(true) on a JFrame.
2. Set the JFrame to be visible.
3. Minimize the JFrame (clicking the yellow jewel on Mac).
4. Click on the dock icon to restore the JFrame.
5. The JFrame disappears.
Disappearing from the fullscreen effect requires use of the com.apple.eawt.FullScreenUtilities API (shown in my example code). The steps to reproduce are the same as with iconification.
1. Call setAlwaysOnTop(true) on a JFrame.
2. Set the JFrame to be visible.
3. Click on the green jewel to fullscreen the JFrame.
4. Click on the green jewel to restore the JFrame to windowed mode.
5. The JFrame disappears.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I didn't expect the JFrame to disappear.
ACTUAL -
The JFrame disappears.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package mcve;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
class AlwaysOnTopDisappears {
public static void main(String[] args) {
SwingUtilities.invokeLater(AlwaysOnTopDisappears::createAndShowFrame);
}
static void createAndShowFrame() {
String osName = System.getProperty("os.name");
JFrame frame = new JFrame(osName);
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(true);
panel.setBackground(Color.WHITE);
JCheckBox check = new JCheckBox("Always On Top", true);
check.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));
panel.add(check, BorderLayout.CENTER);
check.addItemListener(e -> frame.setAlwaysOnTop(check.isSelected()));
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.pack();
frame.setLocationRelativeTo(null);
if (osName.startsWith("Mac OS")) {
enableOsxFullScreen(frame);
// Uncomment the following line to apply the workarounds.
// applyDisappearingFrameWorkaround(frame);
}
frame.setVisible(true);
}
static void enableOsxFullScreen(JFrame frame) {
try {
// Using reflection so the code compiles on non-Mac OS
Class.forName("com.apple.eawt.FullScreenUtilities")
.getMethod("setWindowCanFullScreen", Window.class, boolean.class)
.invoke(null, frame, true);
} catch (ReflectiveOperationException x) {
x.printStackTrace(System.out);
}
}
// Workarounds
static void applyDisappearingFrameWorkaround(JFrame frame) {
frame.addWindowStateListener(new WindowStateListener() {
boolean isIconified(int windowState) {
return (windowState & Frame.ICONIFIED) != 0;
}
@Override
public void windowStateChanged(WindowEvent e) {
if (isIconified(e.getOldState()) && !isIconified(e.getNewState())) {
if (frame.isAlwaysOnTop() && frame.isVisible()) {
frame.setVisible(false);
frame.setVisible(true);
}
}
}
});
try {
// If the bug seems to be present on a non-Mac OS,
// the following could also be accomplished with a
// window state listener.
InvocationHandler fullScreenListenerHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
if ("windowExitedFullScreen".equals(method.getName())) {
if (frame.isAlwaysOnTop()) {
frame.toFront();
}
}
return null;
}
};
Class<?> fullScreenListener =
Class.forName("com.apple.eawt.FullScreenListener");
Object fullScreenListenerProxy =
Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class<?>[] { fullScreenListener },
fullScreenListenerHandler);
Class.forName("com.apple.eawt.FullScreenUtilities")
.getMethod("addFullScreenListenerTo", Window.class, fullScreenListener)
.invoke(null, frame, fullScreenListenerProxy);
} catch (ReflectiveOperationException x) {
x.printStackTrace(System.out);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
A workaround can be found at the bottom of the test case code. After being de-iconified, the only workaround seems to be to call setVisible(false) then setVisible(true). Calling toFront() on the frame seems to work for restoration after the OS X fullscreen effect, but not for de-iconification.
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Mac OS X El Capitan 10.11.6
A DESCRIPTION OF THE PROBLEM :
A JFrame which has been set to be always on top (using setAlwaysOnTop(true)) disappears after being restored from either 1. being iconified to the OS X dock or 2. the OS X fullscreen effect.
The fullscreen effect requires use of the Apple com.apple.eawt.FullScreenUtilities API, but iconification (minimizing) the frame is a standard JFrame feature so the bug may be present on other operating systems.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Call setAlwaysOnTop(true) on a JFrame.
2. Set the JFrame to be visible.
3. Minimize the JFrame (clicking the yellow jewel on Mac).
4. Click on the dock icon to restore the JFrame.
5. The JFrame disappears.
Disappearing from the fullscreen effect requires use of the com.apple.eawt.FullScreenUtilities API (shown in my example code). The steps to reproduce are the same as with iconification.
1. Call setAlwaysOnTop(true) on a JFrame.
2. Set the JFrame to be visible.
3. Click on the green jewel to fullscreen the JFrame.
4. Click on the green jewel to restore the JFrame to windowed mode.
5. The JFrame disappears.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I didn't expect the JFrame to disappear.
ACTUAL -
The JFrame disappears.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package mcve;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
class AlwaysOnTopDisappears {
public static void main(String[] args) {
SwingUtilities.invokeLater(AlwaysOnTopDisappears::createAndShowFrame);
}
static void createAndShowFrame() {
String osName = System.getProperty("os.name");
JFrame frame = new JFrame(osName);
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(true);
panel.setBackground(Color.WHITE);
JCheckBox check = new JCheckBox("Always On Top", true);
check.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));
panel.add(check, BorderLayout.CENTER);
check.addItemListener(e -> frame.setAlwaysOnTop(check.isSelected()));
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.pack();
frame.setLocationRelativeTo(null);
if (osName.startsWith("Mac OS")) {
enableOsxFullScreen(frame);
// Uncomment the following line to apply the workarounds.
// applyDisappearingFrameWorkaround(frame);
}
frame.setVisible(true);
}
static void enableOsxFullScreen(JFrame frame) {
try {
// Using reflection so the code compiles on non-Mac OS
Class.forName("com.apple.eawt.FullScreenUtilities")
.getMethod("setWindowCanFullScreen", Window.class, boolean.class)
.invoke(null, frame, true);
} catch (ReflectiveOperationException x) {
x.printStackTrace(System.out);
}
}
// Workarounds
static void applyDisappearingFrameWorkaround(JFrame frame) {
frame.addWindowStateListener(new WindowStateListener() {
boolean isIconified(int windowState) {
return (windowState & Frame.ICONIFIED) != 0;
}
@Override
public void windowStateChanged(WindowEvent e) {
if (isIconified(e.getOldState()) && !isIconified(e.getNewState())) {
if (frame.isAlwaysOnTop() && frame.isVisible()) {
frame.setVisible(false);
frame.setVisible(true);
}
}
}
});
try {
// If the bug seems to be present on a non-Mac OS,
// the following could also be accomplished with a
// window state listener.
InvocationHandler fullScreenListenerHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
if ("windowExitedFullScreen".equals(method.getName())) {
if (frame.isAlwaysOnTop()) {
frame.toFront();
}
}
return null;
}
};
Class<?> fullScreenListener =
Class.forName("com.apple.eawt.FullScreenListener");
Object fullScreenListenerProxy =
Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class<?>[] { fullScreenListener },
fullScreenListenerHandler);
Class.forName("com.apple.eawt.FullScreenUtilities")
.getMethod("addFullScreenListenerTo", Window.class, fullScreenListener)
.invoke(null, frame, fullScreenListenerProxy);
} catch (ReflectiveOperationException x) {
x.printStackTrace(System.out);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
A workaround can be found at the bottom of the test case code. After being de-iconified, the only workaround seems to be to call setVisible(false) then setVisible(true). Calling toFront() on the frame seems to work for restoration after the OS X fullscreen effect, but not for de-iconification.
- relates to
-
JDK-8222450 Always on top Stage disappears after restoration from iconified
-
- Open
-