Listener for dark mode switch?
Closed this issue · 11 comments
Hi. I am using your very useful library to know whether dark mode has been switched on on a specific target system.
I was wondering if you plan to implement kind of listener. The problem I am currently having: if the OS switches the dark mode while the application is running, the application does not get notified about it. Only code being executed on-runtime, after the switch, will be able to fetch the newest value of the mode.
I hope, my explanation was clear enough. Otherwise, kindly let me know.
Best regards,
christian
i actually have no plans in this regard. This could be a nice enhancement indeed, however I foresee a lot of work and I am not even sure this is possible in pure Python and for all the platform.
Personally, I could invest some time for macOS, but I am not sure when I will have enough capacity for doing this.
Nevertheless, PRs in this direction are more than welcome.
Just FYI, this is something that is easily doable in PySide2 (and I guess pyqt5):
import darkdetect
from PySide2 import QtCore, QtWidgets
class LabelHandler():
def __init__(self):
self.label = QtWidgets.QLabel(f'Mode: {darkdetect.theme()}')
@QtCore.Slot(str)
def mode_change(self):
self.label.setText(f'Mode: {darkdetect.theme()}')
if __name__ == "__main__":
app = QtWidgets.QApplication([])
win = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
lh = LabelHandler()
layout.addWidget(lh.label)
app.paletteChanged.connect(lh.mode_change)
win.setLayout(layout)
win.show()
app.exec_()
Darkdetect was mostly created to overcome the limitations of GUI libraries, and detecting this change on the fly seems to be supported by (at least some) of them. I would encourage you to check whether this listener detection is supported in the library of your choice.
On Windows the dark mode setting is stored in registry key HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize DWORD AppsUseLightTheme
. I found a WIN32 API function named RegNotifyChangeKeyValue
which makes notifies about changes to a specified registry key. Perhaps a native pyd extension is required but I'm not familiar with WIN32 APIs.
I forked this repo and commited the native extension's code to add a listener function on Windows. Pass a callback function and it will be called with string "Dark" or "Light" when the OS switches the dark mode setting. On Linux and macOS it simply raises a NotImplementedError
.
The listener is an infinite loop so a separated thread is required. However the thread is unstoppable so I think the API design and the implementation can be further improved.
Usage example:
import darkdetect, threading
# def listener(callback: typing.Callable[[str], None]) -> None: ...
t = threading.Thread(target=darkdetect.listener, args=(print,))
t.daemon = True
t.start()
Try it out by cloning it and install with command python setup.py build_ext --inplace
and python setup.py install
.
6b14eac9426ebd51311e7c4e848cb898.mp4
I guess we can spawn a subprocess gsettings monitor org.gnome.desktop.interface gtk-theme
and read its output to detect dark mode switch on Linux. I'll try to add it to my fork (and the pull request).
@albertosottile I also found a solution for macOS: Golang: Detect dark mode change in OSX
@albertosottile I also found a solution for macOS: Golang: Detect dark mode change in OSX
The detection method based on defaults read -g AppleInterfaceStyle
is less reliable than the one implemented in darkdetect
([[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]
).
In principle, Foundation allows monitoring values from NSUserDefaults
with callbacks, but I was not able to get this working via ctypes
when I tried.
For the moment, I would merge your PR as it is. We can then continue investigating if callback
can be implemented on macOS with the NSUserDefaults
-based detection method.
Just Googled for any available solutions and I don't have any device running macOS. So I'm afraid I can't provide further help for implementation for macOS.
The listeners for Windows and Linux were released in 0.6.0. I will keep this issue open for macOS.
I invested a lot of time in trying to implement a listener for macOS and failed miserably. Since I want to add more information on what I tried (in view of helping further people that might venture through the same path) I am now closing this issue and putting the macOS endeavor in #25.
@TransparentLC thanks again for having implemented the listeners for Windows and Linux!
Many thanks to all!