Closed l0drex closed 1 year ago
I wasn't able to run it yet, it always hangs while processing resources and compiling Kotlin
I can implement detecting changes, there is a signal for that. For now, I just wanted basic functionality and worry about that once I know the concept works.
To test the implementation, I wrote a test under .../xdg-desktop-portal/src/test/... and run it using the green arrow that IDEA shows next to the test. I also tried to write scratch files, but that didn't work either. Please let me know if there is a better way :sweat_smile:
To test the implementation, I wrote a test under .../xdg-desktop-portal/src/test/... and run it using the green arrow that IDEA shows next to the test. I also tried to write scratch files, but that didn't work either. Please let me know if there is a better way 😅
You'll have to setup the gradle project to use junit.
depenencies {
...
testImplementation(libs.test.junit.api)
testRuntimeOnly(libs.test.junit.engine)
}
tasks {
test {
testLogging {
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
showStandardStreams = true
}
useJUnitPlatform()
}
}
IntelliJ should automatically pick up the gradel task to run tests. If not use gradlew :auto-dark-mode-linux-xdg-desktop-portal:test
If you run into the build spinning on prepareResources
you can try to run gradlew build [whatever command you wanted to execute]
. It seems like there are same issues with task ordering where multiple tasks wait on each other causing the dead-lock. I'll have to investigate what is causing it.
Thanks a lot, its now working!
I now have some questions on the implementation:
isDarkThemeEnabled
throw an exception if its not supported (or otherwise does not know what theme is active) or should it rather return dark / light as a fallback?Thanks a lot, its now working!
I now have some questions on the implementation:
- Should
isDarkThemeEnabled
throw an exception if its not supported (or otherwise does not know what theme is active) or should it rather return dark / light as a fallback?
In this case it should just return the current state i.e. not result in a change at all.
- There is no way to detect high contrast themes yet, should I leave that TODO as is or return a value?
Please simply return false
in this case.
I have some issues implementing the event handling. I guess createEventHandler
and deleteEventHandler
both implement an observer pattern and are called to register or remove event handlers. The creator returns a pointer to the registered callback, whereas the delete method points to the callback that should be deleted.
My issue is the NativePointer
type. From what I understand, these are used together with C/C++ code, but I don't have that.
I found a way to cast the native pointer in the delete method to a callable:
val callback = eventHandle.castSafelyTo<() -> Unit>()
However, I couldn't find a way to cast a callable to a native pointer...
Another thing I couldn't find was a way to return the currently used theme mode of the IDE. Is there a boolean that stores the current theme mode, or can I check if the currently used theme is dark?
I have some issues implementing the event handling. I guess
createEventHandler
anddeleteEventHandler
both implement an observer pattern and are called to register or remove event handlers. The creator returns a pointer to the registered callback, whereas the delete method points to the callback that should be deleted. My issue is theNativePointer
type. From what I understand, these are used together with C/C++ code, but I don't have that.
The contract of the class is that createEventHandler
and deleteEventHandler
are only called once (and after each other).
In createEventHandler
you can simply initialize the listener and return any NativePointer
e.g. NativePointer(0)
. Then in
deleteEventHandler
just revert whatever happened during initialization. No need for casting.
However, I couldn't find a way to cast a callable to a native pointer...
Because it isn't possible ;)
Another thing I couldn't find was a way to return the currently used theme mode of the IDE. Is there a boolean that stores the current theme mode, or can I check if the currently used theme is dark?
There are two options here. Either keep track of the current state yourself and return it, or change the type of callback from () -> Unit
to ThemeInfo -> Unit
, where
data class ThemeInfo(val isDark, val isHighContrast)
You'll have to adjust the interface of ThemeMonitorService
and implementations/usage accordingly.
I looked a bit deeper through the code and I found that if isSupported
is false
, an exception is thrown and isDarkThemeEnabled
is never called, so the value of that when not supported doesn't matter I guess.
I wasn't able to run it yet, it always hangs while processing resources and compiling Kotlin
I ran into a similar issue and the solution for me was to disable parallel builds, in gradle.properties
, set org.gradle.parallel = false
(from true)
XdgThemeMonitorService
still isn't used at all. You'll have to return it in https://github.com/weisJ/auto-dark-mode/blob/master/linux/src/main/java/com/github/weisj/darkmode/platform/linux/LinuxThemeMonitorService.kt
I would advise to check whether isSupported
is true in there. Please don't remove the Gnome implementation, but use the xdg one as the alternative.
There seems to be a deadlock somewhere, when I run the IDE it spins endlessly (at task runIDE
) and never opens the window. I have disabled org.gradle.parallel
as suggested by @zliuva which fixed the spin with resources, but not this one. I also let IDEA search for cyclic dependencies, but it couldn't find any.
I noticed that it fails to load xapp, canberry and appmenu, but from my googling that doesn't seem to be the problem.
Any suggestions? :sweat_smile:
... 2022-05-12T18:10:35.399+0200 [DEBUG] [org.jetbrains.intellij.IntelliJPlugin] [gradle-intellij-plugin :auto-dark-mode-pluginauto-dark-mode-plugin:auto-dark-mode-plugin:runIde] Runtime specified with ideDir='/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1', version='11_0_14_1b2043.25' resolved as: /home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains/jbre/jbr_jcef-11_0_14_1-linux-x64-b2043.25/extracted/jbr/bin/java 2022-05-12T18:10:35.399+0200 [INFO] [org.jetbrains.intellij.IntelliJPlugin] [gradle-intellij-plugin :auto-dark-mode-pluginauto-dark-mode-plugin:auto-dark-mode-plugin:runIde] Resolved JVM Runtime directory: /home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains/jbre/jbr_jcef-11_0_14_1-linux-x64-b2043.25/extracted/jbr/bin/java 2022-05-12T18:10:35.399+0200 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'command '/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains/jbre/jbr_jcef-11_0_14_1-linux-x64-b2043.25/extracted/jbr/bin/java''. Working directory: /home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/bin Command: /home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains/jbre/jbr_jcef-11_0_14_1-linux-x64-b2043.25/extracted/jbr/bin/java -Didea.auto.reload.plugins=true -Didea.classpath.index.enabled=false -Didea.config.path=/home/l0drex/Projekte/auto-dark-mode/plugin/build/idea-sandbox/config -Didea.is.internal=true -Didea.platform.prefix=Idea -Didea.plugins.path=/home/l0drex/Projekte/auto-dark-mode/plugin/build/idea-sandbox/plugins -Didea.required.plugins.id=com.github.weisj.darkmode -Didea.system.path=/home/l0drex/Projekte/auto-dark-mode/plugin/build/idea-sandbox/system -Djava.system.class.loader=com.intellij.util.lang.PathClassLoader -Dsun.awt.disablegrab=true -Xms256m -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=DE -Duser.language=de -Duser.variant -ea -cp /home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/lib/3rd-party-rt.jar:/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/lib/util.jar:/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/lib/util_rt.jar:/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/lib/jna.jar com.intellij.idea.Main 2022-05-12T18:10:35.399+0200 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTING 2022-05-12T18:10:35.399+0200 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Waiting until process started: command '/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains/jbre/jbr_jcef-11_0_14_1-linux-x64-b2043.25/extracted/jbr/bin/java'. 2022-05-12T18:10:35.400+0200 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTED 2022-05-12T18:10:35.400+0200 [DEBUG] [org.gradle.process.internal.ExecHandleRunner] waiting until streams are handled... 2022-05-12T18:10:35.400+0200 [INFO] [org.gradle.process.internal.DefaultExecHandle] Successfully started process 'command '/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains/jbre/jbr_jcef-11_0_14_1-linux-x64-b2043.25/extracted/jbr/bin/java'' 2022-05-12T18:10:35.520+0200 [ERROR] [system.err] WARNING: An illegal reflective access operation has occurred An illegal reflective access operation has occurred 2022-05-12T18:10:35.520+0200 [ERROR] [system.err] WARNING: Illegal reflective access by com.intellij.util.lang.UrlClassLoader (file:/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/lib/util.jar) to field java.lang.ClassLoader.classLoaderValueMap Illegal reflective access by com.intellij.util.lang.UrlClassLoader (file:/home/l0drex/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/lib/util.jar) to field java.lang.ClassLoader.classLoaderValueMap 2022-05-12T18:10:35.520+0200 [ERROR] [system.err] WARNING: Please consider reporting this to the maintainers of com.intellij.util.lang.UrlClassLoader Please consider reporting this to the maintainers of com.intellij.util.lang.UrlClassLoader 2022-05-12T18:10:35.520+0200 [ERROR] [system.err] WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations Use --illegal-access=warn to enable warnings of further illegal reflective access operations 2022-05-12T18:10:35.520+0200 [ERROR] [system.err] WARNING: All illegal access operations will be denied in a future release All illegal access operations will be denied in a future release 2022-05-12T18:10:35.827+0200 [ERROR] [system.err] Gtk-Message: 18:10:35.828: Failed to load module "xapp-gtk3-module" 2022-05-12T18:10:35.827+0200 [ERROR] [system.err] Gtk-Message: 18:10:35.828: Failed to load module "canberra-gtk-module" 2022-05-12T18:10:35.827+0200 [ERROR] [system.err] Gtk-Message: 18:10:35.828: Failed to load module "appmenu-gtk-module" 2022-05-12T18:10:36.552+0200 [ERROR] [system.err] 2022-05-12 18:10:36,551 [ 876] WARN - #c.i.i.DebugAttachDetector - Unable to start DebugAttachDetector, please add `--add-exports java.base/jdk.internal.vm=ALL-UNNAMED` to VM options 2022-05-12T18:10:36.852+0200 [ERROR] [system.err] 2022-05-12 18:10:36,852 [ 1177] WARN - #c.i.n.i.NotificationGroupManagerImpl - Notification group CodeWithMe is already registered (group=com.intellij.notification.NotificationGroup@7d6698aa). Plugin descriptor: PluginDescriptor(name=Code With Me, id=com.jetbrains.codeWithMe, descriptorPath=plugin.xml, path=~/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2022.1/c91a19824ffcb28872ecd2761c83b250f703ff21/ideaIC-2022.1/plugins/cwm-plugin, version=221.5080.210, package=null, isBundled=true) 2022-05-12T18:10:38.941+0200 [LIFECYCLE] [org.gradle.cache.internal.DefaultFileLockManager] ... 2022-05-12T18:12:08.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry. 2022-05-12T18:12:08.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry. 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(73)-127.0.0.1: accepted socket from [127.0.0.1:60090] 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(73)-127.0.0.1: (port 40771) op = 80 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.loader] RMI TCP Connection(73)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@5623f185 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.loader] RMI TCP Connection(73)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@5623f185 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.loader] RMI TCP Connection(73)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@5623f185 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.loader] RMI TCP Connection(73)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@5623f185 2022-05-12T18:12:09.486+0200 [DEBUG] [sun.rmi.loader] RMI TCP Connection(73)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@5623f185 2022-05-12T18:12:18.941+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry. 2022-05-12T18:12:18.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry. 2022-05-12T18:12:18.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry. 2022-05-12T18:12:18.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry. 2022-05-12T18:12:18.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry. 2022-05-12T18:12:18.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry. 2022-05-12T18:12:20.948+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(70)-127.0.0.1: (port 40771) connection closed 2022-05-12T18:12:20.948+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(70)-127.0.0.1: close connection 2022-05-12T18:12:21.047+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(71)-127.0.0.1: (port 40771) connection closed 2022-05-12T18:12:21.048+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(71)-127.0.0.1: close connection 2022-05-12T18:12:21.121+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(72)-127.0.0.1: (port 40771) connection closed 2022-05-12T18:12:21.121+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(72)-127.0.0.1: close connection 2022-05-12T18:12:24.487+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(73)-127.0.0.1: (port 40771) connection closed 2022-05-12T18:12:24.488+0200 [DEBUG] [sun.rmi.transport.tcp] RMI TCP Connection(73)-127.0.0.1: close connection 2022-05-12T18:12:28.941+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry. 2022-05-12T18:12:28.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry. 2022-05-12T18:12:28.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry. 2022-05-12T18:12:28.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry. 2022-05-12T18:12:28.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry. 2022-05-12T18:12:28.942+0200 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry. ...
Have you tried commenting out the code which creates the XdgThemeMonitorService?
Yes, when I do that it works. I made some further debugging and this line seems to be the cause:
private val connection = DBusConnection.getConnection(DBusConnection.DBusBusType.SESSION)
I don't know why yet, but I did found another plugin that uses the dbus so that in itself shouldn't be a problem. I tried to move the connection into the functions instead of using it as a class attribute, but that didn't fix it.
I have now another weird problem. I wanted to update the dbus-java
dependency to the latest version in the libs.versinos.toml
file, but there seems to be some sort of artifact of the old version somewhere.
Specifically, I need to change this:
private val connection = DBusConnection.getConnection(DBusConnection.DBusBusType.SESSION)
to this:
private val connection = DBusConnectionBuilder.forSessionBus().build()
This works when I test it in a new, empty project, but here it throws an error that DBusConnection.CONNECTIONS
is private and can't be accessed. This was in the previous version of the library the case.
I checked the dependency menu in the Gradle toolbar, it only shows the correct version of the library. I deleted all build directories, cache directories, ~/.gradle
and ~/.m2
and ran the clean
task, but the issue persists.
Are you sure this is a gradle issue and not something with your IDE? i.e. does running gradlew build
work when called from the command line? Otherwise you can try to temporarily remove the dependency alltogether and do a build with the code depending on it commented out. I have never experienced this problem so I'm not quite sure what might be causing it.
Yes, it also happens when I run the build from the command line. Building with the dependency commented out didn't help, I even ran it on a different machine and have the same issue there.
To keep you updated, I made a post in the developer forum of JetBrains to see if they can help me with that endless spinning on runIde
, but they have no idea either.
I took this PR and debugged it; what I have right now (at https://github.com/14mRh4X0r/auto-dark-mode/tree/linux-xdg-desktop) is working for me. I'm not quite sure whether the code style fits, as I'm new to Kotlin, but at least it's usable. (FWIW: it's @l0drex' code rebased onto master, my fixes are in the last commit.)
Something I noticed as well though, is that (at least IDEA) already includes a (older) version of dbus-java, so it may be better to use that one. I had to exclude some of its transitive dependencies due to classloading clashes.
The hang seems to be caused by exceptions thrown during initialization.
Thank you very much for picking this up.
I took this PR and debugged it; what I have right now (at 14mRh4X0r/auto-dark-mode@
linux-xdg-desktop
) is working for me. I'm not quite sure whether the code style fits, as I'm new to Kotlin, but at least it's usable. (FWIW: it's @l0drex' code rebased onto master, my fixes are in the last commit.)
I would highly appreciate if you could clean up the commits a bit and submit a PR. We can then hash out the little details.
Something I noticed as well though, is that (at least IDEA) already includes a (older) version of dbus-java, so it may be better to use that one. I had to exclude some of its transitive dependencies due to classloading clashes.
I think this is a good idea. In this case we could even mark the dependency as runtimeOnly
to avoid bundling it ourselves.
The hang seems to be caused by exceptions thrown during initialization.
Good catch!
@14mRh4X0r thank you so much for this! I added your changes in several commits (hoping I understood the changes correctly) and added you as a co-author. I also merged the current master to fix the merge conflict.
However, I am not sure how to mark dbus-java
as a runtimeOnly
dependency. I naively tried replacing implementation
with runtimeOnly
in this line, but that didn't work.
Wonderfull :)
However, I am not sure how to mark dbus-java as a runtimeOnly dependency. I naively tried replacing implementation with runtimeOnly in this line, but that didn't work.
Sorry for the confusion, that was my bad. The dependency would need to be marked as compileOnly
. Just make sure that the version matches the one packaged with IDEA itself. Also I was wondering whether we could apply this to the coroutines dependency aswell. Is it also already provided by IDEA?
I would also highly appreciate if you could add some tests similar to https://github.com/weisJ/auto-dark-mode/blob/master/plugin/src/test/kotlin/com/github/weisj/darkmode/platform/linux/gtk/GtkNativeTest.kt.
Also I was wondering whether we could apply this to the coroutines dependency aswell. Is it also already provided by IDEA?
It seems like it is, it looks like its marked as a dependency in intellij-community
I extracted the theme changer so that it can be used by other tests. I also added a theme changer for kde, however getting the currently used theme is not so straight forward. lookandfeeltool
doesn't provide this, and other tools like kreadconfig5
seem to no longer be able to do this.
I extracted the theme changer so that it can be used by other tests. I also added a theme changer for kde, however getting the currently used theme is not so straight forward.
lookandfeeltool
doesn't provide this, and other tools likekreadconfig5
seem to no longer be able to do this.
I'm not sure myself how to tackle this currently. I think it's ok to leave this as a FIXME for now, as it doesn't influence the tests that much beside the fact that we have to trust the theme being really changed (and if run locally the theme not being preserved for the developer)
Tests are currently failing because there is no xserver running causing the test to be executed headless. I had a similar issue in one of my other projects and the following seemed to fix it: https://github.com/weisJ/darklaf/blob/e2d1e56c24f147737fb9ce173f3362efac429437/.github/workflows/gradle.yml#L65
Sorry for not getting back any sooner. The test not being able to run is rather unfortunate, but I don't have a solution for that right now. I guess we would have to guarantee that the action runner actuallyhas a working dbus with the correct properties exposed. For now I'll disable the test and provide the patch as an optional preview-version.
Linux support for all desktops that implement the
color-scheme
preference. Implementation is based on this gist. First time using Gradle and Kotlin, any help is welcome :smile:Fix #56 Fix #50 Fix #33 Fix #20