from desktop import Desktop
from factory import accessible_factory
from event import Event as _Event
+from base import AccessibleObjectNotAvailable
from interfaces import *
available at the given D-Bus name.
"""
cls = accessible_factory.get_accessible_class(ATSPI_APPLICATION)
- return cls(app_name, self.application_cache[app_name].root, self, ATSPI_APPLICATION)
+ try:
+ return cls(app_name, self.application_cache[app_name].root, self, ATSPI_APPLICATION)
+ except KeyError:
+ raise AccessibleObjectNotAvailable ()
def create_accessible(self, app_name, acc_path, interface, dbus_object=None):
"""
return Desktop(self)
else:
cls = accessible_factory.get_accessible_class(interface)
- return cls(app_name, acc_path, self, interface, dbus_object=dbus_object)
+ try:
+ return cls(app_name, acc_path, self, interface, dbus_object=dbus_object)
+ except KeyError:
+ raise AccessibleObjectNotAvailable ()
@property
def connection(self):
return Desktop(self)
else:
cls = accessible_factory.get_accessible_class(ATSPI_APPLICATION)
- return cls(app_name, self.application_cache[app_name].root, self, ATSPI_APPLICATION)
+ try:
+ return cls(app_name, self.application_cache[app_name].root, self, ATSPI_APPLICATION)
+ except KeyError:
+ raise AccessibleObjectNotAvailable ()
def create_accessible(self, app_name, acc_path, interface, dbus_object=None):
"""
return Desktop(self)
else:
cls = accessible_factory.get_accessible_class(interface)
- return cls(app_name, acc_path, self, interface, dbus_object=dbus_object)
+ try:
+ return cls(app_name, acc_path, self, interface, dbus_object=dbus_object)
+ except KeyError:
+ raise AccessibleObjectNotAvailable ()
@property
def connection(self):
__all__ = [
"AccessibleObjectNoLongerExists",
+ "AccessibleObjectNotAvailable",
"Enum",
"BaseProxy",
]
class AccessibleObjectNoLongerExists(Exception):
pass
+class AccessibleObjectNotAvailable(Exception):
+ pass
+
#------------------------------------------------------------------------------
class Enum(int):
import interfaces
from accessible import BoundingBox
+from base import AccessibleObjectNotAvailable
__all__ = [
"Event",
"org.freedesktop.atspi.Event.Object":"object",
"org.freedesktop.atspi.Event.Window":"window",
"org.freedesktop.atspi.Event.Mouse":"mouse",
+ "org.freedesktop.atspi.Event.Keyboard":"keyboard",
"org.freedesktop.atspi.Event.Terminal":"terminal",
"org.freedesktop.atspi.Event.Document":"document",
"org.freedesktop.atspi.Event.Focus":"focus",
"object":"org.freedesktop.atspi.Event.Object",
"window":"org.freedesktop.atspi.Event.Window",
"mouse":"org.freedesktop.atspi.Event.Mouse",
+ "keyboard":"org.freedesktop.atspi.Event.Keyboard",
"terminal":"org.freedesktop.atspi.Event.Terminal",
"document":"org.freedesktop.atspi.Event.Document",
"focus":"org.freedesktop.atspi.Event.Focus",
if event_type.minor:
kwargs['arg0'] = event_type.minor
- def handler_wrapper(minor, detail1, detail2, any_data,
+ def handler_wrapper(minor, detail1, detail2, any_data,
sender=None, interface=None, member=None, path=None):
event = Event(cache, path, sender, interface, member, (minor, detail1, detail2, any_data))
return event_handler(event)
- return bus.add_signal_receiver(handler_wrapper, **kwargs)
+ return bus.add_signal_receiver(handler_wrapper, **kwargs)
#------------------------------------------------------------------------------
@property
def host_application(self):
if not self._application:
- return self._cache.create_application(self._source_application)
+ try:
+ return self._cache.create_application(self._source_application)
+ except AccessibleObjectNotAvailable:
+ pass
return self._application
@property
def source(self):
if not self._source:
- self._source = self._cache.create_accessible(self._source_application,
- self._source_path,
- interfaces.ATSPI_ACCESSIBLE)
+ try:
+ self._source = self._cache.create_accessible(self._source_application,
+ self._source_path,
+ interfaces.ATSPI_ACCESSIBLE)
+ except AccessibleObjectNotAvailable:
+ pass
return self._source
@property
self._children_changed_type = _EventType("object:children-changed")
self._children_changed_listeners = {}
- self.queue = Queue()
self.clients = {}
+ self.deviceClients = {}
def __call__(self):
"""
"""
return _Desktop(self._app_cache)
+ # -------------------------------------------------------------------------------
+
def _callClients(self, register, event):
for client in register.keys():
client(event)
if registered == []:
del(register[client])
+ # -------------------------------------------------------------------------------
+
def registerEventListener(self, client, *names):
"""
Registers a new client callback for the given event names. Supports
for name in names:
remove_type = _EventType(name)
-
- for i in range(0, len(registered) - 1):
- (type_name, signal_match) = registered[i]
+ for i in range (0, len(registered)):
+ type_name, signal_match = registered[i]
registered_type = _EventType(type_name)
if remove_type.is_subtype(registered_type):
return missing
+ # -------------------------------------------------------------------------------
+
def registerKeystrokeListener(self,
client,
key_set=[],
"""
try:
# see if we already have an observer for this client
- ob = self.clients[client]
+ ob = self.deviceClients[client]
except KeyError:
# create a new device observer for this client
ob = KeyboardDeviceEventListener(self, synchronous, preemptive, global_)
# store the observer to client mapping, and the inverse
- self.clients[ob] = client
- self.clients[client] = ob
+ self.deviceClients[ob] = client
+ self.deviceClients[client] = ob
if mask is None:
# None means all modifier combinations
mask = utils.allModifiers()
@raise KeyError: When the client isn't already registered for events
"""
# see if we already have an observer for this client
- ob = self.clients[client]
+ ob = self.deviceClients[client]
if mask is None:
# None means all modifier combinations
mask = utils.allModifiers()
# register for new keystrokes on the observer
ob.unregister(self.dev, key_set, mask, kind)
- def generateKeyboardEvent(self, keycode, keysym, kind):
- """
- Generates a keyboard event. One of the keycode or the keysym parameters
- should be specified and the other should be None. The kind parameter is
- required and should be one of the KEY_PRESS, KEY_RELEASE, KEY_PRESSRELEASE,
- KEY_SYM, or KEY_STRING.
-
- @param keycode: Hardware keycode or None
- @type keycode: integer
- @param keysym: Symbolic key string or None
- @type keysym: string
- @param kind: Kind of event to synthesize
- @type kind: integer
- """
- if keysym is None:
- self.dev.generateKeyboardEvent(keycode, '', kind)
- else:
- self.dev.generateKeyboardEvent(None, keysym, kind)
-
- def generateMouseEvent(self, x, y, name):
- """
- Generates a mouse event at the given absolute x and y coordinate. The kind
- of event generated is specified by the name. For example, MOUSE_B1P
- (button 1 press), MOUSE_REL (relative motion), MOUSE_B3D (butten 3
- double-click).
-
- @param x: Horizontal coordinate, usually left-hand oriented
- @type x: integer
- @param y: Vertical coordinate, usually left-hand oriented
- @type y: integer
- @param name: Name of the event to generate
- @type name: string
- """
- self.dev.generateMouseEvent(x, y, name)
-
def handleDeviceEvent(self, event, ob):
"""
Dispatches L{event.DeviceEvent}s to registered clients. Clients are called
except Exception:
# print the exception, but don't let it stop notification
traceback.print_exc()
-
- def handleEvent(self, event):
+
+ # -------------------------------------------------------------------------------
+
+ def pumpQueuedEvents (self):
+ """
+ No Longer needed all application events are asyncronous.
"""
- Handles an AT-SPI event by either queuing it for later dispatch when the
- L{Registry.async} flag is set, or dispatching it immediately.
+ pass
- @param event: AT-SPI event
- @type event: L{event.Event}
+ def flushEvents (self):
"""
- if self.async:
- # queue for now
- self.queue.put_nowait(event)
- else:
- # dispatch immediately
- self._dispatchEvent(event)
+ No Longer needed all application events are asyncronous.
+ """
+ pass
- def _dispatchEvent(self, event):
+ # -------------------------------------------------------------------------------
+
+ def generateKeyboardEvent(self, keycode, keysym, kind):
"""
- Dispatches L{event.Event}s to registered clients. Clients are called in
- the order they were registered for the given AT-SPI event. If any client
- returns True, callbacks cease for the event for clients of this registry
- instance. Clients of other registry instances and clients in other processes
- are unaffected.
+ Generates a keyboard event. One of the keycode or the keysym parameters
+ should be specified and the other should be None. The kind parameter is
+ required and should be one of the KEY_PRESS, KEY_RELEASE, KEY_PRESSRELEASE,
+ KEY_SYM, or KEY_STRING.
- @param event: AT-SPI event
- @type event: L{event.Event}
+ @param keycode: Hardware keycode or None
+ @type keycode: integer
+ @param keysym: Symbolic key string or None
+ @type keysym: string
+ @param kind: Kind of event to synthesize
+ @type kind: integer
"""
- et = event.type
- try:
- # try to get the client registered for this event type
- clients = self.clients[et.name]
- except KeyError:
- try:
- # we may not have registered for the complete subtree of events
- # if our tree does not list all of a certain type (e.g.
- # object:state-changed:*); try again with klass and major only
- if et.detail is not None:
- # Strip the 'detail' field.
- clients = self.clients['%s:%s:%s' % (et.klass, et.major, et.minor)]
- elif et.minor is not None:
- # The event could possibly be object:state-changed:*.
- clients = self.clients['%s:%s' % (et.klass, et.major)]
- except KeyError:
- # client may have unregistered recently, ignore event
- return
- # make the call to each client
- consume = False
- for client in clients:
- try:
- consume = client(event) or False
- except Exception:
- # print the exception, but don't let it stop notification
- traceback.print_exc()
- if consume or event.consume:
- # don't allow further processing if a client returns True
- break
-
- def flushEvents(self):
- """
- Flushes the event queue by destroying it and recreating it.
- """
- self.queue = Queue()
-
- def pumpQueuedEvents(self, num=-1):
- """
- Provides asynch processing of events in the queue by executeing them with
- _dispatchEvent() (as is done immediately when synch processing).
- This method would normally be called from a main loop or idle function.
-
- @param num: Number of events to pump. If number is negative it pumps
- the entire queue. Default is -1.
- @type num: integer
- @return: True if queue is not empty after events were pumped.
- @rtype: boolean
+ if keysym is None:
+ self.dev.generateKeyboardEvent(keycode, '', kind)
+ else:
+ self.dev.generateKeyboardEvent(None, keysym, kind)
+
+ def generateMouseEvent(self, x, y, name):
+ """
+ Generates a mouse event at the given absolute x and y coordinate. The kind
+ of event generated is specified by the name. For example, MOUSE_B1P
+ (button 1 press), MOUSE_REL (relative motion), MOUSE_B3D (butten 3
+ double-click).
+
+ @param x: Horizontal coordinate, usually left-hand oriented
+ @type x: integer
+ @param y: Vertical coordinate, usually left-hand oriented
+ @type y: integer
+ @param name: Name of the event to generate
+ @type name: string
"""
- if num < 0:
- # Dequeue as many events as currently in the queue.
- num = self.queue.qsize()
- for i in xrange(num):
- try:
- # get next waiting event
- event = self.queue.get_nowait()
- except Queue.Empty:
- break
- self._dispatchEvent(event)
-
- return not self.queue.empty()
+ self.dev.generateMouseEvent(x, y, name)
priv->xkb_latch_mask = 0;
}
-static void emit(SpiDEController *controller, const char *name, int first_type, ...)
+static void emit(SpiDEController *controller, const char *interface, const char *name, int a1, int a2)
{
- va_list arg;
+ DBusMessage *signal = NULL;
+ DBusMessageIter iter, iter_variant;
+ int nil = 0;
+ const char *minor = "";
+ const char *path = SPI_DBUS_PATH_DEC;
- va_start(arg, first_type);
- spi_dbus_emit_valist(controller->bus, SPI_DBUS_PATH_DEC, SPI_DBUS_INTERFACE_DEC, name, first_type, arg);
- va_end(arg);
+ signal = dbus_message_new_signal (path, interface, name);
+
+ dbus_message_iter_init_append (signal, &iter);
+
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &a1);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &a2);
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant);
+ dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &nil);
+ dbus_message_iter_close_container (&iter, &iter_variant);
+
+ dbus_connection_send (controller->bus, signal, NULL);
}
static gboolean
if (!is_consumed)
{
dbus_uint32_t x = last_mouse_pos->x, y = last_mouse_pos->y;
- emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "button", event_detail, x, y);
+ emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "button", x, y);
}
else
spi_dec_set_unlatch_pending (controller, mask_return);
{
// TODO: combine these two signals?
dbus_uint32_t ix = *x, iy = *y;
- emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "abs", NULL, ix, iy);
+ emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "abs", ix, iy);
ix -= last_mouse_pos->x;
iy -= last_mouse_pos->y;
- emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "rel", NULL, ix, iy);
+ emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "rel", ix, iy);
last_mouse_pos->x = *x;
last_mouse_pos->y = *y;
*moved = True;
d1 = prev_mask & key_modifier_mask;
d2 = current_mask & key_modifier_mask;
- emit(controller, SPI_DBUS_INTERFACE_EVENT_KEYBOARD, "modifiers", NULL, d1, d2);
+ emit(controller, SPI_DBUS_INTERFACE_EVENT_KEYBOARD, "modifiers", d1, d2);
}
static gboolean
DEControllerListener *listener,
const Accessibility_DeviceEvent *key_event)
{
- DBusMessage *message = dbus_message_new_method_call(listener->bus_name, listener->path, "org.freedesktop.atspi.Registry", "notifyEvent");
+ DBusMessage *message = dbus_message_new_method_call(listener->bus_name,
+ listener->path,
+ SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER,
+ "notifyEvent");
DBusError error;
dbus_bool_t consumed = FALSE;