mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 15:07:11 -06:00
Native window decorations:
- API to check whether current platform supports window decorations `FlatLaf.supportsNativeWindowDecorations()` - API to toggle window decorations of all windows `FlatLaf.setUseNativeWindowDecorations(boolean)` - `FlatClientProperties.USE_WINDOW_DECORATIONS` can now used to toggle window decorations for single window - cleaned-up/fixed/simplified window decorations "enabled" checking: 1. if `FlatSystemProperties.USE_WINDOW_DECORATIONS` is set, its value is used 2. if `FlatClientProperties.USE_WINDOW_DECORATIONS` is set, its value is used 3. use value of UI default `TitlePane.useWindowDecorations`
This commit is contained in:
@@ -233,10 +233,14 @@ public interface FlatClientProperties
|
||||
|
||||
/**
|
||||
* Specifies whether FlatLaf native window decorations should be used
|
||||
* when creating {@code JFrame} or {@code JDialog}.
|
||||
* for {@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.
|
||||
* Setting this enables/disables using FlatLaf native window decorations
|
||||
* for the window that contains the root pane.
|
||||
* <p>
|
||||
* This client property has lower priority than system property
|
||||
* {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority
|
||||
* than UI default {@code TitlePane.useWindowDecorations}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* <p>
|
||||
|
||||
@@ -46,6 +46,7 @@ import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.RootPaneContainer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIDefaults.ActiveValue;
|
||||
@@ -59,6 +60,7 @@ import javax.swing.text.StyleContext;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
|
||||
import com.formdev.flatlaf.ui.FlatPopupFactory;
|
||||
import com.formdev.flatlaf.ui.FlatRootPaneUI;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
@@ -715,6 +717,79 @@ public abstract class FlatLaf
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether native window decorations are supported on current platform.
|
||||
* <p>
|
||||
* This requires Windows 10, but may be disabled if running in special environments
|
||||
* (JetBrains Projector, Webswing or WinPE) or if loading native library fails.
|
||||
* If system property {@link FlatSystemProperties#USE_WINDOW_DECORATIONS} is set to
|
||||
* {@code false}, then this method also returns {@code false}.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static boolean supportsNativeWindowDecorations() {
|
||||
return SystemInfo.isWindows_10_orLater && FlatNativeWindowBorder.isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether native window decorations are enabled.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static boolean isUseNativeWindowDecorations() {
|
||||
return UIManager.getBoolean( "TitlePane.useWindowDecorations" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether native window decorations are enabled.
|
||||
* <p>
|
||||
* Existing frames and dialogs will be updated.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static void setUseNativeWindowDecorations( boolean enabled ) {
|
||||
UIManager.put( "TitlePane.useWindowDecorations", enabled );
|
||||
|
||||
if( !(UIManager.getLookAndFeel() instanceof FlatLaf) )
|
||||
return;
|
||||
|
||||
// update existing frames and dialogs
|
||||
for( Window w : Window.getWindows() ) {
|
||||
if( isDisplayableFrameOrDialog( w ) )
|
||||
FlatRootPaneUI.updateNativeWindowBorder( ((RootPaneContainer)w).getRootPane() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revalidate and repaint all displayable frames and dialogs.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static void revalidateAndRepaintAllFramesAndDialogs() {
|
||||
for( Window w : Window.getWindows() ) {
|
||||
if( isDisplayableFrameOrDialog( w ) ) {
|
||||
w.revalidate();
|
||||
w.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaint all displayable frames and dialogs.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static void repaintAllFramesAndDialogs() {
|
||||
for( Window w : Window.getWindows() ) {
|
||||
if( isDisplayableFrameOrDialog( w ) )
|
||||
w.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDisplayableFrameOrDialog( Window w ) {
|
||||
return w.isDisplayable() && (w instanceof JFrame || w instanceof JDialog);
|
||||
}
|
||||
|
||||
public static boolean isShowMnemonics() {
|
||||
return MnemonicHandler.isShowMnemonics();
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ public interface FlatSystemProperties
|
||||
* <p>
|
||||
* Setting this to {@code false} disables using FlatLaf native window decorations.
|
||||
* <p>
|
||||
* This system property has higher priority than client property
|
||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||
* UI default {@code TitlePane.useWindowDecorations}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
|
||||
@@ -99,18 +99,12 @@ public class FlatNativeWindowBorder
|
||||
|
||||
if( window instanceof JFrame ) {
|
||||
JFrame frame = (JFrame) window;
|
||||
JRootPane rootPane = frame.getRootPane();
|
||||
|
||||
// check whether disabled via client property
|
||||
if( !FlatClientProperties.clientPropertyBoolean( frame.getRootPane(), FlatClientProperties.USE_WINDOW_DECORATIONS, true ) )
|
||||
// check whether disabled via system property, client property or UI default
|
||||
if( !useWindowDecorations( rootPane, systemPropertyKey ) )
|
||||
return;
|
||||
|
||||
// do not enable native window border if JFrame should use system window decorations
|
||||
// and if not forced to use FlatLaf/JBR native window decorations
|
||||
if( !JFrame.isDefaultLookAndFeelDecorated() &&
|
||||
!UIManager.getBoolean( "TitlePane.useWindowDecorations" ) &&
|
||||
!FlatSystemProperties.getBoolean( systemPropertyKey, false ) )
|
||||
return;
|
||||
|
||||
// do not enable native window border if frame is undecorated
|
||||
if( frame.isUndecorated() )
|
||||
return;
|
||||
@@ -119,22 +113,16 @@ public class FlatNativeWindowBorder
|
||||
setHasCustomDecoration( frame, true );
|
||||
|
||||
// enable Swing window decoration
|
||||
frame.getRootPane().setWindowDecorationStyle( JRootPane.FRAME );
|
||||
rootPane.setWindowDecorationStyle( JRootPane.FRAME );
|
||||
|
||||
} else if( window instanceof JDialog ) {
|
||||
JDialog dialog = (JDialog) window;
|
||||
JRootPane rootPane = dialog.getRootPane();
|
||||
|
||||
// check whether disabled via client property
|
||||
if( !FlatClientProperties.clientPropertyBoolean( dialog.getRootPane(), FlatClientProperties.USE_WINDOW_DECORATIONS, true ) )
|
||||
// check whether disabled via system property, client property or UI default
|
||||
if( !useWindowDecorations( rootPane, systemPropertyKey ) )
|
||||
return;
|
||||
|
||||
// do not enable native window border if JDialog should use system window decorations
|
||||
// and if not forced to use FlatLaf/JBR native window decorations
|
||||
if( !JDialog.isDefaultLookAndFeelDecorated() &&
|
||||
!UIManager.getBoolean( "TitlePane.useWindowDecorations" ) &&
|
||||
!FlatSystemProperties.getBoolean( systemPropertyKey, false ) )
|
||||
return;
|
||||
|
||||
// do not enable native window border if dialog is undecorated
|
||||
if( dialog.isUndecorated() )
|
||||
return;
|
||||
@@ -143,7 +131,7 @@ public class FlatNativeWindowBorder
|
||||
setHasCustomDecoration( dialog, true );
|
||||
|
||||
// enable Swing window decoration
|
||||
dialog.getRootPane().setWindowDecorationStyle( JRootPane.PLAIN_DIALOG );
|
||||
rootPane.setWindowDecorationStyle( JRootPane.PLAIN_DIALOG );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,12 +141,15 @@ public class FlatNativeWindowBorder
|
||||
return;
|
||||
}
|
||||
|
||||
if( !isSupported() )
|
||||
return;
|
||||
|
||||
// remove listener
|
||||
if( data instanceof PropertyChangeListener )
|
||||
rootPane.removePropertyChangeListener( "ancestor", (PropertyChangeListener) data );
|
||||
|
||||
// do not uninstall when switching to another FlatLaf theme
|
||||
if( UIManager.getLookAndFeel() instanceof FlatLaf )
|
||||
// do not uninstall when switching to another FlatLaf theme and if still enabled
|
||||
if( UIManager.getLookAndFeel() instanceof FlatLaf && useWindowDecorations( rootPane, FlatSystemProperties.USE_WINDOW_DECORATIONS ) )
|
||||
return;
|
||||
|
||||
// uninstall native window border
|
||||
@@ -188,6 +179,20 @@ public class FlatNativeWindowBorder
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean useWindowDecorations( JRootPane rootPane, String systemPropertyKey ) {
|
||||
// check whether forced to enabled/disabled via system property
|
||||
Boolean enabled = FlatSystemProperties.getBooleanStrict( systemPropertyKey, null );
|
||||
if( enabled != null )
|
||||
return enabled;
|
||||
|
||||
// check whether forced to enabled/disabled via client property
|
||||
enabled = FlatClientProperties.clientPropertyBooleanStrict( rootPane, FlatClientProperties.USE_WINDOW_DECORATIONS, null );
|
||||
if( enabled != null )
|
||||
return enabled;
|
||||
|
||||
return UIManager.getBoolean( "TitlePane.useWindowDecorations" );
|
||||
}
|
||||
|
||||
public static boolean hasCustomDecoration( Window window ) {
|
||||
if( canUseJBRCustomDecorations )
|
||||
return JBRCustomDecorations.hasCustomDecoration( window );
|
||||
|
||||
@@ -95,7 +95,7 @@ public class FlatRootPaneUI
|
||||
else
|
||||
installBorder();
|
||||
|
||||
nativeWindowBorderData = FlatNativeWindowBorder.install( rootPane );
|
||||
installNativeWindowBorder();
|
||||
}
|
||||
|
||||
protected void installBorder() {
|
||||
@@ -110,8 +110,7 @@ public class FlatRootPaneUI
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
|
||||
FlatNativeWindowBorder.uninstall( rootPane, nativeWindowBorderData );
|
||||
|
||||
uninstallNativeWindowBorder();
|
||||
uninstallClientDecorations();
|
||||
rootPane = null;
|
||||
}
|
||||
@@ -137,6 +136,34 @@ public class FlatRootPaneUI
|
||||
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.1.2
|
||||
*/
|
||||
protected void installNativeWindowBorder() {
|
||||
nativeWindowBorderData = FlatNativeWindowBorder.install( rootPane );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.1.2
|
||||
*/
|
||||
protected void uninstallNativeWindowBorder() {
|
||||
FlatNativeWindowBorder.uninstall( rootPane, nativeWindowBorderData );
|
||||
nativeWindowBorderData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static void updateNativeWindowBorder( JRootPane rootPane ) {
|
||||
RootPaneUI rui = rootPane.getUI();
|
||||
if( !(rui instanceof FlatRootPaneUI) )
|
||||
return;
|
||||
|
||||
FlatRootPaneUI ui = (FlatRootPaneUI) rui;
|
||||
ui.uninstallNativeWindowBorder();
|
||||
ui.installNativeWindowBorder();
|
||||
}
|
||||
|
||||
protected void installClientDecorations() {
|
||||
boolean isNativeWindowBorderSupported = FlatNativeWindowBorder.isSupported();
|
||||
|
||||
@@ -218,6 +245,10 @@ public class FlatRootPaneUI
|
||||
installBorder();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.USE_WINDOW_DECORATIONS:
|
||||
updateNativeWindowBorder( rootPane );
|
||||
break;
|
||||
|
||||
case FlatClientProperties.MENU_BAR_EMBEDDED:
|
||||
if( titlePane != null ) {
|
||||
titlePane.menuBarChanged();
|
||||
|
||||
Reference in New Issue
Block a user