From 332f05b6e13c41af81153d8fb38552b8071b83df Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Jun 2020 19:36:36 +0200 Subject: [PATCH] Window decorations: allow enabling/disabling custom window decorations via system properties "flatlaf.useWindowDecorations", "flatlaf.useJetBrainsCustomDecorations" and "flatlaf.menuBarEmbedded" (all boolean) --- .../java/com/formdev/flatlaf/FlatLaf.java | 21 ++++++++ .../formdev/flatlaf/FlatSystemProperties.java | 52 +++++++++++++++++++ .../com/formdev/flatlaf/ui/FlatTitlePane.java | 10 ++-- .../flatlaf/ui/JBRCustomDecorations.java | 16 ++++-- 4 files changed, 91 insertions(+), 8 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index 92a9a144..ff319ea2 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -88,6 +88,9 @@ public abstract class FlatLaf private Consumer postInitialization; + private Boolean oldFrameWindowDecorated; + private Boolean oldDialogWindowDecorated; + public static boolean install( LookAndFeel newLookAndFeel ) { try { UIManager.setLookAndFeel( newLookAndFeel ); @@ -242,6 +245,16 @@ public abstract class FlatLaf String.format( "a { color: #%06x; }", linkColor.getRGB() & 0xffffff ) ); } }; + + // enable/disable window decorations, but only if system property is either + // "true" or "false"; in other cases it is not changed + Boolean useWindowDecorations = FlatSystemProperties.getBooleanStrict( FlatSystemProperties.USE_WINDOW_DECORATIONS, null ); + if( useWindowDecorations != null ) { + oldFrameWindowDecorated = JFrame.isDefaultLookAndFeelDecorated(); + oldDialogWindowDecorated = JDialog.isDefaultLookAndFeelDecorated(); + JFrame.setDefaultLookAndFeelDecorated( useWindowDecorations ); + JDialog.setDefaultLookAndFeelDecorated( useWindowDecorations ); + } } @Override @@ -274,6 +287,14 @@ public abstract class FlatLaf new HTMLEditorKit().getStyleSheet().addRule( "a { color: blue; }" ); postInitialization = null; + // restore enable/disable window decorations + if( oldFrameWindowDecorated != null ) { + JFrame.setDefaultLookAndFeelDecorated( oldFrameWindowDecorated ); + JDialog.setDefaultLookAndFeelDecorated( oldDialogWindowDecorated ); + oldFrameWindowDecorated = null; + oldDialogWindowDecorated = null; + } + super.uninitialize(); } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatSystemProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatSystemProperties.java index b6cc16e0..c8a6d858 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatSystemProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatSystemProperties.java @@ -16,6 +16,9 @@ package com.formdev.flatlaf; +import javax.swing.JDialog; +import javax.swing.JFrame; + /** * Defines/documents own system properties used in FlatLaf. * @@ -46,6 +49,41 @@ public interface FlatSystemProperties */ String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"; + /** + * Specifies whether custom look and feel window decorations should be used + * when creating {@code JFrame} or {@code JDialog}. + *

