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);
        }
    }
}
