JDK-4733384 : 1.4.1 REGRESSION: Crash when moving swing window on thinkpad x20 series laptop
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-08-19
  • Updated: 2002-10-23
  • Resolved: 2002-10-23
Related Reports
Duplicate :  
Description

Name: jk109818			Date: 08/19/2002


FULL PRODUCT VERSION :
java version "1.4.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
a swing window is opened off screen, then moved to a point
visible point on the screen. the whole machine crashes.
this is only an error on the ibm x20, x21 and x22
thinkpads. the same code does not cause a crash when the
1.4.0 runtime is used.

REGRESSION.  Last worked in version 1.4

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run code below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
window should just appear, on the x20 series thinkpads, the
whole system crashes.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
no stack traces. no dump files. just blue screen.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.io.*;

import javax.swing.*;

public class AnimatedNotifier implements Runnable{

	/** Static class variables
	 *  only one type of window (qaudrant, speed etc) allowed
	 */
	static final int winW = 250;		// alert window dimensions
	static final int winH = 166;
	
	static ImageIcon tackIcon;
	static ImageIcon tackedIcon;

	static int screenW;					// screen
hieght and width
	static int screenH;
	
	static boolean stackMode = false;	// stack mode indicator
	static boolean autoTack = false;	// automatically tack all alerts
	static boolean playSound = true;	// play sound on alert
	static boolean animate = true;	// play sound on alert
	
	static int[] alertBins;				// array of alert bins
	
	static int pad_t = 10;				// screen padding, top
and bottom
	static int pad_b = 35;
	
	static int slideStep = 10;			// step increment for
sliding window
	
	// delays: opening, closing, and display (milliseconds)
	static int closeDelay = 5;			/* delay between slide
increments */
	static int openDelay = 5;			/* delay between slide
increments */
	static int displayDelay = 10000;	/* how long the window stays
open */
	
	static ImageIcon bgImage = null;	// the alert window background
	
	static Rectangle tackButtonBounds;	// the bounds of the tack button
	static Rectangle sidebarImageBounds;// the bounds of the sidebar image
	static Rectangle exitButtonBounds;	// the bounds of the exit button
	static Rectangle callButtonBounds =
		new Rectangle(68, 122, 106, 20);// the bounds of the callback
button
	
	static Rectangle mesgPanelBounds;	// the bounds of the message
panel
	static Rectangle titleLabelBounds;	// the bounds of the title label
	static Color titleLabelForeground =	// title text color
		Color.white;
	static Rectangle proxyLabelBounds;	// the bounds of the proxy label
	static Color proxyLabelForeground =	// proxy text color
		new Color(0,51,153);
	
	static int quadrant = 4;			// the quadrant
	
	/** Instance variables
	 * per instance settings
	 */
	int currentEdge = 0;				// current edge of the
alert window
	int currentBin = 0;					// current bin
which is occupied
	
	Thread th = null;					// action thread

	Window w = null;					// the display
window
	
	boolean tacked = false;				// the state of the
window tack
	
	String noticeTitle = null;			// message values
	String noticeMessage = null;
	String noticeProxy = null;
	String titleImageName = null;		// location of the title icon
	
		
	String buttonImageName = null;		// the button image for the
callback button

	String sidebarImageName = null;		// the sidebar image
	
	JButton tack;						// the tack
button
	String tackToolTip;	// the tack's tool tip

	static java.applet.AudioClip sound;

	static {
		// Get the screen size
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		screenW =  toolkit.getScreenSize().width;
		screenH =  toolkit.getScreenSize().height;
		
		// create the alert bins and zero them out
		alertBins = new int[(screenH - pad_b - pad_t)/winH];
		for (int i=0; i < alertBins.length; i++){ alertBins[i] = 0;}
	}
	
	public static boolean getPlaySound(){ return playSound;}
	public static void setPlaySound(boolean b){ playSound = b;}

	public static boolean getAnimate(){ return animate;}
	public static void setAnimate(boolean b){ animate = b;}

	public static boolean getStackMode(){ return stackMode;}
	public static void setStackMode(boolean b){ stackMode = b;}

	public static boolean getAutoTack(){ return autoTack; }
	public static void setAutoTack(boolean b){ autoTack = b; }
	
	public static int getDisplayDelay(){ return displayDelay / 1000; }
	public static void setDisplayDelay(int i){ displayDelay = i*1000;
	}
	
