darkdetect: update vendor copy to v0.7.1

This commit is contained in:
Alberto Sottile 2022-11-06 19:19:52 +01:00
parent 7a949b8ccd
commit fa06378b6d
6 changed files with 148 additions and 11 deletions

View File

@ -4,19 +4,31 @@
# Distributed under the terms of the 3-clause BSD License.
#-----------------------------------------------------------------------------
__version__ = '0.5.2'
__version__ = '0.7.1'
import sys
import platform
if sys.platform == "darwin":
from distutils.version import LooseVersion as V
if V(platform.mac_ver()[0]) < V("10.14"):
from ._dummy import *
def macos_supported_version():
sysver = platform.mac_ver()[0] #typically 10.14.2 or 12.3
major = int(sysver.split('.')[0])
if major < 10:
return False
elif major >= 11:
return True
else:
minor = int(sysver.split('.')[1])
if minor < 14:
return False
else:
return True
if sys.platform == "darwin":
if macos_supported_version():
from ._mac_detect import *
del V
elif sys.platform == "win32" and int(platform.release()) >= 10:
else:
from ._dummy import *
elif sys.platform == "win32" and platform.release().isdigit() and int(platform.release()) >= 10:
# Checks if running Windows 10 version 10.0.14393 (Anniversary Update) OR HIGHER. The getwindowsversion method returns a tuple.
# The third item is the build number that we can use to check if the user has a new enough version of Windows.
winver = int(platform.version().split('.')[2])
@ -29,4 +41,4 @@ elif sys.platform == "linux":
else:
from ._dummy import *
del sys, platform
del sys, platform

View File

@ -0,0 +1,9 @@
#-----------------------------------------------------------------------------
# Copyright (C) 2019 Alberto Sottile
#
# Distributed under the terms of the 3-clause BSD License.
#-----------------------------------------------------------------------------
import darkdetect
print('Current theme: {}'.format(darkdetect.theme()))

View File

@ -4,6 +4,8 @@
# Distributed under the terms of the 3-clause BSD License.
#-----------------------------------------------------------------------------
import typing
def theme():
return None
@ -12,3 +14,6 @@ def isDark():
def isLight():
return None
def listener(callback: typing.Callable[[str], None]) -> None:
raise NotImplementedError()

View File

@ -6,7 +6,6 @@
import subprocess
def theme():
# Here we just triage to GTK settings for now
try:
@ -18,7 +17,7 @@ def theme():
return 'Light'
# we have a string, now remove start and end quote
theme = stdout.lower().strip()[1:-1]
if theme.endswith('-dark'):
if '-dark' in theme.lower():
return 'Dark'
else:
return 'Light'
@ -28,3 +27,13 @@ def isDark():
def isLight():
return theme() == 'Light'
# def listener(callback: typing.Callable[[str], None]) -> None:
def listener(callback):
with subprocess.Popen(
('gsettings', 'monitor', 'org.gnome.desktop.interface', 'gtk-theme'),
stdout=subprocess.PIPE,
universal_newlines=True,
) as p:
for line in p.stdout:
callback('Dark' if '-dark' in line.strip().removeprefix("gtk-theme: '").removesuffix("'").lower() else 'Light')

View File

@ -68,3 +68,7 @@ def isDark():
def isLight():
return theme() == 'Light'
#def listener(callback: typing.Callable[[str], None]) -> None:
def listener(callback):
raise NotImplementedError()

View File

@ -1,5 +1,60 @@
from winreg import HKEY_CURRENT_USER as hkey, QueryValueEx as getSubkeyValue, OpenKey as getKey
import ctypes
import ctypes.wintypes
advapi32 = ctypes.windll.advapi32
# LSTATUS RegOpenKeyExA(
# HKEY hKey,
# LPCSTR lpSubKey,
# DWORD ulOptions,
# REGSAM samDesired,
# PHKEY phkResult
# );
advapi32.RegOpenKeyExA.argtypes = (
ctypes.wintypes.HKEY,
ctypes.wintypes.LPCSTR,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD,
ctypes.POINTER(ctypes.wintypes.HKEY),
)
advapi32.RegOpenKeyExA.restype = ctypes.wintypes.LONG
# LSTATUS RegQueryValueExA(
# HKEY hKey,
# LPCSTR lpValueName,
# LPDWORD lpReserved,
# LPDWORD lpType,
# LPBYTE lpData,
# LPDWORD lpcbData
# );
advapi32.RegQueryValueExA.argtypes = (
ctypes.wintypes.HKEY,
ctypes.wintypes.LPCSTR,
ctypes.wintypes.LPDWORD,
ctypes.wintypes.LPDWORD,
ctypes.wintypes.LPBYTE,
ctypes.wintypes.LPDWORD,
)
advapi32.RegQueryValueExA.restype = ctypes.wintypes.LONG
# LSTATUS RegNotifyChangeKeyValue(
# HKEY hKey,
# WINBOOL bWatchSubtree,
# DWORD dwNotifyFilter,
# HANDLE hEvent,
# WINBOOL fAsynchronous
# );
advapi32.RegNotifyChangeKeyValue.argtypes = (
ctypes.wintypes.HKEY,
ctypes.wintypes.BOOL,
ctypes.wintypes.DWORD,
ctypes.wintypes.HANDLE,
ctypes.wintypes.BOOL,
)
advapi32.RegNotifyChangeKeyValue.restype = ctypes.wintypes.LONG
def theme():
""" Uses the Windows Registry to detect if the user is using Dark Mode """
# Registry will return 0 if Windows is in Dark Mode and 1 if Windows is in Light Mode. This dictionary converts that output into the text that the program is expecting.
@ -21,4 +76,47 @@ def isDark():
def isLight():
if theme() is not None:
return theme() == 'Light'
return theme() == 'Light'
#def listener(callback: typing.Callable[[str], None]) -> None:
def listener(callback):
hKey = ctypes.wintypes.HKEY()
advapi32.RegOpenKeyExA(
ctypes.wintypes.HKEY(0x80000001), # HKEY_CURRENT_USER
ctypes.wintypes.LPCSTR(b'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize'),
ctypes.wintypes.DWORD(),
ctypes.wintypes.DWORD(0x00020019), # KEY_READ
ctypes.byref(hKey),
)
dwSize = ctypes.wintypes.DWORD(ctypes.sizeof(ctypes.wintypes.DWORD))
queryValueLast = ctypes.wintypes.DWORD()
queryValue = ctypes.wintypes.DWORD()
advapi32.RegQueryValueExA(
hKey,
ctypes.wintypes.LPCSTR(b'AppsUseLightTheme'),
ctypes.wintypes.LPDWORD(),
ctypes.wintypes.LPDWORD(),
ctypes.cast(ctypes.byref(queryValueLast), ctypes.wintypes.LPBYTE),
ctypes.byref(dwSize),
)
while True:
advapi32.RegNotifyChangeKeyValue(
hKey,
ctypes.wintypes.BOOL(True),
ctypes.wintypes.DWORD(0x00000004), # REG_NOTIFY_CHANGE_LAST_SET
ctypes.wintypes.HANDLE(None),
ctypes.wintypes.BOOL(False),
)
advapi32.RegQueryValueExA(
hKey,
ctypes.wintypes.LPCSTR(b'AppsUseLightTheme'),
ctypes.wintypes.LPDWORD(),
ctypes.wintypes.LPDWORD(),
ctypes.cast(ctypes.byref(queryValue), ctypes.wintypes.LPBYTE),
ctypes.byref(dwSize),
)
if queryValueLast.value != queryValue.value:
queryValueLast.value = queryValue.value
callback('Light' if queryValue.value else 'Dark')