-
Bug
-
Resolution: Fixed
-
P3
-
8u221, 12.0.2, 13, 14
-
b10
-
x86_64
-
windows_10
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8247209 | 13.0.4 | Sergey Bylokhov | P3 | Resolved | Fixed | b05 |
JDK-8241049 | 11.0.8-oracle | Sergey Bylokhov | P3 | Resolved | Fixed | b04 |
JDK-8243374 | 11.0.8 | Sergey Bylokhov | P3 | Resolved | Fixed | b01 |
Java version from 9 to 13.
A DESCRIPTION OF THE PROBLEM :
With the follow conditions the method Frame.setMaximizedBounds() produce wrong results:
* Windows 10
* 2 monitors or more
* display scale larger 100%, for example 125%
* the monitor with the smaller resoultion must be the "main display". For example main:1280*1024 and other:1920*1080
* the app window is on the other, larger, not the main monitor.
There is no continuation in the behavior of the method. It look like that with some height value in the setted bounds there is a different calculation.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test program on a system with the given conditions and press the "toggle" button. The red cross is not in the middle of the display.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
We expected a maximize window size (not full screen). This means without the size of the task bar.
ACTUAL -
Actual the windows size is approx. 50% larger as the the monitor display. It look like some time it used the wrong GraphicsConfiguration.
---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class UndecoratedJFrame extends JFrame {
public static void main( String[] args ) {
UndecoratedJFrame frame = new UndecoratedJFrame();
frame.setVisible( true );
}
@Override
public void setExtendedState( int state ) {
if( state == MAXIMIZED_BOTH ) {
// calculate setMaximizedBounds
GraphicsConfiguration graphicsConfiguration = getGraphicsConfiguration();
Rectangle screenBounds = graphicsConfiguration.getBounds();
Insets in = getToolkit().getScreenInsets( graphicsConfiguration );
Rectangle maxBounds = new Rectangle( in.left, in.top, screenBounds.width - in.left - in.right, screenBounds.height - in.top - in.bottom );
setMaximizedBounds( maxBounds );
super.setExtendedState( MAXIMIZED_BOTH );
// since Java 9 we need calculate the scale factor because setMaximizedBounds reduce the resulting bounds with the display scale factor
Rectangle bounds = getBounds();
if( bounds.width != maxBounds.width || bounds.height != maxBounds.height ) {
double factorX = (double)maxBounds.width / bounds.width;
double factorY = (double)maxBounds.height / bounds.height;
maxBounds = new Rectangle( in.left, in.top, (int)Math.round( screenBounds.width * factorX ) - in.left - in.right, (int)Math.round( screenBounds.height * factorY ) - in.top - in.bottom );
setMaximizedBounds( maxBounds );
super.setExtendedState( ICONIFIED ); // state must change that the new MaximizedBounds is used from the GUI
SwingUtilities.invokeLater( () -> {
UndecoratedJFrame.super.setExtendedState( MAXIMIZED_BOTH );
} );
}
} else {
super.setExtendedState( state );
}
}
/**
* Create a test frame
*/
UndecoratedJFrame() {
setUndecorated( true );
setTitle( "setMaximizedBounds Test" );
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
// find a position in the other monitor
for( GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices() ) {
GraphicsConfiguration gc = gd.getDefaultConfiguration();
Rectangle gcBounds = gc.getBounds();
if( gcBounds.x != 0 || gcBounds.y != 0 ) {
setBounds( gcBounds.x + 100, gcBounds.y + 100, 250, 150 );
break;
}
}
// we use 2 buttons instead a full L&F to make it simple
// Toggle button
JButton button = new JButton( "Toggle" );
button.addActionListener( ( e ) -> {
if( getExtendedState() == MAXIMIZED_BOTH ) {
setExtendedState( NORMAL );
} else {
setExtendedState( MAXIMIZED_BOTH );
}
} );
getContentPane().add( button, BorderLayout.WEST );
// Close Button
button = new JButton( "Close" );
button.addActionListener( ( e ) -> {
dispose();
} );
getContentPane().add( button, BorderLayout.EAST );
getContentPane().add( new JComponent() {
@Override
public void paint( Graphics g ) {
super.paint( g );
// draw a red cross to see the size of the window
g.setColor( Color.RED );
g.drawLine( 0, 0, getWidth(), getHeight() );
g.drawLine( 0, getHeight(), getWidth(), 0 );
}
}, BorderLayout.CENTER );
}
}
---------- END SOURCE ----------
FREQUENCY : always
- backported by
-
JDK-8241049 setMaximizedBounds is broken with large display scale and multiple monitors
- Resolved
-
JDK-8243374 setMaximizedBounds is broken with large display scale and multiple monitors
- Resolved
-
JDK-8247209 setMaximizedBounds is broken with large display scale and multiple monitors
- Resolved
- duplicates
-
JDK-8196006 java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java fails
- Closed
- relates to
-
JDK-8263086 Inconsistent setExtendedState bounds in dual monitor setup
- Open
-
JDK-8243925 Toolkit#getScreenInsets() returns wrong value on HiDPI screens (Windows)
- Resolved
- links to