/*
 * Copyright (c) 2005, 2008, 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 5041219
 * @bug 5101561
 * @bug 5035272
 * @bug 5096011
 * @bug 5101712
 * @bug 5098624
 * @summary Here are a few assertions worth verification:
 *  - the fullscreen window is positioned at 0,0
 *  - the fs window appears on the correct screen
 *  - if the exclusive FS mode is supported, no other widndow should
 *    overlap the fs window (including the taskbar).
 *    You could, however, alt+tab out of a fullscreen window, or at least
 *    minimize it (if you've entered the fs mode with a Window, you'll need
 *    to minimize the owner frame).
 *    Note that there may be issues with FS exclusive mode with ddraw and
 *    multiple fullscreen windows (one per device).
 *  - if display mode is supported that it did change
 *  - that the original display mode is restored once
 *    the ws window is disposed
 *  All of the above should work with and w/o DirectDraw
 *  (-Dsun.java2d.noddraw=true) on windows, and w/ and w/o opengl on X11
 *  (-Dsun.java2d.opengl=True).
 * @run main/manual/othervm -Dsun.java2d.pmoffscreen=true MultimonFullscreenTest
 * @run main/manual/othervm -Dsun.java2d.pmoffscreen=false MultimonFullscreenTest
 * @run main/manual/othervm -Dsun.java2d.d3d=True MultimonFullscreenTest
 * @run main/manual/othervm -Dsun.java2d.noddraw=true MultimonFullscreenTest
 * @run main/manual/othervm -Dsun.java2d.opengl=True MultimonFullscreenTest
 */

import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.util.HashMap;
import java.util.Random;

/**
 */

public class MultimonFullscreenTest extends Frame implements ActionListener {
    GraphicsDevice  defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().
            getDefaultScreenDevice();
    GraphicsDevice  gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment().
            getScreenDevices();
    HashMap<Button, GraphicsDevice> deviceMap;

    private static boolean dmChange = false;
    static boolean setNullOnDispose = false;
    static boolean useFSFrame = true;
    static boolean useFSWindow = false;
    static boolean useFSDialog = false;
    static boolean useBS = false;
    static boolean runRenderLoop = false;
    static boolean addHWChildren = false;
    static volatile boolean done = true;

    public MultimonFullscreenTest(String title) {
        super(title);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        Panel p = new Panel();
        deviceMap = new HashMap<Button, GraphicsDevice>(gd.length);
        int num = 0;
        for (GraphicsDevice dev : gd) {
            Button b;
            if (dev == defDev) {
                b = new Button("Primary screen: " + num);
                System.out.println("Primary Dev : " + dev + " Bounds: " +
                        dev.getDefaultConfiguration().getBounds());
            } else {
                b = new Button("Secondary screen " + num);
                System.out.println("Secondary Dev : " + dev + " Bounds: " +
                        dev.getDefaultConfiguration().getBounds());
            }
            b.addActionListener(this);
            p.add(b);
            deviceMap.put(b, dev);
            num++;
        }
        add("South", p);
        Panel p1 = new Panel();
        p1.setLayout(new GridLayout(2,0));
        Checkbox cb = new Checkbox("Change DM on entering FS");
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                dmChange = ((Checkbox)e.getSource()).getState();
            }
        });
        p1.add(cb);
