1 #Copyright (C) 2008 Codethink Ltd
3 #This library is free software; you can redistribute it and/or
4 #modify it under the terms of the GNU Lesser General Public
5 #License version 2 as published by the Free Software Foundation.
7 #This program is distributed in the hope that it will be useful,
8 #but WITHOUT ANY WARRANTY; without even the implied warranty of
9 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 #GNU General Public License for more details.
11 #You should have received a copy of the GNU Lesser General Public License
12 #along with this program; if not, write to the Free Software
13 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 from accessible import BoundingBox
21 "event_type_to_signal_reciever",
24 #------------------------------------------------------------------------------
26 _interface_to_klass = {
27 "org.freedesktop.atspi.Event.Object":"object",
28 "org.freedesktop.atspi.Event.Window":"window",
29 "org.freedesktop.atspi.Event.Mouse":"mouse",
30 "org.freedesktop.atspi.Event.Terminal":"terminal",
31 "org.freedesktop.atspi.Event.Document":"document",
32 "org.freedesktop.atspi.Event.Focus":"focus",
35 _klass_to_interface = {
36 "object":"org.freedesktop.atspi.Event.Object",
37 "window":"org.freedesktop.atspi.Event.Window",
38 "mouse":"org.freedesktop.atspi.Event.Mouse",
39 "terminal":"org.freedesktop.atspi.Event.Terminal",
40 "document":"org.freedesktop.atspi.Event.Document",
41 "focus":"org.freedesktop.atspi.Event.Focus",
44 #------------------------------------------------------------------------------
46 class _ELessList(list):
47 def __getitem__(self, index):
49 return list.__getitem__(self, index)
55 Wraps the AT-SPI event type string so its components can be accessed
56 individually as klass (can't use the keyword class), major, minor, and detail
57 (klass_major_minor_detail).
59 @note: All attributes of an instance of this class should be considered
60 public readable as it is acting a a struct.
61 @ivar klass: Most general event type identifier (object, window, mouse, etc.)
63 @ivar major: Second level event type description
65 @ivar minor: Third level event type description
67 @ivar detail: Lowest level event type description
69 @ivar name: Full, unparsed event name as received from AT-SPI
71 @cvar format: Names of the event string components
72 @type format: 4-tuple of string
77 def __init__(self, name):
79 Parses the full AT-SPI event name into its components
80 (klass:major:minor:detail). If the provided event name is an integer
81 instead of a string, then the event is really a device event.
83 @param name: Full AT-SPI event name
85 @raise AttributeError: When the given event name is not a valid string
87 stripped = name.strip(self._SEPARATOR)
88 separated = stripped.split(self._SEPARATOR, 3)
89 self._separated = _ELessList(separated)
91 self.klass = self._separated[0]
92 self.major = self._separated[1]
93 self.minor = self._separated[2]
94 self.detail = self._separated[3]
96 def is_subtype(self, event_type):
98 Determines if the passed event type is a subtype
101 if event_type.klass and event_type.klass != self.klass:
104 if event_type.major and event_type.major != self.major:
107 if event_type.minor and event_type.minor != self.minor:
119 #------------------------------------------------------------------------------
121 def event_type_to_signal_reciever(bus, cache, event_handler, event_type):
123 'sender_keyword':'sender',
124 'interface_keyword':'interface',
125 'member_keyword':'member',
126 'path_keyword':'path',
129 major = event_type.major.replace('-', '_')
131 kwargs['dbus_interface'] = _klass_to_interface[event_type.klass]
133 kwargs['signal_name'] = major
135 kwargs['arg0'] = event_type.minor
137 def handler_wrapper(minor, detail1, detail2, any_data,
138 sender=None, interface=None, member=None, path=None):
139 event = Event(cache, path, sender, interface, member, (minor, detail1, detail2, any_data))
140 return event_handler(event)
142 return bus.add_signal_receiver(handler_wrapper, **kwargs)
144 #------------------------------------------------------------------------------
146 def signal_spec_to_event_string (interface, name, minor):
147 interface = _interface_to_klass[interface]
148 name = name.replace('_', '-')
150 if interface == "focus":
153 result = interface + ':'
160 #------------------------------------------------------------------------------
164 Wraps an AT-SPI event with a more Pythonic interface managing exceptions,
165 the differences in any_data across versions, and the reference counting of
166 accessibles provided with the event.
168 @note: All unmarked attributes of this class should be considered public
169 readable and writable as the class is acting as a record object.
171 @ivar type: The type of the AT-SPI event
172 @type type: L{EventType}
173 @ivar detail1: First AT-SPI event parameter
174 @type detail1: integer
175 @ivar detail2: Second AT-SPI event parameter
176 @type detail2: integer
177 @ivar any_data: Extra AT-SPI data payload
178 @type any_data: object
179 @ivar host_application: Application owning the event source
180 @type host_application: Accessibility.Application
181 @ivar source_name: Name of the event source at the time of event dispatch
182 @type source_name: string
183 @ivar source_role: Role of the event source at the time of event dispatch
184 @type source_role: Accessibility.Role
185 @ivar source: Source of the event
186 @type source: Accessibility.Accessible
188 def __init__(self, cache, source_path, source_application, interface, name, event):
190 Extracts information from the provided event. If the event is a "normal"
191 event, pulls the detail1, detail2, any_data, and source values out of the
192 given object and stores it in this object. If the event is a device event,
193 key ID is stored in detail1, scan code is stored in detail2, key name,
194 key modifiers (e.g. ALT, CTRL, etc.), is text flag, and timestamp are
195 stored as a 4-tuple in any_data, and source is None (since key events are
198 @param event: Event from an AT-SPI callback
199 @type event: Accessibility.Event or Accessibility.DeviceEvent
202 self._source_path = source_path
203 self._source_application = source_application
206 self._application = None
208 self.type = EventType(signal_spec_to_event_string(interface, name, event[0]))
210 self.detail1 = event[1]
211 self.detail2 = event[2]
214 if name == "object_bounds_changed":
215 self.any_data = BoundingBox(*data)
220 def host_application(self):
221 if not self._application:
222 return self._cache.create_application(self._source_application)
223 return self._application
228 self._source = self._cache.create_accessible(self._source_application,
230 interfaces.ATSPI_ACCESSIBLE)
234 def source_name(self):
238 def source_role(self):
239 return source.getRole()
243 Builds a human readable representation of the event including event type,
244 parameters, and source info.
246 @return: Event description
249 return '%s(%s, %s, %s)\n\tsource: %s\n\thost_application: %s' % \
250 (self.type, self.detail1, self.detail2, self.any_data,
251 self.source, self.host_application)
253 #END----------------------------------------------------------------------------