--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/AltTabCrashTest/AltTabCrashTest.java Wed Jun 18 13:21:59 2014 +0400
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2005, 2014 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 6275887 6429971 6459792
+ @summary Test that we don't crash when alt+tabbing in and out of
+ fullscreen app
+ @author Dmitri.Trembovetski@sun.com: area=FullScreen
+ @run main/othervm/timeout=100 AltTabCrashTest -auto -changedm
+ @run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -changedm
+ @run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -usebs -changedm
+ @run main/othervm/timeout=100 -Dsun.java2d.opengl=True AltTabCrashTest -auto
+*/
+
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.DisplayMode;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.RenderingHints;
+import java.awt.Robot;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.image.BufferStrategy;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import java.util.Random;
+import java.util.Vector;
+
+/**
+ * Note that the alt+tabbing in and out part will most likely only work
+ * on Windows, and only if there are no interventions.
+ */
+
+public class AltTabCrashTest extends Frame {
+ public static int width;
+ public static int height;
+ public static volatile boolean autoMode;
+ public static boolean useBS;
+ public static final int NUM_OF_BALLS = 70;
+ // number of times to alt+tab in and out of the app
+ public static int altTabs = 5;
+ private final Vector<Ball> balls = new Vector<>();
+ GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice();
+ VolatileImage vimg = null;
+ BufferStrategy bufferStrategy = null;
+ volatile boolean timeToQuit = false;
+ static final Object lock = new Object();
+
+ enum SpriteType {
+ OVALS, VIMAGES, BIMAGES, AAOVALS, TEXT
+ }
+
+ private static boolean changeDM = false;
+ private static SpriteType spriteType;
+ static Random rnd = new Random();
+
+ public AltTabCrashTest( ) {
+ addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ timeToQuit = true;
+ }
+ }
+ });
+ setIgnoreRepaint(true);
+ addMouseListener(new MouseHandler());
+ for (int i = 0; i < NUM_OF_BALLS; i++) {
+ int x = 50 + rnd.nextInt(550), y = 50 + rnd.nextInt(400);
+
+ balls.addElement(createRandomBall(y, x));
+ }
+ setUndecorated(true);
+ gd.setFullScreenWindow(this);
+ GraphicsDevice gd = getGraphicsConfiguration().getDevice();
+ if (gd.isDisplayChangeSupported() && changeDM) {
+ DisplayMode dm = findDisplayMode();
+ if (dm != null) {
+ try {
+ gd.setDisplayMode(dm);
+ } catch (IllegalArgumentException iae) {
+ System.err.println("Error setting display mode");
+ }
+ }
+ }
+ if (useBS) {
+ createBufferStrategy(2);
+ bufferStrategy = getBufferStrategy();
+ } else {
+ Graphics2D g = (Graphics2D) getGraphics();
+ render(g);
+ g.dispose();
+ }
+ Thread t = new BallThread();
+ t.start();
+ if (autoMode) {
+ Thread tt = new AltTabberThread();
+ tt.start();
+ synchronized (lock) {
+ while (!timeToQuit) {
+ try {
+ lock.wait(200);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ t = null;
+ dispose();
+ }
+ }
+
+ private Ball createRandomBall(final int y, final int x) {
+ Ball b;
+ SpriteType type;
+
+ if (spriteType == null) {
+ int index = rnd.nextInt(SpriteType.values().length);
+ type = SpriteType.values()[index];
+ } else {
+ type = spriteType;
+ }
+ switch (type) {
+ case VIMAGES: b = new VISpriteBall(x, y); break;
+ case AAOVALS: b = new AAOvalBall(x, y); break;
+ case BIMAGES: b = new BISpriteBall(x, y); break;
+ case TEXT: b = new TextBall(x,y, "Text Sprite!"); break;
+ default: b = new Ball(x, y); break;
+ }
+ return b;
+ }
+
+ private class MouseHandler extends MouseAdapter {
+ public void mousePressed(MouseEvent e) {
+ synchronized (balls) {
+ balls.addElement(createRandomBall(e.getX(), e.getY()));
+ }
+ }
+ }
+
+ private class AltTabberThread extends Thread {
+ Robot robot;
+
+ void pressAltTab() {
+ robot.keyPress(KeyEvent.VK_ALT);
+ robot.keyPress(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_TAB);
+ robot.keyRelease(KeyEvent.VK_ALT);
+ }
+ void pressShiftAltTab() {
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ pressAltTab();
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ }
+ public void run() {
+ try {
+ robot = new Robot();
+ robot.setAutoDelay(200);
+ } catch (AWTException e) {
+ throw new RuntimeException("Can't create robot");
+ }
+ boolean out = true;
+ while (altTabs-- > 0 && !timeToQuit) {
+ System.err.println("Alt+tabber Iteration: "+altTabs);
+ try { Thread.sleep(2500); } catch (InterruptedException ex) {}
+
+ if (out) {
+ System.err.println("Issuing alt+tab");
+ pressAltTab();
+ } else {
+ System.err.println("Issuing shift ");
+ pressShiftAltTab();
+ }
+ out = !out;
+ }
+ System.err.println("Alt+tabber finished.");
+ synchronized (lock) {
+ timeToQuit = true;
+ lock.notify();
+ }
+ }
+ }
+
+ private class BallThread extends Thread {
+ public void run() {
+ while (!timeToQuit) {
+ if (useBS) {
+ renderToBS();
+ bufferStrategy.show();
+ } else {
+ Graphics g = AltTabCrashTest.this.getGraphics();
+ render(g);
+ g.dispose();
+ }
+ }
+ gd.setFullScreenWindow(null);
+ AltTabCrashTest.this.dispose();
+ }
+ }
+
+ static class Ball {
+
+ int x, y; // current location
+ int dx, dy; // motion delta
+ int diameter = 40;
+ Color color = Color.red;
+
+ public Ball() {
+ }
+
+ public Ball(int x, int y) {
+ this.x = x;
+ this.y = y;
+ dx = x % 20 + 1;
+ dy = y % 20 + 1;
+ color = new Color(rnd.nextInt(0x00ffffff));
+ }
+
+ public void move() {
+ if (x < 10 || x >= AltTabCrashTest.width - 20)
+ dx = -dx;
+ if (y < 10 || y > AltTabCrashTest.height - 20)
+ dy = -dy;
+ x += dx;
+ y += dy;
+ }
+
+ public void paint(Graphics g, Color c) {
+ if (c == null) {
+ g.setColor(color);
+ } else {
+ g.setColor(c);
+ }
+ g.fillOval(x, y, diameter, diameter);
+ }
+
+ }
+
+ static class TextBall extends Ball {
+ String text;
+ public TextBall(int x, int y, String text) {
+ super(x, y);
+ this.text = text;
+ }
+
+ public void paint(Graphics g, Color c) {
+ if (c == null) {
+ g.setColor(color);
+ } else {
+ g.setColor(c);
+ }
+ g.drawString(text, x, y);
+ }
+ }
+
+ static class AAOvalBall extends Ball {
+ public AAOvalBall(int x, int y) {
+ super(x, y);
+ }
+ public void paint(Graphics g, Color c) {
+ if (c == null) {
+ Graphics2D g2d = (Graphics2D)g.create();
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setColor(color);
+ g2d.fillOval(x, y, diameter, diameter);
+ } else {
+ g.setColor(c);
+ g.fillOval(x-2, y-2, diameter+4, diameter+4);
+ }
+ }
+ }
+
+ static abstract class SpriteBall extends Ball {
+ Image image;
+ public SpriteBall(int x, int y) {
+ super(x, y);
+ image = createSprite();
+ Graphics g = image.getGraphics();
+ g.setColor(color);
+ g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
+ }
+ public void paint(Graphics g, Color c) {
+ if (c != null) {
+ g.setColor(c);
+ g.fillRect(x, y, image.getWidth(null), image.getHeight(null));
+ } else do {
+ validateSprite();
+ g.drawImage(image, x, y, null);
+ } while (renderingIncomplete());
+ }
+ public abstract Image createSprite();
+ public void validateSprite() {}
+ public boolean renderingIncomplete() { return false; }
+ }
+ class VISpriteBall extends SpriteBall {
+
+ public VISpriteBall(int x, int y) {
+ super(x, y);
+ }
+ public boolean renderingIncomplete() {
+ return ((VolatileImage)image).contentsLost();
+ }
+
+ public Image createSprite() {
+ return gd.getDefaultConfiguration().
+ createCompatibleVolatileImage(20, 20);
+ }
+ public void validateSprite() {
+ int result =
+ ((VolatileImage)image).validate(getGraphicsConfiguration());
+ if (result == VolatileImage.IMAGE_INCOMPATIBLE) {
+ image = createSprite();
+ result = VolatileImage.IMAGE_RESTORED;
+ }
+ if (result == VolatileImage.IMAGE_RESTORED) {
+ Graphics g = image.getGraphics();
+ g.setColor(color);
+ g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
+ }
+ }
+ }
+ class BISpriteBall extends SpriteBall {
+ public BISpriteBall(int x, int y) {
+ super(x, y);
+ }
+ public Image createSprite() {
+ return new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
+ }
+ }
+
+
+ public void renderOffscreen() {
+ Graphics2D g2d = (Graphics2D) vimg.getGraphics();
+ synchronized (balls) {
+ for (Ball b : balls) {
+ b.paint(g2d, getBackground());
+ b.move();
+ b.paint(g2d, null);
+ }
+ }
+ g2d.dispose();
+ }
+
+ public void renderToBS() {
+ width = getWidth();
+ height = getHeight();
+
+ do {
+ Graphics2D g2d = (Graphics2D)bufferStrategy.getDrawGraphics();
+
+ g2d.clearRect(0, 0, width, height);
+ synchronized (balls) {
+ for (Ball b : balls) {
+ b.move();
+ b.paint(g2d, null);
+ }
+ }
+ g2d.dispose();
+ } while (bufferStrategy.contentsLost() ||
+ bufferStrategy.contentsRestored());
+ }
+
+ public void render(Graphics g) {
+ do {
+ height = getBounds().height;
+ width = getBounds().width;
+ if (vimg == null) {
+ vimg = createVolatileImage(width, height);
+ renderOffscreen();
+ }
+ int returnCode = vimg.validate(getGraphicsConfiguration());
+ if (returnCode == VolatileImage.IMAGE_RESTORED) {
+ renderOffscreen();
+ } else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
+ vimg = getGraphicsConfiguration().
+ createCompatibleVolatileImage(width, height);
+ renderOffscreen();
+ } else if (returnCode == VolatileImage.IMAGE_OK) {
+ renderOffscreen();
+ }
+ g.drawImage(vimg, 0, 0, this);
+ } while (vimg.contentsLost());
+ }
+
+ public static void main(String args[]) {
+ for (String arg : args) {
+ if (arg.equalsIgnoreCase("-auto")) {
+ autoMode = true;
+ System.err.println("Running in automatic mode using Robot");
+ } else if (arg.equalsIgnoreCase("-usebs")) {
+ useBS = true;
+ System.err.println("Using BufferStrategy instead of VI");
+ } else if (arg.equalsIgnoreCase("-changedm")) {
+ changeDM= true;
+ System.err.println("The test will change display mode");
+ } else if (arg.equalsIgnoreCase("-vi")) {
+ spriteType = SpriteType.VIMAGES;
+ } else if (arg.equalsIgnoreCase("-bi")) {
+ spriteType = SpriteType.BIMAGES;
+ } else if (arg.equalsIgnoreCase("-ov")) {
+ spriteType = SpriteType.OVALS;
+ } else if (arg.equalsIgnoreCase("-aaov")) {
+ spriteType = SpriteType.AAOVALS;
+ } else if (arg.equalsIgnoreCase("-tx")) {
+ spriteType = SpriteType.TEXT;
+ } else {
+ System.err.println("Usage: AltTabCrashTest [-usebs][-auto]" +
+ "[-changedm][-vi|-bi|-ov|-aaov|-tx]");
+ System.err.println(" -usebs: use BufferStrategy instead of VI");
+ System.err.println(" -auto: automatically alt+tab in and out" +
+ " of the application ");
+ System.err.println(" -changedm: change display mode");
+ System.err.println(" -(vi|bi|ov|tx|aaov) : use only VI, BI, " +
+ "text or [AA] [draw]Oval sprites");
+ System.exit(0);
+ }
+ }
+ if (spriteType != null) {
+ System.err.println("The test will only use "+spriteType+" sprites.");
+ }
+ new AltTabCrashTest();
+ }
+
+ private DisplayMode findDisplayMode() {
+ GraphicsDevice gd = getGraphicsConfiguration().getDevice();
+ DisplayMode dms[] = gd.getDisplayModes();
+ DisplayMode currentDM = gd.getDisplayMode();
+ for (DisplayMode dm : dms) {
+ if (dm.getBitDepth() > 8 &&
+ dm.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
+ dm.getBitDepth() != currentDM.getBitDepth() &&
+ dm.getWidth() == currentDM.getWidth() &&
+ dm.getHeight() == currentDM.getHeight())
+ {
+ // found a mode which has the same dimensions but different
+ // depth
+ return dm;
+ }
+ if (dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI &&
+ (dm.getWidth() != currentDM.getWidth() ||
+ dm.getHeight() != currentDM.getHeight()))
+ {
+ // found a mode which has the same depth but different
+ // dimensions
+ return dm;
+ }
+ }
+
+ return null;
+ }
+}