-
-
Notifications
You must be signed in to change notification settings - Fork 177
/
Copy pathrun_scaled
executable file
·150 lines (126 loc) · 4.6 KB
/
run_scaled
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python3
# pylint: disable=import-outside-toplevel
import os
import sys
import shlex
from typing import NoReturn
from shutil import which
DEFAULT_XPRA_ARGS = [
"--attach=yes",
"--exit-with-children=yes",
# "--exit-with-client=yes",
"--encodings=rgb",
"--compress=0",
"--audio=no",
"--video=no",
"--mdns=no",
"--start-new-commands=no",
"--systemd-run=no",
]
def usage(msg: str = "", exit_code=1) -> NoReturn:
if msg:
sys.stderr.write("%s\n" % msg)
sys.stderr.write("usage: run_scaled --scale=VALUE application [optionalarguments]\n")
sys.stderr.write(" ie: run_scaled --scale=2 xterm +ls -fg blue\n")
sys.stderr.write("or also using `--` for clarity\n")
sys.stderr.write("usage: run_scaled --scale=VALUE [extra xpra arguments] -- application [optionalarguments]")
sys.stderr.write(" ie: run_scaled --scale=3 --mousewheel=invert-y -- xterm -n foo -fg red\n")
sys.exit(exit_code)
def parse_scale(scale: str) -> float:
try:
try:
if scale.endswith("%"):
value = float(scale[:-1]) / 100
else:
value = float(scale)
except ValueError:
# try parsing it as a fraction:
from fractions import Fraction
value = float(Fraction(scale))
except ValueError:
usage(f"invalid scale value {scale!r}")
if value < 0.1 or value > 10:
usage(f"scale value {value} is out of range")
return value
def dpiv(size: int, size_mm: int) -> int:
""" convert a screen size ratio into a DPI value """
return round(size * 25.4 / size_mm)
def get_screen_spec() -> tuple[int, int, int]:
# figure out the dpi and vfb size to use,
dpi = width = height = 0
try:
from xpra.util.env import OSEnvContext
context = OSEnvContext
except ImportError:
from contextlib import nullcontext
context = nullcontext
with context():
os.environ["GDK_SCALE"] = "1"
os.environ["GDK_DPI_SCALE"] = "1"
try:
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
screen = Gdk.Screen.get_default()
except ImportError:
screen = None
if screen:
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore")
width = screen.get_width()
height = screen.get_height()
if 0 < width < 2 ** 16 and 0 < height < 2 ** 16:
dpi = (dpiv(width, screen.get_width_mm()) + dpiv(height, screen.get_height_mm())) // 2
return width, height, dpi
def parse_argv(argv: list[str]) -> tuple[int, list[str], list[str]]:
# default scaling value is 2:
scale = 2
command_argv: list[str] = []
extra_xpra_args: list[str] = []
# If "--" is present, the command is after that
if "--" in argv:
split_idx = argv.index("--")
else:
split_idx = -1
for i, x in enumerate(argv):
if x in ("--help", "-h"):
usage("", 0)
elif x.startswith("--scale="):
scale = parse_scale(x[len("--scale="):])
elif i == 0 or i == split_idx:
# x == "run_scaled" or x == "--"
continue
else:
if i >= split_idx:
command_argv.append(x)
else:
extra_xpra_args.append(x)
if not command_argv:
usage("missing command argument")
return scale, command_argv, extra_xpra_args
def find_xpra() -> str:
xpra = which("xpra") or ""
if not xpra and sys.argv[0].find("run_scaled") >= 0:
xpra = sys.argv[0].replace("run_scaled", "xpra")
if not xpra or not os.path.exists(xpra):
usage("cannot find 'xpra' on $PATH")
return xpra
xpra_cmd = find_xpra()
def get_argv() -> list[str]:
scale, command_argv, extra_xpra_args = parse_argv(sys.argv)
argv = [xpra_cmd, "start",
"--start-child=%s" % shlex.join(command_argv),
"--desktop-scaling=%s" % scale] + DEFAULT_XPRA_ARGS + extra_xpra_args
width, height, dpi = get_screen_spec()
# if found, prefer Xvfb, as it is faster to startup:
xvfb = which("Xvfb") or ""
if xvfb:
from xpra.scripts.config import get_Xvfb_command
argv.append("--xvfb=%s" % shlex.join(get_Xvfb_command(width, height, dpi * scale)))
if width > 0 and height > 0:
argv.append("--resize-display=%ix%i" % (width // scale, height // scale))
if 10 < dpi < 1000:
argv.append("--dpi=%i" % (dpi * scale))
return argv
os.execv(xpra_cmd, get_argv())