diff --git a/src/calibre/gui2/dbus_export/gtk.py b/src/calibre/gui2/dbus_export/gtk.py index 8d40c0dfce..da82d6a0a6 100644 --- a/src/calibre/gui2/dbus_export/gtk.py +++ b/src/calibre/gui2/dbus_export/gtk.py @@ -208,28 +208,24 @@ class MyApplication(Gtk.Application): conn = xcb.Connection() atoms = conn.core.ListProperties(win_id).reply().atoms atom_names = {atom:conn.core.GetAtomNameUnchecked(atom) for atom in atoms} - atom_names = {k:str(a.reply().name.buf()) for k, a in atom_names.iteritems()} + atom_names = {k:bytes(a.reply().name.buf()) for k, a in atom_names.iteritems()} property_names = {name:atom for atom, name in atom_names.iteritems() if name.startswith('_GTK') or name.startswith('_UNITY') or name.startswith('_GNOME')} replies = {name:conn.core.GetProperty(False, win_id, atom, xcb.xproto.GetPropertyType.Any, 0, 2 ** 32 - 1) for name, atom in property_names.iteritems()} + type_atom_cache = {} + def get_property_value(property_reply): if property_reply.format == 8: - if 0 in property_reply.value[:-1]: - ret = [] - s = [] - for o in property_reply.value: - if o == 0: - ret.append(''.join(s)) - s = [] - else: - s.append(chr(o)) - else: - ret = str(property_reply.value.buf()) - if len(property_reply.value) > 0 and 0 == property_reply.value[-1]: - ret = ret[:-1] - - return ret + is_list_of_strings = 0 in property_reply.value[:-1] + ans = bytes(property_reply.value.buf()) + if property_reply.type not in type_atom_cache: + type_atom_cache[property_reply.type] = bytes(conn.core.GetAtomNameUnchecked(property_reply.type).reply().name.buf()) + if type_atom_cache[property_reply.type] == b'UTF8_STRING': + ans = ans.decode('utf-8') + if is_list_of_strings: + ans = ans.split('\0') + return ans elif property_reply.format in (16, 32): return list(struct.unpack(b'I' * property_reply.value_len, property_reply.value.buf())) diff --git a/src/calibre/gui2/dbus_export/utils.py b/src/calibre/gui2/dbus_export/utils.py index 72b60d6c22..48a443cd2b 100644 --- a/src/calibre/gui2/dbus_export/utils.py +++ b/src/calibre/gui2/dbus_export/utils.py @@ -129,10 +129,19 @@ def setup_for_cli_run(): signal.signal(signal.SIGINT, signal.SIG_DFL) # quit on Ctrl-C def set_X_window_properties(win_id, **properties): + ' Set X Window properties on the window with the specified id. Only string values are supported. ' import xcb, xcb.xproto conn = xcb.connect() + atoms = {name:conn.core.InternAtom(False, len(name), name) for name in properties} + utf8_string_atom = None for name, val in properties.iteritems(): - atom = conn.core.InternAtom(False, len(name), name).reply().atom - conn.core.ChangePropertyChecked(xcb.xproto.PropMode.Replace, win_id, atom, xcb.xproto.Atom.STRING, 8, len(val), val) + atom = atoms[name].reply().atom + type_atom = xcb.xproto.Atom.STRING + if isinstance(val, unicode): + if utf8_string_atom is None: + utf8_string_atom = conn.core.InternAtom(True, len(b'UTF8_STRING'), b'UTF8_STRING').reply().atom + type_atom = utf8_string_atom + val = val.encode('utf-8') + conn.core.ChangePropertyChecked(xcb.xproto.PropMode.Replace, win_id, atom, type_atom, 8, len(val), val) conn.flush() conn.disconnect()