Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/x11/gtk_x11/prop.py : 59%
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.
7"""
8The goo needed to deal with X properties.
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.
13This module adds GTK / GDK specific conversions,
14the conversions for plain python types is found in prop_conv.py
15"""
17import struct
18from gi.repository import Gdk
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
33log = Logger("x11", "window")
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
51def _get_xatom(str_or_int):
52 with xsync:
53 return X11WindowBindings().get_xatom(str_or_int)
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)
64def _get_display_name(disp):
65 try:
66 return disp.get_display().get_name()
67 except Exception:
68 return None
70def set_xsettings(disp, v):
71 from xpra.x11.xsettings_prop import set_settings
72 return set_settings(_get_display_name(disp), v)
74def get_xsettings(disp, v):
75 from xpra.x11.xsettings_prop import get_settings
76 return get_settings(_get_display_name(disp), v)
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)
92def _to_atom(_disp, a):
93 return struct.pack(b"@L", _get_xatom(a))
95def _to_visual(disp, c):
96 return struct.pack(b"@L", get_xvisual(disp, c))
98def _to_window(_disp, w):
99 return struct.pack(b"@L", w.get_xid())
101def get_window(disp, w):
102 return get_pywindow(disp, struct.unpack(b"@L", w)[0])
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 })
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)
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
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
183def prop_del(target, key):
184 with xsync:
185 X11WindowBindings().XDeleteProperty(target.get_xid(), key)