	public static int getQuadrant(){ return quadrant; }
	public static void setQuadrant(int q){
//		quadrant = (q % 4) + 1;
		quadrant = q;
		if ((quadrant == 1) || (quadrant == 4)){
			bgImage = loadImage("ginie-alert-bg14.gif");
			tackButtonBounds = new Rectangle(210, 1, 14, 19);
			exitButtonBounds = new Rectangle(231, 3, 15, 14);
			titleLabelBounds = new Rectangle(4, 2, 189, 17);
			proxyLabelBounds = new Rectangle(50, 150, 173, 12);
			mesgPanelBounds = new Rectangle(11, 28, 203, 88);
			sidebarImageBounds = new Rectangle(233, 32, 17, 100);
			
		} else if ((quadrant == 2) || (quadrant == 3)){
			bgImage = loadImage("ginie-alert-bg23.gif");
			tackButtonBounds = new Rectangle(210, 1, 14, 19);
			exitButtonBounds = new Rectangle(231, 3, 15, 14);
			titleLabelBounds = new Rectangle(4, 2, 189, 17);
			proxyLabelBounds = new Rectangle(25, 150, 173, 12);
			mesgPanelBounds = new Rectangle(34, 28, 203, 88);
			sidebarImageBounds = new Rectangle(0, 32, 17, 100);
		}
	}
	
	public AnimatedNotifier(String title, String titleImageName, String
message, String proxy, String buttonImage, String sidebarImageName){
		// load the audio clip
		loadAllImages();
		this.noticeTitle = title;
		this.titleImageName = titleImageName;
		this.noticeMessage = message;
		this.noticeProxy = proxy;
		this.buttonImageName = buttonImage;
		this.sidebarImageName = sidebarImageName;
	}
	
	private int getFirstFreeEdge(){
		if (stackMode){
			if ((quadrant == 2) || (quadrant == 1))	return pad_t;
			else return screenH - pad_b - winH;
		}
		for (int i=0; i < alertBins.length; i++){
			if (alertBins[i] == 0) {
				alertBins[i] = 1;
				currentBin = i;
				if ((quadrant == 2) || (quadrant == 1))	return
pad_t+(i*winH);
				else return screenH - pad_b - winH - (i*winH);
			}
		}
		currentBin = 0;
		if ((quadrant == 2) || (quadrant == 1))	return pad_t;
		else return screenH - pad_b - winH;
	}
	
	private void tackWindow(){
		tacked = true;
		tackToolTip = "untack window";
		tack.setToolTipText(tackToolTip);
		tack.setSelected(true);
		synchronized(th){
			th.notify();
		}
	}

	public synchronized void notifyUser(String title, String message) {
		w = new Window(new Frame());
		w.setLayout(null);
		w.setFocusable(false);
		w.setSize(winW, winH);

		// init the background
		JPanel jp = new JPanel(){
			public void paintComponent(Graphics g) {
				if (bgImage != null) g.drawImage
(bgImage.getImage(), 0, 0, null);
				super.paintComponent(g);
			}
		};
		jp.setOpaque(false);
		jp.setLayout(null);
		jp.setSize(winW, winH);
		
		// init the tack button
		tack = new JButton();
		tack.setIcon(tackIcon);
		tack.setSelectedIcon(tackedIcon);
		tack.addActionListener(new java.awt.event.ActionListener(){
			public void actionPerformed(java.awt.event.ActionEvent
ae){
				if (tacked) slideClosed();
				else tackWindow();
			}
		});
		tackToolTip = "tack window open";
		tack.setToolTipText(tackToolTip);
		tack.setBounds(tackButtonBounds);
		tack.setOpaque(false);
		tack.setBorder(null);
		jp.add(tack);
		
		// create  the message area
		JTextArea messageArea = new JTextArea(message);
		messageArea.setBounds(mesgPanelBounds);
		messageArea.setOpaque(false);
		messageArea.setLineWrap(true);
		messageArea.setWrapStyleWord(true);
		Font messageFont = new Font("verdana", Font.PLAIN, 10);
		messageArea.setFont(messageFont);
		jp.add(messageArea);

		// create the title label
		JLabel messageTitleLabel = new JLabel(title);
		if (titleImageName != null)
			messageTitleLabel.setIcon( new ImageIcon
(titleImageName) );
		messageTitleLabel.setBounds(titleLabelBounds);
		messageTitleLabel.setForeground( titleLabelForeground );
		Font titleFont = new Font("verdana", Font.BOLD, 12);
		messageTitleLabel.setFont(titleFont);
		jp.add(messageTitleLabel);

		// setup the optoinal proxy label
		if (noticeProxy != null){
			JLabel proxyLabel = new JLabel("from: " + noticeProxy);
			proxyLabel.setBounds(proxyLabelBounds);
			proxyLabel.setForeground( proxyLabelForeground );
			proxyLabel.setFont(messageFont);
			jp.add(proxyLabel);
		}

		// setup the optional proxy label
		if (sidebarImageName != null){
			
			JLabel sidebar = new JLabel(new ImageIcon
(sidebarImageName));
			sidebar.setBounds(sidebarImageBounds);
			jp.add(sidebar);
		}

		// setup the close window button
		JButton exitButton = new JButton();
		exitButton.setBorder(null);
		exitButton.addActionListener(new java.awt.event.ActionListener()
{
			public void actionPerformed(java.awt.event.ActionEvent
ae){
				slideClosed();
			}
		});
		exitButton.setBounds(exitButtonBounds);
		exitButton.setOpaque(false);
		jp.add(exitButton);
		
		jp.setBounds(0,0,winW,winH);
		w.add(jp);

		//window must be visible to be set on top
		if (animate){
			w.setLocation(-winW, -winH);	//move the window off
the screen
			w.setVisible(true);
		}

		currentEdge = getFirstFreeEdge();
		slideOpen();
		stayOpen(displayDelay);
		slideClosed();
		
		cleanUp();
	}
	
