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) 2011-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 

7import os 

8from gi.repository import GObject 

9 

10from xpra.gtk_common.gobject_util import AutoPropGObjectMixin 

11from xpra.log import Logger 

12 

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

14metalog = Logger("x11", "window", "metadata") 

15 

16PROPERTIES_DEBUG = [x.strip() for x in os.environ.get("XPRA_WINDOW_PROPERTIES_DEBUG", "").split(",")] 

17 

18 

19class WindowModelStub(AutoPropGObjectMixin, GObject.GObject): 

20 """ 

21 Stub for all window models 

22 """ 

23 

24 #things that we expose: 

25 _property_names = [] 

26 #exposed and changing (should be watched for notify signals): 

27 _dynamic_property_names = [] 

28 _internal_property_names = [] 

29 _MODELTYPE = "Stub" 

30 

31 def __init__(self): 

32 AutoPropGObjectMixin.__init__(self) 

33 GObject.GObject.__init__(self) 

34 self._setup_done = False #so we can ignore notify() events during setup 

35 self._managed = False 

36 self._managed_handlers = [] 

37 

38 

39 ######################################### 

40 # Setup and teardown 

41 ######################################### 

42 

43 def is_managed(self) -> bool: 

44 return self._managed 

45 

46 def unmanage(self, _exiting=False): 

47 self.managed_disconnect() 

48 

49 

50 ######################################### 

51 # Connect to signals in a "managed" way 

52 ######################################### 

53 

54 def managed_connect(self, detailed_signal, handler, *args): 

55 """ connects a signal handler and makes sure we will clean it up on unmanage() """ 

56 handler_id = self.connect(detailed_signal, handler, *args) 

57 self._managed_handlers.append(handler_id) 

58 return handler_id 

59 

60 def managed_disconnect(self): 

61 for handler_id in self._managed_handlers: 

62 self.disconnect(handler_id) 

63 self._managed_handlers = [] 

64 

65 

66 ################################ 

67 # Property reading 

68 ################################ 

69 

70 def get_dimensions(self): 

71 return NotImplementedError() 

72 

73 

74 ######################################### 

75 # Properties we choose to expose 

76 ######################################### 

77 

78 def get_property_names(self): 

79 """ The properties that should be exposed to clients """ 

80 return self._property_names 

81 

82 def get_dynamic_property_names(self): 

83 """ The properties that may change over time """ 

84 return self._dynamic_property_names 

85 

86 def get_internal_property_names(self): 

87 """ The properties that should not be exposed to the client """ 

88 return self._internal_property_names 

89 

90 def get_logger(self, property_name): 

91 if property_name in PROPERTIES_DEBUG: 

92 return metalog.info 

93 return metalog.debug 

94 

95 def _updateprop(self, name : str, value): 

96 """ Updates the property and fires notify(), 

97 but only if the value has changed 

98 and if the window has finished setting up and it is still managed. 

99 Can only be used for AutoPropGObjectMixin properties. 

100 """ 

101 l = self.get_logger(name) 

102 cur = self._gproperties.get(name, None) 

103 if name not in self._gproperties or cur!=value: 

104 l("updateprop(%s, %s) previous value=%s", name, value, cur) 

105 self._gproperties[name] = value 

106 if self._setup_done and self._managed: 

107 self.notify(name) 

108 else: 

109 l("not sending notify(%s) (setup done=%s, managed=%s)", name, self._setup_done, self._managed) 

110 return True 

111 l("updateprop(%s, %s) unchanged", name, value) 

112 return False 

113 

114 def get(self, name : str, default_value=None): 

115 """ Allows us the avoid defining all the attributes we may ever query, 

116 returns the default value if the property does not exist. 

117 """ 

118 l = self.get_logger(name) 

119 if name in set(self._property_names + self._dynamic_property_names + self._internal_property_names): 

120 v = self.get_property(name) 

121 l("get(%s, %s) using get_property=%s", name, default_value, v) 

122 else: 

123 v = default_value 

124 if name not in ("override-redirect", "tray"): 

125 l("get(%s, %s) not a property of %s, returning default value=%s", name, default_value, type(self), v) 

126 return v 

127 

128 

129 #temporary? / convenience access methods: 

130 def is_OR(self) -> bool: 

131 """ Is this an override-redirect window? """ 

132 return self.get("override-redirect", False) 

133 

134 def is_tray(self) -> bool: 

135 """ Is this a tray window? """ 

136 return self.get("tray", False) 

137 

138 def is_shadow(self) -> bool: 

139 """ Is this a shadow instead of a real window? """ 

140 return False 

141 

142 def has_alpha(self) -> bool: 

143 """ Does the pixel data have an alpha channel? """ 

144 return self.get("has-alpha", False)