Umstellung auf Customtkinter.
This commit is contained in:
124
.venv/Lib/site-packages/darkdetect/_mac_detect.py
Normal file
124
.venv/Lib/site-packages/darkdetect/_mac_detect.py
Normal file
@@ -0,0 +1,124 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) 2019 Alberto Sottile
|
||||
#
|
||||
# Distributed under the terms of the 3-clause BSD License.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
try:
|
||||
from Foundation import NSObject, NSKeyValueObservingOptionNew, NSKeyValueChangeNewKey, NSUserDefaults
|
||||
from PyObjCTools import AppHelper
|
||||
_can_listen = True
|
||||
except ModuleNotFoundError:
|
||||
_can_listen = False
|
||||
|
||||
|
||||
try:
|
||||
# macOS Big Sur+ use "a built-in dynamic linker cache of all system-provided libraries"
|
||||
appkit = ctypes.cdll.LoadLibrary('AppKit.framework/AppKit')
|
||||
objc = ctypes.cdll.LoadLibrary('libobjc.dylib')
|
||||
except OSError:
|
||||
# revert to full path for older OS versions and hardened programs
|
||||
appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('AppKit'))
|
||||
objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
|
||||
|
||||
void_p = ctypes.c_void_p
|
||||
ull = ctypes.c_uint64
|
||||
|
||||
objc.objc_getClass.restype = void_p
|
||||
objc.sel_registerName.restype = void_p
|
||||
|
||||
# See https://docs.python.org/3/library/ctypes.html#function-prototypes for arguments description
|
||||
MSGPROTOTYPE = ctypes.CFUNCTYPE(void_p, void_p, void_p, void_p)
|
||||
msg = MSGPROTOTYPE(('objc_msgSend', objc), ((1 ,'', None), (1, '', None), (1, '', None)))
|
||||
|
||||
def _utf8(s):
|
||||
if not isinstance(s, bytes):
|
||||
s = s.encode('utf8')
|
||||
return s
|
||||
|
||||
def n(name):
|
||||
return objc.sel_registerName(_utf8(name))
|
||||
|
||||
def C(classname):
|
||||
return objc.objc_getClass(_utf8(classname))
|
||||
|
||||
def theme():
|
||||
NSAutoreleasePool = objc.objc_getClass('NSAutoreleasePool')
|
||||
pool = msg(NSAutoreleasePool, n('alloc'))
|
||||
pool = msg(pool, n('init'))
|
||||
|
||||
NSUserDefaults = C('NSUserDefaults')
|
||||
stdUserDef = msg(NSUserDefaults, n('standardUserDefaults'))
|
||||
|
||||
NSString = C('NSString')
|
||||
|
||||
key = msg(NSString, n("stringWithUTF8String:"), _utf8('AppleInterfaceStyle'))
|
||||
appearanceNS = msg(stdUserDef, n('stringForKey:'), void_p(key))
|
||||
appearanceC = msg(appearanceNS, n('UTF8String'))
|
||||
|
||||
if appearanceC is not None:
|
||||
out = ctypes.string_at(appearanceC)
|
||||
else:
|
||||
out = None
|
||||
|
||||
msg(pool, n('release'))
|
||||
|
||||
if out is not None:
|
||||
return out.decode('utf-8')
|
||||
else:
|
||||
return 'Light'
|
||||
|
||||
def isDark():
|
||||
return theme() == 'Dark'
|
||||
|
||||
def isLight():
|
||||
return theme() == 'Light'
|
||||
|
||||
|
||||
def _listen_child():
|
||||
"""
|
||||
Run by a child process, install an observer and print theme on change
|
||||
"""
|
||||
import signal
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
OBSERVED_KEY = "AppleInterfaceStyle"
|
||||
|
||||
class Observer(NSObject):
|
||||
def observeValueForKeyPath_ofObject_change_context_(
|
||||
self, path, object, changeDescription, context
|
||||
):
|
||||
result = changeDescription[NSKeyValueChangeNewKey]
|
||||
try:
|
||||
print(f"{'Light' if result is None else result}", flush=True)
|
||||
except IOError:
|
||||
os._exit(1)
|
||||
|
||||
observer = Observer.new() # Keep a reference alive after installing
|
||||
defaults = NSUserDefaults.standardUserDefaults()
|
||||
defaults.addObserver_forKeyPath_options_context_(
|
||||
observer, OBSERVED_KEY, NSKeyValueObservingOptionNew, 0
|
||||
)
|
||||
|
||||
AppHelper.runConsoleEventLoop()
|
||||
|
||||
|
||||
def listener(callback: Callable[[str], None]) -> None:
|
||||
if not _can_listen:
|
||||
raise NotImplementedError()
|
||||
with subprocess.Popen(
|
||||
(sys.executable, "-c", "import _mac_detect as m; m._listen_child()"),
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
cwd=Path(__file__).parent,
|
||||
) as p:
|
||||
for line in p.stdout:
|
||||
callback(line.strip())
|
||||
Reference in New Issue
Block a user