+ * If this system property is set, FlatLaf invokes {@link JFrame#setDefaultLookAndFeelDecorated(boolean)} + * and {@link JDialog#setDefaultLookAndFeelDecorated(boolean)} on LaF initialization. + *

+ * Allowed Values {@code false} and {@code true}
+ * Default none + */ + String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"; + + /** + * Specifies whether JetBrains Runtime custom window decorations should be used + * when creating {@code JFrame} or {@code JDialog}. + * Requires that the application runs in a + * JetBrains Runtime + * (based on OpenJDK). + *

+ * Setting this to {@code true} forces using JetBrains Runtime custom window decorations + * even if they are not enabled by the application. + *

+ * Allowed Values {@code false} and {@code true}
+ * Default {@code true} + */ + String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"; + + /** + * Specifies whether menubar is embedded into custom window decorations. + *

+ * Allowed Values {@code false} and {@code true}
+ * Default {@code true} + */ + String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded"; + /** * Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens. *

@@ -63,4 +101,18 @@ public interface FlatSystemProperties String value = System.getProperty( key ); return (value != null) ? Boolean.parseBoolean( value ) : defaultValue; } + + /** + * Checks whether a system property is set and returns {@code Boolean.TRUE} if its value + * is {@code "true"} (case-insensitive) or returns {@code Boolean.FALSE} if its value + * is {@code "false"} (case-insensitive). Otherwise {@code defaultValue} is returned. + */ + static Boolean getBooleanStrict( String key, Boolean defaultValue ) { + String value = System.getProperty( key ); + if( "true".equalsIgnoreCase( value ) ) + return Boolean.TRUE; + if( "false".equalsIgnoreCase( value ) ) + return Boolean.FALSE; + return defaultValue; + } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java index 502f3af5..81c84c7d 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java @@ -58,6 +58,7 @@ import javax.swing.UIManager; import javax.swing.border.AbstractBorder; import javax.swing.border.Border; import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.ui.JBRCustomDecorations.JBRWindowTopBorder; import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.UIScale; @@ -320,8 +321,9 @@ class FlatTitlePane } boolean isMenuBarEmbedded() { - return menuBarEmbedded && FlatClientProperties.clientPropertyBoolean( - rootPane, FlatClientProperties.MENU_BAR_EMBEDDED, true ); + return menuBarEmbedded && + FlatClientProperties.clientPropertyBoolean( rootPane, FlatClientProperties.MENU_BAR_EMBEDDED, true ) && + FlatSystemProperties.getBoolean( FlatSystemProperties.MENUBAR_EMBEDDED, true ); } Rectangle getMenuBarBounds() { @@ -376,7 +378,7 @@ class FlatTitlePane // (if not running in JBR and if not modified from the application) if( !hasJBRCustomDecoration() && (frame.getMaximizedBounds() == null || - Objects.equals( frame.getMaximizedBounds(), rootPane.getClientProperty( "flatlaf.maximizedBounds" ) )) ) + Objects.equals( frame.getMaximizedBounds(), rootPane.getClientProperty( "_flatlaf.maximizedBounds" ) )) ) { GraphicsConfiguration gc = window.getGraphicsConfiguration(); @@ -428,7 +430,7 @@ class FlatTitlePane // remember maximized bounds in client property to be able to detect // whether maximized bounds are modified from the application - rootPane.putClientProperty( "flatlaf.maximizedBounds", maximizedBounds ); + rootPane.putClientProperty( "_flatlaf.maximizedBounds", maximizedBounds ); } // maximize window diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java index d06069f8..9054c3f4 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java @@ -39,6 +39,7 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.plaf.BorderUIResource; import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.SystemInfo; @@ -111,8 +112,10 @@ public class JBRCustomDecorations JFrame frame = (JFrame) window; // do not enable JBR decorations if JFrame should use system window decorations - if( !JFrame.isDefaultLookAndFeelDecorated() ) - return; + // and if not forced to use JBR decorations + if( !JFrame.isDefaultLookAndFeelDecorated() && + !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, false )) + return; // do not enable JBR decorations if frame is undecorated if( frame.isUndecorated() ) @@ -128,8 +131,10 @@ public class JBRCustomDecorations JDialog dialog = (JDialog) window; // do not enable JBR decorations if JDialog should use system window decorations - if( !JDialog.isDefaultLookAndFeelDecorated() ) - return; + // and if not forced to use JBR decorations + if( !JDialog.isDefaultLookAndFeelDecorated() && + !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, false )) + return; // do not enable JBR decorations if dialog is undecorated if( dialog.isUndecorated() ) @@ -189,6 +194,9 @@ public class JBRCustomDecorations if( !SystemInfo.IS_JETBRAINS_JVM_11_OR_LATER || !SystemInfo.IS_WINDOWS_10_OR_LATER ) return; + if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, true ) ) + return; + try { Class awtAcessorClass = Class.forName( "sun.awt.AWTAccessor" ); Class compAccessorClass = Class.forName( "sun.awt.AWTAccessor$ComponentAccessor" );