diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java index 65df59cd..059dedb0 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeMacLibrary.java @@ -54,7 +54,7 @@ public class FlatNativeMacLibrary public native static boolean setWindowRoundedBorder( Window window, float radius, float borderWidth, int borderColor ); - public native static void setWindowToolbar( Window window, boolean hasToolbar ); + public native static boolean setWindowToolbar( Window window, boolean hasToolbar ); public native static int getWindowButtonAreaWidth( Window window ); public native static int getWindowTitleBarHeight( Window window ); public native static boolean isWindowFullScreen( Window window ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarBorder.java index 4d66a4a1..f6c17873 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarBorder.java @@ -116,11 +116,7 @@ public class FlatToolBarBorder } // on macOS, add some extra space to left side for close/minimize/zoom buttons (if necessary) - if( c instanceof JToolBar && - FlatToolBarUI.isMacOSMainToolbar( (JToolBar) c ) && - (!FlatNativeMacLibrary.isLoaded() || - !FlatNativeMacLibrary.isWindowFullScreen( SwingUtilities.windowForComponent( c ) )) ) - { + if( c instanceof JToolBar && FlatToolBarUI.isMacOSMainToolbar( (JToolBar) c ) ) { // get button area width from macOS int buttonBarWidth = FlatNativeMacLibrary.isLoaded() ? FlatNativeMacLibrary.getWindowButtonAreaWidth( SwingUtilities.windowForComponent( c ) ) diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-arm64.dylib b/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-arm64.dylib index e29df3b1..61b6e9cd 100755 Binary files a/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-arm64.dylib and b/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-arm64.dylib differ diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-x86_64.dylib b/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-x86_64.dylib index bb1c221c..084b58ca 100755 Binary files a/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-x86_64.dylib and b/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-x86_64.dylib differ diff --git a/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h b/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h index 7964d7f2..f7669308 100644 --- a/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/headers/com_formdev_flatlaf_ui_FlatNativeMacLibrary.h @@ -18,9 +18,9 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW /* * Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary * Method: setWindowToolbar - * Signature: (Ljava/awt/Window;Z)V + * Signature: (Ljava/awt/Window;Z)Z */ -JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowToolbar +JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowToolbar (JNIEnv *, jclass, jobject, jboolean); /* diff --git a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacWindow.mm b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacWindow.mm index 62c41c7a..cc04908a 100644 --- a/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacWindow.mm +++ b/flatlaf-natives/flatlaf-natives-macos/src/main/objcpp/MacWindow.mm @@ -25,6 +25,27 @@ * @author Karl Tauber */ +@interface WindowData : NSObject + // used when window is full screen + @property (nonatomic) int lastWindowButtonAreaWidth; + @property (nonatomic) int lastWindowTitleBarHeight; + + // full screen observers + @property (nonatomic) id willEnterFullScreenObserver; + @property (nonatomic) id didExitFullScreenObserver; +@end + +@implementation WindowData +@end + +// declare internal methods +NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ); +WindowData* getWindowData( NSWindow* nsWindow, bool allocate ); +int getWindowButtonAreaWidth( NSWindow* nsWindow ); +int getWindowTitleBarHeight( NSWindow* nsWindow ); +bool isWindowFullScreen( NSWindow* nsWindow ); + + NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) { if( window == NULL ) return NULL; @@ -50,6 +71,16 @@ NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) { return (NSWindow *) jlong_to_ptr( env->GetLongField( platformWindow, ptrID ) ); } +WindowData* getWindowData( NSWindow* nsWindow, bool allocate ) { + static char key; + WindowData* windowData = objc_getAssociatedObject( nsWindow, &key ); + if( windowData == NULL && allocate ) { + windowData = [WindowData new]; + objc_setAssociatedObject( nsWindow, &key, windowData, OBJC_ASSOCIATION_RETAIN_NONATOMIC ); + } + return windowData; +} + extern "C" JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowRoundedBorder ( JNIEnv* env, jclass cls, jobject window, jfloat radius, jfloat borderWidth, jint borderColor ) @@ -90,20 +121,22 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW } extern "C" -JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowToolbar +JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowToolbar ( JNIEnv* env, jclass cls, jobject window, jboolean hasToolbar ) { JNI_COCOA_ENTER() NSWindow* nsWindow = getNSWindow( env, cls, window ); if( nsWindow == NULL ) - return; + return FALSE; if( hasToolbar == (nsWindow.toolbar != NULL) ) - return; + return TRUE; + + WindowData* windowData = getWindowData( nsWindow, true ); [FlatJNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ - NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] ); +// NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] ); // add/remove toolbar NSToolbar* toolbar = NULL; @@ -113,45 +146,51 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindo } nsWindow.toolbar = toolbar; - 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 // because it otherwise is shown non-transparent and hides Swing components - static char enterObserverKey; - static char exitObserverKey; NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; if( hasToolbar ) { - NSLog( @"add observers %@", nsWindow ); - id enterObserver = [center addObserverForName:NSWindowWillEnterFullScreenNotification +// NSLog( @"add observers %@", nsWindow ); + windowData.willEnterFullScreenObserver = [center addObserverForName:NSWindowWillEnterFullScreenNotification object:nsWindow queue:nil usingBlock:^(NSNotification *note) { - NSLog( @"enter full screen %@", nsWindow ); - if( nsWindow.toolbar != NULL ) +// NSLog( @"enter full screen %@", nsWindow ); + if( nsWindow.toolbar != NULL ) { + // remember button area width, which is used later when window exits full screen + // remembar title bar height so that "main" JToolBar keeps its height in full screen + windowData.lastWindowButtonAreaWidth = getWindowButtonAreaWidth( nsWindow ); + windowData.lastWindowTitleBarHeight = getWindowTitleBarHeight( nsWindow ); + nsWindow.toolbar.visible = NO; + } }]; - id exitObserver = [center addObserverForName:NSWindowDidExitFullScreenNotification + windowData.didExitFullScreenObserver = [center addObserverForName:NSWindowDidExitFullScreenNotification object:nsWindow queue:nil usingBlock:^(NSNotification *note) { - NSLog( @"exit full screen %@", nsWindow ); +// NSLog( @"exit full screen %@", nsWindow ); if( nsWindow.toolbar != NULL ) nsWindow.toolbar.visible = YES; + + windowData.lastWindowButtonAreaWidth = 0; + windowData.lastWindowTitleBarHeight = 0; }]; - objc_setAssociatedObject( nsWindow, &enterObserverKey, enterObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC ); - objc_setAssociatedObject( nsWindow, &exitObserverKey, exitObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC ); } else { - NSLog( @"remove observers %@", nsWindow ); - id enterObserver = objc_getAssociatedObject( nsWindow, &enterObserverKey ); - id exitObserver = objc_getAssociatedObject( nsWindow, &exitObserverKey ); - if( enterObserver != NULL ) { - [center removeObserver:enterObserver]; - objc_setAssociatedObject( nsWindow, &enterObserverKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC ); +// NSLog( @"remove observers %@", nsWindow ); + if( windowData.willEnterFullScreenObserver != NULL ) { + [center removeObserver:windowData.willEnterFullScreenObserver]; + windowData.willEnterFullScreenObserver = nil; } - if( exitObserver != NULL ) { - [center removeObserver:exitObserver]; - objc_setAssociatedObject( nsWindow, &exitObserverKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC ); + if( windowData.didExitFullScreenObserver != NULL ) { + [center removeObserver:windowData.didExitFullScreenObserver]; + windowData.didExitFullScreenObserver = nil; } } }]; + return TRUE; + JNI_COCOA_EXIT() + return FALSE; } extern "C" @@ -164,6 +203,23 @@ JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_getWindo if( nsWindow == NULL ) return -1; + // return zero if window is full screen because close/minimize/zoom buttons are hidden + if( isWindowFullScreen( nsWindow ) ) + return 0; + + // use remembered value if window is in transition from full screen to non-full screen + // because NSToolbar is not yet visible + WindowData* windowData = getWindowData( nsWindow, false ); + if( windowData != NULL && windowData.lastWindowButtonAreaWidth > 0 ) + return windowData.lastWindowButtonAreaWidth; + + return getWindowButtonAreaWidth( nsWindow ); + + JNI_COCOA_EXIT() + return -1; +} + +int getWindowButtonAreaWidth( NSWindow* nsWindow ) { // get buttons NSView* buttons[3] = { [nsWindow standardWindowButton:NSWindowCloseButton], @@ -193,8 +249,6 @@ JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_getWindo // 'right' is the actual button area width (from left window edge) // adding 'left' to add same empty space on right side as on left side return right + left; - - JNI_COCOA_EXIT() } extern "C" @@ -207,14 +261,24 @@ JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_getWindo if( nsWindow == NULL ) return -1; + // use remembered value if window is full screen because NSToolbar is hidden + WindowData* windowData = getWindowData( nsWindow, false ); + if( windowData != NULL && windowData.lastWindowTitleBarHeight > 0 ) + return windowData.lastWindowTitleBarHeight; + + return getWindowTitleBarHeight( nsWindow ); + + JNI_COCOA_EXIT() + return -1; +} + +int getWindowTitleBarHeight( NSWindow* nsWindow ) { NSView* closeButton = [nsWindow standardWindowButton:NSWindowCloseButton]; if( closeButton == NULL ) return -1; NSView* titlebar = closeButton.superview; return titlebar.bounds.size.height; - - JNI_COCOA_EXIT() } extern "C" @@ -227,8 +291,12 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_isWi if( nsWindow == NULL ) return FALSE; - return (jboolean) (([nsWindow styleMask] & NSWindowStyleMaskFullScreen) != 0); + return (jboolean) isWindowFullScreen( nsWindow ); JNI_COCOA_EXIT() + return FALSE; } +bool isWindowFullScreen( NSWindow* nsWindow ) { + return ((nsWindow.styleMask & NSWindowStyleMaskFullScreen) != 0); +}