Popup: popups that request focus were not shown on Linux with Wayland and Java 21 (issue #752)

This commit is contained in:
Karl Tauber
2023-10-21 17:04:22 +02:00
parent 0d2f37e1da
commit 5c56dbfed6
2 changed files with 43 additions and 0 deletions

View File

@@ -1,6 +1,14 @@
FlatLaf Change Log
==================
## 3.2.3
#### Fixed bugs
- Popup: Popups that request focus were not shown on Linux with Wayland and Java 21.
(issue #752)
## 3.2.2
#### Fixed bugs

View File

@@ -36,6 +36,7 @@ import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowFocusListener;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@@ -83,6 +84,8 @@ public class FlatPopupFactory
y = pt.y;
}
fixLinuxWaylandJava21focusIssue( owner );
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" );
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector || SystemInfo.isWebswing )
@@ -420,6 +423,38 @@ public class FlatPopupFactory
return false;
}
/**
* On Linux with Wayland, since Java 21, Swing adds a window focus listener to popup owner/invoker window,
* which hides the popup as soon as the owner/invoker window looses focus.
* This works fine for light-weight popups.
* It also works for heavy-weight popups if the do not request focus.
* Because FlatLaf always uses heavy-weight popups, all popups that request focus
* are broken since Java 21.
*
* This method removes the problematic window focus listener.
*
* https://bugs.openjdk.org/browse/JDK-8280993
* https://github.com/openjdk/jdk/pull/13830
*/
private static void fixLinuxWaylandJava21focusIssue( Component owner ) {
// only necessary on Linux when running in Java 21+
if( !SystemInfo.isLinux || SystemInfo.javaVersion < SystemInfo.toVersion( 21, 0, 0, 0 ) )
return;
// get window
Window window = SwingUtilities.getWindowAncestor( owner );
if( window == null )
return;
// remove window focus listener, which was added from class sun.awt.UNIXToolkit since Java 21
for( WindowFocusListener l : window.getWindowFocusListeners() ) {
if( "sun.awt.UNIXToolkit$1".equals( l.getClass().getName() ) ) {
window.removeWindowFocusListener( l );
break;
}
}
}
//---- class NonFlashingPopup ---------------------------------------------
private static class NonFlashingPopup