Browse Source

Expose bounds of title bar buttons

This is especially useful on macOS with fullSizeContentView enabled
to ensure components in the title bar area don't get obscured by the
buttons.
titlebar_button_bounds
Jannis Weis 3 years ago
parent
commit
eb2a7057ce
No known key found for this signature in database
GPG Key ID: 7C9D8D4B558049AB
  1. 4
      macos/src/main/java/com/github/weisj/darklaf/platform/macos/JNIDecorationsMacOS.java
  2. 14
      macos/src/main/java/com/github/weisj/darklaf/platform/macos/MacOSDecorationsProvider.java
  3. 4
      macos/src/main/java/com/github/weisj/darklaf/platform/macos/ui/MacOSTitlePane.java
  4. 26
      macos/src/main/objcpp/Decorations.mm
  5. 8
      platform-base/src/main/java/com/github/weisj/darklaf/platform/DecorationsProvider.java
  6. 35
      platform-base/src/main/java/com/github/weisj/darklaf/platform/TitlePaneLayoutInfo.java
  7. 5
      platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/DefaultDecorationsProvider.java
  8. 8
      platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/NativeDecorationsManager.java
  9. 12
      windows/src/main/java/com/github/weisj/darklaf/platform/windows/WindowsDecorationsProvider.java
  10. 15
      windows/src/main/java/com/github/weisj/darklaf/platform/windows/ui/WindowsTitlePane.java

4
macos/src/main/java/com/github/weisj/darklaf/platform/macos/JNIDecorationsMacOS.java

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2019-2021 Jannis Weis
* Copyright (c) 2019-2022 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
@ -44,4 +44,6 @@ public final class JNIDecorationsMacOS {
public static native boolean isFullscreen(final long hwnd);
public static native double getTitleFontSize(final long hwnd);
public static native float[] windowButtonRect(final long hwnd);
}

14
macos/src/main/java/com/github/weisj/darklaf/platform/macos/MacOSDecorationsProvider.java

@ -26,10 +26,7 @@ import java.util.List;
import javax.swing.*;
import com.github.weisj.darklaf.platform.CustomTitlePane;
import com.github.weisj.darklaf.platform.DecorationsProvider;
import com.github.weisj.darklaf.platform.SystemInfo;
import com.github.weisj.darklaf.platform.UnsupportedProviderException;
import com.github.weisj.darklaf.platform.*;
import com.github.weisj.darklaf.platform.macos.ui.MacOSTitlePane;
public class MacOSDecorationsProvider implements DecorationsProvider {
@ -65,4 +62,13 @@ public class MacOSDecorationsProvider implements DecorationsProvider {
public boolean supportsNativeTitleLabel() {
return SystemInfo.isMacOSMojave;
}
@Override
public TitlePaneLayoutInfo titlePaneLayoutInfo(final CustomTitlePane customTitlePane) {
if (!(customTitlePane instanceof MacOSTitlePane)) throw new IllegalStateException();
long hwnd = ((MacOSTitlePane) customTitlePane).windowHandle();
if (hwnd == 0) return new TitlePaneLayoutInfo(new Rectangle(0, 0, -1, -1));
float[] b = JNIDecorationsMacOS.windowButtonRect(((MacOSTitlePane) customTitlePane).windowHandle());
return new TitlePaneLayoutInfo(new Rectangle((int) b[0], (int) b[1], (int) b[2], (int) b[3]));
}
}

4
macos/src/main/java/com/github/weisj/darklaf/platform/macos/ui/MacOSTitlePane.java

@ -198,6 +198,10 @@ public class MacOSTitlePane extends CustomTitlePane {
return new RootPanePropertyChangeListener();
}
public long windowHandle() {
return decorationInformation.windowHandle;
}
protected class RootPanePropertyChangeListener implements PropertyChangeListener {
@Override

26
macos/src/main/objcpp/Decorations.mm

@ -155,3 +155,29 @@ JNF_COCOA_ENTER(env);
}];
JNF_COCOA_EXIT(env);
}
NSRect join(NSRect r, NSButton* button) {
NSRect buttonRect = [button convertRect: [button bounds] toView: nil];
return NSUnionRect(r, buttonRect);
}
JNIEXPORT jfloatArray JNICALL
Java_com_github_weisj_darklaf_platform_macos_JNIDecorationsMacOS_windowButtonRect(JNIEnv *env, jclass, jlong hwnd) {
JNF_COCOA_ENTER(env);
NSWindow *nsWindow = OBJC(hwnd);
NSButton *closeButton = [nsWindow standardWindowButton: NSWindowCloseButton];
NSButton *minimizeButton = [nsWindow standardWindowButton: NSWindowMiniaturizeButton];
NSButton *zoomButton = [nsWindow standardWindowButton: NSWindowZoomButton];
NSRect rect = NSMakeRect(0,0, -1, -1);
if (closeButton) rect = join(rect, closeButton);
if (minimizeButton) rect = join(rect, minimizeButton);
if (zoomButton) rect = join(rect, zoomButton);
jfloatArray bounds = env->NewFloatArray(4);
jfloat rawBounds[4] = {rect.origin.x, rect.origin.y, rect.size.width, rect.size.height};
env->SetFloatArrayRegion(bounds, 0, 0, rawBounds);
return bounds;
JNF_COCOA_EXIT(env);
}

