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) 2008, 2009 Nathaniel Smith <njs@pobox.com> 

3# Copyright (C) 2012-2019 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 

7""" 

8The goo needed to deal with X properties. 

9 

10Everyone else should just use prop_set/prop_get with nice clean Python calling 

11conventions, and if you need more (un)marshalling smarts, add them here. 

12 

13This module adds GTK / GDK specific conversions, 

14the conversions for plain python types is found in prop_conv.py 

15""" 

16 

17import struct 

18from gi.repository import Gdk 

19 

20from xpra.x11.prop_conv import prop_encode, prop_decode, unsupported, PROP_TYPES, PROP_SIZES 

21from xpra.x11.gtk_x11.gdk_bindings import ( 

22 get_pywindow, #@UnresolvedImport 

23 get_xvisual, #@UnresolvedImport 

24 ) 

25from xpra.x11.bindings.window_bindings import ( #@UnresolvedImport 

26 X11WindowBindings, 

27 PropertyError, 

28 ) 

29from xpra.gtk_common.error import xsync, XError, XSyncContext 

30from xpra.util import repr_ellipsized 

31from xpra.log import Logger 

32 

33log = Logger("x11", "window") 

34 

35 

36def _get_atom(_disp, d): 

37 unpacked = struct.unpack(b"@L", d)[0] 

38 if unpacked==0: 

39 log.warn("Warning: invalid zero atom value") 

40 return None 

41 with xsync: 

42 pyatom = X11WindowBindings().XGetAtomName(unpacked) 

43 if not pyatom: 

44 log.error("invalid atom: %s - %s", repr(d), repr(unpacked)) 

45 return None 

46 if not isinstance(pyatom, str): 

47 #py3k: 

48 return pyatom.decode() 

49 return pyatom 

50 

51def _get_xatom(str_or_int): 

52 with xsync: 

53 return X11WindowBindings().get_xatom(str_or_int) 

54 

55def _get_multiple(disp, d): 

56 uint_struct = struct.Struct(b"@L") 

57 log("get_multiple struct size=%s, len(%s)=%s", uint_struct.size, d, len(d)) 

58 if len(d)!=uint_struct.size and False: 

59 log.info("get_multiple value is not an atom: %s", d) 

60 return str(d) 

61 return _get_atom(disp, d) 

62 

63 

64def _get_display_name(disp): 

65 try: 

66 return disp.get_display().get_name() 

67 except Exception: 

68 return None 

69 

70def set_xsettings(disp, v): 

71 from xpra.x11.xsettings_prop import set_settings 

72 return set_settings(_get_display_name(disp), v) 

73 

74def get_xsettings(disp, v): 

75 from xpra.x11.xsettings_prop import get_settings 

76 return get_settings(_get_display_name(disp), v) 

77 

78 

79PYTHON_TYPES = { 

80 "UTF8_STRING" : "utf8", 

81 "STRING" : "latin1", 

82 "ATOM" : "atom", 

83 "CARDINAL" : "u32", 

84 "INTEGER" : "integer", 

85 "VISUALID" : "visual", 

86 "WINDOW" : "window", 

87 } 

88def get_python_type(scalar_type): 

89 #ie: get_python_type("STRING") = "latin1" 

90 return PYTHON_TYPES.get(scalar_type) 

91 

92def _to_atom(_disp, a): 

93 return struct.pack(b"@L", _get_xatom(a)) 

94 

95def _to_visual(disp, c): 

96 return struct.pack(b"@L", get_xvisual(disp, c)) 

97 

98def _to_window(_disp, w): 

99 return struct.pack(b"@L", w.get_xid()) 

100 

101def get_window(disp, w): 

102 return get_pywindow(disp, struct.unpack(b"@L", w)[0]) 

103 

104#add the GTK / GDK types to the conversion function list: 

105PROP_TYPES.update({ 

106 "atom": (str, "ATOM", 32, _to_atom, _get_atom, b""), 

107 "visual": (Gdk.Visual, "VISUALID", 32, _to_visual, unsupported, b""), 

108 "window": (Gdk.Window, "WINDOW", 32, _to_window, get_window, b""), 

109 "xsettings-settings": (tuple, "_XSETTINGS_SETTINGS", 8, 

110 set_xsettings, 

111 get_xsettings, 

112 None), 

113 # For fetching the extra information on a MULTIPLE clipboard conversion 

114 # request. The exciting thing about MULTIPLE is that it's not actually 

115 # specified what 'type' one should use; you just fetch with 

116 # AnyPropertyType and assume that what you get is a bunch of pairs of 

117 # atoms. 

118 "multiple-conversion": (str, 0, 32, unsupported, _get_multiple, None), 

119 }) 

120 

121 

122def prop_set(target, key, etype, value): 

123 with xsync: 

124 dtype, dformat, data = prop_encode(target, etype, value) 

125 X11WindowBindings().XChangeProperty(target.get_xid(), key, dtype, dformat, data) 

126 

127 

128def prop_type_get(target, key): 

129 try: 

130 return X11WindowBindings().GetWindowPropertyType(target.get_xid(), key) 

131 except XError: 

132 log("prop_type_get%s", (target, key), exc_info=True) 

133 return None 

134 

135 

136# May return None. 

137def prop_get(target, key, etype, ignore_errors=False, raise_xerrors=False): 

138 if isinstance(etype, (list, tuple)): 

139 scalar_type = etype[0] 

140 def etypestr(): 

141 return "array of %s" % scalar_type 

142 else: 

143 scalar_type = etype 

144 def etypestr(): 

145 return "%s" % etype 

146 atom = PROP_TYPES[scalar_type][1] 

147 try: 

148 buffer_size = PROP_SIZES.get(scalar_type, 64*1024) 

149 with XSyncContext(): 

150 data = X11WindowBindings().XGetWindowProperty(target.get_xid(), key, atom, etype, buffer_size) 

151 if data is None: 

152 if not ignore_errors: 

153 log("Missing property %s (%s)", key, etype) 

154 return None 

155 except XError: 

156 log("prop_get%s", (target, key, etype, ignore_errors, raise_xerrors), exc_info=True) 

157 if raise_xerrors: 

158 raise 

159 log.info("Missing window %s or wrong property type %s (%s)", target, key, etypestr()) 

160 return None 

161 except PropertyError as e: 

162 log("prop_get%s", (target, key, etype, ignore_errors, raise_xerrors), exc_info=True) 

163 if not ignore_errors: 

164 log.info("Missing property or wrong property type %s (%s)", key, etypestr()) 

165 log.info(" %s", e) 

166 return None 

167 try: 

168 with XSyncContext(): 

169 return prop_decode(target, etype, data) 

170 except : 

171 if ignore_errors: 

172 log("prop_get%s", (target, key, etype, ignore_errors, raise_xerrors), exc_info=True) 

173 return None 

174 log.warn("Error parsing property '%s' (%s)", key, etypestr()) 

175 log.warn(" this may be a misbehaving application, or bug in Xpra") 

176 try: 

177 log.warn(" data length=%i", len(data)) 

178 except TypeError: 

179 pass 

180 log.warn(" data: %r", repr_ellipsized(str(data)), exc_info=True) 

181 raise 

182 

183def prop_del(target, key): 

184 with xsync: 

185 X11WindowBindings().XDeleteProperty(target.get_xid(), key)