-
Notifications
You must be signed in to change notification settings - Fork 233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Always on top frames and dialogs BUG #676
Comments
I'm still not sure what exactly doesn't work:
What does "this ability" mean? Which ability? Of staying always on top? Here is an example I've tried and it works properly for me: public class Example
{
public static void main ( final String[] args )
{
SwingTest.run ( () -> {
final WebFrame<?> frame = new WebFrame<> ( "Frame" );
frame.setAlwaysOnTop ( true );
frame.setLayout ( new FlowLayout () );
final JButton button = new JButton ( "Show popup" );
button.addActionListener ( e -> {
final WebPopup<?> popup = new WebPopup<> ();
final JLabel label = new JLabel ( "Sample label", SwingConstants.CENTER );
label.setBorder ( BorderFactory.createEmptyBorder ( 50, 50, 50, 50 ) );
popup.add ( label );
popup.setResizable ( true );
popup.showPopup ( button, button.getWidth () / 2 - popup.getPreferredSize ().width / 2, button.getHeight () );
} );
frame.add ( button );
frame.setSize ( 200, 200 );
frame.setLocationRelativeTo ( null );
frame.setDefaultCloseOperation ( WindowConstants.EXIT_ON_CLOSE );
frame.setVisible ( true );
} );
}
} Popup is displayed correctly above the frame: Frame stays "always on top" even after popup being displayed/closed multiple times. |
Things that may help me to find the issue faster:
|
Mikle, my english is not so good, so I decided to speak on russian with another russian man)). I make small video with sound. Take a look on it. My problem is that always on top window or dialog become an NON-always on top after any WebPopup open call... 2021-10-09.19-28-33.1.mp4OS: Windows 10, |
Thanks for the in-depth showcase! I was able to reproduce and track down this issue and... it seems to be a weird interaction of non-always-on-top popup with always-on-top parent. The thing here is - even though in my example I'll list all the details below (mostly for myself to keep track of such nuance issues) and a TL;DR at the end. Here are the things I've found while investigating this problem:
private void ownedInit(Window owner) {
this.parent = owner;
if (owner != null) {
owner.addOwnedWindow(weakThis);
if (owner.isAlwaysOnTop()) {
try {
setAlwaysOnTop(true);
} catch (SecurityException ignore) {
}
}
}
// WindowDisposerRecord requires a proper value of parent field.
disposerRecord.updateOwner();
}
// Updating window settings
window.setCloseOnFocusLoss ( isCloseOnFocusLoss () );
window.setAlwaysOnTop ( isAlwaysOnTop () );
Here is practical example in regards to (4): public class Example
{
public static void main ( final String[] args )
{
SwingUtilities.invokeLater ( () -> {
final JFrame frame = new JFrame ( "Frame" );
frame.setAlwaysOnTop ( true );
frame.setLayout ( new FlowLayout () );
final JButton button = new JButton ( "Show popup" );
button.addActionListener ( e -> {
final JWindow popup = new JWindow ( frame );
final JLabel label = new JLabel ( "Sample label", SwingConstants.CENTER );
label.setBorder (
BorderFactory.createCompoundBorder (
BorderFactory.createLineBorder ( Color.BLACK ),
BorderFactory.createEmptyBorder ( 50, 50, 50, 50 )
)
);
popup.getContentPane ().add ( label );
// Resetting it here won't reset it for JFrame
popup.setAlwaysOnTop ( false ); // <---------- works as expected
final Point los = CoreSwingUtils.locationOnScreen ( button );
popup.pack ();
// Resetting it here will reset it for JFrame because native window is now initialized via pack() call
// popup.setAlwaysOnTop ( false ); // <---------- will cause parent window to lose always-on-top property
popup.setLocation ( los.x + button.getWidth () / 2 - popup.getPreferredSize ().width / 2, los.y + button.getHeight () );
popup.setVisible ( true );
// Resetting it here will also reset it for JFrame because native window is now initialized via setVisible(true) call
// popup.setAlwaysOnTop ( false ); // <---------- will cause parent window to lose always-on-top property
System.out.println ( "frame.isAlwaysOnTop = " + frame.isAlwaysOnTop () );
System.out.println ( "popup.isAlwaysOnTop = " + popup.isAlwaysOnTop () );
} );
frame.add ( button );
frame.setSize ( 200, 200 );
frame.setLocationRelativeTo ( null );
frame.setDefaultCloseOperation ( WindowConstants.EXIT_ON_CLOSE );
frame.setVisible ( true );
} );
}
} There are 3 lines here that change popup's always-on-top property - if you uncomment and try each one of them separately (other two need to be commented out) you will see that first one doesn't cause an issue and other two do. DisplayabilityI've mentioned in the notes above that updating the always-on-top property will only cause issues when
/**
* Makes this Window displayable by creating the connection to its
* native screen resource.
* This method is called internally by the toolkit and should
* not be called directly by programs.
* @see Component#isDisplayable
* @see Container#removeNotify
* @since JDK1.0
*/
public void addNotify() {
synchronized (getTreeLock()) {
Container parent = this.parent;
if (parent != null && parent.getPeer() == null) {
parent.addNotify();
}
if (peer == null) {
peer = getToolkit().createWindow(this);
}
synchronized (allWindows) {
allWindows.add(this);
}
super.addNotify();
}
} This can normally be called only via two methods in Why it matters in the context of this issue is because once I can only guess that native code part of I'll try to check whether this issue persists on other Java versions later, but it is definitely there on all (seemingly) Java 8 versions. If it exists in later versions as well - I will probably submit a JDK bug report based on this find. TL;DRThis issue may happen in common Swing as well, but usually won't because you usually don't change always-on-top property for popups and it is simply inherited from parent by default. So this is definitely a WebLaF problem, specifically with how I'll fix this by adjusting order of operations during Meanwhile, the easiest fix you can do - simply set the public class Example
{
public static void main ( final String[] args )
{
SwingTest.run ( () -> {
final WebFrame<?> frame = new WebFrame<> ( "Frame" );
frame.setAlwaysOnTop ( true );
frame.setLayout ( new FlowLayout () );
final JButton button = new JButton ( "Show popup" );
button.addActionListener ( e -> {
final WebPopup<?> popup = new WebPopup<> ();
popup.setAlwaysOnTop ( true );
final JLabel label = new JLabel ( "Sample label", SwingConstants.CENTER );
label.setBorder ( BorderFactory.createEmptyBorder ( 50, 50, 50, 50 ) );
popup.add ( label );
popup.setResizable ( true );
popup.showPopup ( button, button.getWidth () / 2 - popup.getPreferredSize ().width / 2, button.getHeight () );
} );
frame.add ( button );
frame.setSize ( 200, 200 );
frame.setLocationRelativeTo ( null );
frame.setDefaultCloseOperation ( WindowConstants.EXIT_ON_CLOSE );
frame.setVisible ( true );
} );
}
} |
WebFrame and WebDialog with always on top function set to true loose this ability in case of any single fire of WebPopup placed on window. I found an crutch - makesetVisible(false) and setVisible(true) calls for window.
The text was updated successfully, but these errors were encountered: