1 #Copyright (C) 2008 Codethink Ltd
2 #copyright: Copyright (c) 2005, 2007 IBM Corporation
4 #This library is free software; you can redistribute it and/or
5 #modify it under the terms of the GNU Lesser General Public
6 #License version 2 as published by the Free Software Foundation.
8 #This program is distributed in the hope that it will be useful,
9 #but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 #GNU General Public License for more details.
12 #You should have received a copy of the GNU Lesser General Public License
13 #along with this program; if not, write to the Free Software
14 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 #Portions of this code originally licensed and copyright (c) 2005, 2007
17 #IBM Corporation under the BSD license, available at
18 #U{http://www.opensource.org/licenses/bsd-license.php}
20 #authors: Peter Parente, Mark Doffman
25 from dbus.mainloop.glib import DBusGMainLoop
26 DBusGMainLoop(set_as_default=True)
28 from test import TestApplicationCache
29 from desktop import Desktop
30 from event import EventType, event_type_to_signal_reciever
32 class Registry(object):
34 Wraps the Accessibility.Registry to provide more Pythonic registration for
37 This object should be treated as a singleton, but such treatment is not
38 enforced. You can construct another instance of this object and give it a
39 reference to the Accessibility.Registry singleton. Doing so is harmless and
42 @ivar async: Should event dispatch to local listeners be decoupled from event
43 receiving from the registry?
45 @ivar reg: Reference to the real, wrapped registry object
46 @type reg: Accessibility.Registry
47 @ivar dev: Reference to the device controller
48 @type dev: Accessibility.DeviceEventController
49 @ivar queue: Queue of events awaiting local dispatch
50 @type queue: Queue.Queue
51 @ivar clients: Map of event names to client listeners
52 @type clients: dictionary
53 @ivar observers: Map of event names to AT-SPI L{_Observer} objects
54 @type observers: dictionary
57 _REGISTRY_NAME = 'org.freedesktop.atspi.Registry'
59 def __init__(self, app_name=None):
61 Stores a reference to the AT-SPI registry. Gets and stores a reference
62 to the DeviceEventController.
64 @param reg: Reference to the AT-SPI registry daemon
65 @type reg: Accessibility.Registry
67 self._bus = dbus.SessionBus()
69 self._app_name = app_name
70 self._cache = TestApplicationCache(self._bus, app_name)
72 self._event_listeners = {}
76 @return: This instance of the registry
81 def start(self, async=False, gil=True):
83 Enter the main loop to start receiving and dispatching events.
85 @param async: Should event dispatch be asynchronous (decoupled) from
86 event receiving from the AT-SPI registry?
88 @param gil: Add an idle callback which releases the Python GIL for a few
89 milliseconds to allow other threads to run? Necessary if other threads
90 will be used in this process.
91 Note - No Longer used.
94 self._loop = gobject.MainLoop()
98 except KeyboardInterrupt:
101 def stop(self, *args):
102 """Quits the main loop."""
106 def getDesktopCount(self):
108 Gets the number of available desktops.
110 @return: Number of desktops
115 def getDesktop(self, i):
117 Gets a reference to the i-th desktop.
119 @param i: Which desktop to get
121 @return: Desktop reference
122 @rtype: Accessibility.Desktop
124 return Desktop(self._cache)
126 def registerEventListener(self, client, *names):
128 Registers a new client callback for the given event names. Supports
129 registration for all subevents if only partial event name is specified.
130 Do not include a trailing colon.
132 For example, 'object' will register for all object events,
133 'object:property-change' will register for all property change events,
134 and 'object:property-change:accessible-parent' will register only for the
135 parent property change event.
137 Registered clients will not be automatically removed when the client dies.
138 To ensure the client is properly garbage collected, call
139 L{deregisterEventListener}.
141 @param client: Callable to be invoked when the event occurs
142 @type client: callable
143 @param names: List of full or partial event names
144 @type names: list of string
147 registered = self._event_listeners[client]
150 self._event_listeners[client] = registered
153 new_type = EventType(name)
154 registered.append((new_type.name,
155 event_type_to_signal_reciever(self._bus, self._cache, client, new_type)))
157 def deregisterEventListener(self, client, *names):
159 Unregisters an existing client callback for the given event names. Supports
160 unregistration for all subevents if only partial event name is specified.
161 Do not include a trailing colon.
163 This method must be called to ensure a client registered by
164 L{registerEventListener} is properly garbage collected.
166 @param client: Client callback to remove
167 @type client: callable
168 @param names: List of full or partial event names
169 @type names: list of string
170 @return: Were event names specified for which the given client was not
175 registered = self._event_listeners[client]
177 # Presumably if were trying to deregister a client with
178 # no names then the return type is always true.
182 remove_type = EventType(name)
184 for i in range(0, len(registered)):
185 (type_name, signal_match) = registered[i]
186 registered_type = EventType(type_name)
187 if remove_type.is_subtype(registered_type):
188 signal_match.remove()
192 del(self._event_listeners[client])