Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dark Mode and brushMetalLook #34

Open
sreilly opened this issue Oct 3, 2018 · 8 comments
Open

Dark Mode and brushMetalLook #34

sreilly opened this issue Oct 3, 2018 · 8 comments
Labels
bug Something isn't working minor

Comments

@sreilly
Copy link
Contributor

sreilly commented Oct 3, 2018

Original report by me.


I've been using a copy of appbundler compiled a couple years ago to build my app launchers, but recently took a look at making some changes and re-compiled. When launching my app using the new launcher, I found the appearance had changed. The apple.awt.brushMetalLook property had been applied to the app's frame root panes and...

  1. On a Mac upgraded to Mojave and set Dark Mode, not only was the title bar dark, but areas where the brush-metal look should have been visible were also dark.

  2. On a Mac using High Sierra and on the Mojave Mac in Light Mode, the color of the brush-metal look areas had changed slightly and there was no longer a clean transition between the title bar at the top of the window and a toolbar area directly below it.

This isn't really a bug with appbundler so much as a warning to others that might be using brush-metal look to be wary. It took me a couple hours to figure out that the problem described in (2) above was not something I messed up in my own code but was due to changes elsewhere.

Luckily I held onto my older compiled copy of appbundler and can continue to use it until I update my app's look to no longer use the brush-metal look.

I also tried modifying the appbundler native code to check if Dark Mode was enabled and to set a flag to be passed to the Java app, but that somehow caused the launcher to crash and burn. If anyone else figures out to pass dark-mode info to the Java code, I'd like to know how you did it.

@sreilly
Copy link
Contributor Author

sreilly commented Oct 5, 2018

I believe I figured out how to get app bundler to pass along whether Dark Mode is on when starting up a java app without crashing. But of course, it only works at the launch time. If the user switches between Dark and Light Mode while the Java app is running, that's another issue to solve.

If anyone thinks this is useful, comment here, and I'll add it to the appbundler code.

@sreilly
Copy link
Contributor Author

sreilly commented Oct 9, 2018

Personally, I'd love to see support for Dark/Light Mode detection upon startup. Even better would be a way to update the mode status while running... even if it's just changing an entry in the system properties.

@sreilly
Copy link
Contributor Author

sreilly commented Oct 10, 2018

I've pushed a commit for the initial detection. After that,...?

@sreilly
Copy link
Contributor Author

sreilly commented Oct 17, 2018

Not so keen on the dark mode but I've noticed the changed appearance of apple.awt.brushMetalLook switch. It intrigues me because launching the jar from the command line looks different and correct. Not enough expertise to investigate but this looks very much an issue with the launcher.

edit: no luck scouring the jdk sources I'm not an ObjC developer. However with the Digital Colour Meter it is clear that the title bar is the only colour that varies with a smooth gradient if launched from the command line java -jar, and a much narrower gradient launched from main.m in the appbundler repo via libjli.dylib interface. So not really an appbundler issue as far as I can tell since this seems the approved way to launch.

However, it looks to me that the dark mode switching is an incidental side-effect of the launcher and the recent (Mojave) changes to Apple's platform. I'd be surprised if it is officially supported so I would suggest holding off customizing your launcher. It only seems to effect the textured window background see CPlatformWindow.java in jdk sources.

@sreilly sreilly closed this as completed Dec 1, 2018
@sreilly sreilly added minor bug Something isn't working labels May 31, 2019
@patrickangle
Copy link

patrickangle commented Feb 4, 2020

If at all possible, can this issue be reopened, as it was never really resolved.

For what it's worth, I've run in to the same issue. After some brief experimentation, I found that the issue is not present if I build on Mac OS X 10.10 Yosemite, but is present when I build on macOS 10.15 Catalina. I still have some more experimenting to do to determine when this broke, but right now we are going to ship with a slightly modified version of the launcher that can still be built against OS X 10.10.

In order to build on 10.10, we had to replace all the new NSEventModifierFlags with their old deprecated values, but otherwise the launcher built as-is. (https://developer.apple.com/documentation/appkit/nseventmodifierflags?language=objc)

I'll loop back when I narrow down when exactly this issue appeared; hopefully there is a resolution that will allow us to return to building the launcher on a modern version of macOS again.

@sreilly sreilly reopened this Feb 4, 2020
@rsbfox
Copy link

rsbfox commented Apr 20, 2020

@patrickangle

Try adding <plistentry key="NSRequiresAquaSystemAppearance" value="true" type="boolean"/> to your build.

I think that might help.

@patrickangle
Copy link

Oh man, I'd forgotten about this. Unfortunately, we furloughed everyone in our software group due to the coronavirus, including myself, so haven't really moved forward on anything. I've been learning SwiftUI and SceneKit in my new free time, but I do recall making progress on this in the weeks leading up to that.

@rsbfox, If I'm interpreting that entry correctly, it will force the app to run in light mode, which isn't our desired behavior.

I'll take a look at this tomorrow so we can look at closing this issue out. Looking at the source code, we defined a method that called this for us using the Java-Objective-C-Bridge (https://github.com/shannah/Java-Objective-C-Bridge)

public static void setWindowTitlebarAppearsTransparent(Window window, boolean titlebarAppearsTransparent) {
    if (isMac()) {
        long windowPointer = getNativeWindowPointer(window);
        if (windowPointer != -1) {
            CocoaUtils.dispatch_sync(() -> {
                Proxy windowProxy = new Proxy(new Pointer(windowPointer));
                windowProxy.send("setTitlebarAppearsTransparent:", titlebarAppearsTransparent);
            });
        }
    }
}

with getNativeWindowPointer(…) defined as such…

public static long getNativeWindowPointer(Window window) {
    if (isMac()) {
        if (!window.isDisplayable()) {
            window.addNotify();
        }

        Object peer = AWTAccessor.getComponentAccessor().getPeer(window);
        try {

            Class lwWindowPeerClass = AquaUtils.class.getClassLoader().loadClass("sun.lwawt.LWWindowPeer");
            Method getPlatformWindowMethod = lwWindowPeerClass.getMethod("getPlatformWindow");

            Object platformWindow = getPlatformWindowMethod.invoke(peer);

            Class cPlatformWindowClass = AquaUtils.class.getClassLoader().loadClass("sun.lwawt.macosx.CFRetainedResource");
            Field f = cPlatformWindowClass.getDeclaredField("ptr");
            f.setAccessible(true);
            return (long) f.get(platformWindow);
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    } else {
        return -1;
    }
}

The implementation of isMac() is inconsequential.

This solved the actual problem, which is that Apple now expects you to call setTitlebarAppearsTransparent on your NSWindow to make the titlebar not draw it's own background. We combine the above code with the Mac-specific apple.awt.brushMetalLook client property on the JFrame. A bonus we got here was the the window took on the tint of the wallpaper when Dark Mode is enabled on Catalina. We also force our app into dark mode programmatically from Java but that is a different story for a different time. (Give me a day or two and I'll write it up if anyone is interested.)

Let me shift some code around to produce a working example that doesn't contain the software I was working on for the company, and confirm this is indeed the case.

@rsbfox
Copy link

rsbfox commented Apr 20, 2020

In light mode I see title bars that look like this.
image
With that entry added they look like this.
image

So I was thinking it might fix it for you without needing to build on older macOS SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working minor
Projects
None yet
Development

No branches or pull requests

3 participants