//        cb = new Checkbox("Exit FS on window dispose");
//        cb.addItemListener(new ItemListener() {
//            public void itemStateChanged(ItemEvent e) {
//                setNullOnDispose = ((Checkbox)e.getSource()).getState();
//            }
//        });
//        p1.add(cb);
        CheckboxGroup cbg = new CheckboxGroup();
        cb = new Checkbox("Use Frame to enter FS", cbg, true);
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                useFSFrame = true;
                useFSWindow = false;
                useFSDialog = false;
            }
        });
        p1.add(cb);
        cb = new Checkbox("Use Window to enter FS", cbg, false);
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                useFSFrame = false;
                useFSWindow = true;
                useFSDialog = false;
            }
        });
        p1.add(cb);
        cb = new Checkbox("Use Dialog to enter FS", cbg, false);
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                useFSFrame = false;
                useFSWindow = false;
                useFSDialog = true;
            }
        });
        p1.add(cb);
        cb = new Checkbox("Run render loop");
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                runRenderLoop = ((Checkbox)e.getSource()).getState();
            }
        });
        p1.add(cb);
        cb = new Checkbox("Use BufferStrategy in render loop");
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                useBS = ((Checkbox)e.getSource()).getState();
            }
        });
        p1.add(cb);
        cb = new Checkbox("Add Children to FS window");
        cb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                addHWChildren = ((Checkbox)e.getSource()).getState();
            }
        });
        p1.add(cb);
        add("North", p1);

        pack();
        setVisible(true);
    }

    Font f = new Font("Dialog", Font.BOLD, 24);
    Random rnd = new Random();
    public void renderDimensions(Graphics g, Rectangle rectWndBounds,
                                 GraphicsConfiguration gc) {
        g.setColor(new Color(rnd.nextInt(0xffffff)));
        g.fillRect(0, 0, rectWndBounds.width, rectWndBounds.height);

        g.setColor(new Color(rnd.nextInt(0xffffff)));
        Rectangle rectStrBounds;

        g.setFont(f);

        rectStrBounds = g.getFontMetrics().
                getStringBounds(rectWndBounds.toString(), g).getBounds();
        rectStrBounds.height += 30;
        g.drawString(rectWndBounds.toString(), 50, rectStrBounds.height);
        int oldHeight = rectStrBounds.height;
        String isFSupported = "Exclusive Fullscreen mode supported: " +
                              gc.getDevice().isFullScreenSupported();
        rectStrBounds = g.getFontMetrics().
                getStringBounds(isFSupported, g).getBounds();
        rectStrBounds.height += (10 + oldHeight);
        g.drawString(isFSupported, 50, rectStrBounds.height);

        oldHeight = rectStrBounds.height;
        String isDMChangeSupported = "Display Mode Change supported: " +
                              gc.getDevice().isDisplayChangeSupported();
        rectStrBounds = g.getFontMetrics().
                getStringBounds(isDMChangeSupported, g).getBounds();
        rectStrBounds.height += (10 + oldHeight);
        g.drawString(isDMChangeSupported, 50, rectStrBounds.height);

        oldHeight = rectStrBounds.height;
        String usingBS = "Using BufferStrategy: " + useBS;
        rectStrBounds = g.getFontMetrics().
                getStringBounds(usingBS, g).getBounds();
        rectStrBounds.height += (10 + oldHeight);
        g.drawString(usingBS, 50, rectStrBounds.height);

        final String m_strQuitMsg = "Double-click to dispose FullScreen Window";
        rectStrBounds = g.getFontMetrics().
                getStringBounds(m_strQuitMsg, g).getBounds();
        g.drawString(m_strQuitMsg,
                (rectWndBounds.width - rectStrBounds.width) / 2,
                (rectWndBounds.height - rectStrBounds.height) / 2);


    }

    public void actionPerformed(ActionEvent ae) {
        GraphicsDevice dev = deviceMap.get(ae.getSource());
        System.err.println("Setting FS on device:"+dev);
        final Window fsWindow;

        if (useFSWindow) {
            fsWindow = new Window(this, dev.getDefaultConfiguration()) {
                public void paint(Graphics g) {
                    renderDimensions(g, getBounds(),
                                     this.getGraphicsConfiguration());
                }
            };
        } else if (useFSDialog) {
            fsWindow = new Dialog((Frame)null, "FS Dialog on device "+dev, false,
                                 dev.getDefaultConfiguration());
            fsWindow.add(new Component() {
                public void paint(Graphics g) {
                    renderDimensions(g, getBounds(),
                                     this.getGraphicsConfiguration());
                }
            });
        } else {
            fsWindow = new Frame("FS Frame on device "+dev,
                                 dev.getDefaultConfiguration())
            {
                public void paint(Graphics g) {
                    renderDimensions(g, getBounds(),
                                     this.getGraphicsConfiguration());
                }
            };
            if (addHWChildren) {
                fsWindow.add("South", new Panel() {
                    public void paint(Graphics g) {
                        g.setColor(Color.red);
                        g.fillRect(0, 0, getWidth(), getHeight());
                    }
                });
                fsWindow.add("North", new Button("Button, sucka!"));
            }
        }
        fsWindow.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() > 1) {
                    done = true;
                    fsWindow.dispose();
                }
            }
        });

        fsWindow.addWindowListener(new WindowHandler());
        dev.setFullScreenWindow(fsWindow);
        if (dmChange && dev.isDisplayChangeSupported()) {
            DisplayMode dms[] = dev.getDisplayModes();
            DisplayMode myDM = null;
            for (DisplayMode dm : dms) {
                if (dm.getWidth() == 800 && dm.getHeight() == 600 &&
                    (dm.getBitDepth() >= 16 ||
                     dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI) &&
                     (dm.getRefreshRate() >= 60 ||
                      dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN))
                {
                    myDM = dm;
                    break;
                }
            }
            if (myDM != null) {
                System.err.println("Setting Display Mode: "+
                        myDM.getWidth() + "x" + myDM.getHeight() + "x" +
                        myDM.getBitDepth() + "@" + myDM.getRefreshRate() +
                        "Hz on device" + dev);
                dev.setDisplayMode(myDM);
            } else {
                System.err.println("Can't find suitable display mode.");
            }
        }
        done = false;
        if (runRenderLoop) {
            Thread updateThread = new Thread(new Runnable() {
                public void run() {
                    BufferStrategy bs = null;
                    if (useBS) {
                        fsWindow.createBufferStrategy(2);
                        bs = fsWindow.getBufferStrategy();
                    }
                    while (!done) {
                        if (useBS) {
                            Graphics g = bs.getDrawGraphics();
                            renderDimensions(g, fsWindow.getBounds(),
                                           fsWindow.getGraphicsConfiguration());
                            bs.show();
                        } else {
                            fsWindow.repaint();
                        }
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {}
                    }
                    if (useBS) {
                        bs.dispose();
                    }
                }
            });
            updateThread.start();
        }
    }

    public static void main(String args[]) {
        for (String s : args) {
            if (s.equalsIgnoreCase("-dm")) {
                System.err.println("Do Display Change after entering FS mode");
                dmChange = true;
            } else if (s.equalsIgnoreCase("-usewindow")) {
                System.err.println("Using Window to enter FS mode");
                useFSWindow = true;
            } else if (s.equalsIgnoreCase("-setnull")) {
                System.err.println("Setting null FS window on dispose");
                setNullOnDispose = true;
            } else {
                System.err.println("Usage: MultimonFullscreenTest " +
                        "[-dm][-usewindow][-setnull]");
            }

        }
        MultimonFullscreenTest fs =
                new MultimonFullscreenTest("Test Full Screen");
    }
    class WindowHandler extends WindowAdapter {
        public void windowClosing(WindowEvent we) {
            done = true;
            Window w = (Window)we.getSource();
            if (setNullOnDispose) {
                w.getGraphicsConfiguration().getDevice().setFullScreenWindow(null);
            }
            w.dispose();
        }
    }
}
