From c6d1ed91a7820848ef600f4f742f1c077bb537ad Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 13 Aug 2021 20:32:07 +0200 Subject: [PATCH] Menus: fixed missing modifiers flags in `ActionEvent` (issue #371; regression since FlatLaf 1.3) --- CHANGELOG.md | 7 +++ .../formdev/flatlaf/ui/FlatRootPaneUI.java | 52 ++++++++++++++----- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43edd683..b3c3b977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ FlatLaf Change Log - InternalFrame: Double-click on icon in internal frame title bar now closes the internal frame. (issue #374) +#### Fixed bugs + +- Menus: Fixed missing modifiers flags in `ActionEvent` (e.g. `Ctrl` key + pressed) when running in Java 9+ on Linux, macOS. Occurs also on Windows in + large popup menus that do not fit into the window. (issue #371; regression + since FlatLaf 1.3) + ## 1.5 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java index 35d50741..1209b6c8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java @@ -27,9 +27,11 @@ import java.awt.Insets; import java.awt.LayoutManager; import java.awt.LayoutManager2; import java.awt.Window; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.function.Function; import javax.swing.JComponent; import javax.swing.JDialog; @@ -38,6 +40,7 @@ import javax.swing.JLayeredPane; import javax.swing.JMenuBar; import javax.swing.JRootPane; import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.BorderUIResource; @@ -81,7 +84,8 @@ public class FlatRootPaneUI private Object nativeWindowBorderData; private LayoutManager oldLayout; - private HierarchyListener hierarchyListener; + private PropertyChangeListener ancestorListener; + private ComponentListener componentListener; public static ComponentUI createUI( JComponent c ) { return new FlatRootPaneUI(); @@ -149,16 +153,32 @@ public class FlatRootPaneUI // This is very disturbing in dark themes, but hard to notice in light themes. // Seems to be a rounding issue when Swing adds dirty region of window // using RepaintManager.nativeAddDirtyRegion(). - hierarchyListener = e -> { - if( (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 && - rootPane.getParent() instanceof Window ) - { - // add whole root pane to dirty regions when window is initially shown - rootPane.getParent().repaint( rootPane.getX(), rootPane.getY(), - rootPane.getWidth(), rootPane.getHeight() ); + // + // Note: Not using a HierarchyListener here, which would be much easier, + // because this causes problems with mouse clicks in heavy-weight popups. + // Instead, add a listener to the root pane that waits until it is added + // to a window, then add a component listener to the window. + // See: https://github.com/JFormDesigner/FlatLaf/issues/371 + ancestorListener = e -> { + Object oldValue = e.getOldValue(); + Object newValue = e.getNewValue(); + if( newValue instanceof Window ) { + if( componentListener == null ) { + componentListener = new ComponentAdapter() { + @Override + public void componentShown( ComponentEvent e ) { + // add whole root pane to dirty regions when window is initially shown + root.getParent().repaint( root.getX(), root.getY(), root.getWidth(), root.getHeight() ); + } + }; + } + ((Window)newValue).addComponentListener( componentListener ); + } else if( newValue == null && oldValue instanceof Window ) { + if( componentListener != null ) + ((Window)oldValue).removeComponentListener( componentListener ); } }; - root.addHierarchyListener( hierarchyListener ); + root.addPropertyChangeListener( "ancestor", ancestorListener ); } } @@ -167,8 +187,14 @@ public class FlatRootPaneUI super.uninstallListeners( root ); if( SystemInfo.isJava_9_orLater ) { - root.removeHierarchyListener( hierarchyListener ); - hierarchyListener = null; + if( componentListener != null ) { + Window window = SwingUtilities.windowForComponent( root ); + if( window != null ) + window.removeComponentListener( componentListener ); + componentListener = null; + } + root.removePropertyChangeListener( "ancestor", ancestorListener ); + ancestorListener = null; } }