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# -*- coding: utf-8 -*- 

2# This file is part of Xpra. 

3# Copyright (C) 2010-2020 Antoine Martin <antoine@xpra.org> 

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

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

6 

7from xpra.os_util import strtobytes 

8from xpra.util import get_screen_info, envint, first_time, iround, typedict 

9from xpra.server.source.stub_source_mixin import StubSourceMixin 

10from xpra.log import Logger 

11 

12log = Logger("av-sync") 

13 

14 

15""" 

16Store information and manage events related to the client's display 

17""" 

18class ClientDisplayMixin(StubSourceMixin): 

19 

20 def cleanup(self): 

21 self.init_state() 

22 

23 def init_state(self): 

24 self.icc = {} 

25 self.display_icc = {} 

26 self.randr_notify = False 

27 self.desktop_size = None 

28 self.desktop_mode_size = None 

29 self.desktop_size_unscaled = None 

30 self.desktop_size_server = None 

31 self.screen_sizes = () 

32 self.screen_resize_bigger = True 

33 self.desktops = 1 

34 self.desktop_names = () 

35 self.show_desktop_allowed = False 

36 self.opengl_props = {} 

37 

38 def get_info(self) -> dict: 

39 info = { 

40 "desktop_size" : self.desktop_size or "", 

41 "desktops" : self.desktops, 

42 "desktop_names" : self.desktop_names, 

43 "randr_notify" : self.randr_notify, 

44 "opengl" : self.opengl_props, 

45 } 

46 info.update(get_screen_info(self.screen_sizes)) 

47 if self.desktop_mode_size: 

48 info["desktop_mode_size"] = self.desktop_mode_size 

49 if self.desktop_size_unscaled: 

50 info["desktop_size"] = {"unscaled" : self.desktop_size_unscaled} 

51 return info 

52 

53 def parse_client_caps(self, c : typedict): 

54 self.randr_notify = c.boolget("randr_notify") 

55 self.desktop_size = c.intpair("desktop_size") 

56 if self.desktop_size is not None: 

57 w, h = self.desktop_size 

58 if w<=0 or h<=0 or w>=32768 or h>=32768: 

59 log.warn("ignoring invalid desktop dimensions: %sx%s", w, h) 

60 self.desktop_size = None 

61 self.desktop_mode_size = c.intpair("desktop_mode_size") 

62 self.desktop_size_unscaled = c.intpair("desktop_size.unscaled") 

63 self.screen_resize_bigger = c.boolget("screen-resize-bigger", True) 

64 self.set_screen_sizes(c.tupleget("screen_sizes")) 

65 self.set_desktops(c.intget("desktops", 1), c.strtupleget("desktop.names")) 

66 self.show_desktop_allowed = c.boolget("show-desktop") 

67 self.icc = c.dictget("icc", {}) 

68 self.display_icc = c.dictget("display-icc", {}) 

69 self.opengl_props = c.dictget("opengl", {}) 

70 

71 

72 def set_screen_sizes(self, screen_sizes): 

73 log("set_screen_sizes(%s)", screen_sizes) 

74 self.screen_sizes = list(screen_sizes) 

75 #validate dpi / screen size in mm 

76 #(ticket 2480: GTK3 on macos can return bogus values) 

77 MIN_DPI = envint("XPRA_MIN_DPI", 10) 

78 MAX_DPI = envint("XPRA_MIN_DPI", 500) 

79 def dpi(size_pixels, size_mm): 

80 if size_mm==0: 

81 return 0 

82 return int(size_pixels * 254 / size_mm / 10) 

83 for i,screen in enumerate(list(screen_sizes)): 

84 if len(screen)<10: 

85 continue 

86 sw, sh, wmm, hmm, monitors = screen[1:6] 

87 xdpi = dpi(sw, wmm) 

88 ydpi = dpi(sh, hmm) 

89 if xdpi<MIN_DPI or xdpi>MAX_DPI or ydpi<MIN_DPI or ydpi>MAX_DPI: 

90 warn = first_time("invalid-screen-size-%ix%i" % (wmm, hmm)) 

91 if warn: 

92 log.warn("Warning: ignoring invalid screen size %ix%i mm", wmm, hmm) 

93 if monitors: 

94 #[plug_name, xs(geom.x), ys(geom.y), xs(geom.width), ys(geom.height), wmm, hmm] 

95 wmm = sum(monitor[5] for monitor in monitors) 

96 hmm = sum(monitor[6] for monitor in monitors) 

97 xdpi = dpi(sw, wmm) 

98 ydpi = dpi(sh, hmm) 

99 if xdpi<MIN_DPI or xdpi>MAX_DPI or ydpi<MIN_DPI or ydpi>MAX_DPI: 

100 #still invalid, generate one from DPI=96 

101 wmm = iround(sw*25.4/96) 

102 hmm = iround(sh*25.4/96) 

103 if warn: 

104 log.warn(" using %ix%i mm", wmm, hmm) 

105 screen = list(screen) 

106 screen[3] = wmm 

107 screen[4] = hmm 

108 self.screen_sizes[i] = tuple(screen) 

109 log("client validated screen sizes: %s", self.screen_sizes) 

110 

111 def set_desktops(self, desktops, desktop_names): 

112 self.desktops = desktops or 1 

113 #older clients send strings, 

114 #newer clients send bytes... 

115 def b(v): 

116 try : 

117 return strtobytes(v).decode("utf8") 

118 except UnicodeDecodeError: 

119 return v 

120 if desktop_names: 

121 self.desktop_names = [b(d) for d in desktop_names] 

122 else: 

123 self.desktop_names = [] 

124 

125 def updated_desktop_size(self, root_w, root_h, max_w, max_h): 

126 log("updated_desktop_size%s randr_notify=%s, desktop_size=%s", 

127 (root_w, root_h, max_w, max_h), self.randr_notify, self.desktop_size) 

128 if not self.hello_sent: 

129 return False 

130 if self.randr_notify and (not self.desktop_size_server or tuple(self.desktop_size_server)!=(root_w, root_h)): 

131 self.desktop_size_server = root_w, root_h 

132 self.send("desktop_size", root_w, root_h, max_w, max_h) 

133 return True 

134 return False 

135 

136 def show_desktop(self, show): 

137 if self.show_desktop_allowed and self.hello_sent: 

138 self.send_async("show-desktop", show)