	private void cleanUp(){
		th = null;					// action thread
	
		w = null;					// the display
window
		
		noticeTitle = null;			// message values
		noticeMessage = null;
		noticeProxy = null;
		titleImageName = null;		// location of the title icon
		
		buttonImageName = null;		// the button image for the
callback button
	
		sidebarImageName = null;		// the sidebar image
		tack = null;						// the
tack button
		tackToolTip = null;	// the tack's tool tip
	}

	public void stayOpen(int duration){
		synchronized (th){
			if (autoTack){
				tackWindow();
			}

			try{ th.wait(duration);}
			catch (Exception e) { e.printStackTrace(); }
			
			
			// we break from above when we click the tack button
			if (tacked){
				// we breack from this when we click the tack
button again
				try{ th.wait(); }
				catch (Exception e) { /*e.printStackTrace();*/ }
			}
		}
	}
	
	private void moveWindow(int x){
		     if (quadrant == 1) w.setLocation(screenW - x, currentEdge);
		else if (quadrant == 2) w.setLocation(x - winW   , currentEdge);
		else if (quadrant == 3) w.setLocation(x - winW   , currentEdge);
		else if (quadrant == 4) w.setLocation(screenW - x, currentEdge);
	}
	
	private static void pause(int time){
		try {
			Thread.sleep(time);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void slideOpen(){
		if (animate){
			for (int i = 0; i <= winW; i += slideStep) {
				moveWindow(i);
				pause(openDelay);
			}
		} else {
			w.setLocation(-winW, -winH);	//move the window off
the screen
			w.setVisible(true);
			moveWindow(winW);

		}
	}
	
	public void slideClosed(){
		// free this bin for a new window
		alertBins[currentBin] = 0;

		if (animate){
			for (int i = winW; i >= 0; i -= slideStep) {
				moveWindow(i);
				pause(closeDelay);
			}
		}
		w.dispose();
		th = null;
		return;
	}

	public static void main(String[] args) {

		AnimatedNotifier.setQuadrant(1);
		//AnimatedNotifier.setStackMode(true);
		//AnimatedNotifier.setAutoTack(true);

		AnimatedNotifier an = new AnimatedNotifier
("test", "", "", "", "", "");
		an.alert();
	}
	
	public void alert(){
		th = new Thread(this);
		th.start();
	}

	public void run() {
		notifyUser(noticeTitle, noticeMessage);
	}

	public void loadAllImages(){
		if ( bgImage == null ) setQuadrant(quadrant);
		if ( tackIcon == null ) tackIcon = loadImage("tack.gif");
		if ( tackedIcon == null ) tackedIcon = loadImage("tacked.gif");
	}

	private static ImageIcon loadImage(String im){
		String imgPath = "\\images\\";
		//MagicCarpet.debugTrace("Notifier image path: " + imgPath);
		File imgFile = new File(imgPath + im);
		if (imgFile.exists())
			return new ImageIcon(imgPath + im);
		else return null;
	}
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
must use jdk 1.4.0, however another bug was fixed in 1.4.1
that we need to work as well.

Release Regression From : 1.4
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 163346) 
======================================================================

Comments
EVALUATION What graphics card/driver do you have? Have you tried upgrading the video driver? ###@###.### 2002-08-19 We were finally able to reproduce this bug by getting ahold of the same model of laptop (thinkpad x20) and upgrading the video driver from IBM's site (to version 5.13.1.5058; same as the bug submitter's driver). This is apparently the same bug as reported in 4713003, which boils down to a bug in the ATI drivers that hangs/reboots/blue-screens the system when too many (> 8) d3d devices are created. We have fixed that bug internally and it should be in the next external releases (1.4.1_02 and 1.4.2). We have verified that that new code fixes the bug on this thinkpad platform (as well as the other ATI platforms with the problem). Closing this bug as duplicate of that earlier bug. ###@###.### 2002-10-22
22-10-2002