Native window decorations: support disabling native window decorations per window via client property (issue #277)

This commit is contained in:
Karl Tauber
2021-03-23 13:18:07 +01:00
parent eabb052107
commit fe1e364a1d
5 changed files with 56 additions and 0 deletions

View File

@@ -3,6 +3,12 @@ FlatLaf Change Log
## 1.2-SNAPSHOT ## 1.2-SNAPSHOT
#### New features and improvements
- Native window decorations: Support disabling native window decorations per
window. (set client property `JRootPane.useWindowDecorations` to `false` on
root pane).
#### Fixed bugs #### Fixed bugs
- Native window decorations: Fixed double window title bar when first disposing - Native window decorations: Fixed double window title bar when first disposing

View File

@@ -231,10 +231,28 @@ public interface FlatClientProperties
//---- JRootPane ---------------------------------------------------------- //---- JRootPane ----------------------------------------------------------
/**
* Specifies whether FlatLaf native window decorations should be used
* when creating {@code JFrame} or {@code JDialog}.
* <p>
* Setting this to {@code false} disables using FlatLaf native window decorations
* for the window that contains the root pane. Needs to be set before showing the window.
* <p>
* (requires Window 10)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*
* @since 1.1.1
*/
String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations";
/** /**
* Specifies whether the menu bar is embedded into the title pane if custom * Specifies whether the menu bar is embedded into the title pane if custom
* window decorations are enabled. Default is {@code true}. * window decorations are enabled. Default is {@code true}.
* <p> * <p>
* (requires Window 10)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
*/ */

View File

@@ -27,6 +27,7 @@ import javax.swing.JRootPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.ui.JBRCustomDecorations.JBRWindowTopBorder; import com.formdev.flatlaf.ui.JBRCustomDecorations.JBRWindowTopBorder;
@@ -99,6 +100,10 @@ public class FlatNativeWindowBorder
if( window instanceof JFrame ) { if( window instanceof JFrame ) {
JFrame frame = (JFrame) window; JFrame frame = (JFrame) window;
// check whether disabled via client property
if( !FlatClientProperties.clientPropertyBoolean( frame.getRootPane(), FlatClientProperties.USE_WINDOW_DECORATIONS, true ) )
return;
// do not enable native window border if JFrame should use system window decorations // do not enable native window border if JFrame should use system window decorations
// and if not forced to use FlatLaf/JBR native window decorations // and if not forced to use FlatLaf/JBR native window decorations
if( !JFrame.isDefaultLookAndFeelDecorated() && if( !JFrame.isDefaultLookAndFeelDecorated() &&
@@ -119,6 +124,10 @@ public class FlatNativeWindowBorder
} else if( window instanceof JDialog ) { } else if( window instanceof JDialog ) {
JDialog dialog = (JDialog) window; JDialog dialog = (JDialog) window;
// check whether disabled via client property
if( !FlatClientProperties.clientPropertyBoolean( dialog.getRootPane(), FlatClientProperties.USE_WINDOW_DECORATIONS, true ) )
return;
// do not enable native window border if JDialog should use system window decorations // do not enable native window border if JDialog should use system window decorations
// and if not forced to use FlatLaf/JBR native window decorations // and if not forced to use FlatLaf/JBR native window decorations
if( !JDialog.isDefaultLookAndFeelDecorated() && if( !JDialog.isDefaultLookAndFeelDecorated() &&

View File

@@ -28,6 +28,7 @@ import java.util.WeakHashMap;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel; import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatDarculaLaf; import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf; import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf; import com.formdev.flatlaf.FlatIntelliJLaf;
@@ -303,6 +304,12 @@ public class FlatNativeWindowBorderTest
FlatNativeWindowBorder.setHasCustomDecoration( window, nativeCheckBox.isSelected() ); FlatNativeWindowBorder.setHasCustomDecoration( window, nativeCheckBox.isSelected() );
} }
private void native2Changed() {
((RootPaneContainer)window).getRootPane().putClientProperty( FlatClientProperties.USE_WINDOW_DECORATIONS, native2CheckBox.isSelected() );
window.dispose();
window.setVisible( true );
}
private void revalidateLayout() { private void revalidateLayout() {
window.revalidate(); window.revalidate();
} }
@@ -372,6 +379,7 @@ public class FlatNativeWindowBorderTest
undecoratedCheckBox = new JCheckBox(); undecoratedCheckBox = new JCheckBox();
fullScreenCheckBox = new JCheckBox(); fullScreenCheckBox = new JCheckBox();
nativeCheckBox = new JCheckBox(); nativeCheckBox = new JCheckBox();
native2CheckBox = new JCheckBox();
openDialogButton = new JButton(); openDialogButton = new JButton();
hideWindowButton = new JButton(); hideWindowButton = new JButton();
reopenButton = new JButton(); reopenButton = new JButton();
@@ -433,6 +441,12 @@ public class FlatNativeWindowBorderTest
nativeCheckBox.addActionListener(e -> nativeChanged()); nativeCheckBox.addActionListener(e -> nativeChanged());
add(nativeCheckBox, "cell 0 3 3 1"); add(nativeCheckBox, "cell 0 3 3 1");
//---- native2CheckBox ----
native2CheckBox.setText("JRootPane.useWindowDecorations");
native2CheckBox.setSelected(true);
native2CheckBox.addActionListener(e -> native2Changed());
add(native2CheckBox, "cell 0 3 3 1");
//---- openDialogButton ---- //---- openDialogButton ----
openDialogButton.setText("Open Dialog"); openDialogButton.setText("Open Dialog");
openDialogButton.setMnemonic('D'); openDialogButton.setMnemonic('D');
@@ -490,6 +504,7 @@ public class FlatNativeWindowBorderTest
private JCheckBox undecoratedCheckBox; private JCheckBox undecoratedCheckBox;
private JCheckBox fullScreenCheckBox; private JCheckBox fullScreenCheckBox;
private JCheckBox nativeCheckBox; private JCheckBox nativeCheckBox;
private JCheckBox native2CheckBox;
private JButton openDialogButton; private JButton openDialogButton;
private JButton hideWindowButton; private JButton hideWindowButton;
private JButton reopenButton; private JButton reopenButton;

View File

@@ -65,6 +65,14 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1" "value": "cell 0 3 3 1"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "native2CheckBox"
"text": "JRootPane.useWindowDecorations"
"selected": true
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "native2Changed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "openDialogButton" name: "openDialogButton"
"text": "Open Dialog" "text": "Open Dialog"