JDK-4868278 : Problem with Action button tooltips with some multiple monitor configurations
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0,1.4.2,1.4.2_06,6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2003-05-22
  • Updated: 2013-07-15
  • Resolved: 2005-03-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u5Fixed 6 b27Fixed
Related Reports
Duplicate :  
Duplicate :  
Description
Name: rmT116609			Date: 05/22/2003


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

java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)


FULL OS VERSION :
Windows XP Version 5.1.2600

EXTRA RELEVANT SYSTEM CONFIGURATION :
The problem occurs with XP running with certain multiple monitor configurations.

The easiest multiple monitor setup to test with, is using a laptop with dual monitor support which has an external monitor hooked up to it where the combined screens of the LCD laptop monitor and the external monitor are in use.

The external monitor should be on the left hand side of the laptop, and the windows XP display properties should be set up so that "monitor 1" (the laptop lcd) is on the right of "monitor 2".

A DESCRIPTION OF THE PROBLEM :
Basically the problem occurs with dialog with buttons that have been added using Action classes.

If the window is initially displayed on the non-primary display (the LHS of the above setup), then tooltips for the buttons are displayed on the far left of the right hand side (primary) display. The problem goes away once the dialog is moved with the mouse to the right hand display and then back to the left hand display.

I've had a look at the code for ToolTipManager, and in showTipWindow(..) the bounds used to restrain the tool tip position are obtained using :

Rectangle sBounds = insideComponent.getGraphicsConfiguration().                                getBounds();

Unfortunately, this gives the bounds of the primary display at this point in time, rather than the bounds of the left hand display in which the dialog has been displayed.


I think what is happening, is that when a Window is initially displayed on the non-primary screen, the window.getGraphicsConfiguration() is returning the default GraphicsConfiguration, and this is not updated until the window is
moved back to the primary display and away from it again.

Also I meant to mention in the bug report, that this problem does not occur when tested on an NT PC with a Matrox dual head graphics card connected to two monitors. With this setup, the combined workspace of the two monitors is treated as a single graphics configuration.

I've included a simple code example that will demonstrate the problem below.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the simple java code included below.

java -cp . testToolTips

This displays a dialog with some text and a simple button on the left hand display.

Hover you mouse over the button.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the tool tip to be displayed near the button it belongs to, which is displayed on the left hand display (external monitor.)
ACTUAL -
The tool tip appears on  the left hand edge of the primary (righthand/laptop) display.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class testToolTips
{
	
	// Create action class for button.
	protected static Action action = new AbstractAction("Press this button to exit..",null)
	{
		// javadoc from java.awt.event.ActionListener
		public void actionPerformed(ActionEvent ae)
		{
			System.out.println("Button pressed, so we are exiting....");
			System.exit(0);
		}
	};

	public static void main(String[] args)
	{
	
		Rectangle virtualBounds = getScreenBounds();
	
		System.out.println("Hello there");
	
		// Set windows look and feel.
		try
		{
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (Throwable t)
		{
		}
	 
		// create toolBar
		JToolBar toolBar = new JToolBar();

		// add button to tool bar
		JButton button = toolBar.add(action);

		// set tooltip text on button
		button.setToolTipText((String)action.getValue(Action.NAME));
		
		// create text area
		JTextArea text = new JTextArea("Hello! Check out the tool tip and see \nif it is drawn on the on primary display.");

		// create dialog and add the tool bar and text
		JDialog dialog = new JDialog();
		dialog.getContentPane().add(toolBar, BorderLayout.NORTH);
		dialog.getContentPane().add(text, BorderLayout.CENTER);

		// position on dialog on the left hand display (assuming 2 screens)
		dialog.setBounds(virtualBounds.x + virtualBounds.width/4, virtualBounds.y + virtualBounds.height/4,virtualBounds.width/4,virtualBounds.height/4);
	
		// display the dialog.
		dialog.show();

                // This prints out the wrong bounds for where the dialog is located, and this is the exactCode used in ToolTipManager.showTipWindow()
		System.out.println(" dialogs graphics config bounds are " + dialog.getGraphicsConfiguration().getBounds());

	}



	static public Rectangle getScreenBounds()
	{
		Rectangle virtualBounds = new Rectangle();
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		GraphicsDevice[] gs = ge.getScreenDevices();
		for (int j = 0; j < gs.length; j++) {
			GraphicsDevice gd = gs[j];
			GraphicsConfiguration[] gc = gd.getConfigurations();
			for (int i=0; i < gc.length; i++) {
				virtualBounds = virtualBounds.union(gc[i].getBounds());
			}
		}
		System.out.println("Virtual bounds are " + virtualBounds);
		return virtualBounds;
	}

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
It basically makes our software look unprofessional when used with this particular monitor set up.
(Review ID: 186322) 
======================================================================

Also note that this problem causes a severe performance penalty, as reported in duplicate bug 6231735.

###@###.### 2005-05-25 14:37:27 GMT

Comments
EVALUATION Reproducible as described on Windows 2000 using 1.4.1 and 1.4.2b24. This problem did not occur with 1.4 or 1.3.1. ###@###.### 2003-05-22 As suggested, the mechanism for updating the Dialog's GraphicsConfiguration is not being triggered if the Dialog first appears on a device with negative coordinates. A workaround which avoids the problem is to call pack() on the Dialog before calling setBounds(). This creates the native resources for the Dialog. In this case when setBounds() is called, the Dialog's GraphicsConfiguration is updated and the app behaves as expected. Special thanks to the submitter for a very well written bug report. =) ###@###.### 2003-05-22 The submitter reports that for resizable frames, one must call: pack(); setResizable(false); setResizable(true); setBounds(...); ###@###.### 2003-06-03 If we create a window with a specific GraphicsConfig, and then move it with setLocation() or setBounds() to another one before its peer has been created, then calling Window.getGraphicsConfig() returns wrong config. That may lead to some problems like wrong-placed tooltips. It is caused by calling super.displayChanged() in WWindowPeer.displayChanged() regardless of whether GraphicsDevice was really changed, or not. We should track this issue, when the window is shown. ###@###.### 2005-05-24 06:52:10 GMT It is worth noting the performance problem/fix here as well (as reported in duplicate bug 6231735); if we create rendering resources one one GraphicsDevice that for peers that are actually on a different device, then performance can be pretty awful as we cause the system to copy from the video memory of one device to another (causing all kinds of performance problems such as reading from VRAM and copying the pixels up the bus, through the CPU, and down the bus to the other device). Fixing the problem of tooltips for this bug report also fixes the performance problem because we are now creating the rendering resources on the correct device when the peer is shown. The fix here is to update the graphicsConfig object appropriately in the show() method of the peer to ensure that it is correct for the device where the peer is appearing. ###@###.### 2005-05-25 14:37:27 GMT
25-05-2005

SUGGESTED FIX In bried, the fix can be described as - update peer's graphics config in WWindowPeer.show() ###@###.### 2005-05-24 06:52:11 GMT
24-05-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
21-08-2004

WORK AROUND Call pack() before setBounds(): // create dialog and add the tool bar and text JDialog dialog = new JDialog(); dialog.getContentPane().add(toolBar, BorderLayout.NORTH); dialog.getContentPane().add(text, BorderLayout.CENTER); + dialog.pack(); // position on dialog on the left hand display (assuming 2 screens) dialog.setBounds(virtualBounds.x + virtualBounds.width/4, virtualBounds.y + virtualBounds.height/4,virtualBounds.width/4,virtualBounds.height/4); // display the dialog. dialog.show(); ###@###.### 2003-05-22
22-05-2003