mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-08 06:50:56 +03:00
macOS window button style: support NSWindowToolbarStyleUnified (availaible since macOS 11+; standard in macOS Finder, etc) to allow even larger space around close/minimize/zoom buttons
This commit is contained in:
@@ -527,21 +527,6 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String WINDOW_STYLE_SMALL = "small";
|
String WINDOW_STYLE_SMALL = "small";
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies whether the window should have a large title bar.
|
|
||||||
* This adds extra space around the close/minimize/zoom buttons.
|
|
||||||
* Useful if <a href="https://www.formdev.com/flatlaf/macos/#full_window_content">full window content</a>
|
|
||||||
* is enabled.
|
|
||||||
* <p>
|
|
||||||
* (requires macOS 10.14+, Java 17+ and client property {@code apple.awt.fullWindowContent} set to {@code true})
|
|
||||||
* <p>
|
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
|
||||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String MACOS_LARGE_WINDOW_TITLE_BAR = "FlatLaf.macOS.largeWindowTitleBar";
|
|
||||||
|
|
||||||
|
|
||||||
//---- JScrollBar / JScrollPane -------------------------------------------
|
//---- JScrollBar / JScrollPane -------------------------------------------
|
||||||
|
|
||||||
@@ -1278,6 +1263,46 @@ public interface FlatClientProperties
|
|||||||
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
||||||
|
|
||||||
|
|
||||||
|
//---- macOS --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style of macOS window close/minimize/zoom buttons.
|
||||||
|
* This does not change visual appearance but adds extra space around the buttons.
|
||||||
|
* Useful if <a href="https://www.formdev.com/flatlaf/macos/#full_window_content">full window content</a>
|
||||||
|
* is enabled.
|
||||||
|
* <p>
|
||||||
|
* (requires macOS 10.14+ or 11+ for style 'large', Java 17+ and client property {@code apple.awt.fullWindowContent} set to {@code true})
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String} or {@link java.lang.Boolean}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #MACOS_WINDOW_TITLE_BAR_STYLE_MEDIUM},
|
||||||
|
* {@link #MACOS_WINDOW_TITLE_BAR_STYLE_LARGE} (requires macOS 11+) or
|
||||||
|
* {@code true} (equal to 'large')
|
||||||
|
*
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String MACOS_WINDOW_BUTTON_STYLE = "FlatLaf.macOS.windowButtonStyle";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add medium space around the macOS window close/minimize/zoom buttons.
|
||||||
|
*
|
||||||
|
* @see #MACOS_WINDOW_BUTTON_STYLE
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String MACOS_WINDOW_BUTTON_STYLE_MEDIUM = "medium";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add large space around the macOS window close/minimize/zoom buttons.
|
||||||
|
* <p>
|
||||||
|
* (requires macOS 11+; 'medium' is used on older systems)
|
||||||
|
*
|
||||||
|
* @see #MACOS_WINDOW_BUTTON_STYLE
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String MACOS_WINDOW_BUTTON_STYLE_LARGE = "large";
|
||||||
|
|
||||||
|
|
||||||
//---- helper methods -----------------------------------------------------
|
//---- helper methods -----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -54,7 +54,12 @@ public class FlatNativeMacLibrary
|
|||||||
|
|
||||||
public native static boolean setWindowRoundedBorder( Window window, float radius, float borderWidth, int borderColor );
|
public native static boolean setWindowRoundedBorder( Window window, float radius, float borderWidth, int borderColor );
|
||||||
|
|
||||||
public native static boolean setWindowToolbar( Window window, boolean hasToolbar );
|
public static final int
|
||||||
|
BUTTON_STYLE_DEFAULT = 0,
|
||||||
|
BUTTON_STYLE_MEDIUM = 1,
|
||||||
|
BUTTON_STYLE_LARGE = 2;
|
||||||
|
|
||||||
|
public native static boolean setWindowButtonStyle( Window window, int buttonStyle );
|
||||||
public native static int getWindowButtonAreaWidth( Window window );
|
public native static int getWindowButtonAreaWidth( Window window );
|
||||||
public native static int getWindowTitleBarHeight( Window window );
|
public native static int getWindowTitleBarHeight( Window window );
|
||||||
public native static boolean isWindowFullScreen( Window window );
|
public native static boolean isWindowFullScreen( Window window );
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ public class FlatRootPaneUI
|
|||||||
throw new IllegalComponentStateException( "The client property 'Window.style' must be set before the window becomes displayable." );
|
throw new IllegalComponentStateException( "The client property 'Window.style' must be set before the window becomes displayable." );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.MACOS_LARGE_WINDOW_TITLE_BAR:
|
case FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE:
|
||||||
case "ancestor":
|
case "ancestor":
|
||||||
if( SystemInfo.isMacFullWindowContentSupported &&
|
if( SystemInfo.isMacFullWindowContentSupported &&
|
||||||
SystemInfo.isJava_17_orLater &&
|
SystemInfo.isJava_17_orLater &&
|
||||||
@@ -376,10 +376,21 @@ public class FlatRootPaneUI
|
|||||||
FlatClientProperties.clientPropertyBoolean( rootPane, "apple.awt.fullWindowContent", false ) &&
|
FlatClientProperties.clientPropertyBoolean( rootPane, "apple.awt.fullWindowContent", false ) &&
|
||||||
FlatNativeMacLibrary.isLoaded() )
|
FlatNativeMacLibrary.isLoaded() )
|
||||||
{
|
{
|
||||||
|
int buttonStyle = FlatNativeMacLibrary.BUTTON_STYLE_DEFAULT;
|
||||||
|
Object value = rootPane.getClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE );
|
||||||
|
switch( String.valueOf( value ) ) {
|
||||||
|
case FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE_MEDIUM:
|
||||||
|
buttonStyle = FlatNativeMacLibrary.BUTTON_STYLE_MEDIUM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "true":
|
||||||
|
case FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE_LARGE:
|
||||||
|
buttonStyle = FlatNativeMacLibrary.BUTTON_STYLE_LARGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Window window = SwingUtilities.windowForComponent( rootPane );
|
Window window = SwingUtilities.windowForComponent( rootPane );
|
||||||
boolean enabled = FlatClientProperties.clientPropertyBoolean( rootPane,
|
FlatNativeMacLibrary.setWindowButtonStyle( window, buttonStyle );
|
||||||
FlatClientProperties.MACOS_LARGE_WINDOW_TITLE_BAR, false );
|
|
||||||
FlatNativeMacLibrary.setWindowToolbar( window, enabled );
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class DemoFrame
|
|||||||
// expand window content into window title bar and make title bar transparent
|
// expand window content into window title bar and make title bar transparent
|
||||||
rootPane.putClientProperty( "apple.awt.fullWindowContent", true );
|
rootPane.putClientProperty( "apple.awt.fullWindowContent", true );
|
||||||
rootPane.putClientProperty( "apple.awt.transparentTitleBar", true );
|
rootPane.putClientProperty( "apple.awt.transparentTitleBar", true );
|
||||||
rootPane.putClientProperty( FlatClientProperties.MACOS_LARGE_WINDOW_TITLE_BAR, true );
|
rootPane.putClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE, true );
|
||||||
|
|
||||||
// hide window title
|
// hide window title
|
||||||
if( SystemInfo.isJava_17_orLater )
|
if( SystemInfo.isJava_17_orLater )
|
||||||
@@ -902,15 +902,19 @@ class DemoFrame
|
|||||||
buttonGroup1.add(radioButtonMenuItem3);
|
buttonGroup1.add(radioButtonMenuItem3);
|
||||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
|
||||||
|
//TODO remove
|
||||||
backButton.addActionListener( e -> {
|
backButton.addActionListener( e -> {
|
||||||
rootPane.putClientProperty( FlatClientProperties.MACOS_LARGE_WINDOW_TITLE_BAR, true );
|
rootPane.putClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE, FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE_LARGE );
|
||||||
});
|
});
|
||||||
forwardButton.addActionListener( e -> {
|
forwardButton.addActionListener( e -> {
|
||||||
rootPane.putClientProperty( FlatClientProperties.MACOS_LARGE_WINDOW_TITLE_BAR, null );
|
rootPane.putClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE, FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE_MEDIUM );
|
||||||
|
});
|
||||||
|
cutButton.addActionListener( e -> {
|
||||||
|
rootPane.putClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTON_STYLE, null );
|
||||||
});
|
});
|
||||||
|
|
||||||
cutButton.addActionListener( e -> System.out.println( e ) );
|
copyButton.addActionListener( e -> System.out.println( e ) );
|
||||||
cutButton.addMouseListener( new MouseListener() {
|
copyButton.addMouseListener( new MouseListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased( MouseEvent e ) {
|
public void mouseReleased( MouseEvent e ) {
|
||||||
@@ -942,7 +946,7 @@ class DemoFrame
|
|||||||
System.out.println( "m click" );
|
System.out.println( "m click" );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
cutButton.addMouseMotionListener( new MouseMotionListener() {
|
copyButton.addMouseMotionListener( new MouseMotionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved( MouseEvent e ) {
|
public void mouseMoved( MouseEvent e ) {
|
||||||
|
|||||||
@@ -7,6 +7,12 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_DEFAULT
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_DEFAULT 0L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_MEDIUM
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_MEDIUM 1L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_LARGE
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_LARGE 2L
|
||||||
/*
|
/*
|
||||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||||
* Method: setWindowRoundedBorder
|
* Method: setWindowRoundedBorder
|
||||||
@@ -17,11 +23,11 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||||
* Method: setWindowToolbar
|
* Method: setWindowButtonStyle
|
||||||
* Signature: (Ljava/awt/Window;Z)Z
|
* Signature: (Ljava/awt/Window;I)Z
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowToolbar
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowButtonStyle
|
||||||
(JNIEnv *, jclass, jobject, jboolean);
|
(JNIEnv *, jclass, jobject, jint);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) {
|
|||||||
if( window == NULL )
|
if( window == NULL )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// initialize field IDs (done only once because fields are static)
|
// initialize field IDs (done only once because variables are static)
|
||||||
static jfieldID peerID = getFieldID( env, "java/awt/Component", "peer", "Ljava/awt/peer/ComponentPeer;" );
|
static jfieldID peerID = getFieldID( env, "java/awt/Component", "peer", "Ljava/awt/peer/ComponentPeer;" );
|
||||||
static jfieldID platformWindowID = getFieldID( env, "sun/lwawt/LWWindowPeer", "platformWindow", "Lsun/lwawt/PlatformWindow;" );
|
static jfieldID platformWindowID = getFieldID( env, "sun/lwawt/LWWindowPeer", "platformWindow", "Lsun/lwawt/PlatformWindow;" );
|
||||||
static jfieldID ptrID = getFieldID( env, "sun/lwawt/macosx/CFRetainedResource", "ptr", "J" );
|
static jfieldID ptrID = getFieldID( env, "sun/lwawt/macosx/CFRetainedResource", "ptr", "J" );
|
||||||
@@ -121,8 +121,8 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowToolbar
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowButtonStyle
|
||||||
( JNIEnv* env, jclass cls, jobject window, jboolean hasToolbar )
|
( JNIEnv* env, jclass cls, jobject window, jint buttonStyle )
|
||||||
{
|
{
|
||||||
JNI_COCOA_ENTER()
|
JNI_COCOA_ENTER()
|
||||||
|
|
||||||
@@ -130,7 +130,20 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
|||||||
if( nsWindow == NULL )
|
if( nsWindow == NULL )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if( hasToolbar == (nsWindow.toolbar != NULL) )
|
#define STYLE_DEFAULT com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_DEFAULT
|
||||||
|
#define STYLE_MEDIUM com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_MEDIUM
|
||||||
|
#define STYLE_LARGE com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTON_STYLE_LARGE
|
||||||
|
|
||||||
|
bool isMacOS_11_orLater = @available( macOS 11, * );
|
||||||
|
if( !isMacOS_11_orLater && buttonStyle == STYLE_LARGE )
|
||||||
|
buttonStyle = STYLE_MEDIUM;
|
||||||
|
int oldButtonStyle = (nsWindow.toolbar != NULL)
|
||||||
|
? ((isMacOS_11_orLater && nsWindow.toolbarStyle == NSWindowToolbarStyleUnified)
|
||||||
|
? STYLE_LARGE
|
||||||
|
: STYLE_MEDIUM)
|
||||||
|
: STYLE_DEFAULT;
|
||||||
|
|
||||||
|
if( buttonStyle == oldButtonStyle )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
WindowData* windowData = getWindowData( nsWindow, true );
|
WindowData* windowData = getWindowData( nsWindow, true );
|
||||||
@@ -140,12 +153,26 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
|||||||
|
|
||||||
// add/remove toolbar
|
// add/remove toolbar
|
||||||
NSToolbar* toolbar = NULL;
|
NSToolbar* toolbar = NULL;
|
||||||
|
bool hasToolbar = (buttonStyle != STYLE_DEFAULT);
|
||||||
if( hasToolbar ) {
|
if( hasToolbar ) {
|
||||||
toolbar = [NSToolbar new];
|
toolbar = [NSToolbar new];
|
||||||
toolbar.showsBaselineSeparator = NO; // necessary for older macOS versions
|
toolbar.showsBaselineSeparator = NO; // necessary for older macOS versions
|
||||||
|
if( isWindowFullScreen( nsWindow ) )
|
||||||
|
toolbar.visible = NO;
|
||||||
}
|
}
|
||||||
nsWindow.toolbar = toolbar;
|
nsWindow.toolbar = toolbar;
|
||||||
|
|
||||||
|
if( isMacOS_11_orLater ) {
|
||||||
|
nsWindow.toolbarStyle = (buttonStyle == STYLE_LARGE)
|
||||||
|
? NSWindowToolbarStyleUnified
|
||||||
|
: (buttonStyle == STYLE_MEDIUM)
|
||||||
|
? NSWindowToolbarStyleUnifiedCompact
|
||||||
|
: NSWindowToolbarStyleAutomatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
windowData.lastWindowButtonAreaWidth = 0;
|
||||||
|
windowData.lastWindowTitleBarHeight = 0;
|
||||||
|
|
||||||
// NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] );
|
// NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] );
|
||||||
|
|
||||||
// when window becomes full screen, it is necessary to hide the toolbar
|
// when window becomes full screen, it is necessary to hide the toolbar
|
||||||
@@ -161,6 +188,7 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
|||||||
// remembar title bar height so that "main" JToolBar keeps its height in full screen
|
// remembar title bar height so that "main" JToolBar keeps its height in full screen
|
||||||
windowData.lastWindowButtonAreaWidth = getWindowButtonAreaWidth( nsWindow );
|
windowData.lastWindowButtonAreaWidth = getWindowButtonAreaWidth( nsWindow );
|
||||||
windowData.lastWindowTitleBarHeight = getWindowTitleBarHeight( nsWindow );
|
windowData.lastWindowTitleBarHeight = getWindowTitleBarHeight( nsWindow );
|
||||||
|
// NSLog(@"%d %d",windowData.lastWindowButtonAreaWidth,windowData.lastWindowTitleBarHeight);
|
||||||
|
|
||||||
nsWindow.toolbar.visible = NO;
|
nsWindow.toolbar.visible = NO;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user