Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# This file is part of Xpra. 

2# Copyright (C) 2018 Antoine Martin <antoine@xpra.org> 

3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any 

4# later version. See the file COPYING for details. 

5 

6from xpra.log import Logger 

7from xpra.scripts.config import TRUE_OPTIONS 

8 

9log = Logger("scaling") 

10 

11 

12def parse_scaling(desktop_scaling, root_w, root_h, min_scaling=0.1, max_scaling=8): 

13 log("parse_scaling(%s)", (desktop_scaling, root_w, root_h, min_scaling, max_scaling)) 

14 if desktop_scaling in TRUE_OPTIONS: 

15 return 1, 1 

16 if desktop_scaling.startswith("auto"): 

17 #figure out if the command line includes settings to use for auto mode: 

18 #here are our defaults: 

19 limits = ((3960, 2160, 1, 1), #100% no auto scaling up to 4k 

20 (7680, 4320, 1.25, 1.25), #125% 

21 (8192, 8192, 1.5, 1.5), #150% 

22 (16384, 16384, 5.0/3, 5.0/3), #166% 

23 (32768, 32768, 2, 2), 

24 (65536, 65536, 4, 4), 

25 ) #200% if higher (who has this anyway?) 

26 if desktop_scaling=="auto": 

27 pass 

28 elif desktop_scaling.startswith("auto:"): 

29 limstr = desktop_scaling[5:] #ie: '1920x1080:1,2560x1600:1.5,... 

30 limp = limstr.split(",") 

31 limits = [] 

32 for l in limp: 

33 try: 

34 ldef = l.split(":") 

35 assert len(ldef)==2, "could not find 2 parts separated by ':' in '%s'" % ldef 

36 dims = ldef[0].split("x") 

37 assert len(dims)==2, "could not find 2 dimensions separated by 'x' in '%s'" % ldef[0] 

38 x, y = int(dims[0]), int(dims[1]) 

39 scaleparts = ldef[1].replace("*", "x").replace("/", "x").split("x") 

40 assert len(scaleparts)<=2, "found more than 2 scaling dimensions!" 

41 if len(scaleparts)==1: 

42 sx = sy = float(scaleparts[0]) 

43 else: 

44 sx = float(scaleparts[0]) 

45 sy = float(scaleparts[1]) 

46 limits.append((x, y, sx, sy)) 

47 log("parsed desktop-scaling auto limits: %s", limits) 

48 except Exception as e: 

49 log.warn("Warning: failed to parse limit string '%s':", l) 

50 log.warn(" %s", e) 

51 log.warn(" should use the format WIDTHxHEIGTH:SCALINGVALUE") 

52 else: 

53 log.warn("Warning: invalid auto attributes '%s'", desktop_scaling[5:]) 

54 sx, sy = 1, 1 

55 matched = False 

56 for mx, my, tsx, tsy in limits: 

57 if root_w*root_h<=mx*my: 

58 sx, sy = tsx, tsy 

59 matched = True 

60 break 

61 log("matched=%s : %sx%s with limits %s: %sx%s", matched, root_w, root_h, limits, sx, sy) 

62 return sx,sy 

63 def parse_item(v): 

64 div = 1 

65 try: 

66 if v.endswith("%"): 

67 div = 100 

68 v = v[:-1] 

69 except ValueError: 

70 pass 

71 if div==1: 

72 try: 

73 return int(v) #ie: desktop-scaling=2 

74 except ValueError: 

75 pass 

76 try: 

77 return float(v)/div #ie: desktop-scaling=1.5 

78 except (ValueError, ZeroDivisionError): 

79 pass 

80 #ie: desktop-scaling=3/2, or desktop-scaling=3:2 

81 pair = v.replace(":", "/").split("/", 1) 

82 try: 

83 return float(pair[0])/float(pair[1]) 

84 except (ValueError, ZeroDivisionError): 

85 pass 

86 log.warn("Warning: failed to parse scaling value '%s'", v) 

87 return None 

88 if desktop_scaling.find("x")>0 and desktop_scaling.find(":")>0: 

89 log.warn("Warning: found both 'x' and ':' in desktop-scaling fixed value") 

90 log.warn(" maybe the 'auto:' prefix is missing?") 

91 return 1, 1 

92 #split if we have two dimensions: "1600x1200" -> ["1600", "1200"], if not: "2" -> ["2"] 

93 values = desktop_scaling.replace(",", "x").split("x", 1) 

94 x = parse_item(values[0]) 

95 if x is None: 

96 return 1, 1 

97 if len(values)==1: 

98 #just one value: use the same for X and Y 

99 y = x 

100 else: 

101 y = parse_item(values[1]) 

102 if y is None: 

103 return 1, 1 

104 log("parse_scaling(%s) parsed items=%s", desktop_scaling, (x, y)) 

105 #normalize absolute values into floats: 

106 if x>max_scaling or y>max_scaling: 

107 log(" normalizing dimensions to a ratio of %ix%i", root_w, root_h) 

108 x = float(x) / root_w 

109 y = float(y) / root_h 

110 if x<min_scaling or y<min_scaling or x>max_scaling or y>max_scaling: 

111 log.warn("Warning: scaling values %sx%s are out of range", x, y) 

112 return 1, 1 

113 log("parse_scaling(%s)=%s", desktop_scaling, (x, y)) 

114 return x, y