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) 2010-2019 Antoine Martin <antoine@xpra.org> 

3# Copyright (C) 2008 Nathaniel Smith <njs@pobox.com> 

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 gi.repository import GObject, Gdk, Gtk 

8 

9from xpra.gtk_common.gobject_util import no_arg_signal, one_arg_signal 

10from xpra.gtk_common.error import xlog, XError 

11from xpra.x11.gtk_x11.prop import prop_set, prop_get 

12from xpra.x11.gtk_x11.selection import ManagerSelection 

13from xpra.x11.gtk_x11.gdk_bindings import ( 

14 add_event_receiver, #@UnresolvedImport 

15 remove_event_receiver, #@UnresolvedImport 

16 get_pywindow, #@UnresolvedImport 

17 get_xatom, #@UnresolvedImport 

18 ) 

19from xpra.log import Logger 

20 

21log = Logger("x11", "xsettings") 

22 

23#the X11 atom name for the XSETTINGS property: 

24XSETTINGS = "_XSETTINGS_SETTINGS" 

25#constant type in prop.py: 

26XSETTINGS_TYPE = "xsettings-settings" 

27 

28XNone = 0 

29 

30 

31class XSettingsManager: 

32 def __init__(self, screen_number=0): 

33 selection = "_XSETTINGS_S%i" % screen_number 

34 self._manager = ManagerSelection(selection) 

35 # Technically I suppose ICCCM says we should use FORCE, but it's not 

36 # like a window manager where you have to wait for the old wm to clean 

37 # things up before you can do anything... as soon as the selection is 

38 # gone, the settings are gone. (Also, if we're stealing from 

39 # ourselves, we probably don't clean up the window properly.) 

40 self._manager.acquire(self._manager.FORCE_AND_RETURN) 

41 self._window = self._manager.window() 

42 

43 def set_settings(self, settings): 

44 if isinstance(settings, list): 

45 settings = tuple(settings) 

46 elif not isinstance(settings, tuple): 

47 log.warn("Warning: discarding xsettings because of incompatible format: %s", type(settings)) 

48 return 

49 try: 

50 prop_set(self._window, XSETTINGS, XSETTINGS_TYPE, settings) 

51 except XError as e: 

52 log("set_settings(%s)", settings, exc_info=True) 

53 log.error("Error: XSettings not applied") 

54 log.error(" %s", e) 

55 

56 

57class XSettingsHelper: 

58 """ 

59 Convenience class for accessing XSETTINGS, 

60 without all the code from the watcher. 

61 """ 

62 def __init__(self, screen_number=0): 

63 self._selection = "_XSETTINGS_S%s" % screen_number 

64 atom = Gdk.Atom.intern(self._selection, False) 

65 self._clipboard = Gtk.Clipboard.get(atom) 

66 

67 def xsettings_owner(self): 

68 with xlog: 

69 from xpra.x11.bindings.window_bindings import X11WindowBindings #@UnresolvedImport 

70 X11Window = X11WindowBindings() 

71 owner_x = X11Window.XGetSelectionOwner(self._selection) 

72 log("XGetSelectionOwner(%s)=%#x", self._selection, owner_x) 

73 if owner_x == XNone: 

74 return None 

75 return get_pywindow(self._clipboard, owner_x) 

76 

77 def get_settings(self): 

78 owner = self.xsettings_owner() 

79 log("Fetching current XSettings data, owner=%s", owner) 

80 if owner is None: 

81 return None 

82 try: 

83 return prop_get(owner, XSETTINGS, XSETTINGS_TYPE) 

84 except XError: 

85 log("X error while fetching XSettings data; ignored", exc_info=True) 

86 return None 

87 

88 

89class XSettingsWatcher(XSettingsHelper, GObject.GObject): 

90 __gsignals__ = { 

91 "xsettings-changed": no_arg_signal, 

92 

93 "xpra-property-notify-event": one_arg_signal, 

94 "xpra-client-message-event": one_arg_signal, 

95 } 

96 def __init__(self, screen_number=0): 

97 GObject.GObject.__init__(self) 

98 XSettingsHelper.__init__(self, screen_number) 

99 self._root = self._clipboard.get_display().get_default_screen().get_root_window() 

100 add_event_receiver(self._root, self) 

101 self._add_watch() 

102 

103 def cleanup(self): 

104 remove_event_receiver(self._root, self) 

105 

106 def _add_watch(self): 

107 owner = self.xsettings_owner() 

108 if owner is not None: 

109 add_event_receiver(owner, self) 

110 

111 def do_xpra_client_message_event(self, event): 

112 if (event.window is self._root 

113 and event.message_type == "MANAGER" 

114 and event.data[1] == get_xatom(self._selection)): 

115 log("XSettings manager changed") 

116 self._add_watch() 

117 self.emit("xsettings-changed") 

118 

119 def do_xpra_property_notify_event(self, event): 

120 if str(event.atom) == XSETTINGS: 

121 log("XSettings property value changed") 

122 self.emit("xsettings-changed") 

123 

124GObject.type_register(XSettingsWatcher) 

125 

126 

127def main(): 

128 from xpra.x11.xsettings_prop import XSettingsNames 

129 from xpra.x11.gtk_x11.gdk_display_source import init_gdk_display_source 

130 init_gdk_display_source() 

131 s = XSettingsHelper().get_settings() 

132 assert s 

133 seq, data = s 

134 print("XSettings: (sequence %i)" % seq) 

135 for vtype, prop, value, serial in data: 

136 if isinstance(value, bytes): 

137 vstr = value.decode() 

138 else: 

139 vstr = str(value) 

140 if serial>0: 

141 vstr += " (serial=%#x)" % serial 

142 print("%8s: %32s = %-32s" % (XSettingsNames.get(vtype, "?"), prop.decode(), vstr)) 

143 

144 

145if __name__ == "__main__": 

146 main()