-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscaling.py
More file actions
137 lines (105 loc) · 4.16 KB
/
scaling.py
File metadata and controls
137 lines (105 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import re
import customtkinter as ctk
import sys
import os
import subprocess
class Scaling:
"""
These values are hardcoded to my system setups for now
b/c Tk scaling is profoundly busted.
May want to revisit and generalize properly but maybe not.
"""
ctk_window_scale = 1.0
ctk_widget_scale = 1.0
system_scale = 1.0 # system's reported pixel scaling; may or may not be used for concrete app values; TBD
canvas_scale = 1.0
canvas_font_scale = 1.0
system_scale = 1.0
canvas_scale = 1.0
@staticmethod
def init():
# System scale
if sys.platform.startswith("linux"):
Scaling.system_scale = Scaling.get_system_scale_linux()
else: # assume windows
Scaling.system_scale = Scaling.get_system_scale_windows()
# Ctk scaling factors
if sys.platform.startswith("linux"):
Scaling.ctk_window_scale = Scaling.system_scale
Scaling.ctk_widget_scale = Scaling.system_scale
else:
Scaling.ctk_window_scale = 1.0
Scaling.ctk_widget_scale = 1.0
ctk.set_window_scaling(Scaling.ctk_window_scale)
ctk.set_widget_scaling(Scaling.ctk_widget_scale)
# Various
if sys.platform.startswith("linux"):
Scaling.canvas_scale = 2.0
Scaling.canvas_font_scale = 1.0
else:
Scaling.canvas_scale = 2.0
Scaling.canvas_font_scale = 2.0
@staticmethod
def init_OLD():
""" Unused; keep for reference in case I want to revisit """
if sys.platform.startswith("linux"):
Scaling.system_scale = Scaling.get_system_scale_linux()
ctk.set_window_scaling(Scaling.system_scale)
ctk.set_widget_scaling(Scaling.system_scale)
Scaling.canvas_scale = Scaling.system_scale
elif sys.platform == "win32":
Scaling.system_scale = Scaling.get_system_scale_windows()
Scaling.canvas_scale = Scaling.get_system_scale_windows()
elif sys.platform == "darwin":
... # Do nothing
else:
... # Do nothing
print("System scale", Scaling.system_scale)
print("Canvas scale", Scaling.canvas_scale)
# FYI this doesn't seem to affect behavior one way or another
# ctk.deactivate_automatic_dpi_awareness()
@staticmethod
def get_system_scale_linux() -> float:
# 1. Start with a baseline scale
scale = 1.0
if sys.platform.startswith("linux"):
dpi = get_linux_dpi()
if dpi:
# 96 is the standard "100%" scale baseline
# print("linux dpi", dpi)
scale = dpi / 96.0
else:
# Fallback for some Wayland setups or systems without xrdb
# This looks at the physical mm vs pixel width
try:
import tkinter as tk
root = tk.Tk()
# 25.4 mm in an inch. This calculates pixels per inch.
dpi = (root.winfo_screenwidth() / (root.winfo_screenmmwidth() / 25.4))
root.destroy()
scale = dpi / 96.0
except:
scale = 1.0
elif sys.platform == "win32":
# Windows handling (standard)
from ctypes import windll
scale = windll.shcore.GetScaleFactorForDevice(0) / 100.0
return scale
@staticmethod
def get_system_scale_windows() -> float:
# Windows handling (standard)
from ctypes import windll # type: ignore
scale = windll.shcore.GetScaleFactorForDevice(0) / 100.0
return scale
# ---
def get_linux_dpi():
"""Queries the X11 resource database for the actual DPI."""
try:
# xrdb is the most reliable way to get the DPI Linux actually uses to render
output = subprocess.check_output(["xrdb", "-query"], stderr=subprocess.DEVNULL).decode()
m = re.search(r"Xft\.dpi:\s+(\d+)", output)
if m:
return float(m.group(1))
except:
pass
return None