/*
 * 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 6240507 6662642
 * @summary verify that isFullScreenSupported and getFullScreenWindow work
 * correctly with and without a SecurityManager. Note that the test may fail
 * on older Gnome versions (see bug 6500686).
 * @run main FSFrame
 * @run main/othervm -Dsun.java2d.noddraw=true FSFrame
 * @author cheth
 */

import java.awt.*;
import java.awt.image.*;
import java.applet.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.imageio.ImageIO;

public class FSFrame extends Frame implements Runnable {

    // Don't start the test until the window is visible
    boolean visible = false;
    Robot robot = null;
    static volatile boolean done = false;

    public void paint(Graphics g) {
        if (!visible && getWidth() != 0 && getHeight() != 0) {
            visible = true;
            try {
                GraphicsDevice gd = getGraphicsConfiguration().getDevice();
                robot = new Robot(gd);
            } catch (Exception e) {
                System.out.println("Problem creating robot: cannot verify FS " +
                                   "window display");
            }
        }
        g.setColor(Color.green);
        g.fillRect(0, 0, getWidth(), getHeight());
    }

    @Override
    public void update(Graphics g) {
        paint(g);
    }

    boolean checkColor(int x, int y, BufferedImage bImg) {
        int pixelColor;
        int correctColor = Color.green.getRGB();
        pixelColor = bImg.getRGB(x, y);
        if (pixelColor != correctColor) {
            System.out.println("FAILURE: pixelColor " +
                               Integer.toHexString(pixelColor) +
                               " != correctColor " +
                               Integer.toHexString(correctColor) +
                               " at coordinates (" + x + ", " + y + ")");
            return false;
        }
        return true;
    }

    void checkFSDisplay(boolean fsSupported) {
        GraphicsConfiguration gc = getGraphicsConfiguration();
        GraphicsDevice gd = gc.getDevice();
        Rectangle r = gc.getBounds();
        Insets in = null;
        if (!fsSupported) {
            in = Toolkit.getDefaultToolkit().getScreenInsets(gc);
            r = new Rectangle(in.left, in.top,
                              r.width -  (in.left + in.right),
                              r.height - (in.top  + in.bottom));
        }
        BufferedImage bImg = robot.createScreenCapture(r);
        // Check that all four corners and middle pixel match the window's
        // fill color
        if (robot == null) {
            return;
        }
        boolean colorCorrect = true;
        colorCorrect &= checkColor(0, 0, bImg);
        colorCorrect &= checkColor(0, bImg.getHeight() - 1, bImg);
        colorCorrect &= checkColor(bImg.getWidth() - 1, 0, bImg);
        colorCorrect &= checkColor(bImg.getWidth() - 1, bImg.getHeight() - 1, bImg);
        colorCorrect &= checkColor(bImg.getWidth() / 2, bImg.getHeight() / 2, bImg);
        if (!colorCorrect) {
            System.err.println("Test failed for mode: fsSupported="+fsSupported);
            if (in != null) {
                System.err.println("screen insets   : " + in);
            }
            System.err.println("screen shot rect: " + r);
            String name = "FSFrame_fs_"+
                    (fsSupported?"supported":"not_supported")+".png";
            try {
                ImageIO.write(bImg, "png", new File(name));
                System.out.println("Dumped screen shot to "+name);
            } catch (IOException ex) {}
            throw new Error("Some pixel colors not correct; FS window may not" +
                            " have been displayed correctly");
        }
    }

    void checkFSFunctionality(boolean withSecurity) {
        GraphicsDevice gd = getGraphicsConfiguration().getDevice();
        if (withSecurity) {
            SecurityManager sm = new SecurityManager();
            System.setSecurityManager(sm);
        }
        try {
            // None of these should throw an exception
            final boolean fs = gd.isFullScreenSupported();
            System.out.println("FullscreenSupported: " + (fs ? "yes" : "no"));
            gd.setFullScreenWindow(this);
            try {
                // Give the system time to set the FS window and display it
                // properly
                Thread.sleep(2000);
            } catch (Exception e) {}
            if (!withSecurity) {
                // See if FS window got displayed correctly
                try {
                    EventQueue.invokeAndWait(new Runnable() {
                        public void run() {
                            repaint();
                            checkFSDisplay(fs);
                        }
                    });
                } catch (InvocationTargetException ex) {
                    ex.printStackTrace();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            // reset window
            gd.setFullScreenWindow(null);
            try {
                // Give the system time to set the FS window and display it
                // properly
                Thread.sleep(2000);
            } catch (Exception e) {}
        } catch (SecurityException e) {
            e.printStackTrace();
            throw new Error("Failure: should not get an exception when " +
                            "calling isFSSupported or setFSWindow");
        }
    }

    public void run() {
        boolean firstTime = true;
        while (!done) {
            if (visible) {
                checkFSFunctionality(false);
                checkFSFunctionality(true);
                done = true;
            } else {
                // sleep while we wait
                try {
                    // Give the system time to set the FS window and display it
                    // properly
                    Thread.sleep(100);
                } catch (Exception e) {}
            }
        }
        System.out.println("PASS");
    }

    public static void main(String args[]) {
        FSFrame frame = new FSFrame();
        frame.setUndecorated(true);
        Thread t = new Thread(frame);
        frame.setSize(500, 500);
        frame.setVisible(true);
        t.start();
        while (!done) {
            try {
                // Do not exit the main thread until the test is finished
                Thread.sleep(1000);
            } catch (Exception e) {}
        }
        frame.dispose();
    }
}
