From c946ec170d7436427877ca773e5b93b3972a61db Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Jan 2024 11:06:01 +0100 Subject: [PATCH] macOS window buttons spacing: - uninstall when switching from FlatLaf to another Laf - install when switching from another Laf to FlatLaf (for PR #779) --- .../formdev/flatlaf/ui/FlatRootPaneUI.java | 92 +++++++++++++------ .../flatlaf/ui/FullWindowContentSupport.java | 7 ++ .../flatlaf/testing/FlatMacOSTest.java | 8 ++ 3 files changed, 78 insertions(+), 29 deletions(-) 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 5664f8c7..38ccd08b 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 @@ -50,6 +50,7 @@ import javax.swing.plaf.RootPaneUI; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicRootPaneUI; import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.UIScale; @@ -107,6 +108,7 @@ public class FlatRootPaneUI installBorder(); installNativeWindowBorder(); + macInstallFullWindowContentSupport(); } protected void installBorder() { @@ -123,6 +125,7 @@ public class FlatRootPaneUI uninstallNativeWindowBorder(); uninstallClientDecorations(); + macUninstallFullWindowContentSupport(); rootPane = null; } @@ -324,6 +327,61 @@ public class FlatRootPaneUI titlePane = newTitlePane; } + private void macInstallFullWindowContentSupport() { + if( !SystemInfo.isMacOS ) + return; + + // set window buttons spacing + if( isMacButtonsSpacingSupported() && rootPane.isDisplayable() ) { + int buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_DEFAULT; + String value = (String) rootPane.getClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING ); + if( value != null ) { + switch( value ) { + case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_MEDIUM: + buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_MEDIUM; + break; + + case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_LARGE: + buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_LARGE; + break; + } + } + + FlatNativeMacLibrary.setWindowButtonsSpacing( getParentWindow(), buttonsSpacing ); + } + + // update buttons bounds client property + FullWindowContentSupport.macUpdateFullWindowContentButtonsBoundsProperty( rootPane ); + } + + private void macUninstallFullWindowContentSupport() { + if( !SystemInfo.isMacOS ) + return; + + // do not uninstall when switching to another FlatLaf theme + if( UIManager.getLookAndFeel() instanceof FlatLaf ) + return; + + // reset window buttons spacing + if( isMacButtonsSpacingSupported() ) + FlatNativeMacLibrary.setWindowButtonsSpacing( getParentWindow(), FlatNativeMacLibrary.BUTTONS_SPACING_DEFAULT ); + + // remove buttons bounds client property + FullWindowContentSupport.macUninstallFullWindowContentButtonsBoundsProperty( rootPane ); + } + + private boolean isMacButtonsSpacingSupported() { + return SystemInfo.isMacOS && SystemInfo.isJava_17_orLater && FlatNativeMacLibrary.isLoaded(); + } + + private Window getParentWindow() { + // not using SwingUtilities.windowForComponent() or SwingUtilities.getWindowAncestor() + // here because root panes may be nested and used anywhere (e.g. in JInternalFrame) + // but we're only interested in the "root" root pane, which is a direct child of the window + Container parent = rootPane.getParent(); + return (parent instanceof Window) ? (Window) parent : null; + } + @Override public void propertyChange( PropertyChangeEvent e ) { super.propertyChange( e ); @@ -388,40 +446,16 @@ public class FlatRootPaneUI // "apple.awt.fullWindowContent" or FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING // is usually done before the native window is created // --> try again when native window is created - if( !SystemInfo.isMacOS || e.getNewValue() == null ) - break; - - // fall through + if( e.getNewValue() instanceof Window ) + macInstallFullWindowContentSupport(); + break; case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING: - if( SystemInfo.isMacOS ) { - // set window buttons spacing - if( SystemInfo.isJava_17_orLater && rootPane.isDisplayable() && FlatNativeMacLibrary.isLoaded() ) { - int buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_DEFAULT; - String value = (String) rootPane.getClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING ); - if( value != null ) { - switch( value ) { - case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_MEDIUM: - buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_MEDIUM; - break; - - case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_LARGE: - buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_LARGE; - break; - } - } - - Window window = SwingUtilities.windowForComponent( rootPane ); - FlatNativeMacLibrary.setWindowButtonsSpacing( window, buttonsSpacing ); - } - - // update buttons bounds client property - FullWindowContentSupport.macUpdateFullWindowContentButtonsBoundsProperty( rootPane ); - } + macInstallFullWindowContentSupport(); break; case "apple.awt.fullWindowContent": - if( SystemInfo.isMacOS ) + if( SystemInfo.isMacFullWindowContentSupported ) FullWindowContentSupport.macUpdateFullWindowContentButtonsBoundsProperty( rootPane ); break; } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FullWindowContentSupport.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FullWindowContentSupport.java index 5665ce5c..87950f32 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FullWindowContentSupport.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FullWindowContentSupport.java @@ -172,6 +172,13 @@ class FullWindowContentSupport rootPane.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, bounds ); } + static void macUninstallFullWindowContentButtonsBoundsProperty( JRootPane rootPane ) { + if( !SystemInfo.isMacFullWindowContentSupported ) + return; + + rootPane.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, null ); + } + static void debugPaint( Graphics g, JComponent c ) { if( !UIManager.getBoolean( KEY_DEBUG_SHOW_PLACEHOLDERS ) ) return; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMacOSTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMacOSTest.java index 226392d0..d4887189 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMacOSTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMacOSTest.java @@ -75,6 +75,14 @@ public class FlatMacOSTest updateNativeButtonBounds(); } + @Override + public void updateUI() { + super.updateUI(); + + if( nativeButtonsBoundsField != null ) + updateNativeButtonBounds(); + } + private void fullWindowContentChanged() { getRootPane().putClientProperty( "apple.awt.fullWindowContent", fullWindowContentCheckBox.isSelected() ); }