Skip to content

Commit

Permalink
Fix corner radius for macos popups
Browse files Browse the repository at this point in the history
  • Loading branch information
weisJ committed Jul 17, 2024
1 parent d60dfaf commit 8f5b1b0
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 16 deletions.
20 changes: 11 additions & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.github.vlsi.gradle.publishing.dsl.simplifyXml
import com.github.vlsi.gradle.publishing.dsl.versionFromResolution
import net.ltgt.gradle.errorprone.errorprone
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import java.util.*
import java.util.Locale

plugins {
idea
Expand Down Expand Up @@ -96,7 +96,7 @@ allprojects {
github(
user = "weisj",
repository = "darklaf",
workflow = "libs.yml"
workflow = "libs.yml",
) {
branches = listOfNotNull(currentBranch, "master", "v$projectVersion", projectVersion)
accessToken = githubAccessToken
Expand Down Expand Up @@ -188,7 +188,7 @@ allprojects {
configure<SigningExtension> {
useInMemoryPgpKeys(
project.stringProperty("signing.inMemoryKey")?.replace("#", "\n"),
project.stringProperty("signing.password")
project.stringProperty("signing.password"),
)
}
}
Expand All @@ -213,7 +213,7 @@ allprojects {
disable(
"StringSplitter",
"InlineMeSuggester",
"MissingSummary"
"MissingSummary",
)
}
}
Expand Down Expand Up @@ -314,16 +314,18 @@ allprojects {

description.set(
project.description
?: "A themeable Look and Feel for java swing"
?: "A themeable Look and Feel for java swing",
)
name.set(
(project.findProperty("artifact.name") as? String)
?: project.name
.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault())
else it.toString()
}
.replace("-", " ")
if (it.isLowerCase()) {
it.titlecase(Locale.getDefault())
} else {
it.toString()
}
}.replace("-", " "),
)
url.set("https://github.com/weisJ/darklaf")
organization {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2023 Jannis Weis
* Copyright (c) 2023-2024 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,
Expand All @@ -25,8 +25,9 @@
import javax.swing.border.Border;

import com.github.weisj.darklaf.graphics.PaintUtil;
import com.github.weisj.darklaf.platform.RoundedFrame;

public class RoundedLineBorder implements Border {
public class RoundedLineBorder implements Border, RoundedFrame {

private final Color color;
private final int arc;
Expand All @@ -38,6 +39,21 @@ public RoundedLineBorder(final Color color, final int arc, final int thickness)
this.thickness = thickness;
}

@Override
public int getRadius() {
return arc;
}

@Override
public Color getColor() {
return color;
}

@Override
public int getThickness() {
return thickness;
}

@Override
public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width,
final int height) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2019-2023 Jannis Weis
* Copyright (c) 2019-2024 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,
Expand Down Expand Up @@ -109,14 +109,14 @@ protected void configureScroller() {
protected void configurePopup() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorderPainted(true);
setOpaque(false);
add(overlayScrollPane);
setFocusable(false);
setOpaque(true);
}

@Override
public void show() {
setBackground(new Color(list.getBackground().getRGB()));
comboBox.firePopupMenuWillBecomeVisible();
setListSelection(comboBox.getSelectedIndex());
Point location = getPopupLocation();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2019-2022 Jannis Weis
* Copyright (c) 2019-2024 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,
Expand Down Expand Up @@ -34,6 +34,8 @@ public final class JNIDecorationsMacOS {

public static native void installDecorations(final long hwnd);

public static native void installPopup(final long hwnd, final int radius, final int thickness, final int rgb);

public static native void uninstallDecorations(final long hwnd,
final boolean fullSizeContent, final boolean transparentTitleBar);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2019-2022 Jannis Weis
* Copyright (c) 2019-2024 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,
Expand All @@ -25,8 +25,11 @@
import java.util.List;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;

import com.github.weisj.darklaf.platform.*;
import com.github.weisj.darklaf.platform.macos.ui.MacOSDecorationsUtil;
import com.github.weisj.darklaf.platform.macos.ui.MacOSTitlePane;

public class MacOSDecorationsProvider implements DecorationsProvider {
Expand Down Expand Up @@ -58,6 +61,40 @@ public List<String> getPropertyResourcePaths() {
return Collections.singletonList("macos_decorations");
}

@Override
public void installPopupWindow(final Window window) {
if (!window.isDisplayable()) {
window.addNotify();
}
if (window instanceof RootPaneContainer) {
JRootPane rootPane = ((RootPaneContainer) window).getRootPane();
Border border = getOutermostBorder((JComponent) rootPane.getContentPane());
while (border instanceof CompoundBorder) {
border = ((CompoundBorder) border).getOutsideBorder();
}
if (border instanceof RoundedFrame) {
MacOSDecorationsUtil.installPopupWindow(window,
((RoundedFrame) border).getRadius(),
((RoundedFrame) border).getThickness(),
((RoundedFrame) border).getColor().getRGB());
window.repaint();
}
}
}

private static Border getOutermostBorder(final JComponent component) {
JComponent c = component;
while (c.getComponentCount() == 1 && c.getBorder() == null) {
JComponent child = (JComponent) c.getComponent(0);
if (child.getWidth() == c.getWidth() && child.getHeight() == c.getHeight()) {
c = child;
} else {
break;
}
}
return c.getBorder();
}

@Override
public boolean supportsNativeTitleLabel() {
return SystemInfo.isMacOSMojave;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2020-2022 Jannis Weis
* Copyright (c) 2020-2024 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,
Expand Down Expand Up @@ -69,6 +69,11 @@ static DecorationInformation installDecorations(final JRootPane rootPane,
rootPane, titleVisible, titleBarHeight, titleFontSize);
}

public static void installPopupWindow(final Window window, final int radius, final int thickness, final int rgb) {
long windowHandle = JNIDecorationsMacOS.getComponentPointer(window);
JNIDecorationsMacOS.installPopup(windowHandle, radius, thickness, radius);
}

private static void setFullSizeContent(final long windowHandle, final boolean enabled) {
if (enabled) {
JNIDecorationsMacOS.installDecorations(windowHandle);
Expand Down
30 changes: 30 additions & 0 deletions macos/src/main/objcpp/Decorations.mm
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,36 @@
JNF_COCOA_EXIT(env);
}

JNIEXPORT void JNICALL
Java_com_github_weisj_darklaf_platform_macos_JNIDecorationsMacOS_installPopup(JNIEnv *env, jclass obj, jlong hwnd, jint radius, jint borderWidth, jint borderColor) {
JNF_COCOA_ENTER(env);
NSWindow *nsWindow = OBJC(hwnd);
[JNF_RunLoop performOnMainThreadWaiting:YES withBlock:^{
nsWindow.hasShadow = YES;
nsWindow.contentView.wantsLayer = YES;
nsWindow.contentView.layer.cornerRadius = radius;
nsWindow.contentView.layer.masksToBounds = YES;

nsWindow.backgroundColor = NSColor.clearColor;
nsWindow.opaque = NO;

nsWindow.contentView.layer.borderWidth = borderWidth;
if( borderWidth > 0 ) {
CGFloat red = ((borderColor >> 16) & 0xff) / 255.;
CGFloat green = ((borderColor >> 8) & 0xff) / 255.;
CGFloat blue = (borderColor & 0xff) / 255.;
CGFloat alpha = ((borderColor >> 24) & 0xff) / 255.;

nsWindow.contentView.layer.borderColor = [[NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha] CGColor];
}

nsWindow.contentView.needsDisplay = YES;
[nsWindow.contentView.layer removeAllAnimations];
[nsWindow invalidateShadow];
}];
JNF_COCOA_EXIT(env);
}

NSRect join(NSRect r, NSButton* button) {
NSRect buttonRect = [button convertRect: [button bounds] toView: nil];
return NSUnionRect(r, buttonRect);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* MIT License
*
* Copyright (c) 2024 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 interface RoundedFrame {
int getRadius();

Color getColor();

int getThickness();
}

0 comments on commit 8f5b1b0

Please sign in to comment.