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
17 from base import AccessibleObjectNotAvailable
22 "event_type_to_signal_reciever",
25 #------------------------------------------------------------------------------
27 _interface_to_klass = {
28 "org.freedesktop.atspi.Event.Object":"object",
29 "org.freedesktop.atspi.Event.Window":"window",
30 "org.freedesktop.atspi.Event.Mouse":"mouse",
31 "org.freedesktop.atspi.Event.Keyboard":"keyboard",
32 "org.freedesktop.atspi.Event.Terminal":"terminal",
33 "org.freedesktop.atspi.Event.Document":"document",
34 "org.freedesktop.atspi.Event.Focus":"focus",
37 _klass_to_interface = {
38 "object":"org.freedesktop.atspi.Event.Object",
39 "window":"org.freedesktop.atspi.Event.Window",
40 "mouse":"org.freedesktop.atspi.Event.Mouse",
41 "keyboard":"org.freedesktop.atspi.Event.Keyboard",
42 "terminal":"org.freedesktop.atspi.Event.Terminal",
43 "document":"org.freedesktop.atspi.Event.Document",
44 "focus":"org.freedesktop.atspi.Event.Focus",
47 #------------------------------------------------------------------------------
49 class _ELessList(list):
50 def __getitem__(self, index):
52 return list.__getitem__(self, index)
58 Wraps the AT-SPI event type string so its components can be accessed
59 individually as klass (can't use the keyword class), major, minor, and detail
60 (klass_major_minor_detail).
62 @note: All attributes of an instance of this class should be considered
63 public readable as it is acting a a struct.
64 @ivar klass: Most general event type identifier (object, window, mouse, etc.)
66 @ivar major: Second level event type description
68 @ivar minor: Third level event type description
70 @ivar detail: Lowest level event type description
72 @ivar name: Full, unparsed event name as received from AT-SPI
74 @cvar format: Names of the event string components
75 @type format: 4-tuple of string
80 def __init__(self, name):
82 Parses the full AT-SPI event name into its components
83 (klass:major:minor:detail). If the provided event name is an integer
84 instead of a string, then the event is really a device event.
86 @param name: Full AT-SPI event name
88 @raise AttributeError: When the given event name is not a valid string
90 stripped = name.strip(self._SEPARATOR)
91 separated = stripped.split(self._SEPARATOR, 3)
92 self._separated = _ELessList(separated)
94 self.klass = self._separated[0]
95 self.major = self._separated[1]
96 self.minor = self._separated[2]
97 self.detail = self._separated[3]
99 def is_subtype(self, event_type):
101 Determines if the passed event type is a subtype
104 if event_type.klass and event_type.klass != self.klass:
107 if event_type.major and event_type.major != self.major:
110 if event_type.minor and event_type.minor != self.minor:
122 #------------------------------------------------------------------------------
124 def event_type_to_signal_reciever(bus, cache, event_handler, event_type):
126 'sender_keyword':'sender',
127 'interface_keyword':'interface',
128 'member_keyword':'member',
129 'path_keyword':'path',
132 major = event_type.major.replace('-', '_')
134 kwargs['dbus_interface'] = _klass_to_interface[event_type.klass]
136 kwargs['signal_name'] = major
138 kwargs['arg0'] = event_type.minor
140 def handler_wrapper(minor, detail1, detail2, any_data,
141 sender=None, interface=None, member=None, path=None):
142 event = Event(cache, path, sender, interface, member, (minor, detail1, detail2, any_data))
143 return event_handler(event)
145 return bus.add_signal_receiver(handler_wrapper, **kwargs)
147 #------------------------------------------------------------------------------
149 def signal_spec_to_event_string (interface, name, minor):
150 interface = _interface_to_klass[interface]
151 name = name.replace('_', '-')
153 if interface == "focus":
156 result = interface + ':'
163 #------------------------------------------------------------------------------
167 Wraps an AT-SPI event with a more Pythonic interface managing exceptions,
168 the differences in any_data across versions, and the reference counting of
169 accessibles provided with the event.
171 @note: All unmarked attributes of this class should be considered public
172 readable and writable as the class is acting as a record object.
174 @ivar type: The type of the AT-SPI event
175 @type type: L{EventType}
176 @ivar detail1: First AT-SPI event parameter
177 @type detail1: integer
178 @ivar detail2: Second AT-SPI event parameter
179 @type detail2: integer
180 @ivar any_data: Extra AT-SPI data payload
181 @type any_data: object
182 @ivar host_application: Application owning the event source
183 @type host_application: Accessibility.Application
184 @ivar source_name: Name of the event source at the time of event dispatch
185 @type source_name: string
186 @ivar source_role: Role of the event source at the time of event dispatch
187 @type source_role: Accessibility.Role
188 @ivar source: Source of the event
189 @type source: Accessibility.Accessible
191 def __init__(self, cache, source_path, source_application, interface, name, event):
193 Extracts information from the provided event. If the event is a "normal"
194 event, pulls the detail1, detail2, any_data, and source values out of the
195 given object and stores it in this object. If the event is a device event,
196 key ID is stored in detail1, scan code is stored in detail2, key name,
197 key modifiers (e.g. ALT, CTRL, etc.), is text flag, and timestamp are
198 stored as a 4-tuple in any_data, and source is None (since key events are
201 @param event: Event from an AT-SPI callback
202 @type event: Accessibility.Event or Accessibility.DeviceEvent
205 self._source_path = source_path
206 self._source_application = source_application
209 self._application = None
211 self.type = EventType(signal_spec_to_event_string(interface, name, event[0]))
213 self.detail1 = event[1]
214 self.detail2 = event[2]
217 if name == "object_bounds_changed":
218 self.any_data = BoundingBox(*data)
223 def host_application(self):
224 if not self._application:
226 return self._cache.create_application(self._source_application)
227 except AccessibleObjectNotAvailable:
229 return self._application
235 self._source = self._cache.create_accessible(self._source_application,
237 interfaces.ATSPI_ACCESSIBLE)
238 except AccessibleObjectNotAvailable:
243 def source_name(self):
247 def source_role(self):
248 return source.getRole()
252 Builds a human readable representation of the event including event type,
253 parameters, and source info.
255 @return: Event description
258 return '%s(%s, %s, %s)\n\tsource: %s\n\thost_application: %s' % \
259 (self.type, self.detail1, self.detail2, self.any_data,
260 self.source, self.host_application)
262 #END----------------------------------------------------------------------------