diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h index ab33c7d8adef..94a4f4035492 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h @@ -76,6 +76,7 @@ @property (nonatomic, retain) NSNumber *currentDisplayID; @property (nonatomic, readonly) CGFloat customTitleBarHeight; @property (nonatomic) BOOL customTitleBarControlsVisible; +@property (nonatomic) BOOL customTitleBarControlsRtl; @property (nonatomic, retain) NSMutableArray *customTitleBarConstraints; @property (nonatomic, retain) NSLayoutConstraint *customTitleBarHeightConstraint; @property (nonatomic, retain) NSMutableArray *customTitleBarButtonCenterXConstraints; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index d6fc31b4ac2c..7c7aa6b94838 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -1390,6 +1390,7 @@ - (CGFloat) customTitleBarHeight { DECLARE_CLASS_RETURN(jc_Window, "java/awt/Window", 0.0f); DECLARE_METHOD_RETURN(jm_internalCustomTitleBarHeight, jc_Window, "internalCustomTitleBarHeight", "()F", 0.0f); DECLARE_METHOD_RETURN(jm_internalCustomTitleBarControlsVisible, jc_Window, "internalCustomTitleBarControlsVisible", "()Z", 0.0f); + DECLARE_METHOD_RETURN(jm_internalCustomTitleBarControlsRtl, jc_Window, "internalCustomTitleBarControlsRtl", "()Z", 0.0f); jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow); if (!platformWindow) return 0.0f; @@ -1399,6 +1400,9 @@ - (CGFloat) customTitleBarHeight { if (!(*env)->ExceptionCheck(env)) { self.customTitleBarControlsVisible = (BOOL) (*env)->CallBooleanMethod(env, target, jm_internalCustomTitleBarControlsVisible); } + if (!(*env)->ExceptionCheck(env)) { + self.customTitleBarControlsRtl = (BOOL) (*env)->CallBooleanMethod(env, target, jm_internalCustomTitleBarControlsRtl); + } (*env)->DeleteLocalRef(env, target); } CHECK_EXCEPTION(); @@ -1433,7 +1437,11 @@ - (void) updateCustomTitleBarInsets:(BOOL)hasControls { if (!platformWindow) return; jobject target = (*env)->GetObjectField(env, platformWindow, jf_target); if (target) { - (*env)->CallVoidMethod(env, target, jm_internalCustomTitleBarUpdateInsets, (jfloat) leftInset, (jfloat) 0.0f); + if (self.customTitleBarControlsRtl) { + (*env)->CallVoidMethod(env, target, jm_internalCustomTitleBarUpdateInsets, (jfloat) 0.0f, (jfloat) leftInset); + } else { + (*env)->CallVoidMethod(env, target, jm_internalCustomTitleBarUpdateInsets, (jfloat) leftInset, (jfloat) 0.0f); + } (*env)->DeleteLocalRef(env, target); } CHECK_EXCEPTION(); @@ -1704,12 +1712,15 @@ - (void) setUpCustomTitleBar { CGFloat shrinkingFactor = self.customTitleBarButtonShrinkingFactor; CGFloat horizontalButtonOffset = shrinkingFactor * DefaultHorizontalTitleBarButtonOffset; + BOOL rtl = self.customTitleBarControlsRtl; + NSLayoutAnchor* anchorX = rtl ? titlebarContainer.rightAnchor : titlebarContainer.leftAnchor; self.customTitleBarButtonCenterXConstraints = [[NSMutableArray alloc] initWithCapacity:3]; [@[closeButtonView, miniaturizeButtonView, zoomButtonView] enumerateObjectsUsingBlock:^(NSView* button, NSUInteger index, BOOL* stop) { button.translatesAutoresizingMaskIntoConstraints = NO; - NSLayoutConstraint* buttonCenterXConstraint = [button.centerXAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor - constant:(self.customTitleBarHeight / 2.0 + (index * horizontalButtonOffset))]; + CGFloat offset = self.customTitleBarHeight / 2.0 + (index * horizontalButtonOffset); + NSLayoutConstraint* buttonCenterXConstraint = [button.centerXAnchor constraintEqualToAnchor:anchorX + constant:(rtl ? -offset : offset)]; [self.customTitleBarButtonCenterXConstraints addObject:buttonCenterXConstraint]; [self.customTitleBarConstraints addObjectsFromArray:@[ [button.widthAnchor constraintLessThanOrEqualToAnchor:titlebarContainer.heightAnchor multiplier:0.5], @@ -1733,9 +1744,11 @@ - (void) updateCustomTitleBarConstraints { self.customTitleBarHeightConstraint.constant = self.customTitleBarHeight; CGFloat shrinkingFactor = self.customTitleBarButtonShrinkingFactor; CGFloat horizontalButtonOffset = shrinkingFactor * DefaultHorizontalTitleBarButtonOffset; + BOOL rtl = self.customTitleBarControlsRtl; [self.customTitleBarButtonCenterXConstraints enumerateObjectsUsingBlock:^(NSLayoutConstraint* buttonConstraint, NSUInteger index, BOOL *stop) { - buttonConstraint.constant = (self.customTitleBarHeight / 2.0 + (index * horizontalButtonOffset)); + CGFloat offset = self.customTitleBarHeight / 2.0 + (index * horizontalButtonOffset); + buttonConstraint.constant = rtl ? -offset : offset; }]; [self setWindowControlsHidden:!self.customTitleBarControlsVisible]; [self updateCustomTitleBarInsets:self.customTitleBarControlsVisible]; @@ -1850,10 +1863,17 @@ - (void)updateFullScreenButtons { NSView *parent = self.nsWindow.contentView; CGFloat w = 80; CGFloat h = _fullScreenOriginalButtons.frame.size.height; - CGFloat x = 6; + CGFloat inset = 6; + CGFloat buttonsWidth = w - inset; + CGFloat x; + if (self.customTitleBarControlsRtl) { + x = parent.frame.size.width - buttonsWidth; + } else { + x = inset; + } CGFloat y = parent.frame.size.height - h - (self.customTitleBarHeight - h) / 2.0; - [_fullScreenButtons setFrame:NSMakeRect(x, y, w - x, h)]; + [_fullScreenButtons setFrame:NSMakeRect(x, y, buttonsWidth, h)]; } - (void)updateFullScreenButtons: (BOOL) dfm { @@ -1891,9 +1911,11 @@ - (void) forceHideCustomTitleBarTitle: (BOOL) hide { } - (void) updateCustomTitleBar { + BOOL oldRtl = self.customTitleBarControlsRtl; _customTitleBarHeight = -1.0f; // Reset for lazy init BOOL enabled = self.isCustomTitleBarEnabled; BOOL fullscreen = self.isFullScreen; + BOOL rtlChanged = (oldRtl != self.customTitleBarControlsRtl); jint mask = [AWTWindow affectedStyleMaskForCustomTitleBar]; jint newBits = [AWTWindow overrideStyleBits:self.styleBits customTitleBarEnabled:enabled fullscreen:fullscreen]; @@ -1920,7 +1942,7 @@ - (void) updateCustomTitleBar { [self _deliverMoveResizeEvent]; } - if (enabled != (self.customTitleBarConstraints != nil)) { + if (enabled != (self.customTitleBarConstraints != nil) || (enabled && rtlChanged)) { if (!fullscreen) { if (self.isCustomTitleBarEnabled) { [self setUpCustomTitleBar]; diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index eab59bc19817..73e917e53527 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -4023,6 +4023,14 @@ private boolean internalCustomTitleBarControlsVisible() { CustomTitleBar t = customTitleBar; return t == null || Boolean.TRUE.equals(t.getProperties().getOrDefault("controls.visible", Boolean.TRUE)); } + /** + * Convenience method for JNI access. + * @return true if custom title bar controls should be on the right (RTL). + */ + private boolean internalCustomTitleBarControlsRtl() { + CustomTitleBar t = customTitleBar; + return t != null && Boolean.TRUE.equals(t.getProperties().get("controls.rtl")); + } /** * Convenience method for JNI access. */