from component import *
from constants import *
from desktop import *
+from deviceevent import *
from document import *
from editabletext import *
+from event import *
from hyperlink import *
from hypertext import *
from image import *
component.py \
constants.py \
desktop.py \
+ deviceevent.py \
document.py \
editabletext.py \
event.py \
("parent", 0, 0, ""))
self._registry._notifyParentChange(event)
- added, removed = _list_items_added_removed (olddata.children, newdata.children):
+ added, removed = _list_items_added_removed (olddata.children, newdata.children)
if added:
event = _Event(self._registry._cache,
from factory import accessible_factory
from event import Event as _Event
-import interfaces
+from interfaces import *
__all__ = [
"ApplicationCache",
Creates an accessible object for the root of the application
available at the given D-Bus name.
"""
- cls = accessible_factory.get_accessible_class(interfaces.ATSPI_APPLICATION)
- return cls(app_name, self.application_cache[app_name].root, self, interfaces.ATSPI_APPLICATION)
+ cls = accessible_factory.get_accessible_class(ATSPI_APPLICATION)
+ return cls(app_name, self.application_cache[app_name].root, self, ATSPI_APPLICATION)
def create_accessible(self, app_name, acc_path, interface, dbus_object=None):
"""
D-Bus path.
"""
- _REGISTRY_PATH = '/org/freedesktop/atspi/registry'
- _REGISTRY_INTERFACE = 'org.freedesktop.atspi.Registry'
- _REGISTRY_NAME = 'org.freedesktop.atspi.Registry'
-
# An accessible path of '/' implies the desktop object, whatever the application name.
_DESKTOP_PATH = '/'
self.application_cache = {}
self._regsig = connection.add_signal_receiver(self.update_handler,
- dbus_interface=ApplicationCache._REGISTRY_INTERFACE,
+ dbus_interface=ATSPI_REGISTRY_INTERFACE,
signal_name="updateApplications")
- obj = connection.get_object(ApplicationCache._REGISTRY_NAME,
- ApplicationCache._REGISTRY_PATH,
+ obj = connection.get_object(ATSPI_REGISTRY_NAME,
+ ATSPI_REGISTRY_PATH,
introspect=False)
- self._app_register = dbus.Interface(obj, ApplicationCache._REGISTRY_INTERFACE)
+ self._app_register = dbus.Interface(obj, ATSPI_REGISTRY_INTERFACE)
self.application_list.extend(self._app_register.getApplications())
for bus_name in self.application_list:
self.application_cache[bus_name] = AccessibleCache(self._registry, self._connection, bus_name)
event = _Event(self,
ApplicationCache._DESKTOP_PATH,
- ApplicationCache._REGISTRY_NAME,
+ ATSPI_REGISTRY_NAME,
"org.freedesktop.atspi.Event.Object",
"children-changed",
("add", 0, 0, ""))
del(self.application_cache[bus_name])
event = _Event(self,
ApplicationCache._DESKTOP_PATH,
- ApplicationCache._REGISTRY_NAME,
+ ATSPI_REGISTRY_NAME,
"org.freedesktop.atspi.Event.Object",
"children-changed",
("remove", 0, 0, ""))
Creates an accessible object for the root of the application
available at the given D-Bus name.
"""
- if app_name == ApplicationCache._REGISTRY_NAME:
+ if app_name == ATSPI_REGISTRY_NAME:
return Desktop(self)
else:
- cls = accessible_factory.get_accessible_class(interfaces.ATSPI_APPLICATION)
- return cls(app_name, self.application_cache[app_name].root, self, interfaces.ATSPI_APPLICATION)
+ cls = accessible_factory.get_accessible_class(ATSPI_APPLICATION)
+ return cls(app_name, self.application_cache[app_name].root, self, ATSPI_APPLICATION)
def create_accessible(self, app_name, acc_path, interface, dbus_object=None):
"""
--- /dev/null
+#Copyright (C) 2008 Codethink Ltd
+
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License version 2 as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import dbus as _dbus
+import dbus.service as _service
+import interfaces
+
+from base import Enum as _Enum
+
+#------------------------------------------------------------------------------
+
+class PressedEventType(_Enum):
+ _enum_lookup = {
+ 0:'KEY_PRESSED_EVENT',
+ 1:'KEY_RELEASED_EVENT',
+ 2:'BUTTON_PRESSED_EVENT',
+ 3:'BUTTON_RELEASED_EVENT',
+ }
+
+KEY_PRESSED_EVENT = PressedEventType(0)
+KEY_RELEASED_EVENT = PressedEventType(1)
+BUTTON_PRESSED_EVENT = PressedEventType(2)
+BUTTON_RELEASED_EVENT = PressedEventType(3)
+
+#------------------------------------------------------------------------------
+
+class ControllerEventMask(_Enum):
+ _enum_lookup = {
+ 1:'KEY_PRESSED_EVENT_MASK',
+ 2:'KEY_RELEASED_EVENT_MASK',
+ 4:'BUTTON_PRESSED_EVENT_MASK',
+ 8:'BUTTON_RELEASED_EVENT_MASK',
+ }
+
+KEY_PRESSED_EVENT_MASK = ControllerEventMask(1)
+KEY_RELEASED_EVENT_MASK = ControllerEventMask(2)
+BUTTON_PRESSED_EVENT_MASK = ControllerEventMask(4)
+BUTTON_RELEASED_EVENT_MASK = ControllerEventMask(8)
+
+#------------------------------------------------------------------------------
+
+class KeyEventType(_Enum):
+ _enum_lookup = {
+ 0:'KEY_PRESSED',
+ 1:'KEY_RELEASED',
+ }
+KEY_PRESSED = KeyEventType(0)
+KEY_RELEASED = KeyEventType(1)
+
+#------------------------------------------------------------------------------
+
+class KeySynthType(_Enum):
+ _enum_lookup = {
+ 0:'KEY_PRESS',
+ 1:'KEY_RELEASE',
+ 2:'KEY_PRESSRELEASE',
+ 3:'KEY_SYM',
+ 4:'KEY_STRING',
+ }
+
+KEY_PRESS = KeySynthType(0)
+KEY_PRESSRELEASE = KeySynthType(2)
+KEY_RELEASE = KeySynthType(1)
+KEY_STRING = KeySynthType(4)
+KEY_SYM = KeySynthType(3)
+
+#------------------------------------------------------------------------------
+
+class ModifierType(_Enum):
+ _enum_lookup = {
+ 0:'MODIFIER_SHIFT',
+ 1:'MODIFIER_SHIFTLOCK',
+ 2:'MODIFIER_CONTROL',
+ 3:'MODIFIER_ALT',
+ 4:'MODIFIER_META',
+ 5:'MODIFIER_META2',
+ 6:'MODIFIER_META3',
+ 7:'MODIFIER_NUMLOCK',
+ }
+
+MODIFIER_ALT = ModifierType(3)
+MODIFIER_CONTROL = ModifierType(2)
+MODIFIER_META = ModifierType(4)
+MODIFIER_META2 = ModifierType(5)
+MODIFIER_META3 = ModifierType(6)
+MODIFIER_NUMLOCK = ModifierType(7)
+MODIFIER_SHIFT = ModifierType(0)
+MODIFIER_SHIFTLOCK = ModifierType(1)
+
+#------------------------------------------------------------------------------
+
+class DeviceEvent(list):
+ """
+ Wraps an AT-SPI device event with a more Pythonic interface. Primarily adds
+ a consume attribute which can be used to cease propagation of a device event.
+
+ @ivar consume: Should this event be consumed and not allowed to pass on to
+ observers further down the dispatch chain in this process or possibly
+ system wide?
+ @type consume: boolean
+ @ivar type: Kind of event, KEY_PRESSED_EVENT or KEY_RELEASED_EVENT
+ @type type: Accessibility.EventType
+ @ivar id: Serial identifier for this key event
+ @type id: integer
+ @ivar hw_code: Hardware scan code for the key
+ @type hw_code: integer
+ @ivar modifiers: Modifiers held at the time of the key event
+ @type modifiers: integer
+ @ivar timestamp: Time at which the event occurred relative to some platform
+ dependent starting point (e.g. XWindows start time)
+ @type timestamp: integer
+ @ivar event_string: String describing the key pressed (e.g. keysym)
+ @type event_string: string
+ @ivar is_text: Is the event representative of text to be inserted (True), or
+ of a control key (False)?
+ @type is_text: boolean
+ """
+ def __new__(cls, type, id, hw_code, modifiers, timestamp, event_string, is_text):
+ return list.__new__(cls, (type, id, hw_code, modifiers, timestamp, event_string, is_text))
+ def __init__(self, type, id, hw_code, modifiers, timestamp, event_string, is_text):
+ list.__init__(self, (type, id, hw_code, modifiers, timestamp, event_string, is_text))
+ self.consume = False
+ def _get_type(self):
+ return self[0]
+ def _set_type(self, val):
+ self[0] = val
+ type = property(fget=_get_type, fset=_set_type)
+ def _get_id(self):
+ return self[1]
+ def _set_id(self, val):
+ self[1] = val
+ id = property(fget=_get_id, fset=_set_id)
+ def _get_hw_code(self):
+ return self[2]
+ def _set_hw_code(self, val):
+ self[2] = val
+ hw_code = property(fget=_get_hw_code, fset=_set_hw_code)
+ def _get_modifiers(self):
+ return self[3]
+ def _set_modifiers(self, val):
+ self[3] = val
+ modifiers = property(fget=_get_modifiers, fset=_set_modifiers)
+ def _get_timestamp(self):
+ return self[4]
+ def _set_timestamp(self, val):
+ self[4] = val
+ timestamp = property(fget=_get_timestamp, fset=_set_timestamp)
+ def _get_event_string(self):
+ return self[5]
+ def _set_event_string(self, val):
+ self[5] = val
+ event_string = property(fget=_get_event_string, fset=_set_event_string)
+ def _get_is_text(self):
+ return self[6]
+ def _set_is_text(self, val):
+ self[6] = val
+ is_text = property(fget=_get_is_text, fset=_set_is_text)
+
+ def __str__(self):
+ """
+ Builds a human readable representation of the event.
+
+ @return: Event description
+ @rtype: string
+ """
+ if self.type == constants.KEY_PRESSED_EVENT:
+ kind = 'pressed'
+ elif self.type == constants.KEY_RELEASED_EVENT:
+ kind = 'released'
+ return """\
+%s
+\thw_code: %d
+\tevent_string: %s
+\tmodifiers: %d
+\tid: %d
+\ttimestamp: %d
+\tis_text: %s""" % (kind, self.hw_code, self.event_string, self.modifiers,
+ self.id, self.timestamp, self.is_text)
+
+#------------------------------------------------------------------------------
+
+class EventListenerMode(list):
+ def __new__(cls, synchronous, preemptive, global_):
+ return list.__new__(cls, (synchronous, preemptive, global_))
+ def __init__(self, synchronous, preemptive, global_):
+ list.__init__(self, (synchronous, preemptive, global_))
+ def _get_synchronous(self):
+ return self[0]
+ def _set_synchronous(self, val):
+ self[0] = val
+ synchronous = property(fget=_get_synchronous, fset=_set_synchronous)
+ def _get_preemptive(self):
+ return self[1]
+ def _set_preemptive(self, val):
+ self[1] = val
+ preemptive = property(fget=_get_preemptive, fset=_set_preemptive)
+ def _get_global_(self):
+ return self[2]
+ def _set_global_(self, val):
+ self[2] = val
+ global_ = property(fget=_get_global_, fset=_set_global_)
+
+#------------------------------------------------------------------------------
+
+class KeyDefinition(list):
+ def __new__(cls, keycode, keysym, keystring, unused):
+ return list.__new__(cls, (keycode, keysym, keystring, unused))
+ def __init__(self, keycode, keysym, keystring, unused):
+ list.__init__(self, (keycode, keysym, keystring, unused))
+ def _get_keycode(self):
+ return self[0]
+ def _set_keycode(self, val):
+ self[0] = val
+ keycode = property(fget=_get_keycode, fset=_set_keycode)
+ def _get_keysym(self):
+ return self[1]
+ def _set_keysym(self, val):
+ self[1] = val
+ keysym = property(fget=_get_keysym, fset=_set_keysym)
+ def _get_keystring(self):
+ return self[2]
+ def _set_keystring(self, val):
+ self[2] = val
+ keystring = property(fget=_get_keystring, fset=_set_keystring)
+ def _get_unused(self):
+ return self[3]
+ def _set_unused(self, val):
+ self[3] = val
+ unused = property(fget=_get_unused, fset=_set_unused)
+
+#------------------------------------------------------------------------------
+
+class DeviceEventController(object):
+ """
+ The interface via which clients request notification of device
+ events, and through which device events may be simulated.
+ """
+
+ def __init__ (self, connection):
+ dec_object = connection.get_object(interfaces.ATSPI_REGISTRY_NAME,
+ interfaces.ATSPI_DEVICE_EVENT_CONTROLLER_PATH,
+ introspect=True)
+ self._dec = _dbus.Interface(dec_object, interfaces.ATSPI_DEVICE_EVENT_CONTROLLER_INTERFACE)
+
+ def registerKeystrokeListener(self,
+ event_listener,
+ keys,
+ event_mask,
+ key_event_types,
+ event_listener_mode):
+ """
+ Register to intercept keyboard events, and either pass them on
+ or consume them.
+ @param : listener
+ A DeviceEventListener which will intercept key events.
+ @param : keys
+ A list of KeyDefinition indicating which keys to intercept, or KEYSET_ALL_KEYS.
+ @param : mask
+ A ControllerEventMask bitmask for filtering the intercepted key events.
+ @param : type
+ A list of KeyEventType
+ @param : mode
+ An EventListenerMode indicating whether the listener should receive
+ the events synchronously, potentially consuming them, or just
+ be notified asynchronously of those events that have been generated.
+
+ @return True if the DeviceEventListener was successfully registered
+ for the requested KeySet, ControllerEventMask, event types, and
+ EventListenerMode; otherwise returns False.
+ """
+ func = self._dec.get_dbus_method("registerKeystrokeListener")
+ return func(event_listener,
+ keys,
+ event_mask,
+ key_event_types,
+ event_listener_mode)
+
+ def deregisterKeystrokeListener(self,
+ event_listener,
+ keys,
+ event_mask,
+ key_event_types):
+ """
+ De-register a previously registered keyboard eventlistener.
+ @param : listener
+ A DeviceEventListener which will intercept key events.
+ @param : keys
+ A list of KeyDefinition indicating which keys to intercept, or KEYSET_ALL_KEYS.
+ @param : mask
+ A ControllerEventMask filtering the intercepted key events.
+ @param : type
+ A list of KeyEventType
+ """
+ func = self._dec.get_dbus_method("deregisterKeystrokeListener")
+ return func(event_listener,
+ keys,
+ event_mask,
+ key_event_types)
+
+ def registerDeviceEventListener(self,
+ event_listener,
+ event_types):
+ """
+ Register to intercept events, and either pass them on or consume
+ them. To listen to keyboard events use registerKeystrokeListener
+ instead.
+ @param : listener
+ A DeviceEventListener which will intercept events.
+ @param : typeseq
+ A list of EventType indicating which event types to listen for.
+ @return True if successful, False if not
+ """
+ func = self._dec.get_dbus_method("registerDeviceEventListener")
+ return func(event_listener, event_types)
+
+ def deregisterDeviceEventListener(self,
+ event_listener,
+ event_types):
+ """
+ De-register a previously registered keyboard eventlistener.
+ @param : listener
+ A DeviceEventListener which will intercept events.
+ @param : typeseq
+ A List of EventType indicating which event types to stop listening
+ for.
+ """
+ func = self._dec.get_dbus_method("deregisterDeviceEventListener")
+ return func(event_listener, event_types)
+
+ def notifyListenersSync(self, event):
+ """
+ Notify the Registry instance that a device event has taken place,
+ and allow pre-emptive listeners the opportunity to 'consume'
+ the event and thus prevent its further issuance/forwarding. This
+ is the method used by accessibility bridges to forward "toolkit
+ dependent" device events to the Registry from the application's
+ process space.
+ @return True if the event was consumed by a (pre-emptive) listener,
+ False if not (in which case the device event will be forwarded
+ as normal to any application which would normally receive it,
+ e.g. the currently active application in the case of mouse or
+ keyboard events).
+ """
+ func = self._dec.get_dbus_method("notifyListenersSync")
+ return func(event)
+
+ def notifyListenersAsync(self, event):
+ """
+ Notify the Registry instance that a device event has taken place
+ in an asynchronous manner. This is the method used by accessibility
+ bridges to forward "toolkit dependent" device events to the Registry
+ from the application's process space. If the event in question
+ is potentially pre-emptible. notifyListenersSync should be used
+ instead.
+ """
+ func = self._dec.get_dbus_method("notifyListenersAsync")
+ return func(event)
+
+ def generateKeyboardEvent(self, keycode, keystring, type):
+ """
+ Synthesize a keyboard event.
+ @param : keycode
+ A long integer indicating the keycode of the keypress to be synthesized.
+ @param : keystring
+ an optional UTF-8 string indicating a complex keyboard input
+ event.
+ @param : type
+ A KeySynthType indicating the type of event(s) to be synthesized:
+ a key press, release, press-release pair, or a complex input
+ string (for instance from an internationalized or complex text
+ input method, or a composed character).
+ """
+ func = self._dec.get_dbus_method("generateKeyboardEvent")
+ return func(keycode, keystring, type)
+
+ def generateMouseEvent(self, x, y, name):
+ """
+ Synthesize a mouse event.
+ @param : x
+ A long integer indicating the screen x coord for the mouse event.
+ @param : y
+ A long integer indicating the screen y coord for the mouse event.
+ @param : name
+ A string indicating the type of mouse event, e.g. "button1up"
+ """
+ func = self._dec.get_dbus_method("generateMouseEvent")
+ return func(x, y, name)
+
+#------------------------------------------------------------------------------
+
+class _TestDeviceEventController(object):
+ """
+ Used for testing when no Registry daemon is present.
+ """
+
+ def registerKeystrokeListener(self, event_listener, keys, event_mask, key_event_types, event_listener_mode):
+ return True
+
+ def deregisterKeystrokeListener(self, event_listener, keys, event_mask, key_event_types):
+ pass
+
+ def registerDeviceEventListener(self, event_listener, event_types):
+ return True
+
+ def deregisterDeviceEventListener(self, event_listener, event_types):
+ pass
+
+ def notifyListenersSync(self, event):
+ return False
+
+ def notifyListenersAsync(self, event):
+ pass
+
+ def generateKeyboardEvent(self, keycode, keystring, type):
+ pass
+
+ def generateMouseEvent(self, x, y, name):
+ pass
+
+#------------------------------------------------------------------------------
+
+class KeyboardDeviceEventListener(_service.Object):
+ """
+ Observes keyboard press and release events.
+
+ @ivar registry: The L{Registry} that created this observer
+ @type registry: L{Registry}
+ @ivar key_set: Set of keys to monitor
+ @type key_set: list of integer
+ @ivar mask: Watch for key events while these modifiers are held
+ @type mask: integer
+ @ivar kind: Kind of events to monitor
+ @type kind: integer
+ @ivar mode: Keyboard event mode
+ @type mode: Accessibility.EventListenerMode
+ """
+
+ _next_listener_id = 0
+
+ def _get_unique_path (self):
+ KeyboardDeviceEventListener._next_listener_id += 1
+ return "/org/freedesktop/atspi/keyeventlistener/%d" % (KeyboardDeviceEventListener._next_listener_id,)
+
+ def __init__(self, registry, synchronous, preemptive, global_):
+ """
+ Creates a mode object that defines when key events will be received from
+ the system. Stores all other information for later registration.
+
+ @param registry: The L{Registry} that created this observer
+ @type registry: L{Registry}
+ @param synchronous: Handle the key event synchronously?
+ @type synchronous: boolean
+ @param preemptive: Allow event to be consumed?
+ @type preemptive: boolean
+ @param global_: Watch for events on inaccessible applications too?
+ @type global_: boolean
+ """
+ self._upath = self._get_unique_path()
+ _service.Object.__init__(self, registry._bus, self._upath)
+ self.mode = EventListenerMode(synchronous, preemptive, global_)
+
+ def register(self, dc, key_set, mask, kind):
+ """
+ Starts keyboard event monitoring.
+
+ @param dc: Reference to a device controller
+ @type dc: Accessibility.DeviceEventController
+ @param key_set: Set of keys to monitor
+ @type key_set: list of integer
+ @param mask: Integer modifier mask or an iterable over multiple masks to
+ unapply all at once
+ @type mask: integer, iterable, or None
+ @param kind: Kind of events to monitor
+ @type kind: integer
+ """
+ try:
+ # check if the mask is iterable
+ iter(mask)
+ except TypeError:
+ # register a single integer if not
+ dc.registerKeystrokeListener(self._upath, key_set, mask, kind, self.mode)
+ else:
+ for m in mask:
+ dc.registerKeystrokeListener(self._upath, key_set, m, kind, self.mode)
+
+ def unregister(self, dc, key_set, mask, kind):
+ """
+ Stops keyboard event monitoring.
+
+ @param dc: Reference to a device controller
+ @type dc: Accessibility.DeviceEventController
+ @param key_set: Set of keys to monitor
+ @type key_set: list of integer
+ @param mask: Integer modifier mask or an iterable over multiple masks to
+ unapply all at once
+ @type mask: integer, iterable, or None
+ @param kind: Kind of events to monitor
+ @type kind: integer
+ """
+ try:
+ # check if the mask is iterable
+ iter(mask)
+ except TypeError:
+ # unregister a single integer if not
+ dc.deregisterKeystrokeListener(self._upath, key_set, mask, kind)
+ else:
+ for m in mask:
+ dc.deregisterKeystrokeListener(self._upath, key_set, m, kind)
+
+ @_service.method(dbus_interface=interfaces.ATSPI_DEVICE_EVENT_LISTENER_INTERFACE,
+ in_signature="(uinnisb)",
+ out_signature="b")
+ def notifyEvent(self, ev):
+ """
+ Notifies the L{Registry} that an event has occurred. Wraps the raw event
+ object in our L{Event} class to support automatic ref and unref calls. An
+ observer can return True to indicate this event should not be allowed to pass
+ to other AT-SPI observers or the underlying application.
+
+ @param ev: Keyboard event
+ @type ev: Accessibility.DeviceEvent
+ @return: Should the event be consumed (True) or allowed to pass on to other
+ AT-SPI observers (False)?
+ @rtype: boolean
+ """
+ # wrap the device event
+ ev = event.DeviceEvent(ev)
+ return self.registry.handleDeviceEvent(ev, self)
+
+#END---------------------------------------------------------------------------
ATSPI_TABLE = 'org.freedesktop.atspi.Table'
ATSPI_TEXT = 'org.freedesktop.atspi.Text'
ATSPI_VALUE = 'org.freedesktop.atspi.Value'
+
+ATSPI_REGISTRY_INTERFACE = 'org.freedesktop.atspi.Registry'
+ATSPI_REGISTRY_PATH = '/org/freedesktop/atspi/registry'
+ATSPI_REGISTRY_NAME = 'org.freedesktop.atspi.Registry'
+
+ATSPI_DEVICE_EVENT_CONTROLLER_INTERFACE = 'org.freedesktop.atspi.DeviceEventController'
+ATSPI_DEVICE_EVENT_CONTROLLER_PATH = '/org/freedesktop/atspi/registry/deviceeventcontroller'
+ATSPI_DEVICE_EVENT_LISTENER_INTERFACE = 'org.freedesktop.atspi.DeviceEventListener'
import dbus as _dbus
import gobject as _gobject
-from base import Enum as _Enum
from desktop import Desktop as _Desktop
+
from event import EventType as _EventType
from event import event_type_to_signal_reciever as _event_type_to_signal_reciever
+
from applicationcache import TestApplicationCache, ApplicationCache
from dbus.mainloop.glib import DBusGMainLoop as _DBusGMainLoop
-_DBusGMainLoop(set_as_default=True)
-
-#------------------------------------------------------------------------------
-
-class PressedEventType(_Enum):
- _enum_lookup = {
- 0:'KEY_PRESSED_EVENT',
- 1:'KEY_RELEASED_EVENT',
- 2:'BUTTON_PRESSED_EVENT',
- 3:'BUTTON_RELEASED_EVENT',
- }
-
-KEY_PRESSED_EVENT = PressedEventType(0)
-KEY_RELEASED_EVENT = PressedEventType(1)
-BUTTON_PRESSED_EVENT = PressedEventType(2)
-BUTTON_RELEASED_EVENT = PressedEventType(3)
-#------------------------------------------------------------------------------
-
-class KeyEventType(_Enum):
- _enum_lookup = {
- 0:'KEY_PRESSED',
- 1:'KEY_RELEASED',
- }
-KEY_PRESSED = KeyEventType(0)
-KEY_RELEASED = KeyEventType(1)
-#------------------------------------------------------------------------------
-
-class KeySynthType(_Enum):
- _enum_lookup = {
- 0:'KEY_PRESS',
- 1:'KEY_RELEASE',
- 2:'KEY_PRESSRELEASE',
- 3:'KEY_SYM',
- 4:'KEY_STRING',
- }
-
-KEY_PRESS = KeySynthType(0)
-KEY_PRESSRELEASE = KeySynthType(2)
-KEY_RELEASE = KeySynthType(1)
-KEY_STRING = KeySynthType(4)
-KEY_SYM = KeySynthType(3)
-
-#------------------------------------------------------------------------------
+from Queue import Queue
+from deviceevent import *
+from deviceevent import _TestDeviceEventController
-class ModifierType(_Enum):
- _enum_lookup = {
- 0:'MODIFIER_SHIFT',
- 1:'MODIFIER_SHIFTLOCK',
- 2:'MODIFIER_CONTROL',
- 3:'MODIFIER_ALT',
- 4:'MODIFIER_META',
- 5:'MODIFIER_META2',
- 6:'MODIFIER_META3',
- 7:'MODIFIER_NUMLOCK',
- }
-
-MODIFIER_ALT = ModifierType(3)
-MODIFIER_CONTROL = ModifierType(2)
-MODIFIER_META = ModifierType(4)
-MODIFIER_META2 = ModifierType(5)
-MODIFIER_META3 = ModifierType(6)
-MODIFIER_NUMLOCK = ModifierType(7)
-MODIFIER_SHIFT = ModifierType(0)
-MODIFIER_SHIFTLOCK = ModifierType(1)
+_DBusGMainLoop(set_as_default=True)
#------------------------------------------------------------------------------
app_name = None
if "ATSPI_TEST_APP_NAME" in _os.environ.keys():
app_name = _os.environ["ATSPI_TEST_APP_NAME"]
+
if app_name:
- self._app_name = app_name
self._appcache = TestApplicationCache(self, self._bus, app_name)
+ self.dev = _TestDeviceEventController()
else:
self._appcache = ApplicationCache(self, self._bus)
+ self.dev = DeviceEventController(self._bus)
self._event_listeners = {}
self._children_changed_type = _EventType("object:children-changed")
self._children_changed_listeners = {}
+ self.queue = Queue()
+ self.clients = {}
+
def __call__(self):
"""
@return: This instance of the registry
AT-SPI is in the foreground? (requires xevie)
@type global_: boolean
"""
- pass
+ try:
+ # see if we already have an observer for this client
+ ob = self.clients[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
+ if mask is None:
+ # None means all modifier combinations
+ mask = utils.allModifiers()
+ # register for new keystrokes on the observer
+ ob.register(self.dev, key_set, mask, kind)
def deregisterKeystrokeListener(self,
client,
@type kind: list
@raise KeyError: When the client isn't already registered for events
"""
- pass
+ # see if we already have an observer for this client
+ ob = self.clients[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):
"""
@param kind: Kind of event to synthesize
@type kind: integer
"""
- pass
+ if keysym is None:
+ self.dev.generateKeyboardEvent(keycode, '', kind)
+ else:
+ self.dev.generateKeyboardEvent(None, keysym, kind)
def generateMouseEvent(self, x, y, name):
"""
@param name: Name of the event to generate
@type name: string
"""
- pass
+ self.dev.generateMouseEvent(x, y, name)
def handleDeviceEvent(self, event, ob):
"""
@param event: AT-SPI device event
@type event: L{event.DeviceEvent}
@param ob: Observer that received the event
- @type ob: L{_DeviceObserver}
+ @type ob: L{KeyboardDeviceEventListener}
@return: Should the event be consumed (True) or allowed to pass on to other
AT-SPI observers (False)?
@rtype: boolean
"""
- return True
+ try:
+ # try to get the client registered for this event type
+ client = self.clients[ob]
+ except KeyError:
+ # client may have unregistered recently, ignore event
+ return False
+ # make the call to the client
+ try:
+ return client(event) or event.consume
+ except Exception:
+ # print the exception, but don't let it stop notification
+ traceback.print_exc()
def handleEvent(self, event):
- """
+ """
Handles an AT-SPI event by either queuing it for later dispatch when the
L{Registry.async} flag is set, or dispatching it immediately.
@param event: AT-SPI event
@type event: L{event.Event}
"""
- pass
+ if self.async:
+ # queue for now
+ self.queue.put_nowait(event)
+ else:
+ # dispatch immediately
+ self._dispatchEvent(event)
+
+ def _dispatchEvent(self, event):
+ """
+ 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.
+
+ @param event: AT-SPI event
+ @type event: L{event.Event}
+ """
+ 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.
"""
- pass
+ self.queue = Queue()
def pumpQueuedEvents(self, num=-1):
"""
@return: True if queue is not empty after events were pumped.
@rtype: boolean
"""
- return False
+ 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()
registry-main.c \
registry.c \
registry.h \
+ deviceeventcontroller.c \
+ deviceeventcontroller.h \
+ reentrant-list.c \
+ reentrant-list.h \
ucs2keysym.c
-
-# deviceeventcontroller.c
-# deviceeventcontroller.h
#include <atk-adaptor/spi-private.h>
#include <spi-common/keymasks.h>
#include <droute/droute.h>
+#include <droute/introspect-loader.h>
#include <spi-common/spi-dbus.h>
#include <spi-common/spi-types.h>
{
DEControllerPrivateData *priv =
g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
- priv->xkb_latch_mask = 0;
+ priv->xkb_latch_mask = 0;
}
static void emit(SpiDEController *controller, const char *name, int first_type, ...)
va_list arg;
va_start(arg, first_type);
- spi_dbus_emit_valist(controller->registry->droute.bus, SPI_DBUS_PATH_DEC, SPI_DBUS_INTERFACE_DEC, name, first_type, arg);
+ spi_dbus_emit_valist(controller->droute->bus, SPI_DBUS_PATH_DEC, SPI_DBUS_INTERFACE_DEC, name, first_type, arg);
va_end(arg);
}
static gboolean
-spi_dec_button_update_and_emit (SpiDEController *controller,
+spi_dec_button_update_and_emit (SpiDEController *controller,
guint mask_return)
{
Accessibility_DeviceEvent mouse_e;
static gboolean
spi_dec_poll_mouse_moved (gpointer data)
{
- SpiRegistry *registry = SPI_REGISTRY (data);
- SpiDEController *controller = registry->de_controller;
- int x, y;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(data);
+ int x, y;
gboolean moved;
guint mask_return;
mask_return = spi_dec_mouse_check (controller, &x, &y, &moved);
-
+
if ((mask_return & key_modifier_mask) !=
(mouse_mask_state & key_modifier_mask))
{
static gboolean
spi_dec_poll_mouse_idle (gpointer data)
{
- if (! spi_dec_poll_mouse_moved (data))
+ if (! spi_dec_poll_mouse_moved (data))
return TRUE;
else
{
#endif
static void
-spi_dec_init_mouse_listener (SpiRegistry *registry)
+spi_dec_init_mouse_listener (SpiDEController *dec)
{
#ifdef GRAB_BUTTON
Display *display = spi_get_display ();
#endif
- g_timeout_add (100, spi_dec_poll_mouse_idle, registry);
+ g_timeout_add (100, spi_dec_poll_mouse_idle, dec);
#ifdef GRAB_BUTTON
if (display)
cur_mask->pending_remove = TRUE;
}
}
- else
- {
- DBG (1, g_warning ("De-registering non-existant grab"));
- }
}
static void
controller->key_listeners = g_list_prepend (controller->key_listeners,
key_listener);
- spi_dbus_add_disconnect_match (controller->registry->droute.bus, key_listener->listener.bus_name);
+ spi_dbus_add_disconnect_match (controller->droute->bus, key_listener->listener.bus_name);
if (key_listener->mode->global)
{
return spi_controller_register_global_keygrabs (controller, key_listener);
break;
case SPI_DEVICE_TYPE_MOUSE:
controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
- spi_dbus_add_disconnect_match (controller->registry->droute.bus, listener->bus_name);
+ spi_dbus_add_disconnect_match (controller->droute->bus, listener->bus_name);
break;
default:
- DBG (1, g_warning ("listener registration for unknown device type.\n"));
break;
}
- return FALSE;
+ return FALSE;
}
-static gboolean Accessibility_DeviceEventListener_notifyEvent(SpiRegistry *registry, DEControllerListener *listener, const Accessibility_DeviceEvent *key_event)
+static gboolean
+Accessibility_DeviceEventListener_notifyEvent(SpiDEController *controller,
+ SpiRegistry *registry,
+ DEControllerListener *listener,
+ const Accessibility_DeviceEvent *key_event)
{
DBusMessage *message = dbus_message_new_method_call(listener->bus_name, listener->path, "org.freedesktop.atspi.Registry", "notifyEvent");
DBusError error;
{
// TODO: Evaluate performance: perhaps rework this whole architecture
// to avoid blocking calls
- DBusMessage *reply = dbus_connection_send_with_reply_and_block(registry->droute.bus, message, 1000, &error);
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(controller->droute->bus, message, 1000, &error);
if (reply)
{
DBusError error;
is_consumed = FALSE;
for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
{
- DEControllerListener *listener = l2->data;
+ DEControllerListener *listener = l2->data;
+
+ is_consumed = Accessibility_DeviceEventListener_notifyEvent (controller, controller->registry, listener, event);
- is_consumed = Accessibility_DeviceEventListener_notifyEvent (controller->registry, listener, event);
-
spi_listener_clone_free ((DEControllerListener *) l2->data);
}
for (; l2; l2 = l2->next)
{
- DEControllerListener *listener = l2->data;
+ DEControllerListener *listener = l2->data;
spi_listener_clone_free (listener);
/* clone doesn't have its own ref, so don't use spi_device_listener_free */
}
spi_controller_notify_mouselisteners (controller, &mouse_e);
ix = last_mouse_pos->x;
iy = last_mouse_pos->y;
- emit(controller, event_name, DBUS_TYPE_UINT32, &ix, DBUS_TYPE_UINT32, &iy, DBUS_TYPE_INVALID);
+ /* TODO - Work out which part of the spec this emit is fulfilling */
+ //emit(controller, event_name, DBUS_TYPE_UINT32, &ix, DBUS_TYPE_UINT32, &iy, DBUS_TYPE_INVALID);
}
xkb_mod_unlatch_occurred = (xevent->type == ButtonPress ||
priv->xkb_latch_mask = xkb_snev->latched_mods;
}
}
- else
- DBG (2, g_warning ("XKB event %d\n", xkb_ev->xkb_type));
XSynchronize (display, FALSE);
}
static void
spi_controller_register_with_devices (SpiDEController *controller)
{
- DEControllerPrivateData *priv = (DEControllerPrivateData *)
- g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
- /* FIXME: should check for extension first! */
- XTestGrabControl (spi_get_display (), True);
+ DEControllerPrivateData *priv;
+ int event_base, error_base, major_version, minor_version;
+
+ priv = (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+ if (XTestQueryExtension (spi_get_display(), &event_base, &error_base, &major_version, &minor_version))
+ {
+ XTestGrabControl (spi_get_display (), True);
+ }
/* calls to device-specific implementations and routines go here */
/* register with: keyboard hardware code handler */
{
DEControllerKeyListener *key_listener = l2->data;
- is_consumed = Accessibility_DeviceEventListener_notifyEvent (controller->registry, &key_listener->listener, key_event) &&
+ is_consumed = Accessibility_DeviceEventListener_notifyEvent (controller, controller->registry, &key_listener->listener, key_event) &&
key_listener->mode->preemptive;
spi_key_listener_clone_free (key_listener);
DBusMessage *message,
void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
DEControllerKeyListener *dec_listener;
DBusMessageIter iter, iter_array;
const char *path;
DBusMessage *message,
void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
DEControllerListener *dec_listener;
DBusError error;
const char *path;
{
RemoveListenerClosure ctx;
- ctx.bus = controller->registry->droute.bus;
+ ctx.bus = controller->droute->bus;
ctx.listener = listener;
spi_re_entrant_list_foreach (&controller->mouse_listeners,
{
RemoveListenerClosure ctx;
- ctx.bus = controller->registry->droute.bus;
+ ctx.bus = controller->droute->bus;
ctx.listener = (DEControllerListener *) key_listener;
/* special case, copy keyset from existing controller list entry */
spi_re_entrant_list_foreach (&controller->key_listeners,
copy_key_listener_cb, &ctx);
}
-
+
spi_controller_deregister_global_keygrabs (controller, key_listener);
spi_re_entrant_list_foreach (&controller->key_listeners,
DBusMessage *message,
void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
DEControllerKeyListener *key_listener;
DBusMessageIter iter, iter_array;
const char *path;
DBusMessage *message,
void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
DEControllerListener *listener;
DBusError error;
const char *path;
*/
static DBusMessage * impl_generate_keyboard_event (DBusConnection *bus, DBusMessage *message, void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
DBusError error;
dbus_int32_t keycode;
char *keystring;
keystring);
break;
}
- if ((err = gdk_error_trap_pop ()))
- {
- DBG (-1, g_warning ("Error [%d] emitting keystroke", err));
- }
if (synth_type == Accessibility_KEY_SYM) {
keysym = keycode;
}
static DBusMessage *
impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
Accessibility_DeviceEvent event;
dbus_bool_t ret;
DBusMessage *reply;
static DBusMessage *
impl_notify_listeners_async (DBusConnection *bus, DBusMessage *message, void *user_data)
{
- SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
Accessibility_DeviceEvent event;
DBusMessage *reply;
GObjectClass * object_class = (GObjectClass *) klass;
spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
-
+
object_class->finalize = spi_device_event_controller_object_finalize;
if (!spi_dec_private_quark)
return ret;
}
-SpiDEController *
-spi_device_event_controller_new (SpiRegistry *registry)
-{
- SpiDEController *retval = g_object_new (
- SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
-
- retval->registry = g_object_ref (registry);
-
- spi_dec_init_mouse_listener (registry);
- /* TODO: kill mouse listener on finalize */
- return retval;
-}
static gboolean
is_key_released (KeyCode code)
check_release_handler = g_timeout_add (CHECK_RELEASE_DELAY, check_release, &pressed_event);
}
-static DRouteMethod methods[] =
+static DBusMessage *
+impl_introspect (DBusConnection *bus, DBusMessage *message,
+ void *user_data)
+{
+ const char *path;
+ GString *output;
+ char *final;
+
+ DBusMessage *reply;
+
+ path = dbus_message_get_path(message);
+
+ output = g_string_new(spi_introspection_header);
+
+ g_string_append_printf(output, spi_introspection_node_element, path);
+
+ spi_append_interface(output, SPI_DBUS_INTERFACE_DEC);
+
+ g_string_append(output, spi_introspection_footer);
+ final = g_string_free(output, FALSE);
+
+ reply = dbus_message_new_method_return (message);
+ g_assert(reply != NULL);
+ dbus_message_append_args(reply, DBUS_TYPE_STRING, &final,
+ DBUS_TYPE_INVALID);
+
+ g_free(final);
+ return reply;
+}
+
+static DRouteMethod dev_methods[] =
{
{ impl_register_keystroke_listener, "registerKeystrokeListener" },
{ impl_register_device_listener, "registerDeviceListener" },
{ NULL, NULL }
};
-static void
-spi_registry_initialize_dec_interface (DRouteData * data)
-{
- droute_add_interface (data, SPI_DBUS_INTERFACE_DEC, methods,
- NULL, NULL, NULL);
+static DRouteMethod intro_methods[] = {
+ {impl_introspect, "Introspect"},
+ {NULL, NULL}
};
SpiDEController *
-spi_registry_dec_new (DRouteData *droute)
+spi_registry_dec_new (SpiRegistry *reg, DRouteData *droute)
{
- SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, 1);
- spi_registry_initialize_dec_interface (&droute);
+ SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
+
+ dec->registry = g_object_ref (reg);
+ dec->droute = droute;
+
+ droute_add_interface (droute,
+ SPI_DBUS_INTERFACE_DEC,
+ dev_methods,
+ NULL, NULL, NULL);
+ droute_add_interface (droute,
+ "org.freedesktop.DBus.Introspectable",
+ intro_methods,
+ NULL, NULL, NULL);
+
+ spi_dec_init_mouse_listener (dec);
+ /* TODO: kill mouse listener on finalize */
+
return dec;
}
#include <X11/Xlib.h>
#include <gdk/gdk.h>
+#include <droute/droute.h>
typedef struct _SpiDEController SpiDEController;
GObject parent;
SpiRegistry *registry;
+ DRouteData *droute;
GList *key_listeners;
GList *mouse_listeners;
GList *keygrabs_list;
void spi_remove_device_listeners (SpiDEController *controller, const char *bus_name);
-void spi_registry_initialize_dec_interface (DRouteData * data);
-
G_END_DECLS
#endif /* DEVICEEVENTCONTROLLER_H_ */
--- /dev/null
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "reentrant-list.h"
+
+typedef struct {
+ GList **list;
+ GList *iterator;
+} Iteration;
+
+static GSList *working_list = NULL; /* of Iteration */
+
+/*
+ * deletes an element from the list - in a re-entrant
+ * safe fashion; advances the element pointer to the next
+ * element.
+ */
+void
+spi_re_entrant_list_delete_link (GList * const *element_ptr)
+{
+ GSList *l;
+ GList *next;
+ GList *element;
+ gboolean first_item;
+
+ g_return_if_fail (element_ptr != NULL);
+
+ element = *element_ptr;
+ g_return_if_fail (element != NULL);
+
+ next = element->next;
+ first_item = (element->prev == NULL);
+
+ g_list_remove_link (NULL, element);
+
+ for (l = working_list; l; l = l->next)
+ {
+ Iteration *i = l->data;
+
+ if (i->iterator == element)
+ {
+ i->iterator = next;
+ }
+
+ if (first_item && *(i->list) == element)
+ {
+ *(i->list) = next;
+ }
+ }
+
+ g_list_free_1 (element);
+}
+
+void
+spi_re_entrant_list_foreach (GList **list,
+ SpiReEntrantFn func,
+ gpointer user_data)
+{
+ Iteration i;
+
+ if (!list || !*list)
+ {
+ return;
+ }
+
+ i.list = list;
+ i.iterator = *list;
+
+ working_list = g_slist_prepend (working_list, &i);
+
+ while (i.iterator) {
+ GList *l = i.iterator;
+
+ func (&i.iterator, user_data);
+
+ if (i.iterator == l)
+ i.iterator = i.iterator->next;
+ }
+
+ working_list = g_slist_remove (working_list, &i);
+}
--- /dev/null
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef REENTRANT_LIST_H_
+#define REENTRANT_LIST_H_
+
+#include <glib/glist.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ SPI_RE_ENTRANT_CONTINUE = 0,
+ SPI_RE_ENTRANT_TERMINATE
+} SpiReEntrantContinue;
+
+typedef SpiReEntrantContinue (*SpiReEntrantFn) (GList * const *list,
+ gpointer user_data);
+
+void spi_re_entrant_list_delete_link (GList * const *element_ptr);
+void spi_re_entrant_list_foreach (GList **list,
+ SpiReEntrantFn func,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* REENTRANT_LIST_H_ */
#include <glib/gmain.h>
#include <spi-common/spi-dbus.h>
+#include <droute/droute.h>
#include "registry.h"
+#include "deviceeventcontroller.h"
static gchar *dbus_name = NULL;
{NULL}
};
+static DBusObjectPathVTable droute_vtable =
+{
+ NULL,
+ &droute_message,
+ NULL, NULL, NULL, NULL
+};
+
int
main (int argc, char **argv)
{
SpiRegistry *registry;
- /*SpiDEController *dec;*/
+ SpiDEController *dec;
+ DRouteData droute;
GMainLoop *mainloop;
DBusConnection *bus;
g_type_init();
+ /* We depend on GDK as well as XLib for device event processing */
+ gdk_init(&argc, &argv);
+
/*Parse command options*/
opt = g_option_context_new(NULL);
g_option_context_add_main_entries(opt, optentries, NULL);
dbus_error_init (&error);
bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+ droute.bus = bus;
if (!bus)
{
g_warning("Couldn't connect to dbus: %s\n", error.message);
g_print ("SpiRegistry daemon is running with well-known name - %s\n", dbus_name);
}
- /*dec = spi_registry_dec_new (bus);*/
+ /* Set up D-Route for use by the dec */
+ if (!dbus_connection_register_object_path (droute.bus,
+ "/org/freedesktop/atspi/registry/deviceeventcontroller",
+ &droute_vtable,
+ &droute))
+ {
+ g_error("AT-SPI Registry daemon: Couldn't register droute.\n");
+ return 0;
+ }
+
registry = spi_registry_new (bus);
+ dec = spi_registry_dec_new (registry, &droute);
+ droute.user_data = dec;
g_main_loop_run (mainloop);
return 0;
A ControllerEventMask filtering the intercepted key events.
</tp:docstring>
</arg>
- <arg direction="in" name="type" type="u" tp:type="KeyEventTypeSeq">
+ <arg direction="in" name="type" type="au" tp:type="KeyEventTypeSeq">
<tp:docstring>
A KeyEventTypeSeq that may created by ORing event types together.
</tp:docstring>