Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/x11/models/model_stub.py : 87%
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.
7import os
8from gi.repository import GObject
10from xpra.gtk_common.gobject_util import AutoPropGObjectMixin
11from xpra.log import Logger
13log = Logger("x11", "window")
14metalog = Logger("x11", "window", "metadata")
16PROPERTIES_DEBUG = [x.strip() for x in os.environ.get("XPRA_WINDOW_PROPERTIES_DEBUG", "").split(",")]
19class WindowModelStub(AutoPropGObjectMixin, GObject.GObject):
20 """
21 Stub for all window models
22 """
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"
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 = []
39 #########################################
40 # Setup and teardown
41 #########################################
43 def is_managed(self) -> bool:
44 return self._managed
46 def unmanage(self, _exiting=False):
47 self.managed_disconnect()
50 #########################################
51 # Connect to signals in a "managed" way
52 #########################################
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
60 def managed_disconnect(self):
61 for handler_id in self._managed_handlers:
62 self.disconnect(handler_id)
63 self._managed_handlers = []
66 ################################
67 # Property reading
68 ################################
70 def get_dimensions(self):
71 return NotImplementedError()
74 #########################################
75 # Properties we choose to expose
76 #########################################
78 def get_property_names(self):
79 """ The properties that should be exposed to clients """
80 return self._property_names
82 def get_dynamic_property_names(self):
83 """ The properties that may change over time """
84 return self._dynamic_property_names
86 def get_internal_property_names(self):
87 """ The properties that should not be exposed to the client """
88 return self._internal_property_names
90 def get_logger(self, property_name):
91 if property_name in PROPERTIES_DEBUG:
92 return metalog.info
93 return metalog.debug
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
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
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)
134 def is_tray(self) -> bool:
135 """ Is this a tray window? """
136 return self.get("tray", False)
138 def is_shadow(self) -> bool:
139 """ Is this a shadow instead of a real window? """
140 return False
142 def has_alpha(self) -> bool:
143 """ Does the pixel data have an alpha channel? """
144 return self.get("has-alpha", False)