From 5c56dbfed6cf3d5e6809fc02f9c00b9b4f265249 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 21 Oct 2023 17:04:22 +0200 Subject: [PATCH] Popup: popups that request focus were not shown on Linux with Wayland and Java 21 (issue #752) --- CHANGELOG.md | 8 +++++ .../formdev/flatlaf/ui/FlatPopupFactory.java | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec69eb7..73898d62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java index 04b2d16b..80c24812 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java @@ -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