Path: blob/master/test/jdk/java/awt/FullScreen/AltTabCrashTest/AltTabCrashTest.java
41154 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24@test25@key headful26@bug 6275887 6429971 6459792 819861327@summary Test that we don't crash when alt+tabbing in and out of28fullscreen app29@author [email protected]: area=FullScreen30@run main/othervm/timeout=100 AltTabCrashTest -auto -changedm31@run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -changedm32@run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -usebs -changedm33*/3435import java.awt.AWTException;36import java.awt.Color;37import java.awt.DisplayMode;38import java.awt.Frame;39import java.awt.Graphics;40import java.awt.Graphics2D;41import java.awt.GraphicsDevice;42import java.awt.GraphicsEnvironment;43import java.awt.Image;44import java.awt.RenderingHints;45import java.awt.Robot;46import java.awt.event.KeyAdapter;47import java.awt.event.KeyEvent;48import java.awt.event.MouseAdapter;49import java.awt.event.MouseEvent;50import java.awt.image.BufferStrategy;51import java.awt.image.BufferedImage;52import java.awt.image.VolatileImage;53import java.util.Random;54import java.util.Vector;5556/**57* Note that the alt+tabbing in and out part will most likely only work58* on Windows, and only if there are no interventions.59*/6061public class AltTabCrashTest extends Frame {62public static int width;63public static int height;64public static volatile boolean autoMode;65public static boolean useBS;66public static final int NUM_OF_BALLS = 70;67// number of times to alt+tab in and out of the app68public static int altTabs = 5;69private final Vector<Ball> balls = new Vector<>();70GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment()71.getDefaultScreenDevice();72VolatileImage vimg = null;73BufferStrategy bufferStrategy = null;74volatile boolean timeToQuit = false;7576enum SpriteType {77OVALS, VIMAGES, BIMAGES, AAOVALS, TEXT78}7980private static boolean changeDM = false;81private static SpriteType spriteType;82static Random rnd = new Random();8384public AltTabCrashTest( ) {85addKeyListener(new KeyAdapter() {86public void keyPressed(KeyEvent e) {87if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {88timeToQuit = true;89}90}91});92setIgnoreRepaint(true);93addMouseListener(new MouseHandler());94for (int i = 0; i < NUM_OF_BALLS; i++) {95int x = 50 + rnd.nextInt(550), y = 50 + rnd.nextInt(400);9697balls.addElement(createRandomBall(y, x));98}99setUndecorated(true);100gd.setFullScreenWindow(this);101GraphicsDevice gd = getGraphicsConfiguration().getDevice();102if (gd.isDisplayChangeSupported() && changeDM) {103DisplayMode dm = findDisplayMode();104if (dm != null) {105try {106gd.setDisplayMode(dm);107} catch (IllegalArgumentException iae) {108System.err.println("Error setting display mode");109}110}111}112if (useBS) {113createBufferStrategy(2);114bufferStrategy = getBufferStrategy();115} else {116Graphics2D g = (Graphics2D) getGraphics();117render(g);118g.dispose();119}120Thread ballThread = new BallThread();121ballThread.start();122if (autoMode) {123Thread tabberThread = new AltTabberThread();124tabberThread.start();125try {126ballThread.join();127tabberThread.join();128} catch (InterruptedException e) {129throw new RuntimeException(e);130}131dispose();132}133}134135private Ball createRandomBall(final int y, final int x) {136Ball b;137SpriteType type;138139if (spriteType == null) {140int index = rnd.nextInt(SpriteType.values().length);141type = SpriteType.values()[index];142} else {143type = spriteType;144}145switch (type) {146case VIMAGES: b = new VISpriteBall(x, y); break;147case AAOVALS: b = new AAOvalBall(x, y); break;148case BIMAGES: b = new BISpriteBall(x, y); break;149case TEXT: b = new TextBall(x,y, "Text Sprite!"); break;150default: b = new Ball(x, y); break;151}152return b;153}154155private class MouseHandler extends MouseAdapter {156public void mousePressed(MouseEvent e) {157synchronized (balls) {158balls.addElement(createRandomBall(e.getX(), e.getY()));159}160}161}162163private class AltTabberThread extends Thread {164Robot robot;165166void pressAltTab() {167robot.keyPress(KeyEvent.VK_ALT);168robot.keyPress(KeyEvent.VK_TAB);169robot.keyRelease(KeyEvent.VK_TAB);170robot.keyRelease(KeyEvent.VK_ALT);171}172void pressShiftAltTab() {173robot.keyPress(KeyEvent.VK_SHIFT);174pressAltTab();175robot.keyRelease(KeyEvent.VK_SHIFT);176}177public void run() {178try {179robot = new Robot();180robot.setAutoDelay(200);181} catch (AWTException e) {182throw new RuntimeException("Can't create robot");183}184boolean out = true;185while (altTabs-- > 0 && !timeToQuit) {186System.err.println("Alt+tabber Iteration: "+altTabs);187try { Thread.sleep(2500); } catch (InterruptedException ex) {}188189if (out) {190System.err.println("Issuing alt+tab");191pressAltTab();192} else {193System.err.println("Issuing shift ");194pressShiftAltTab();195}196out = !out;197}198System.err.println("Alt+tabber finished.");199timeToQuit = true;200}201}202203private class BallThread extends Thread {204public void run() {205while (!timeToQuit) {206if (useBS) {207renderToBS();208bufferStrategy.show();209} else {210Graphics g = AltTabCrashTest.this.getGraphics();211render(g);212g.dispose();213}214}215gd.setFullScreenWindow(null);216AltTabCrashTest.this.dispose();217}218}219220static class Ball {221222int x, y; // current location223int dx, dy; // motion delta224int diameter = 40;225Color color = Color.red;226227public Ball() {228}229230public Ball(int x, int y) {231this.x = x;232this.y = y;233dx = x % 20 + 1;234dy = y % 20 + 1;235color = new Color(rnd.nextInt(0x00ffffff));236}237238public void move() {239if (x < 10 || x >= AltTabCrashTest.width - 20)240dx = -dx;241if (y < 10 || y > AltTabCrashTest.height - 20)242dy = -dy;243x += dx;244y += dy;245}246247public void paint(Graphics g, Color c) {248if (c == null) {249g.setColor(color);250} else {251g.setColor(c);252}253g.fillOval(x, y, diameter, diameter);254}255256}257258static class TextBall extends Ball {259String text;260public TextBall(int x, int y, String text) {261super(x, y);262this.text = text;263}264265public void paint(Graphics g, Color c) {266if (c == null) {267g.setColor(color);268} else {269g.setColor(c);270}271g.drawString(text, x, y);272}273}274275static class AAOvalBall extends Ball {276public AAOvalBall(int x, int y) {277super(x, y);278}279public void paint(Graphics g, Color c) {280if (c == null) {281Graphics2D g2d = (Graphics2D)g.create();282g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,283RenderingHints.VALUE_ANTIALIAS_ON);284g2d.setColor(color);285g2d.fillOval(x, y, diameter, diameter);286} else {287g.setColor(c);288g.fillOval(x-2, y-2, diameter+4, diameter+4);289}290}291}292293static abstract class SpriteBall extends Ball {294Image image;295public SpriteBall(int x, int y) {296super(x, y);297image = createSprite();298Graphics g = image.getGraphics();299g.setColor(color);300g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));301}302public void paint(Graphics g, Color c) {303if (c != null) {304g.setColor(c);305g.fillRect(x, y, image.getWidth(null), image.getHeight(null));306} else do {307validateSprite();308g.drawImage(image, x, y, null);309} while (renderingIncomplete());310}311public abstract Image createSprite();312public void validateSprite() {}313public boolean renderingIncomplete() { return false; }314}315class VISpriteBall extends SpriteBall {316317public VISpriteBall(int x, int y) {318super(x, y);319}320public boolean renderingIncomplete() {321return ((VolatileImage)image).contentsLost();322}323324public Image createSprite() {325return gd.getDefaultConfiguration().326createCompatibleVolatileImage(20, 20);327}328public void validateSprite() {329int result =330((VolatileImage)image).validate(getGraphicsConfiguration());331if (result == VolatileImage.IMAGE_INCOMPATIBLE) {332image = createSprite();333result = VolatileImage.IMAGE_RESTORED;334}335if (result == VolatileImage.IMAGE_RESTORED) {336Graphics g = image.getGraphics();337g.setColor(color);338g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));339}340}341}342class BISpriteBall extends SpriteBall {343public BISpriteBall(int x, int y) {344super(x, y);345}346public Image createSprite() {347return new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);348}349}350351352public void renderOffscreen() {353Graphics2D g2d = (Graphics2D) vimg.getGraphics();354synchronized (balls) {355for (Ball b : balls) {356b.paint(g2d, getBackground());357b.move();358b.paint(g2d, null);359}360}361g2d.dispose();362}363364public void renderToBS() {365width = getWidth();366height = getHeight();367368do {369Graphics2D g2d = (Graphics2D)bufferStrategy.getDrawGraphics();370371g2d.clearRect(0, 0, width, height);372synchronized (balls) {373for (Ball b : balls) {374b.move();375b.paint(g2d, null);376}377}378g2d.dispose();379} while (bufferStrategy.contentsLost() ||380bufferStrategy.contentsRestored());381}382383public void render(Graphics g) {384do {385height = getBounds().height;386width = getBounds().width;387if (vimg == null) {388vimg = createVolatileImage(width, height);389renderOffscreen();390}391int returnCode = vimg.validate(getGraphicsConfiguration());392if (returnCode == VolatileImage.IMAGE_RESTORED) {393renderOffscreen();394} else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {395vimg = getGraphicsConfiguration().396createCompatibleVolatileImage(width, height);397renderOffscreen();398} else if (returnCode == VolatileImage.IMAGE_OK) {399renderOffscreen();400}401g.drawImage(vimg, 0, 0, this);402} while (vimg.contentsLost());403}404405public static void main(String args[]) {406for (String arg : args) {407if (arg.equalsIgnoreCase("-auto")) {408autoMode = true;409System.err.println("Running in automatic mode using Robot");410} else if (arg.equalsIgnoreCase("-usebs")) {411useBS = true;412System.err.println("Using BufferStrategy instead of VI");413} else if (arg.equalsIgnoreCase("-changedm")) {414changeDM= true;415System.err.println("The test will change display mode");416} else if (arg.equalsIgnoreCase("-vi")) {417spriteType = SpriteType.VIMAGES;418} else if (arg.equalsIgnoreCase("-bi")) {419spriteType = SpriteType.BIMAGES;420} else if (arg.equalsIgnoreCase("-ov")) {421spriteType = SpriteType.OVALS;422} else if (arg.equalsIgnoreCase("-aaov")) {423spriteType = SpriteType.AAOVALS;424} else if (arg.equalsIgnoreCase("-tx")) {425spriteType = SpriteType.TEXT;426} else {427System.err.println("Usage: AltTabCrashTest [-usebs][-auto]" +428"[-changedm][-vi|-bi|-ov|-aaov|-tx]");429System.err.println(" -usebs: use BufferStrategy instead of VI");430System.err.println(" -auto: automatically alt+tab in and out" +431" of the application ");432System.err.println(" -changedm: change display mode");433System.err.println(" -(vi|bi|ov|tx|aaov) : use only VI, BI, " +434"text or [AA] [draw]Oval sprites");435System.exit(0);436}437}438if (spriteType != null) {439System.err.println("The test will only use "+spriteType+" sprites.");440}441new AltTabCrashTest();442}443444private DisplayMode findDisplayMode() {445GraphicsDevice gd = getGraphicsConfiguration().getDevice();446DisplayMode dms[] = gd.getDisplayModes();447DisplayMode currentDM = gd.getDisplayMode();448for (DisplayMode dm : dms) {449if (dm.getBitDepth() > 8 &&450dm.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&451dm.getBitDepth() != currentDM.getBitDepth() &&452dm.getWidth() == currentDM.getWidth() &&453dm.getHeight() == currentDM.getHeight())454{455// found a mode which has the same dimensions but different456// depth457return dm;458}459if (dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI &&460(dm.getWidth() != currentDM.getWidth() ||461dm.getHeight() != currentDM.getHeight()))462{463// found a mode which has the same depth but different464// dimensions465return dm;466}467}468469return null;470}471}472473474