more fixes for AWT components on macOS (issue #583)

- use light theme for AWT components if dark FlatLaf theme is active (AWT is always light)
- made AWT peer background compatible with Aqua Laf
This commit is contained in:
Karl Tauber
2022-09-10 15:30:43 +02:00
parent 7858e42e37
commit 16c6ffb032
11 changed files with 158 additions and 15 deletions

View File

@@ -181,7 +181,7 @@ public class FlatButtonUI
private AtomicBoolean borderShared;
public static ComponentUI createUI( JComponent c ) {
return FlatUIUtils.canUseSharedUI( c )
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
? FlatUIUtils.createSharedUI( FlatButtonUI.class, () -> new FlatButtonUI( true ) )
: new FlatButtonUI( false );
}
@@ -193,6 +193,13 @@ public class FlatButtonUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
installStyle( (AbstractButton) c );

View File

@@ -43,7 +43,7 @@ public class FlatCheckBoxUI
extends FlatRadioButtonUI
{
public static ComponentUI createUI( JComponent c ) {
return FlatUIUtils.canUseSharedUI( c )
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
? FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, () -> new FlatCheckBoxUI( true ) )
: new FlatCheckBoxUI( false );
}

View File

@@ -132,6 +132,7 @@ public class FlatComboBoxUI
@Styleable protected String arrowType;
protected boolean isIntelliJTheme;
private Color background;
@Styleable protected Color editableBackground;
@Styleable protected Color focusedBackground;
@Styleable protected Color disabledBackground;
@@ -165,6 +166,13 @@ public class FlatComboBoxUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
installStyle();
@@ -227,6 +235,7 @@ public class FlatComboBoxUI
arrowType = UIManager.getString( "Component.arrowType" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
background = UIManager.getColor( "ComboBox.background" );
editableBackground = UIManager.getColor( "ComboBox.editableBackground" );
focusedBackground = UIManager.getColor( "ComboBox.focusedBackground" );
disabledBackground = UIManager.getColor( "ComboBox.disabledBackground" );
@@ -259,6 +268,7 @@ public class FlatComboBoxUI
protected void uninstallDefaults() {
super.uninstallDefaults();
background = null;
editableBackground = null;
focusedBackground = null;
disabledBackground = null;
@@ -632,7 +642,7 @@ public class FlatComboBoxUI
protected Color getBackground( boolean enabled ) {
if( enabled ) {
if( FlatUIUtils.isAWTPeer( comboBox ) )
return UIManager.getColor( "ComboBox.background" );
return background;
Color background = comboBox.getBackground();

View File

@@ -90,6 +90,13 @@ public class FlatListUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
installStyle();

View File

@@ -83,7 +83,7 @@ public class FlatRadioButtonUI
private Map<String, Object> oldStyleValues;
public static ComponentUI createUI( JComponent c ) {
return FlatUIUtils.canUseSharedUI( c )
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
? FlatUIUtils.createSharedUI( FlatRadioButtonUI.class, () -> new FlatRadioButtonUI( true ) )
: new FlatRadioButtonUI( false );
}
@@ -95,6 +95,13 @@ public class FlatRadioButtonUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
if( FlatUIUtils.isAWTPeer( c ) )

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.ui;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
@@ -37,11 +38,13 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -230,6 +233,24 @@ public class FlatScrollBarUI
}
SwingUtilities.replaceUIInputMap( scrollbar, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap );
break;
case "ancestor":
// check whether scroll bar is used as AWT peer on macOS and
// dark theme is active --> reinstall using light theme
if( SystemInfo.isMacOS && FlatLaf.isLafDark() ) {
Container p = scrollbar.getParent();
for( int i = 0; i < 2 && p != null; i++, p = p.getParent() ) {
if( FlatUIUtils.isAWTPeer( p ) ) {
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> {
JScrollBar scrollbar = this.scrollbar;
uninstallUI( scrollbar );
installUI( scrollbar );
} );
break;
}
}
}
break;
}
};
}

View File

@@ -87,6 +87,13 @@ public class FlatScrollPaneUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
int focusWidth = UIManager.getInt( "Component.focusWidth" );

View File

@@ -86,6 +86,13 @@ public class FlatTextAreaUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
installStyle();

View File

@@ -128,6 +128,13 @@ public class FlatTextFieldUI
@Override
public void installUI( JComponent c ) {
if( FlatUIUtils.needsLightAWTPeer( c ) )
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
else
installUIImpl( c );
}
private void installUIImpl( JComponent c ) {
super.installUI( c );
leadingIcon = clientProperty( c, TEXT_FIELD_LEADING_ICON, null, Icon.class );

View File

@@ -33,6 +33,7 @@ import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.SystemColor;
import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
@@ -45,16 +46,22 @@ import java.util.WeakHashMap;
import java.util.function.Predicate;
import java.util.function.Supplier;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.Graphics2DProxy;
@@ -257,13 +264,38 @@ public class FlatUIUtils
(window != null && window.getType() == Window.Type.POPUP && window.getOwner() == activeWindow);
}
static boolean isAWTPeer( JComponent c ) {
static boolean isAWTPeer( Component c ) {
// on macOS, Swing components are used for AWT components
if( SystemInfo.isMacOS )
return c.getClass().getName().startsWith( "sun.lwawt.LW" );
return false;
}
/**
* Checks whether component is used as peer for AWT (on macOS) and
* whether a dark FlatLaf theme is active, which requires special handling
* because AWT always uses light colors.
*/
static boolean needsLightAWTPeer( JComponent c ) {
return FlatUIUtils.isAWTPeer( c ) && FlatLaf.isLafDark();
}
private static UIDefaults lightAWTPeerDefaults;
static void runWithLightAWTPeerUIDefaults( Runnable runnable ) {
if( lightAWTPeerDefaults == null ) {
FlatLaf lightLaf = UIManager.getInt( "Component.focusWidth" ) >= 2
? new FlatIntelliJLaf()
: new FlatLightLaf();
lightAWTPeerDefaults = lightLaf.getDefaults();
}
FlatLaf.runWithUIDefaultsGetter( key -> {
Object value = lightAWTPeerDefaults.get( key );
return (value != null) ? value : FlatLaf.NULL_VALUE;
}, runnable );
}
/**
* Returns whether the given component is in a window that is in full-screen mode.
*/
@@ -694,7 +726,17 @@ public class FlatUIUtils
// parent.getBackground() may return null
// (e.g. for Swing delegate components used for AWT components on macOS)
Color background = (parent != null) ? parent.getBackground() : null;
return (background != null) ? background : UIManager.getColor( "Panel.background" );
if( background != null )
return background;
if( isAWTPeer( c ) ) {
// AWT peers usually use component background, except for TextField and ScrollPane
return c instanceof JTextField || c instanceof JScrollPane || c.getBackground() == null
? SystemColor.window
: c.getBackground();
}
return UIManager.getColor( "Panel.background" );
}
/**