Closed weisJ closed 4 years ago
As I have commented on the original issue:
I has to do with a weird behaviour of how auto is implemented. Generally there is the value "AppleInterfaceStyle" that is either nil or "Dark" depending of the mode. But in some scenarios their semantic is swapped. The saver approach would be to read
NSApp.effectiveAppearance
but as I have mentioned before this always return the same value. I guess this has to do with the dll running outside of a valid cocoa application.
The issue here is that NSApp.effectiveAppearance
only works if the library is build against an SDK with version 10.14
or higher. Currently I'm using 10.10
to support the contrast feature on older machines. I will have to drop it and build against 10.14
but I don't know yet if this will work.
This behaviour is describedhere.
An alternative solution would be to specify NSRequiresAquaSystemAppearance = false
in the Info.plist
file. Sadly this is impossible as there is no Info.plist
for shared libraries (as to my knowledge).
@bric3 could you try out this pre-release to test if
I will try to install this later tonight. But due to my timezone it may wait one or two days till I can be sure rebut is gone.
By the way you could probably build two native libraries. And only load the class with the binding for the matching OS version. This class implementing the same interface.
I will try to install this later tonight. But due to my timezone it may wait one or two days till I can be sure rebut is gone.
You could manually change your timezone s.t. it is just before switching. But I’m fine with waiting :D
By the way you could probably build two native libraries. And only load the class with the binding for the matching OS version. This class implementing the same interface.
I know but I don’t think that it’s actually worth it considering that there are probably not a lot of people using the plugin for the contrast feature (considering that if you use high contrast mode in macOS you probably don’t switch it very much)
So I installed the 1.2.0-pre1 yesterday I got this exception, right after restarting IJ. At that time the UI was using the dark mode.
java.lang.RuntimeException: Non-Java exception raised, not handled! (Original problem: -[NSCompositeAppearance bestMatchFromAppearanceWithNames:]: unrecognized selector sent to instance 0x60000061cb80)
at com.github.weisj.darkmode.platform.macos.MacOSNative.isDarkThemeEnabled(Native Method)
at com.github.weisj.darkmode.platform.macos.MacOSThemeMonitorService.isDarkThemeEnabled(MacOSThemeMonitorService.java:12)
at com.github.weisj.darkmode.platform.ThemeMonitor.start(ThemeMonitor.java:43)
at com.github.weisj.darkmode.platform.ThemeMonitor.setRunning(ThemeMonitor.java:65)
at com.github.weisj.darkmode.AutoDarkMode.start(AutoDarkMode.java:42)
at com.github.weisj.darkmode.AutoDarkModeStartupListener.appFrameCreated(AutoDarkModeStartupListener.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.intellij.util.messages.impl.MessageBusImpl.invokeListener(MessageBusImpl.java:546)
at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverMessage(MessageBusConnectionImpl.java:139)
at com.intellij.util.messages.impl.MessageBusImpl.doPumpMessages(MessageBusImpl.java:465)
at com.intellij.util.messages.impl.MessageBusImpl.pumpWaitingBuses(MessageBusImpl.java:426)
at com.intellij.util.messages.impl.MessageBusImpl.pumpMessages(MessageBusImpl.java:415)
at com.intellij.util.messages.impl.MessageBusImpl.sendMessage(MessageBusImpl.java:397)
at com.intellij.util.messages.impl.MessageBusImpl.lambda$createTopicHandler$3(MessageBusImpl.java:237)
at com.sun.proxy.$Proxy41.appFrameCreated(Unknown Source)
at com.intellij.idea.IdeStarter.main(IdeStarter.kt:103)
at com.intellij.idea.ApplicationLoader$startApp$8.run(ApplicationLoader.kt:222)
at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:783)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1085)
at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
And later today I got this one after starting IJ (light mode used by the UI)
java.lang.RuntimeException: Non-Java exception raised, not handled! (Original problem: -[NSCompositeAppearance bestMatchFromAppearanceWithNames:]: unrecognized selector sent to instance 0x6000035b3500)
at com.github.weisj.darkmode.platform.macos.MacOSNative.isDarkThemeEnabled(Native Method)
at com.github.weisj.darkmode.platform.macos.MacOSThemeMonitorService.isDarkThemeEnabled(MacOSThemeMonitorService.java:12)
at com.github.weisj.darkmode.platform.ThemeMonitor.start(ThemeMonitor.java:43)
at com.github.weisj.darkmode.platform.ThemeMonitor.setRunning(ThemeMonitor.java:65)
at com.github.weisj.darkmode.AutoDarkMode.start(AutoDarkMode.java:42)
at com.github.weisj.darkmode.AutoDarkModeStartupListener.appFrameCreated(AutoDarkModeStartupListener.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.intellij.util.messages.impl.MessageBusImpl.invokeListener(MessageBusImpl.java:546)
at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverMessage(MessageBusConnectionImpl.java:139)
at com.intellij.util.messages.impl.MessageBusImpl.doPumpMessages(MessageBusImpl.java:465)
at com.intellij.util.messages.impl.MessageBusImpl.pumpWaitingBuses(MessageBusImpl.java:426)
at com.intellij.util.messages.impl.MessageBusImpl.pumpMessages(MessageBusImpl.java:415)
at com.intellij.util.messages.impl.MessageBusImpl.sendMessage(MessageBusImpl.java:397)
at com.intellij.util.messages.impl.MessageBusImpl.lambda$createTopicHandler$3(MessageBusImpl.java:237)
at com.sun.proxy.$Proxy40.appFrameCreated(Unknown Source)
at com.intellij.idea.IdeStarter.main(IdeStarter.kt:103)
at com.intellij.idea.ApplicationLoader$startApp$8.run(ApplicationLoader.kt:222)
at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:783)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1085)
at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
The UI mode is enabled by sunrise / sunset of Nightowl. Of course the IDE doesn't change anymore to UI mode change (manual or automatic).
Seems like there is a typo in the native code (sadly objective-c doesn't check for non existing selector methods).
Should be better with pre-release 2
The exception is gone however IJ doesn't detect the UI mode change, be it manual or not.
Would you mind building the plugin locally? I have added a log statement in the native code. You can run and build the project using
./gradlew build
./gradlew :auto-dark-mode:buildPlugin
./gradlew :auto-dark-mode:runIde
Hi, I looked at the code NSLog(@"%@", appearance.name)
I believe this is the log you are looking for
2020-04-22 00:15:03.515 java[71631:995017] NSAppearanceNameAqua
it appears in the terminal (not idea.log
) after running
./gradlew :auto-dark-mode-plugin:runIde
Yes exactly. Does it always log NSAppearanceNameAqua
(It logs every time the dark mode changes)?
Yes it does. switching manually, activating the sunset/sunrise, clock schedule based (with NightOwl). It's always the same value
2020-04-22 10:34:25.477 java[96324:1116595] NSAppearanceNameAqua
2020-04-22 10:35:16.526 java[96324:1116595] NSAppearanceNameAqua
2020-04-22 10:35:26.227 java[96324:1116595] NSAppearanceNameAqua
2020-04-22 10:35:34.092 java[96324:1116595] NSAppearanceNameAqua
2020-04-22 10:37:09.018 java[96324:1116595] NSAppearanceNameAqua
<============-> 92% EXECUTING [2m 38s]
It looks like IntelliJ manually sets the NSApplication.appearance
property (probably to make sure the correct title bar is used). In this case NSApplication.effectiveAppearance
doesn't use the system appearance. I have changed the code s.t. it sets NSApplication.appearance
to nil
while getting the effective appearance. I hope this doesn't cause any titlebar flickering. Could you try if this works?
I pulled change form master
(6c40139), but it didn't change a thing. This macOS API is weird.
2020-04-22 11:19:31,087 [ 5128] WARN - j.internal.DebugAttachDetector - Unable to start DebugAttachDetector, please add `--add-exports java.base/jdk.internal.vm=ALL-UNNAMED` to VM options
2020-04-22 11:19:32.758 java[2877:1149320] NSAppearanceNameAqua
2020-04-22 11:19:33,247 [ 7288] WARN - nSystem.impl.ActionManagerImpl - keymap "Xcode" not found [Plugin: com.intellij]
2020-04-22 11:21:07.412 java[2877:1149275] NSAppearanceNameAqua
2020-04-22 11:21:38.113 java[2877:1149275] NSAppearanceNameAqua
<============-> 92% EXECUTING [2m 56s]
Maybe it would be a good thing to try swift ? But maybe it won't change a thing since IJ defines this variable itself.
/// True if the application is in dark mode, and false otherwise
var inDarkMode: Bool {
let mode = UserDefaults.standard.string(forKey: "AppleInterfaceStyle")
return mode == "Dark"
}
Fetching "AppleInterfaceStyle"
is what the code did before. The value in it is wrong if in auto
mode. Swift wouldn't make a difference here.
I have changed it up a bit. Might make a difference but maybe it will just result in a crash.. Not sure.
Mmh it didn't crash, but it didn't react to UI mode change.
By the way thanks for the explanation regarding swift suggestion.
Is it still logging the same thing?
Yes I didn't mentionned it because it was the same
2020-04-22 15:40:33.363 java[17439:1224846] NSAppearanceNameAqua
2020-04-22 15:40:33,470 [ 2046] WARN - nSystem.impl.ActionManagerImpl - keymap "Xcode" not found [Plugin: com.intellij]
2020-04-22 15:40:47.444 java[17439:1224802] NSAppearanceNameAqua
2020-04-22 15:41:14,828 [ 43404] WARN - ConfigurableExtensionPointUtil - ignore deprecated groupId: language for id: preferences.language.Kotlin.scripting
2020-04-22 15:41:26.440 java[17439:1224802] NSAppearanceNameAqua
Could you recompile it? The log should contain something like Current appearance
and Effective appearance
.
Ahhh, I didn't look at gradle script I thought the task would pick changed files and run build. So here's the new log:
2020-04-22 23:40:49.208 java[44805:1361303] Effective appearance: NSAppearanceNameAqua
2020-04-22 23:40:49.208 java[44805:1361303] +[NSAppearance current]: unrecognized selector sent to class 0x7fff8b8d7830
2020-04-22 23:40:49,210 [ 1650] ERROR - .impl.MessageBusConnectionImpl - Non-Java exception raised, not handled! (Original problem: +[NSAppearance current]: unrecognized selector sent to class 0x7fff8b8d7830)
java.lang.RuntimeException: Non-Java exception raised, not handled! (Original problem: +[NSAppearance current]: unrecognized selector sent to class 0x7fff8b8d7830)
at com.github.weisj.darkmode.platform.macos.MacOSNative.isDarkThemeEnabled(Native Method)
at com.github.weisj.darkmode.platform.macos.MacOSThemeMonitorService.isDarkThemeEnabled(MacOSThemeMonitorService.java:12)
at com.github.weisj.darkmode.platform.ThemeMonitor.start(ThemeMonitor.java:43)
at com.github.weisj.darkmode.platform.ThemeMonitor.setRunning(ThemeMonitor.java:65)
at com.github.weisj.darkmode.AutoDarkMode.start(AutoDarkMode.java:42)
at com.github.weisj.darkmode.AutoDarkModeStartupListener.appFrameCreated(AutoDarkModeStartupListener.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.intellij.util.messages.impl.MessageBusImpl.invokeListener(MessageBusImpl.java:554)
at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverMessage(MessageBusConnectionImpl.java:139)
at com.intellij.util.messages.impl.MessageBusImpl.doPumpMessages(MessageBusImpl.java:472)
at com.intellij.util.messages.impl.MessageBusImpl.pumpWaitingBuses(MessageBusImpl.java:432)
at com.intellij.util.messages.impl.MessageBusImpl.pumpMessages(MessageBusImpl.java:420)
at com.intellij.util.messages.impl.MessageBusImpl.sendMessage(MessageBusImpl.java:404)
at com.intellij.util.messages.impl.MessageBusImpl.lambda$createTopicHandler$3(MessageBusImpl.java:243)
at com.sun.proxy.$Proxy34.appFrameCreated(Unknown Source)
at com.intellij.idea.IdeStarter.main(IdeStarter.kt:102)
at com.intellij.idea.ApplicationLoader$startApp$8.run(ApplicationLoader.kt:222)
at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:783)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1085)
at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
2020-04-22 23:40:49,213 [ 1653] ERROR - .impl.MessageBusConnectionImpl - IntelliJ IDEA 2020.1 Build #IC-201.6668.121
2020-04-22 23:40:49,213 [ 1653] ERROR - .impl.MessageBusConnectionImpl - JDK: 11.0.6; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o
2020-04-22 23:40:49,214 [ 1654] ERROR - .impl.MessageBusConnectionImpl - OS: Mac OS X
2020-04-22 23:40:49,214 [ 1654] ERROR - .impl.MessageBusConnectionImpl - Plugin to blame: Auto Dark Mode version: 1.2.0-pre2
2020-04-22 23:40:49,214 [ 1654] ERROR - .impl.MessageBusConnectionImpl - Last Action:
2020-04-22 23:40:49,332 [ 1772] WARN - nSystem.impl.ActionManagerImpl - keymap "Xcode" not found [Plugin: com.intellij]
This is the same wether the runIde task is run with dark or with light mode. Also the IDE UI is now always using Darcula, and does not respond to os mode change.
The unknown selector problem is fixed now.
It's a cat and mouse game, here's the log, swithing back and forth dark mode but the IJ ui didn't change.
2020-04-23 02:29:19.526 java[67649:1471736] Effective appearance: NSAppearanceNameAqua
2020-04-23 02:29:19.527 java[67649:1471736] Current appearance: NSAppearanceNameAqua
2020-04-23 02:29:19,639 [ 1977] WARN - nSystem.impl.ActionManagerImpl - keymap "Xcode" not found [Plugin: com.intellij]
2020-04-23 02:29:42.634 java[67649:1471425] Effective appearance: NSAppearanceNameAqua
2020-04-23 02:29:42.634 java[67649:1471425] Current appearance: NSAppearanceNameAqua
2020-04-23 02:29:47.842 java[67649:1471425] Effective appearance: NSAppearanceNameAqua
2020-04-23 02:29:47.842 java[67649:1471425] Current appearance: NSAppearanceNameAqua
<============-> 92% EXECUTING [50s]
I think I’ll have to stall this for a bit. If you want you could experiment a bit if there is a combination that reports the correct system NSAppearance
.
It looks like the key problem is that the resulting library doesn’t have the load command LC_VERSION_MIN_MACOSX specified (moreover it should have 10.14
as a property. This can be checked using otool -l
Haven’t yet found out how to produce a library with the load command.
@bric3 Do you have Xcode installed? If yes could you build the library from there (i.e. as a separate project) and check the invoked command line options?
I have some good news. Using a new plugin to create the native binaries the correct load command is now inserted. See https://github.com/weisJ/darklaf/pull/154#issuecomment-625384763
Hopefully this resolved this issue. @bric3 would you be so kind and check if it works?
Hi. Sorry I hadn't the time since my last reply, and this mroning I just played 2min (b/c kids), but I got this issue right after runIde
. (12.0-pre2, commit 8d08f9a)
java.lang.IllegalStateException: Could not load library.
at com.github.weisj.darkmode.platform.ThemeMonitor.<init>(ThemeMonitor.java:22)
at com.github.weisj.darkmode.AutoDarkMode.createMonitor(AutoDarkMode.java:33)
at com.github.weisj.darkmode.AutoDarkMode.start(AutoDarkMode.java:41)
at com.github.weisj.darkmode.AutoDarkModeStartupListener.appFrameCreated(AutoDarkModeStartupListener.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.intellij.util.messages.impl.MessageBusImpl.invokeListener(MessageBusImpl.java:554)
at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverMessage(MessageBusConnectionImpl.java:139)
at com.intellij.util.messages.impl.MessageBusImpl.doPumpMessages(MessageBusImpl.java:472)
at com.intellij.util.messages.impl.MessageBusImpl.pumpWaitingBuses(MessageBusImpl.java:432)
at com.intellij.util.messages.impl.MessageBusImpl.pumpMessages(MessageBusImpl.java:420)
at com.intellij.util.messages.impl.MessageBusImpl.sendMessage(MessageBusImpl.java:404)
at com.intellij.util.messages.impl.MessageBusImpl.lambda$createTopicHandler$3(MessageBusImpl.java:243)
at com.sun.proxy.$Proxy34.appFrameCreated(Unknown Source)
at com.intellij.idea.IdeStarter.main(IdeStarter.kt:102)
at com.intellij.idea.ApplicationLoader$startApp$8.run(ApplicationLoader.kt:222)
at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:783)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1085)
at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Hi. Sorry I hadn't the time since my last reply, and this mroning I just played 2min (b/c kids), but I got this issue right after
runIde
. (12.0-pre2, commit 8d08f9a)
No need to apologize. I am thankful for any help.
When switching to the new gradle plugin I forgot to update the load path of the library. This should be fixed now.
Edit: Not quite fixed yet. Will check back later when it’s actually fixed.
@bric3 Ok dark mode detection should work fine now. Note that when running through the runIde
task the detection doesn't actually function. The plugin needs to be installed locally and IntelliJ has to be restarted at least once before proper detection works (At least when running on Catalina and Auto
is selected). But from then on it should work fine.
There is a new pre-release to try out.
For future reference here the cause of the issue:
Because IntelliJ doesn't specify the NSRequiresAquaSystemAppearance
key in its Info.plist
file and the JVM binaries aren't compiled against a suitable SDK version macOS assumes a value of true
(i.e. dark mode is not supported) which causes a version of AppKit
to be linked that always returns NSAppearanceAqua
when calling NSApp.effectiveAppearance
. When the plugin is loaded it writes the NSRequiresAquaSystemAppearance
with the value false
to the apps bundle. All subsequent times IntelliJ starts the appropriate version of AppKit
will be linked.
This is effectively non-intrusive as it makes no difference for the appearance of IntelliJ.
However when running the runIde
task the applications identification is something of the sorts of net.java.openjdk.cmd
which is the same for any java program that isn't bundled as a separate .app
. There is a check whether the app id contains jetbrains
before patching the app bundle. Thats why it won't work property when using the gradle task.
Hi, it works !
Indeed a proper restart had to be done, I actually had to close then start IJ in different start; put it differently using the restart button from IJ after installing the plugin don't work.
Anyway good investigation, thanks !
After much configuration work I am now at the point where the resulting binary is again compatible with macOS 10.14 (Mojave). Next version coming tomorrow.
Hey just for reference, at this time the plugin is working flawlessly.
Thanks for the information. Glad to hear it's working!
Actually I think I encountered a bug.
Maybe I should log that in another issue.
Originally posted by @bric3 in https://github.com/weisJ/auto-dark-mode/issues/1#issuecomment-616386572