8
platform-base/src/main/java/com/github/weisj/darklaf/platform/DecorationsProvider.java

@ -77,4 +77,12 @@ public interface DecorationsProvider {
default boolean supportsNativeTitleLabel() {
return false;
}
/**
* Compute the layout information for the title pane.
*
* @param customTitlePane the given title pane
* @return information about the layout of the title pane
*/
TitlePaneLayoutInfo titlePaneLayoutInfo(final CustomTitlePane customTitlePane);
}

35
platform-base/src/main/java/com/github/weisj/darklaf/platform/TitlePaneLayoutInfo.java

@ -0,0 +1,35 @@
/*
* MIT License
*
* Copyright (c) 2022 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.github.weisj.darklaf.platform;
import java.awt.*;
public class TitlePaneLayoutInfo {
private final Rectangle windowButtonRect;
public TitlePaneLayoutInfo(final Rectangle windowButtonRect) {
this.windowButtonRect = windowButtonRect;
}
public Rectangle windowButtonRect() {
return windowButtonRect;
}
}

5
platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/DefaultDecorationsProvider.java

@ -28,6 +28,7 @@ import javax.swing.*;
import com.github.weisj.darklaf.platform.CustomTitlePane;
import com.github.weisj.darklaf.platform.DecorationsProvider;
import com.github.weisj.darklaf.platform.TitlePaneLayoutInfo;
class DefaultDecorationsProvider implements DecorationsProvider {
@ -59,4 +60,8 @@ class DefaultDecorationsProvider implements DecorationsProvider {
return Collections.emptyList();
}
@Override
public TitlePaneLayoutInfo titlePaneLayoutInfo(final CustomTitlePane customTitlePane) {
return new TitlePaneLayoutInfo(new Rectangle());
}
}

8
platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/NativeDecorationsManager.java

@ -24,10 +24,12 @@ import java.awt.*;
import java.util.Properties;
import javax.swing.*;
import javax.swing.plaf.RootPaneUI;
import com.github.weisj.darklaf.platform.CustomTitlePane;
import com.github.weisj.darklaf.platform.DecorationsProvider;
import com.github.weisj.darklaf.platform.SystemInfo;
import com.github.weisj.darklaf.platform.TitlePaneLayoutInfo;
import com.github.weisj.darklaf.platform.macos.MacOSDecorationsProvider;
import com.github.weisj.darklaf.platform.windows.WindowsDecorationsProvider;
import com.github.weisj.darklaf.properties.PropertyLoader;
@ -114,4 +116,10 @@ public class NativeDecorationsManager {
public boolean supportsNativeTitleText() {
return decorationsProvider.supportsNativeTitleLabel();
}
public TitlePaneLayoutInfo titlePaneLayoutInfo(final RootPaneContainer frameOrDialog) {
RootPaneUI ui = frameOrDialog.getRootPane().getUI();
if (!(ui instanceof AbstractNativeDecorationsRootPaneUI)) throw new IllegalStateException();
return decorationsProvider.titlePaneLayoutInfo(((AbstractNativeDecorationsRootPaneUI) ui).titlePane());
}
}

12
windows/src/main/java/com/github/weisj/darklaf/platform/windows/WindowsDecorationsProvider.java

@ -27,10 +27,7 @@ import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
import com.github.weisj.darklaf.platform.CustomTitlePane;
import com.github.weisj.darklaf.platform.DecorationsProvider;
import com.github.weisj.darklaf.platform.SystemInfo;
import com.github.weisj.darklaf.platform.UnsupportedProviderException;
import com.github.weisj.darklaf.platform.*;
import com.github.weisj.darklaf.platform.windows.ui.WindowsTitlePane;
public class WindowsDecorationsProvider implements DecorationsProvider {
@ -96,6 +93,13 @@ public class WindowsDecorationsProvider implements DecorationsProvider {
}
}
@Override
public TitlePaneLayoutInfo titlePaneLayoutInfo(final CustomTitlePane customTitlePane) {
if (!(customTitlePane instanceof WindowsTitlePane)) throw new IllegalStateException();
WindowsTitlePane titlePane = (WindowsTitlePane) customTitlePane;
return new TitlePaneLayoutInfo(titlePane.windowButtonRect());
}
@Override
public List<String> getPropertyResourcePaths() {
ArrayList<String> properties = new ArrayList<>();

15
windows/src/main/java/com/github/weisj/darklaf/platform/windows/ui/WindowsTitlePane.java

@ -26,6 +26,7 @@ import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.function.Consumer;
import java.util.logging.Logger;
import javax.accessibility.AccessibleContext;
@ -689,6 +690,20 @@ public class WindowsTitlePane extends CustomTitlePane {
}
}
public Rectangle windowButtonRect() {
Rectangle rect = new Rectangle(0, 0, -1, -1);
if (hideTitleBar()) return rect;
Consumer<JComponent> joinRect = c -> {
if (c != null && c.isVisible()) {
rect.setBounds(rect.union(c.getBounds()));
}
};
joinRect.accept(closeButton);
joinRect.accept(maximizeToggleButton);
joinRect.accept(minimizeButton);
return rect;
}
private abstract class TitlePaneAction extends AbstractAction {
private TitlePaneAction(Icon icon, String... resourceNames) {
super("", icon);

Loading…
Cancel
Save