diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java
index 17ffa839..669271e6 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowsLibrary.java
@@ -16,6 +16,7 @@
package com.formdev.flatlaf.ui;
+import java.awt.Color;
import java.awt.Window;
import com.formdev.flatlaf.util.SystemInfo;
@@ -31,6 +32,12 @@ public class FlatNativeWindowsLibrary
{
private static long osBuildNumber = Long.MIN_VALUE;
+ /**
+ * Checks whether native library is loaded/available.
+ *
+ * Note: It is required to invoke this method before invoking any other
+ * method of this class. Otherwise, the native library may not be loaded.
+ */
public static boolean isLoaded() {
return SystemInfo.isWindows && FlatNativeLibrary.isLoaded();
}
@@ -93,15 +100,60 @@ public class FlatNativeWindowsLibrary
public native static boolean setWindowCornerPreference( long hwnd, int cornerPreference );
/**
- * Sets the color of the window border.
- * The red/green/blue values must be in range {@code 0 - 255}.
- * If red is {@code -1}, then the system default border color is used (useful to reset the border color).
- * If red is {@code -2}, then no border is painted.
- *
- * Invokes Win32 API method {@code DwmSetWindowAttribute(DWMWA_BORDER_COLOR)}.
+ * DWMWINDOWATTRIBUTE
+ * see https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
+ *
+ * @since 3.3
+ */
+ public static final int
+ DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
+ DWMWA_BORDER_COLOR = 34,
+ DWMWA_CAPTION_COLOR = 35,
+ DWMWA_TEXT_COLOR = 36;
+
+ /**
+ * Invokes Win32 API method {@code DwmSetWindowAttribute()} with a {@code BOOL} attribute value.
+ * See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
+ *
+ * @since 3.3
+ */
+ public native static boolean dwmSetWindowAttributeBOOL( long hwnd, int attribute, boolean value );
+
+ /**
+ * Invokes Win32 API method {@code DwmSetWindowAttribute()} with a {@code DWORD} attribute value.
+ * See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
+ *
+ * @since 3.3
+ */
+ public native static boolean dwmSetWindowAttributeDWORD( long hwnd, int attribute, int value );
+
+ /** @since 3.3 */
+ public static final int
+ // use this constant to reset any window part colors to the system default behavior
+ DWMWA_COLOR_DEFAULT = 0xFFFFFFFF,
+ // use this constant to specify that a window part should not be rendered
+ DWMWA_COLOR_NONE = 0xFFFFFFFE;
+
+ /** @since 3.3 */
+ public static final Color COLOR_NONE = new Color( 0, true );
+
+ /**
+ * Invokes Win32 API method {@code DwmSetWindowAttribute()} with a {@code COLORREF} attribute value.
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
*
* Supported since Windows 11 Build 22000.
+ *
+ * @since 3.3
*/
- public native static boolean setWindowBorderColor( long hwnd, int red, int green, int blue );
+ public static boolean dwmSetWindowAttributeCOLORREF( long hwnd, int attribute, Color color ) {
+ // convert color to Windows RGB value
+ int rgb = (color == COLOR_NONE)
+ ? DWMWA_COLOR_NONE
+ : (color != null
+ ? (color.getRed() | (color.getGreen() << 8) | (color.getBlue() << 16))
+ : DWMWA_COLOR_DEFAULT);
+
+ // DwmSetWindowAttribute() expects COLORREF as attribute value, which is defined as DWORD
+ return dwmSetWindowAttributeDWORD( hwnd, attribute, rgb );
+ }
}
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java
index eeca80ef..7a25b907 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java
@@ -361,29 +361,20 @@ public class FlatPopupFactory
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, cornerPreference );
// set border color
- int red = -1; // use system default color
- int green = 0;
- int blue = 0;
+ Color borderColor = null; // use system default color
if( contents instanceof JComponent ) {
Border border = ((JComponent)contents).getBorder();
border = FlatUIUtils.unwrapNonUIResourceBorder( border );
// get color from border of contents (e.g. JPopupMenu or JToolTip)
- Color borderColor = null;
if( border instanceof FlatLineBorder )
borderColor = ((FlatLineBorder)border).getLineColor();
else if( border instanceof LineBorder )
borderColor = ((LineBorder)border).getLineColor();
else if( border instanceof EmptyBorder )
- red = -2; // do not paint border
-
- if( borderColor != null ) {
- red = borderColor.getRed();
- green = borderColor.getGreen();
- blue = borderColor.getBlue();
- }
+ borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border
}
- FlatNativeWindowsLibrary.setWindowBorderColor( hwnd, red, green, blue );
+ FlatNativeWindowsLibrary.dwmSetWindowAttributeCOLORREF( hwnd, FlatNativeWindowsLibrary.DWMWA_BORDER_COLOR, borderColor );
}
private static void resetWindows11Border( Window popupWindow ) {
diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinWrapper.cpp b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinWrapper.cpp
index 37fc9e84..1983a075 100644
--- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinWrapper.cpp
+++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinWrapper.cpp
@@ -50,29 +50,6 @@ JNIEXPORT jlong JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_get
//---- Desktop Window Manager (DWM) -------------------------------------------
-// define constants that may not available in older development environments
-
-#ifndef DWMWA_COLOR_DEFAULT
-
-#define DWMWA_WINDOW_CORNER_PREFERENCE 33
-#define DWMWA_BORDER_COLOR 34
-
-typedef enum {
- DWMWCP_DEFAULT = 0,
- DWMWCP_DONOTROUND = 1,
- DWMWCP_ROUND = 2,
- DWMWCP_ROUNDSMALL = 3
-} DWM_WINDOW_CORNER_PREFERENCE;
-
-// Use this constant to reset any window part colors to the system default behavior
-#define DWMWA_COLOR_DEFAULT 0xFFFFFFFF
-
-// Use this constant to specify that a window part should not be rendered
-#define DWMWA_COLOR_NONE 0xFFFFFFFE
-
-#endif
-
-
extern "C"
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_setWindowCornerPreference
( JNIEnv* env, jclass cls, jlong hwnd, jint cornerPreference )
@@ -85,18 +62,23 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_
}
extern "C"
-JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_setWindowBorderColor
- ( JNIEnv* env, jclass cls, jlong hwnd, jint red, jint green, jint blue )
+JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_dwmSetWindowAttributeBOOL
+ ( JNIEnv* env, jclass cls, jlong hwnd, jint attribute, jboolean value )
{
if( hwnd == 0 )
return FALSE;
- COLORREF attr;
- if( red == -1 )
- attr = DWMWA_COLOR_DEFAULT;
- else if( red == -2 )
- attr = DWMWA_COLOR_NONE;
- else
- attr = RGB( red, green, blue );
- return ::DwmSetWindowAttribute( reinterpret_cast( hwnd ), DWMWA_BORDER_COLOR, &attr, sizeof( attr ) ) == S_OK;
+ BOOL attr = value;
+ return ::DwmSetWindowAttribute( reinterpret_cast( hwnd ), attribute, &attr, sizeof( attr ) ) == S_OK;
+}
+
+extern "C"
+JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_dwmSetWindowAttributeDWORD
+ ( JNIEnv* env, jclass cls, jlong hwnd, jint attribute, jint value )
+{
+ if( hwnd == 0 )
+ return FALSE;
+
+ DWORD attr = value;
+ return ::DwmSetWindowAttribute( reinterpret_cast( hwnd ), attribute, &attr, sizeof( attr ) ) == S_OK;
}
diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h
index 921c7a99..1701cb3b 100644
--- a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h
+++ b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h
@@ -15,6 +15,18 @@ extern "C" {
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWCP_ROUND 2L
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWCP_ROUNDSMALL
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWCP_ROUNDSMALL 3L
+#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_USE_IMMERSIVE_DARK_MODE
+#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_USE_IMMERSIVE_DARK_MODE 20L
+#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_BORDER_COLOR
+#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_BORDER_COLOR 34L
+#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_CAPTION_COLOR
+#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_CAPTION_COLOR 35L
+#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_TEXT_COLOR
+#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_TEXT_COLOR 36L
+#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_DEFAULT
+#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_DEFAULT -1L
+#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_NONE
+#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_NONE -2L
/*
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
* Method: getOSBuildNumberImpl
@@ -41,11 +53,19 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_
/*
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
- * Method: setWindowBorderColor
- * Signature: (JIII)Z
+ * Method: dwmSetWindowAttributeBOOL
+ * Signature: (JIZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_setWindowBorderColor
- (JNIEnv *, jclass, jlong, jint, jint, jint);
+JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_dwmSetWindowAttributeBOOL
+ (JNIEnv *, jclass, jlong, jint, jboolean);
+
+/*
+ * Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
+ * Method: dwmSetWindowAttributeDWORD
+ * Signature: (JII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_dwmSetWindowAttributeDWORD
+ (JNIEnv *, jclass, jlong, jint, jint);
#ifdef __cplusplus
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindows11DwmTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindows11DwmTest.java
new file mode 100644
index 00000000..df9a30fc
--- /dev/null
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindows11DwmTest.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2023 FormDev Software GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.formdev.flatlaf.testing;
+
+import java.awt.Color;
+import javax.swing.*;
+import com.formdev.flatlaf.FlatSystemProperties;
+import com.formdev.flatlaf.ui.FlatNativeWindowsLibrary;
+import net.miginfocom.swing.*;
+
+/**
+ * @author Karl Tauber
+ */
+public class FlatWindows11DwmTest
+ extends FlatTestPanel
+{
+ public static void main( String[] args ) {
+ SwingUtilities.invokeLater( () -> {
+ System.setProperty( FlatSystemProperties.USE_WINDOW_DECORATIONS, "false" );
+
+ FlatTestFrame frame = FlatTestFrame.create( args, FlatWindows11DwmTest.class.getSimpleName() );
+ frame.showFrame( FlatWindows11DwmTest::new );
+ } );
+ }
+
+ FlatWindows11DwmTest() {
+ initComponents();
+ }
+
+ private void modeChanged() {
+ if( !checkNativeLibraryLoaded() )
+ return;
+
+ boolean dark = darkModeRadioButton.isSelected();
+ FlatNativeWindowsLibrary.dwmSetWindowAttributeBOOL( getHWND(), FlatNativeWindowsLibrary.DWMWA_USE_IMMERSIVE_DARK_MODE, dark );
+ }
+
+ private void borderColorChanged() {
+ if( !checkNativeLibraryLoaded() )
+ return;
+
+ Color color = null;
+ if( borderRedRadioButton.isSelected() )
+ color = Color.red;
+ else if( borderGreenRadioButton.isSelected() )
+ color = Color.green;
+ else if( borderNoneRadioButton.isSelected() )
+ color = FlatNativeWindowsLibrary.COLOR_NONE;
+
+ FlatNativeWindowsLibrary.dwmSetWindowAttributeCOLORREF( getHWND(), FlatNativeWindowsLibrary.DWMWA_BORDER_COLOR, color );
+ }
+
+ private void captionColorChanged() {
+ if( !checkNativeLibraryLoaded() )
+ return;
+
+ Color color = null;
+ if( captionGreenRadioButton.isSelected() )
+ color = Color.green;
+ else if( captionYellowRadioButton.isSelected() )
+ color = Color.yellow;
+ else if( captionBlackRadioButton.isSelected() )
+ color = Color.black;
+
+ FlatNativeWindowsLibrary.dwmSetWindowAttributeCOLORREF( getHWND(), FlatNativeWindowsLibrary.DWMWA_CAPTION_COLOR, color );
+ }
+
+ private void textColorChanged() {
+ if( !checkNativeLibraryLoaded() )
+ return;
+
+ Color color = null;
+ if( textRedRadioButton.isSelected() )
+ color = Color.red;
+ else if( textBlueRadioButton.isSelected() )
+ color = Color.blue;
+ else if( textWhiteRadioButton.isSelected() )
+ color = Color.white;
+
+ FlatNativeWindowsLibrary.dwmSetWindowAttributeCOLORREF( getHWND(), FlatNativeWindowsLibrary.DWMWA_TEXT_COLOR, color );
+ }
+
+ private void cornerChanged() {
+ if( !checkNativeLibraryLoaded() )
+ return;
+
+ int cornerPreference = FlatNativeWindowsLibrary.DWMWCP_DEFAULT;
+ if( cornerDontRoundRadioButton.isSelected() )
+ cornerPreference = FlatNativeWindowsLibrary.DWMWCP_DONOTROUND;
+ else if( cornerRoundRadioButton.isSelected() )
+ cornerPreference = FlatNativeWindowsLibrary.DWMWCP_ROUND;
+ else if( cornerRoundSmallRadioButton.isSelected() )
+ cornerPreference = FlatNativeWindowsLibrary.DWMWCP_ROUNDSMALL;
+
+ FlatNativeWindowsLibrary.setWindowCornerPreference( getHWND(), cornerPreference );
+ }
+
+ private long getHWND() {
+ return FlatNativeWindowsLibrary.getHWND( SwingUtilities.getWindowAncestor( this ) );
+ }
+
+ private boolean checkNativeLibraryLoaded() {
+ if( FlatNativeWindowsLibrary.isLoaded() )
+ return true;
+
+ JOptionPane.showMessageDialog( this, "FlatLaf native windows library not loaded/available." );
+ return false;
+ }
+
+ private void initComponents() {
+ // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
+ JLabel modeLabel = new JLabel();
+ lightModeRadioButton = new JRadioButton();
+ darkModeRadioButton = new JRadioButton();
+ JLabel borderLabel = new JLabel();
+ borderDefaultRadioButton = new JRadioButton();
+ borderRedRadioButton = new JRadioButton();
+ borderGreenRadioButton = new JRadioButton();
+ borderNoneRadioButton = new JRadioButton();
+ JLabel captionLabel = new JLabel();
+ captionDefaultRadioButton = new JRadioButton();
+ captionGreenRadioButton = new JRadioButton();
+ captionYellowRadioButton = new JRadioButton();
+ captionBlackRadioButton = new JRadioButton();
+ JLabel textLabel = new JLabel();
+ textDefaultRadioButton = new JRadioButton();
+ textRedRadioButton = new JRadioButton();
+ textBlueRadioButton = new JRadioButton();
+ textWhiteRadioButton = new JRadioButton();
+ JLabel cornerLabel = new JLabel();
+ cornerDefaultRadioButton = new JRadioButton();
+ cornerDontRoundRadioButton = new JRadioButton();
+ cornerRoundRadioButton = new JRadioButton();
+ cornerRoundSmallRadioButton = new JRadioButton();
+
+ //======== this ========
+ setLayout(new MigLayout(
+ "ltr,insets dialog,hidemode 3",
+ // columns
+ "[fill]" +
+ "[left]" +
+ "[left]" +
+ "[left]" +
+ "[left]",
+ // rows
+ "[fill]para" +
+ "[]" +
+ "[]" +
+ "[]" +
+ "[]"));
+
+ //---- modeLabel ----
+ modeLabel.setText("Mode:");
+ add(modeLabel, "cell 0 0");
+
+ //---- lightModeRadioButton ----
+ lightModeRadioButton.setText("Light");
+ lightModeRadioButton.setSelected(true);
+ lightModeRadioButton.addActionListener(e -> modeChanged());
+ add(lightModeRadioButton, "cell 1 0");
+
+ //---- darkModeRadioButton ----
+ darkModeRadioButton.setText("Dark");
+ darkModeRadioButton.addActionListener(e -> modeChanged());
+ add(darkModeRadioButton, "cell 2 0");
+
+ //---- borderLabel ----
+ borderLabel.setText("Border Color:");
+ add(borderLabel, "cell 0 1");
+
+ //---- borderDefaultRadioButton ----
+ borderDefaultRadioButton.setText("Default");
+ borderDefaultRadioButton.setSelected(true);
+ borderDefaultRadioButton.addActionListener(e -> borderColorChanged());
+ add(borderDefaultRadioButton, "cell 1 1");
+
+ //---- borderRedRadioButton ----
+ borderRedRadioButton.setText("Red");
+ borderRedRadioButton.addActionListener(e -> borderColorChanged());
+ add(borderRedRadioButton, "cell 2 1");
+
+ //---- borderGreenRadioButton ----
+ borderGreenRadioButton.setText("Green");
+ borderGreenRadioButton.addActionListener(e -> borderColorChanged());
+ add(borderGreenRadioButton, "cell 3 1");
+
+ //---- borderNoneRadioButton ----
+ borderNoneRadioButton.setText("None");
+ borderNoneRadioButton.addActionListener(e -> borderColorChanged());
+ add(borderNoneRadioButton, "cell 4 1");
+
+ //---- captionLabel ----
+ captionLabel.setText("Caption Color:");
+ add(captionLabel, "cell 0 2");
+
+ //---- captionDefaultRadioButton ----
+ captionDefaultRadioButton.setText("Default");
+ captionDefaultRadioButton.setSelected(true);
+ captionDefaultRadioButton.addActionListener(e -> captionColorChanged());
+ add(captionDefaultRadioButton, "cell 1 2");
+
+ //---- captionGreenRadioButton ----
+ captionGreenRadioButton.setText("Green");
+ captionGreenRadioButton.addActionListener(e -> captionColorChanged());
+ add(captionGreenRadioButton, "cell 2 2");
+
+ //---- captionYellowRadioButton ----
+ captionYellowRadioButton.setText("Yellow");
+ captionYellowRadioButton.addActionListener(e -> captionColorChanged());
+ add(captionYellowRadioButton, "cell 3 2");
+
+ //---- captionBlackRadioButton ----
+ captionBlackRadioButton.setText("Black");
+ captionBlackRadioButton.addActionListener(e -> captionColorChanged());
+ add(captionBlackRadioButton, "cell 4 2");
+
+ //---- textLabel ----
+ textLabel.setText("Text Color:");
+ add(textLabel, "cell 0 3");
+
+ //---- textDefaultRadioButton ----
+ textDefaultRadioButton.setText("Default");
+ textDefaultRadioButton.setSelected(true);
+ textDefaultRadioButton.addActionListener(e -> textColorChanged());
+ add(textDefaultRadioButton, "cell 1 3");
+
+ //---- textRedRadioButton ----
+ textRedRadioButton.setText("Red");
+ textRedRadioButton.addActionListener(e -> textColorChanged());
+ add(textRedRadioButton, "cell 2 3");
+
+ //---- textBlueRadioButton ----
+ textBlueRadioButton.setText("Blue");
+ textBlueRadioButton.addActionListener(e -> textColorChanged());
+ add(textBlueRadioButton, "cell 3 3");
+
+ //---- textWhiteRadioButton ----
+ textWhiteRadioButton.setText("White");
+ textWhiteRadioButton.addActionListener(e -> textColorChanged());
+ add(textWhiteRadioButton, "cell 4 3");
+
+ //---- cornerLabel ----
+ cornerLabel.setText("Corner:");
+ add(cornerLabel, "cell 0 4");
+
+ //---- cornerDefaultRadioButton ----
+ cornerDefaultRadioButton.setText("Default");
+ cornerDefaultRadioButton.setSelected(true);
+ cornerDefaultRadioButton.addActionListener(e -> cornerChanged());
+ add(cornerDefaultRadioButton, "cell 1 4 4 1");
+
+ //---- cornerDontRoundRadioButton ----
+ cornerDontRoundRadioButton.setText("Don't Round");
+ cornerDontRoundRadioButton.addActionListener(e -> cornerChanged());
+ add(cornerDontRoundRadioButton, "cell 1 4 4 1");
+
+ //---- cornerRoundRadioButton ----
+ cornerRoundRadioButton.setText("Round");
+ cornerRoundRadioButton.addActionListener(e -> cornerChanged());
+ add(cornerRoundRadioButton, "cell 1 4 4 1");
+
+ //---- cornerRoundSmallRadioButton ----
+ cornerRoundSmallRadioButton.setText("Round Small");
+ cornerRoundSmallRadioButton.addActionListener(e -> cornerChanged());
+ add(cornerRoundSmallRadioButton, "cell 1 4 4 1");
+
+ //---- modeButtonGroup ----
+ ButtonGroup modeButtonGroup = new ButtonGroup();
+ modeButtonGroup.add(lightModeRadioButton);
+ modeButtonGroup.add(darkModeRadioButton);
+
+ //---- borderColorButtonGroup ----
+ ButtonGroup borderColorButtonGroup = new ButtonGroup();
+ borderColorButtonGroup.add(borderDefaultRadioButton);
+ borderColorButtonGroup.add(borderRedRadioButton);
+ borderColorButtonGroup.add(borderGreenRadioButton);
+ borderColorButtonGroup.add(borderNoneRadioButton);
+
+ //---- captionColorButtonGroup ----
+ ButtonGroup captionColorButtonGroup = new ButtonGroup();
+ captionColorButtonGroup.add(captionDefaultRadioButton);
+ captionColorButtonGroup.add(captionGreenRadioButton);
+ captionColorButtonGroup.add(captionYellowRadioButton);
+ captionColorButtonGroup.add(captionBlackRadioButton);
+
+ //---- textColorButtonGroup ----
+ ButtonGroup textColorButtonGroup = new ButtonGroup();
+ textColorButtonGroup.add(textDefaultRadioButton);
+ textColorButtonGroup.add(textRedRadioButton);
+ textColorButtonGroup.add(textBlueRadioButton);
+ textColorButtonGroup.add(textWhiteRadioButton);
+
+ //---- cornerButtonGroup ----
+ ButtonGroup cornerButtonGroup = new ButtonGroup();
+ cornerButtonGroup.add(cornerDefaultRadioButton);
+ cornerButtonGroup.add(cornerDontRoundRadioButton);
+ cornerButtonGroup.add(cornerRoundRadioButton);
+ cornerButtonGroup.add(cornerRoundSmallRadioButton);
+ // JFormDesigner - End of component initialization //GEN-END:initComponents
+ }
+
+ // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
+ private JRadioButton lightModeRadioButton;
+ private JRadioButton darkModeRadioButton;
+ private JRadioButton borderDefaultRadioButton;
+ private JRadioButton borderRedRadioButton;
+ private JRadioButton borderGreenRadioButton;
+ private JRadioButton borderNoneRadioButton;
+ private JRadioButton captionDefaultRadioButton;
+ private JRadioButton captionGreenRadioButton;
+ private JRadioButton captionYellowRadioButton;
+ private JRadioButton captionBlackRadioButton;
+ private JRadioButton textDefaultRadioButton;
+ private JRadioButton textRedRadioButton;
+ private JRadioButton textBlueRadioButton;
+ private JRadioButton textWhiteRadioButton;
+ private JRadioButton cornerDefaultRadioButton;
+ private JRadioButton cornerDontRoundRadioButton;
+ private JRadioButton cornerRoundRadioButton;
+ private JRadioButton cornerRoundSmallRadioButton;
+ // JFormDesigner - End of variables declaration //GEN-END:variables
+}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindows11DwmTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindows11DwmTest.jfd
new file mode 100644
index 00000000..36f01e3c
--- /dev/null
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindows11DwmTest.jfd
@@ -0,0 +1,278 @@
+JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8"
+
+new FormModel {
+ contentType: "form/swing"
+ root: new FormRoot {
+ auxiliary() {
+ "JavaCodeGenerator.defaultVariableLocal": true
+ }
+ add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
+ "$layoutConstraints": "ltr,insets dialog,hidemode 3"
+ "$columnConstraints": "[fill][left][left][left][left]"
+ "$rowConstraints": "[fill]para[][][][]"
+ } ) {
+ name: "this"
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "modeLabel"
+ "text": "Mode:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 0"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "lightModeRadioButton"
+ "text": "Light"
+ "$buttonGroup": new FormReference( "modeButtonGroup" )
+ "selected": true
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "modeChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 0"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "darkModeRadioButton"
+ "text": "Dark"
+ "$buttonGroup": new FormReference( "modeButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "modeChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 2 0"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "borderLabel"
+ "text": "Border Color:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "borderDefaultRadioButton"
+ "text": "Default"
+ "$buttonGroup": new FormReference( "borderColorButtonGroup" )
+ "selected": true
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "borderColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "borderRedRadioButton"
+ "text": "Red"
+ "$buttonGroup": new FormReference( "borderColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "borderColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 2 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "borderGreenRadioButton"
+ "text": "Green"
+ "$buttonGroup": new FormReference( "borderColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "borderColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 3 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "borderNoneRadioButton"
+ "text": "None"
+ "$buttonGroup": new FormReference( "borderColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "borderColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 4 1"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "captionLabel"
+ "text": "Caption Color:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 2"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "captionDefaultRadioButton"
+ "text": "Default"
+ "$buttonGroup": new FormReference( "captionColorButtonGroup" )
+ "selected": true
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "captionColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 2"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "captionGreenRadioButton"
+ "text": "Green"
+ "$buttonGroup": new FormReference( "captionColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "captionColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 2 2"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "captionYellowRadioButton"
+ "text": "Yellow"
+ "$buttonGroup": &FormReference0 new FormReference( "captionColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "captionColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 3 2"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "captionBlackRadioButton"
+ "text": "Black"
+ "$buttonGroup": #FormReference0
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "captionColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 4 2"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "textLabel"
+ "text": "Text Color:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 3"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "textDefaultRadioButton"
+ "text": "Default"
+ "$buttonGroup": new FormReference( "textColorButtonGroup" )
+ "selected": true
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "textColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 3"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "textRedRadioButton"
+ "text": "Red"
+ "$buttonGroup": new FormReference( "textColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "textColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 2 3"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "textBlueRadioButton"
+ "text": "Blue"
+ "$buttonGroup": &FormReference1 new FormReference( "textColorButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "textColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 3 3"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "textWhiteRadioButton"
+ "text": "White"
+ "$buttonGroup": #FormReference1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "textColorChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 4 3"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "cornerLabel"
+ "text": "Corner:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 4"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "cornerDefaultRadioButton"
+ "text": "Default"
+ "$buttonGroup": new FormReference( "cornerButtonGroup" )
+ "selected": true
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "cornerChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 4 4 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "cornerDontRoundRadioButton"
+ "text": "Don't Round"
+ "$buttonGroup": new FormReference( "cornerButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "cornerChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 4 4 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "cornerRoundRadioButton"
+ "text": "Round"
+ "$buttonGroup": new FormReference( "cornerButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "cornerChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 4 4 1"
+ } )
+ add( new FormComponent( "javax.swing.JRadioButton" ) {
+ name: "cornerRoundSmallRadioButton"
+ "text": "Round Small"
+ "$buttonGroup": new FormReference( "cornerButtonGroup" )
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "cornerChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 4 4 1"
+ } )
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 0 )
+ "size": new java.awt.Dimension( 415, 350 )
+ } )
+ add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
+ name: "modeButtonGroup"
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 360 )
+ } )
+ add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
+ name: "borderColorButtonGroup"
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 414 )
+ } )
+ add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
+ name: "captionColorButtonGroup"
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 468 )
+ } )
+ add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
+ name: "textColorButtonGroup"
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 522 )
+ } )
+ add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
+ name: "cornerButtonGroup"
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 576 )
+ } )
+ }
+}