+2001-11-09 Bill Haneman <bill.haneman@sun.com
+
+ * libspi/Makefile.am:
+ * registryd/Makefile.am:
+ (temporary) hack to include libXtst in libspi and registryd.
+ (Needed for keystroke synthesis, see below).
+
+ * idl/Registry.idl:
+ Improved API for registerKeystrokeListener, in accordance with
+ discussions with Gnopernicus team and X server research.
+
+ * libspi/registry.c:
+ * libspi/deviceeventcontroller.c:
+ * libspi/accessible.c:
+ * libspi/keystrokelistener.c:
+ Changes and fixes to support keylisteners for potentially
+ consumed key events (that is, 'passive grabs').
+ Added implementation for generateKeyEvent() [untested].
+
+ * cspi/spi.h:
+ Changes to registerKeystrokeListener() API, as above.
+ Added deregisterGlobalEventListenerAll(), and
+ deregisterKeystrokeListener(), which are needed for clean exit of
+ clients.
+ Added typedefs for KeyListenerSyncType, KeyEventMask, and KeySet,
+ and a macro ALL_KEYS which may be used in place of a KeySet pointer.
+
+ * cspi/spi_registry.c:
+ Added implementations of function prototypes mentioned above.
+
+ * registryd/registryd.c:
+ Added the key listener event source as a g_timeout(), to allow
+ receipt of key events that are not caught by GDK (since GDK
+ doesn't support passive keygrabs, this was necessary).
+
+ * test/simple-at.c:
+ Changed to attach a keylistener to 'Alt' keys, and
+ respond to the following keycommands: Alt-M (toggle magnifier);
+ Alt-F (toggle speech); Alt-Q (quit).
+ Added an exit routine to deregister the listeners, and a key
+ listener that prints some key info to the console when a key
+ matches the listener mask (and is thus received by the listener).
+
+ * util/idl/Magnifier.idl:
+ Changes to magnifier API to support multiple zoom regions,
+ non-uniform scaling in x and y, markDirty, and a host of other
+ features that would be useful to magnification.
+
+ * util/mag_image.h:
+ * util/mag_client.c:
+ * util/mag_client.h:
+ * util/mag_control.c:
+ * util/magnifier.c:
+ Source code changes to support the above IDL changes.
+
+ * util/mag_image.c:
+ As above, and also changes to use a (slower) generic conversion
+ path for colormap conversions, since the fast RGB conversions have been
+ reported to fail for 16-bit displays.
+
2001-10-26 Michael Meeks <michael@ximian.com>
* libspi/Makefile.am (orbittypelibdir): install in orbit-2.0
AT_SPI_MAJOR_VERSION=0
AT_SPI_MINOR_VERSION=0
-AT_SPI_MICRO_VERSION=2
+AT_SPI_MICRO_VERSION=3
AT_SPI_INTERFACE_AGE=0
AT_SPI_BINARY_AGE=0
AT_SPI_VERSION="$AT_SPI_MAJOR_VERSION.$AT_SPI_MINOR_VERSION.$AT_SPI_MICRO_VERSION"
extern "C" {
#endif /* __cplusplus */
-#include "keystrokelistener.h"
#include "accessibleeventlistener.h"
+#include "keystrokelistener.h"
+
/*
*
KEY_RELEASED
} KeyEventType;
+typedef enum _KeyListenerSyncType {
+ KEYLISTENER_SYNCHRONOUS = 1,
+ KEYLISTENER_CANCONSUME = 2,
+ KEYLISTENER_ALLWINDOWS = 4
+} KeyListenerSyncType;
+
+typedef unsigned long KeyEventMask;
+
typedef struct _KeyStroke
{
long keyID;
+ short keycode;
KeyEventType type;
unsigned short modifiers;
} KeyStroke;
+typedef struct _KeySet
+{
+ unsigned long *keysyms;
+ unsigned short *keycodes;
+ short len;
+} KeySet;
+
+#define ALL_KEYS ((void *)NULL)
/*
*
*
**/
void
-registerKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask);
+registerKeystrokeListener (KeystrokeListener *listener,
+ KeySet *keys,
+ KeyMaskType modmask,
+ KeyEventMask eventmask,
+ KeyListenerSyncType sync_type);
/**
* generateKeyEvent:
KeystrokeListener *
createKeystrokeListener (KeystrokeListenerCB callback)
{
- KeystrokeListener *listener = g_object_new (KEYSTROKE_LISTENER_TYPE, NULL);
+ KeystrokeListener *listener = keystroke_listener_new ();
if (callback)
{
keystroke_listener_add_callback (listener, callback);
keystroke_listener_remove_callback (listener, callback);
return TRUE;
}
+
void
SPI_event_main (boolean isGNOMEApp)
{
- if (isGNOMEApp) {
+ if (isGNOMEApp) {
g_atexit(SPI_exit);
bonobo_main();
}
*
*/
+/* static stuff used only by registry C bindings */
+static GList *key_listeners = NULL;
+static Display *display = NULL;
+
/**
* registerGlobalEventListener:
* @listener: the #AccessibleEventListener to be registered against an event type.
}
}
+/**
+ * deregisterGlobalEventListener:
+ * @listener: the #AccessibleEventListener to be registered against an event type.
+ *
+ * deregisters an AccessibleEventListener from the registry, for all event types it may be listening to.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+boolean
+deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
+{
+ Accessibility_Registry_deregisterGlobalEventListenerAll (
+ registry,
+ (Accessibility_EventListener)
+ CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), &ev),
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
/**
* getDesktopCount:
*
return 0;
}
+static gboolean
+key_event_source_func (void *p)
+{
+ GList *listeners = (GList *)p;
+ XEvent *x_event = g_new0 (XEvent, 1);
+ while (XPending (display))
+ {
+ XNextEvent (display, x_event);
+ while (listeners)
+ {
+ /* if the listener mask matches, notify it*/
+ if (1)
+ {
+ ;
+ }
+ }
+ }
+ return TRUE;
+}
+
+void
+save_this_impl_registerKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask)
+{
+ static gboolean initialized = FALSE;
+ static Window grab_window;
+ XEvent *x_event = g_new0(XEvent, 1);
+ key_listeners = g_list_append (key_listeners, listener);
+ if (!initialized)
+ {
+ g_timeout_add_full (G_PRIORITY_HIGH_IDLE, 200, key_event_source_func, key_listeners, NULL);
+ display = XOpenDisplay (getenv ("DISPLAY"));
+ grab_window = DefaultRootWindow (display);
+ XSelectInput (display, grab_window, KeyPress | KeyRelease);
+ initialized = TRUE;
+ }
+ /* */
+ XGrabKey (display,
+ AnyKey,
+ LockMask,
+ grab_window,
+ False,
+ GrabModeAsync,
+ GrabModeAsync);
+ while (0)
+ {
+ XNextEvent (display, x_event);
+ g_print ("foo!\n");
+ }
+}
+
/**
* registerKeystrokeListener:
* @listener: a pointer to the #KeystrokeListener for which
* keystroke events are requested.
*
- * Not Yet Implemented.
- *
**/
void
-registerKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask)
+registerKeystrokeListener (KeystrokeListener *listener,
+ KeySet *keys,
+ KeyMaskType modmask,
+ KeyEventMask eventmask,
+ KeyListenerSyncType sync_type)
{
Accessibility_ControllerEventMask *controller_event_mask =
Accessibility_ControllerEventMask__alloc();
Accessibility_Registry_getDeviceEventController (registry, &ev);
Accessibility_KeySet *all_keys = Accessibility_KeySet__alloc();
Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
+ Accessibility_KeystrokeListener listener_corba_ref;
Accessibility_DeviceEventController_ref (device_event_controller, &ev);
- controller_event_mask->value = (CORBA_unsigned_long) keymask;
+ controller_event_mask->value = (CORBA_unsigned_long) modmask;
controller_event_mask->refcount = (CORBA_unsigned_short) 1;
- /*
- fprintf (stderr, "controller %p, mask value %lu\n", (void *) device_event_controller,
- (unsigned long) controller_event_mask->value );
- */
+ listener_corba_ref = (Accessibility_KeystrokeListener)
+ CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), &ev);
+
+ Accessibility_DeviceEventController_registerKeystrokeListener (
+ device_event_controller,
+ listener_corba_ref,
+ all_keys,
+ controller_event_mask,
+ key_events,
+ (CORBA_boolean) ((sync_type | KEYLISTENER_CANCONSUME)!=0),
+ &ev);
+}
+
+/**
+ * deregisterKeystrokeListener:
+ * @listener: a pointer to the #KeystrokeListener for which
+ * keystroke events are requested.
+ *
+ **/
+void
+deregisterKeystrokeListener (KeystrokeListener *listener, KeyMaskType keymask)
+{
+ Accessibility_ControllerEventMask *controller_event_mask =
+ Accessibility_ControllerEventMask__alloc();
+ Accessibility_DeviceEventController device_event_controller =
+ Accessibility_Registry_getDeviceEventController (registry, &ev);
+ Accessibility_KeySet *all_keys = Accessibility_KeySet__alloc();
+ Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
+ Accessibility_KeystrokeListener listener_corba_ref;
+ Accessibility_DeviceEventController_unref (device_event_controller, &ev);
+ controller_event_mask->value = (CORBA_unsigned_long) keymask;
+ controller_event_mask->refcount = (CORBA_unsigned_short) 1;
- Accessibility_DeviceEventController_registerKeystrokeListener (
+ listener_corba_ref = (Accessibility_KeystrokeListener)
+ CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), &ev);
+
+ Accessibility_DeviceEventController_deregisterKeystrokeListener (
device_event_controller,
- (Accessibility_KeystrokeListener)
- bonobo_object_corba_objref (bonobo_object (listener)),
+ listener_corba_ref,
all_keys,
controller_event_mask,
key_events,
struct KeyStroke {
long keyID;
+ short keycode;
KeyEventType type;
unsigned short modifiers;
};
typedef sequence< long > KeySet;
typedef sequence< KeyEventType > KeyEventTypeSeq;
- interface KeystrokeListener {
+ interface KeystrokeListener : Bonobo::Unknown {
boolean keyEvent (in KeyStroke key);
};
in KeyEventTypeSeq type,
in boolean is_synchronous);
+ /**
+ * deregisterKeystrokeListener:
+ * @listener: a @KeystrokeListener which will intercept key events.
+ * @keys: a @KeySet indicating which keys to intercept, or KEYSET_ALL_KEYS.
+ * @mask: a @ControllerEventMask filtering the intercepted key events.
+ * @type: an @EventType mask that may created by ORing event types together.
+ * @is_synchronous: a @boolean indicating whether the listener should
+ * receive the events synchronously, potentially consuming them,
+ * or just be notified asynchronously of those events that have
+ * been generated.
+ * Returns: void
+ *
+ * De-register a previously registered keyboard eventlistener.
+ *
+ **/
+ void deregisterKeystrokeListener (in KeystrokeListener listener,
+ in KeySet keys,
+ in ControllerEventMask mask,
+ in KeyEventTypeSeq type,
+ in boolean is_synchronous);
+
/**
* generateKeyEvent:
* @keyEventID: a long integer indicating which keypress is synthesized.
struct KeyStroke {
long keyID;
+ short keycode;
KeyEventType type;
unsigned short modifiers;
};
typedef sequence< long > KeySet;
typedef sequence< KeyEventType > KeyEventTypeSeq;
- interface KeystrokeListener {
+ interface KeystrokeListener : Bonobo::Unknown {
boolean keyEvent (in KeyStroke key);
};
in KeyEventTypeSeq type,
in boolean is_synchronous);
+ /**
+ * deregisterKeystrokeListener:
+ * @listener: a @KeystrokeListener which will intercept key events.
+ * @keys: a @KeySet indicating which keys to intercept, or KEYSET_ALL_KEYS.
+ * @mask: a @ControllerEventMask filtering the intercepted key events.
+ * @type: an @EventType mask that may created by ORing event types together.
+ * @is_synchronous: a @boolean indicating whether the listener should
+ * receive the events synchronously, potentially consuming them,
+ * or just be notified asynchronously of those events that have
+ * been generated.
+ * Returns: void
+ *
+ * De-register a previously registered keyboard eventlistener.
+ *
+ **/
+ void deregisterKeystrokeListener (in KeystrokeListener listener,
+ in KeySet keys,
+ in ControllerEventMask mask,
+ in KeyEventTypeSeq type,
+ in boolean is_synchronous);
+
/**
* generateKeyEvent:
* @keyEventID: a long integer indicating which keypress is synthesized.
-I $(top_builddir)/libspi \
$(LIBSPI_CFLAGS)
-LDFLAGS = $(LIBSPI_LIBS) @LT_VERSION_INFO@
+LDFLAGS = $(LIBSPI_LIBS) -lXtst @LT_VERSION_INFO@
DEBUG_CFLAGS=-DSPI_DEBUG
bonobo_object_add_interface (bonobo_object (retval),
BONOBO_OBJECT (action_interface_new (o)));
}
-
+
if (ATK_IS_COMPONENT (o))
{
bonobo_object_add_interface (bonobo_object (retval),
#endif
#include <X11/Xlib.h>
+#include <X11/extensions/XTest.h>
#include <config.h>
#include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
#include <gdk/gdkwindow.h>
static gboolean kbd_registered = FALSE;
+static Display *display;
+
+static Window root_window;
+
typedef enum {
DEVICE_TYPE_KBD,
DEVICE_TYPE_MOUSE,
static gint
_eventmask_compare_value (gconstpointer p1, gconstpointer p2)
{
+ long d;
if (!p1 || !p2)
return (gint) (p1?1:(p2?-1:0));
else
- return ((long)((Accessibility_ControllerEventMask*)p2)->value) -
+ d = ((long)((Accessibility_ControllerEventMask*)p2)->value) -
((long)((Accessibility_ControllerEventMask*)p1)->value);
+ return (gint) d;
}
static void
DeviceTypeCategory type,
CORBA_Environment *ev)
{
- Accessibility_ControllerEventMask *mask_ptr;
+ Accessibility_ControllerEventMask *mask_ptr = NULL;
switch (type) {
case DEVICE_TYPE_KBD:
list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects);
if (list_ptr)
controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr);
-
- mask_ptr = (Accessibility_ControllerEventMask *)
+ list_ptr = (GList *)
g_list_find_custom (controller->keymask_list, (gpointer) mask,
_eventmask_compare_value);
- if (mask_ptr)
+ if (list_ptr)
+ {
+ mask_ptr = (Accessibility_ControllerEventMask *) list_ptr->data;
+ if (mask_ptr)
--mask_ptr->refcount;
- if (!mask_ptr->refcount)
- {
- controller->keymask_list = g_list_remove (controller->keymask_list, mask_ptr);
- ; /* TODO: release any key grabs that are in place for this key mask */
- }
+ if (!mask_ptr->refcount)
+ {
+ controller->keymask_list =
+ g_list_remove (controller->keymask_list, mask_ptr);
+ ; /* TODO: release any key grabs that are in place for this key mask */
+ }
+ }
break;
case DEVICE_TYPE_MOUSE:
/* controller->mouse_listeners = g_list_append (controller->mouse_listeners,
_controller_register_with_devices (DeviceEventController *controller)
{
gboolean retval = FALSE;
- Display *default_display;
- Window root_window;
- default_display = GDK_DISPLAY();
- root_window = GDK_ROOT_WINDOW();
/* calls to device-specific implementations and routines go here */
/* register with: keyboard hardware code handler */
/* register with: (translated) keystroke handler */
#ifdef SPI_DEBUG
- fprintf (stderr, "About to request events on window %ld of display %p\n",
- (unsigned long) root_window, default_display);
+ fprintf (stderr, "About to request events on window %ld of display %x\n",
+ (unsigned long) GDK_ROOT_WINDOW(), GDK_DISPLAY());
#endif
- XSelectInput (default_display,
- root_window,
- KeyPressMask);
- XSelectInput (default_display,
+ /* We must open a new connection to the server to avoid clashing with the GDK event loop */
+ display = XOpenDisplay (getenv ("DISPLAY"));
+ root_window = DefaultRootWindow (display);
+ XSelectInput (display,
root_window,
- KeyReleaseMask);
+ KeyPressMask | KeyReleaseMask);
/* register with: mouse hardware device handler? */
/* register with: mouse event handler */
return retval;
}
-static gboolean _check_key_event (DeviceEventController *controller)
+static gboolean
+_check_key_event (DeviceEventController *controller)
{
-#ifdef SPI_DEBUG
- static Accessibility_ControllerEventMask shiftlock_mask =
- {(CORBA_unsigned_long) LockMask, (CORBA_unsigned_short) 1};
-#endif
static gboolean initialized = FALSE;
static gboolean is_active = FALSE;
XEvent *x_event = g_new0 (XEvent, 1);
int n_listeners = g_list_length (controller->key_listeners);
Accessibility_KeyStroke key_event;
static CORBA_Environment ev;
-
+
if (!initialized)
{
- initialized = TRUE;
- CORBA_exception_init (&ev);
+ initialized = TRUE;
+ CORBA_exception_init (&ev);
}
-/* if (!XPending(GDK_DISPLAY())) return TRUE; */
-
- /*
- * the call to XPending seemed like a good idea, why did it
- * wreak such havoc?
- */
-
- XPeekEvent (GDK_DISPLAY(), x_event);
- if (x_event->type == KeyPress)
- {
- x_key_event = (XKeyEvent *)x_event;
- keysym = XLookupKeysym (x_key_event, 0);
- key_event.keyID = (CORBA_long)(keysym);
- key_event.type = Accessibility_KEY_PRESSED;
- key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
-#if defined SPI_KEYEVENT_DEBUG
+ while (XPending(display))
+ {
+ XNextEvent (display, x_event);
+ if (x_event->type == KeyPress)
+ {
+ x_key_event = (XKeyEvent *)x_event;
+ keysym = XLookupKeysym (x_key_event, 0);
+ key_event.keyID = (CORBA_long)(keysym);
+ key_event.keycode = (CORBA_short) x_key_event->keycode;
+ key_event.type = Accessibility_KEY_PRESSED;
+ key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
+#ifdef SPI_KEYEVENT_DEBUG
fprintf (stderr,
"Key %lu pressed (%c), modifiers %d\n",
(unsigned long) keysym,
- (char) keysym,
+ keysym ? (int) keysym : '*',
(int) x_key_event->state);
-#elif defined SPI_DEBUG
+#endif
+#ifdef SPI_DEBUG
fprintf(stderr, "%s%c",
(x_key_event->state & Mod1Mask)?"Alt-":"",
((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
(char) toupper((int) keysym) : (char) tolower((int)keysym));
#endif /* SPI_DEBUG */
- }
- else
- {
+ }
+ else
+ {
#ifdef SPI_KEYEVENT_DEBUG
- fprintf (stderr, "other event, type %d\n", (int) x_event->type);
-#endif
- }
- /* relay to listeners, and decide whether to consume it or not */
- for (i=0; i<n_listeners && !is_consumed; ++i)
- {
- Accessibility_KeystrokeListener ls;
- ls = (Accessibility_KeystrokeListener)
- g_list_nth_data (controller->key_listeners, i);
- if (!CORBA_Object_is_nil(ls, &ev))
- {
- is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
- }
- }
- if (is_consumed) XNextEvent (GDK_DISPLAY(), x_event);
- XAllowEvents (GDK_DISPLAY(), ReplayKeyboard, CurrentTime);
-/*
- * I haven't figure out how to make this work correctly yet :-(
- *
- * XGrabKeyboard (GDK_DISPLAY(), GDK_ROOT_WINDOW(), True,
- * GrabModeAsync, GrabModeSync, CurrentTime);
- * XAllowEvents (GDK_DISPLAY(), SyncKeyboard, CurrentTime);
- *
- *
- * ControlMask grabs are broken, must be in use already.
- *
- */
-
-/* Always grab ShiftLock in DEBUG mode */
-#ifdef SPI_DEBUG
- if (!controller->keymask_list)
- controller->keymask_list =
- g_list_append (controller->keymask_list, &shiftlock_mask);
+ fprintf (stderr, "other event, type %d\n", (int) x_event->type);
#endif
+ }
+ /* relay to listeners, and decide whether to consume it or not */
+ for (i=0; i<n_listeners && !is_consumed; ++i)
+ {
+ Accessibility_KeystrokeListener ls;
+ ls = (Accessibility_KeystrokeListener)
+ g_list_nth_data (controller->key_listeners, i);
+ if (!CORBA_Object_is_nil(ls, &ev))
+ {
+ is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
+ }
+ }
+ if (is_consumed)
+ {
+ XAllowEvents (display, SyncKeyboard, CurrentTime);
+ }
+ else
+ {
+ XAllowEvents (display, ReplayKeyboard, CurrentTime);
+ }
+ }
+ XUngrabKey (display, AnyKey, AnyModifier, root_window);
return _controller_grab_keyboard (controller);
}
static gboolean
_controller_grab_keyboard (DeviceEventController *controller)
{
- Display *display = GDK_DISPLAY();
- Window root_window = GDK_ROOT_WINDOW();
GList *maskList = controller->keymask_list;
int i;
- int last_mask = g_list_length (maskList);
+ int last_mask;
+ last_mask = g_list_length (maskList);
/*
* masks known to work with default RH 7.1:
#endif
if (!(maskVal & ControlMask))
{
-#ifdef SPI_KEYEVENT_DEBUG
- fprintf (stderr, "grabbing for mod %lu\n", (unsigned long) maskVal);
-#endif
XGrabKey (display,
AnyKey,
maskVal,
static void
impl_register_keystroke_listener (PortableServer_Servant servant,
const Accessibility_KeystrokeListener l,
+ const Accessibility_KeySet *keys,
const Accessibility_ControllerEventMask *mask,
+ const Accessibility_KeyEventTypeSeq *type,
+ const CORBA_boolean is_synchronous,
CORBA_Environment *ev)
{
DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n",
(void *) l, (unsigned long) mask->value);
#endif
+ /* TODO: change this to an enum, indicating if event can be consumed */
+ if (is_synchronous)
_controller_register_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev);
+ else
+ ; /* register with toolkit instead */
+}
+/*
+ * CORBA Accessibility::DeviceEventController::deregisterKeystrokeListener
+ * method implementation
+ */
+static void
+impl_deregister_keystroke_listener (PortableServer_Servant servant,
+ const Accessibility_KeystrokeListener l,
+ const Accessibility_KeySet *keys,
+ const Accessibility_ControllerEventMask *mask,
+ const Accessibility_KeyEventTypeSeq *type,
+ const CORBA_boolean is_synchronous,
+ CORBA_Environment *ev)
+{
+ DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
+ bonobo_object_from_servant (servant));
+#ifdef SPI_DEBUG
+ fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
+ (void *) l, (unsigned long) mask->value);
+#endif
+ _controller_deregister_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev);
}
/*
#ifdef SPI_DEBUG
fprintf (stderr, "synthesizing keystroke %ld\n", (long) keyEventID);
#endif
+ /* TODO: hide/wrap/remove X dependency */
+ XTestFakeKeyEvent (GDK_DISPLAY(), (unsigned int) keyEventID, True, CurrentTime);
+ XTestFakeKeyEvent (GDK_DISPLAY(), (unsigned int) keyEventID, False, CurrentTime);
}
/*
object_class->finalize = device_event_controller_object_finalize;
epv->registerKeystrokeListener = impl_register_keystroke_listener;
+ epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
/* epv->registerMouseListener = impl_register_mouse_listener; */
epv->generateKeyEvent = impl_generate_key_event;
epv->generateMouseEvent = impl_generate_mouse_event;
device_event_controller_init (DeviceEventController *device_event_controller)
{
device_event_controller->key_listeners = NULL;
- device_event_controller->key_listeners = NULL;
+ device_event_controller->mouse_listeners = NULL;
device_event_controller->keymask_list = NULL;
kbd_registered = _controller_register_with_devices (device_event_controller);
}
/*
* CORBA Accessibility::KeystrokeListener::keyEvent method implementation
*/
-
static CORBA_boolean
impl_key_event (PortableServer_Servant servant,
const Accessibility_KeyStroke *key,
CORBA_Environment *ev)
{
-#ifdef SPI_DEBUG
+ KeystrokeListener *listener = KEYSTROKE_LISTENER (bonobo_object_from_servant (servant));
+ GList *callbacks = listener->callbacks;
+ gboolean was_consumed = FALSE;
+#ifdef SPI_KEYEVENT_DEBUG
if (ev->_major != CORBA_NO_EXCEPTION) {
fprintf(stderr,
("Accessibility app error: exception during keystroke notification: %s\n"),
(char) toupper((int) key->keyID) : (char) tolower((int) key->keyID));
}
#endif
+ while (callbacks)
+ {
+ BooleanKeystrokeListenerCB cb = (BooleanKeystrokeListenerCB) callbacks->data;
+ was_consumed = (*cb) (key) || was_consumed;
+ callbacks = g_list_next (callbacks);
+ }
+ return was_consumed;
}
static void
{
CORBA_Environment ev;
gint retval;
- retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
#ifdef SPI_DEBUG
- fprintf (stderr, "comparing %p to %p; result %d\n",
- p1, p2,
- retval);
+ fprintf (stderr, "comparing %p to %p\n",
+ p1, p2);
#endif
+
+ retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
return retval;
}
return (((ListenerStruct *)p2)->event_type_hash - ((ListenerStruct *)p1)->event_type_hash);
}
+static gint
+compare_listener_corbaref (gconstpointer p1, gconstpointer p2)
+{
+ return compare_corba_objects (((ListenerStruct *)p2)->listener,
+ ((ListenerStruct *)p1)->listener);
+}
+
static void
parse_event_type (EventTypeStruct *etype, char *event_name)
{
CORBA_Environment * ev)
{
Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
- GList *list = g_list_find_custom (registry->desktop->applications, application, compare_corba_objects);
+ GList *list = g_list_find_custom (registry->desktop->applications, &application, compare_corba_objects);
#ifdef SPI_DEBUG
gint i;
CORBA_Environment *ev)
{
Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
- GList *list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects);
+ ListenerStruct *ls = g_malloc (sizeof (ListenerStruct));
+ GList *list;
+ ls->listener = listener;
+ list = g_list_find_custom (registry->object_listeners, ls,
+ compare_listener_corbaref);
/*
* TODO : de-register with toolkit if the last instance of a listener
{
fprintf (stderr, "deregistering listener\n");
registry->object_listeners = g_list_delete_link (registry->object_listeners, list);
- list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects);
+ list = g_list_find_custom (registry->object_listeners, ls, compare_listener_corbaref);
}
- list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
+ list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref);
while (list)
{
fprintf (stderr, "deregistering listener\n");
registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list);
- list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
+ list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref);
}
}
registryd_SOURCES = registryd.c
-LDADD = ../libspi/libspi.la $(REGISTRYD_LIBS)
+LDADD = ../libspi/libspi.la -lXtst $(REGISTRYD_LIBS)
serverinfodir = $(libdir)/bonobo/servers
serverinfo_DATA = Accessibility_Registry.server
#endif
#include <X11/Xlib.h>
+#include <X11/extensions/XTest.h>
#include <config.h>
#include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
#include <gdk/gdkwindow.h>
static gboolean kbd_registered = FALSE;
+static Display *display;
+
+static Window root_window;
+
typedef enum {
DEVICE_TYPE_KBD,
DEVICE_TYPE_MOUSE,
static gint
_eventmask_compare_value (gconstpointer p1, gconstpointer p2)
{
+ long d;
if (!p1 || !p2)
return (gint) (p1?1:(p2?-1:0));
else
- return ((long)((Accessibility_ControllerEventMask*)p2)->value) -
+ d = ((long)((Accessibility_ControllerEventMask*)p2)->value) -
((long)((Accessibility_ControllerEventMask*)p1)->value);
+ return (gint) d;
}
static void
DeviceTypeCategory type,
CORBA_Environment *ev)
{
- Accessibility_ControllerEventMask *mask_ptr;
+ Accessibility_ControllerEventMask *mask_ptr = NULL;
switch (type) {
case DEVICE_TYPE_KBD:
list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects);
if (list_ptr)
controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr);
-
- mask_ptr = (Accessibility_ControllerEventMask *)
+ list_ptr = (GList *)
g_list_find_custom (controller->keymask_list, (gpointer) mask,
_eventmask_compare_value);
- if (mask_ptr)
+ if (list_ptr)
+ {
+ mask_ptr = (Accessibility_ControllerEventMask *) list_ptr->data;
+ if (mask_ptr)
--mask_ptr->refcount;
- if (!mask_ptr->refcount)
- {
- controller->keymask_list = g_list_remove (controller->keymask_list, mask_ptr);
- ; /* TODO: release any key grabs that are in place for this key mask */
- }
+ if (!mask_ptr->refcount)
+ {
+ controller->keymask_list =
+ g_list_remove (controller->keymask_list, mask_ptr);
+ ; /* TODO: release any key grabs that are in place for this key mask */
+ }
+ }
break;
case DEVICE_TYPE_MOUSE:
/* controller->mouse_listeners = g_list_append (controller->mouse_listeners,
_controller_register_with_devices (DeviceEventController *controller)
{
gboolean retval = FALSE;
- Display *default_display;
- Window root_window;
- default_display = GDK_DISPLAY();
- root_window = GDK_ROOT_WINDOW();
/* calls to device-specific implementations and routines go here */
/* register with: keyboard hardware code handler */
/* register with: (translated) keystroke handler */
#ifdef SPI_DEBUG
- fprintf (stderr, "About to request events on window %ld of display %p\n",
- (unsigned long) root_window, default_display);
+ fprintf (stderr, "About to request events on window %ld of display %x\n",
+ (unsigned long) GDK_ROOT_WINDOW(), GDK_DISPLAY());
#endif
- XSelectInput (default_display,
- root_window,
- KeyPressMask);
- XSelectInput (default_display,
+ /* We must open a new connection to the server to avoid clashing with the GDK event loop */
+ display = XOpenDisplay (getenv ("DISPLAY"));
+ root_window = DefaultRootWindow (display);
+ XSelectInput (display,
root_window,
- KeyReleaseMask);
+ KeyPressMask | KeyReleaseMask);
/* register with: mouse hardware device handler? */
/* register with: mouse event handler */
return retval;
}
-static gboolean _check_key_event (DeviceEventController *controller)
+static gboolean
+_check_key_event (DeviceEventController *controller)
{
-#ifdef SPI_DEBUG
- static Accessibility_ControllerEventMask shiftlock_mask =
- {(CORBA_unsigned_long) LockMask, (CORBA_unsigned_short) 1};
-#endif
static gboolean initialized = FALSE;
static gboolean is_active = FALSE;
XEvent *x_event = g_new0 (XEvent, 1);
int n_listeners = g_list_length (controller->key_listeners);
Accessibility_KeyStroke key_event;
static CORBA_Environment ev;
-
+
if (!initialized)
{
- initialized = TRUE;
- CORBA_exception_init (&ev);
+ initialized = TRUE;
+ CORBA_exception_init (&ev);
}
-/* if (!XPending(GDK_DISPLAY())) return TRUE; */
-
- /*
- * the call to XPending seemed like a good idea, why did it
- * wreak such havoc?
- */
-
- XPeekEvent (GDK_DISPLAY(), x_event);
- if (x_event->type == KeyPress)
- {
- x_key_event = (XKeyEvent *)x_event;
- keysym = XLookupKeysym (x_key_event, 0);
- key_event.keyID = (CORBA_long)(keysym);
- key_event.type = Accessibility_KEY_PRESSED;
- key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
-#if defined SPI_KEYEVENT_DEBUG
+ while (XPending(display))
+ {
+ XNextEvent (display, x_event);
+ if (x_event->type == KeyPress)
+ {
+ x_key_event = (XKeyEvent *)x_event;
+ keysym = XLookupKeysym (x_key_event, 0);
+ key_event.keyID = (CORBA_long)(keysym);
+ key_event.keycode = (CORBA_short) x_key_event->keycode;
+ key_event.type = Accessibility_KEY_PRESSED;
+ key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
+#ifdef SPI_KEYEVENT_DEBUG
fprintf (stderr,
"Key %lu pressed (%c), modifiers %d\n",
(unsigned long) keysym,
- (char) keysym,
+ keysym ? (int) keysym : '*',
(int) x_key_event->state);
-#elif defined SPI_DEBUG
+#endif
+#ifdef SPI_DEBUG
fprintf(stderr, "%s%c",
(x_key_event->state & Mod1Mask)?"Alt-":"",
((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
(char) toupper((int) keysym) : (char) tolower((int)keysym));
#endif /* SPI_DEBUG */
- }
- else
- {
+ }
+ else
+ {
#ifdef SPI_KEYEVENT_DEBUG
- fprintf (stderr, "other event, type %d\n", (int) x_event->type);
-#endif
- }
- /* relay to listeners, and decide whether to consume it or not */
- for (i=0; i<n_listeners && !is_consumed; ++i)
- {
- Accessibility_KeystrokeListener ls;
- ls = (Accessibility_KeystrokeListener)
- g_list_nth_data (controller->key_listeners, i);
- if (!CORBA_Object_is_nil(ls, &ev))
- {
- is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
- }
- }
- if (is_consumed) XNextEvent (GDK_DISPLAY(), x_event);
- XAllowEvents (GDK_DISPLAY(), ReplayKeyboard, CurrentTime);
-/*
- * I haven't figure out how to make this work correctly yet :-(
- *
- * XGrabKeyboard (GDK_DISPLAY(), GDK_ROOT_WINDOW(), True,
- * GrabModeAsync, GrabModeSync, CurrentTime);
- * XAllowEvents (GDK_DISPLAY(), SyncKeyboard, CurrentTime);
- *
- *
- * ControlMask grabs are broken, must be in use already.
- *
- */
-
-/* Always grab ShiftLock in DEBUG mode */
-#ifdef SPI_DEBUG
- if (!controller->keymask_list)
- controller->keymask_list =
- g_list_append (controller->keymask_list, &shiftlock_mask);
+ fprintf (stderr, "other event, type %d\n", (int) x_event->type);
#endif
+ }
+ /* relay to listeners, and decide whether to consume it or not */
+ for (i=0; i<n_listeners && !is_consumed; ++i)
+ {
+ Accessibility_KeystrokeListener ls;
+ ls = (Accessibility_KeystrokeListener)
+ g_list_nth_data (controller->key_listeners, i);
+ if (!CORBA_Object_is_nil(ls, &ev))
+ {
+ is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev);
+ }
+ }
+ if (is_consumed)
+ {
+ XAllowEvents (display, SyncKeyboard, CurrentTime);
+ }
+ else
+ {
+ XAllowEvents (display, ReplayKeyboard, CurrentTime);
+ }
+ }
+ XUngrabKey (display, AnyKey, AnyModifier, root_window);
return _controller_grab_keyboard (controller);
}
static gboolean
_controller_grab_keyboard (DeviceEventController *controller)
{
- Display *display = GDK_DISPLAY();
- Window root_window = GDK_ROOT_WINDOW();
GList *maskList = controller->keymask_list;
int i;
- int last_mask = g_list_length (maskList);
+ int last_mask;
+ last_mask = g_list_length (maskList);
/*
* masks known to work with default RH 7.1:
#endif
if (!(maskVal & ControlMask))
{
-#ifdef SPI_KEYEVENT_DEBUG
- fprintf (stderr, "grabbing for mod %lu\n", (unsigned long) maskVal);
-#endif
XGrabKey (display,
AnyKey,
maskVal,
static void
impl_register_keystroke_listener (PortableServer_Servant servant,
const Accessibility_KeystrokeListener l,
+ const Accessibility_KeySet *keys,
const Accessibility_ControllerEventMask *mask,
+ const Accessibility_KeyEventTypeSeq *type,
+ const CORBA_boolean is_synchronous,
CORBA_Environment *ev)
{
DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n",
(void *) l, (unsigned long) mask->value);
#endif
+ /* TODO: change this to an enum, indicating if event can be consumed */
+ if (is_synchronous)
_controller_register_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev);
+ else
+ ; /* register with toolkit instead */
+}
+/*
+ * CORBA Accessibility::DeviceEventController::deregisterKeystrokeListener
+ * method implementation
+ */
+static void
+impl_deregister_keystroke_listener (PortableServer_Servant servant,
+ const Accessibility_KeystrokeListener l,
+ const Accessibility_KeySet *keys,
+ const Accessibility_ControllerEventMask *mask,
+ const Accessibility_KeyEventTypeSeq *type,
+ const CORBA_boolean is_synchronous,
+ CORBA_Environment *ev)
+{
+ DeviceEventController *controller = DEVICE_EVENT_CONTROLLER (
+ bonobo_object_from_servant (servant));
+#ifdef SPI_DEBUG
+ fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
+ (void *) l, (unsigned long) mask->value);
+#endif
+ _controller_deregister_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev);
}
/*
#ifdef SPI_DEBUG
fprintf (stderr, "synthesizing keystroke %ld\n", (long) keyEventID);
#endif
+ /* TODO: hide/wrap/remove X dependency */
+ XTestFakeKeyEvent (GDK_DISPLAY(), (unsigned int) keyEventID, True, CurrentTime);
+ XTestFakeKeyEvent (GDK_DISPLAY(), (unsigned int) keyEventID, False, CurrentTime);
}
/*
object_class->finalize = device_event_controller_object_finalize;
epv->registerKeystrokeListener = impl_register_keystroke_listener;
+ epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
/* epv->registerMouseListener = impl_register_mouse_listener; */
epv->generateKeyEvent = impl_generate_key_event;
epv->generateMouseEvent = impl_generate_mouse_event;
device_event_controller_init (DeviceEventController *device_event_controller)
{
device_event_controller->key_listeners = NULL;
- device_event_controller->key_listeners = NULL;
+ device_event_controller->mouse_listeners = NULL;
device_event_controller->keymask_list = NULL;
kbd_registered = _controller_register_with_devices (device_event_controller);
}
#endif
gdk_init(&argc, &argv);
- g_idle_add (registry->kbd_event_hook, registry);
+ g_timeout_add_full (G_PRIORITY_HIGH_IDLE, 200, registry->kbd_event_hook, registry, NULL);
/* keyevent_source =
g_source_new (registry->kbd_event_hook, sizeof (GSourceFunc));
g_source_attach (keyevent_source, g_main_context_default());*/
{
CORBA_Environment ev;
gint retval;
- retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
#ifdef SPI_DEBUG
- fprintf (stderr, "comparing %p to %p; result %d\n",
- p1, p2,
- retval);
+ fprintf (stderr, "comparing %p to %p\n",
+ p1, p2);
#endif
+
+ retval = !CORBA_Object_is_equivalent ((CORBA_Object) p1, (CORBA_Object) p2, &ev);
return retval;
}
return (((ListenerStruct *)p2)->event_type_hash - ((ListenerStruct *)p1)->event_type_hash);
}
+static gint
+compare_listener_corbaref (gconstpointer p1, gconstpointer p2)
+{
+ return compare_corba_objects (((ListenerStruct *)p2)->listener,
+ ((ListenerStruct *)p1)->listener);
+}
+
static void
parse_event_type (EventTypeStruct *etype, char *event_name)
{
CORBA_Environment * ev)
{
Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
- GList *list = g_list_find_custom (registry->desktop->applications, application, compare_corba_objects);
+ GList *list = g_list_find_custom (registry->desktop->applications, &application, compare_corba_objects);
#ifdef SPI_DEBUG
gint i;
CORBA_Environment *ev)
{
Registry *registry = REGISTRY (bonobo_object_from_servant (servant));
- GList *list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects);
+ ListenerStruct *ls = g_malloc (sizeof (ListenerStruct));
+ GList *list;
+ ls->listener = listener;
+ list = g_list_find_custom (registry->object_listeners, ls,
+ compare_listener_corbaref);
/*
* TODO : de-register with toolkit if the last instance of a listener
{
fprintf (stderr, "deregistering listener\n");
registry->object_listeners = g_list_delete_link (registry->object_listeners, list);
- list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects);
+ list = g_list_find_custom (registry->object_listeners, ls, compare_listener_corbaref);
}
- list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
+ list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref);
while (list)
{
fprintf (stderr, "deregistering listener\n");
registry->toolkit_listeners = g_list_delete_link (registry->toolkit_listeners, list);
- list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects);
+ list = g_list_find_custom (registry->toolkit_listeners, ls, compare_listener_corbaref);
}
}
#endif
gdk_init(&argc, &argv);
- g_idle_add (registry->kbd_event_hook, registry);
+ g_timeout_add_full (G_PRIORITY_HIGH_IDLE, 200, registry->kbd_event_hook, registry, NULL);
/* keyevent_source =
g_source_new (registry->kbd_event_hook, sizeof (GSourceFunc));
g_source_attach (keyevent_source, g_main_context_default());*/
static boolean use_festival = FALSE;
static boolean festival_chatty = FALSE;
+static AccessibleEventListener *focus_listener;
+static AccessibleEventListener *property_listener;
+static AccessibleEventListener *button_listener;
+static KeystrokeListener *key_listener;
+
int
main(int argc, char **argv)
{
int n_apps;
Accessible *desktop;
Accessible *application;
- AccessibleEventListener *focus_listener;
- AccessibleEventListener *property_listener;
- AccessibleEventListener *button_listener;
- KeystrokeListener *key_listener;
if ((argc > 1) && (!strncmp(argv[1],"-h",2)))
{
}
/* prepare the keyboard snoopers */
- /* key_listener = createKeystrokeListener(report_key_event);
- registerKeystrokeListener(key_listener, KEYMASK_SHIFT); */
+ key_listener = createKeystrokeListener(report_key_event);
+ /* will listen only to Alt-key combinations */
+ registerKeystrokeListener(key_listener,
+ (KeySet *) ALL_KEYS,
+ KEYMASK_ALT,
+ (unsigned long) ( KeyPress | KeyRelease),
+ KEYLISTENER_CANCONSUME);
get_environment_vars();
- SPI_event_main(FALSE);
+ SPI_event_main(TRUE);
}
static void
fprintf (stderr, "Bounding box: (%ld, %ld) ; (%ld, %ld)\n",
x, y, x+width, y+height);
if (use_magnifier) {
- magnifier_set_roi (x, y, width, height);
+ magnifier_set_roi ((short) 0, x, y, width, height);
}
}
/* if this is a text object, speak the first sentence. */
}
}
+static void
+simple_at_exit()
+{
+ deregisterGlobalEventListenerAll (focus_listener);
+ deregisterGlobalEventListenerAll (property_listener);
+ deregisterGlobalEventListenerAll (button_listener);
+ deregisterKeystrokeListener (key_listener, KEYMASK_ALT );
+
+ SPI_exit ();
+}
+
+static boolean
+is_command_key (KeyStroke *key)
+{
+ switch (key->keyID)
+ {
+ case 'Q':
+ case 'q':
+ simple_at_exit();
+ return TRUE; /* not reached */
+ case 'M':
+ case 'm':
+ use_magnifier = ! use_magnifier;
+ return TRUE;
+ case 'F':
+ case 'f':
+ use_festival = ! use_festival;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
static boolean
report_key_event (void *p)
{
KeyStroke *key = (KeyStroke *) p;
- fprintf (stderr, ".");
- return FALSE;
+ fprintf(stderr, "KeyEvent %s%c (keycode %d)\n",
+ (key->modifiers & KEYMASK_ALT)?"Alt-":"",
+ ((key->modifiers & KEYMASK_SHIFT)^(key->modifiers & KEYMASK_SHIFTLOCK))?
+ (char) toupper((int) key->keyID) : (char) tolower((int) key->keyID),
+ (int) key->keycode);
+ return is_command_key (key);
}
static int _festival_init ()
interface Magnifier : Bonobo::Unknown {
/**
- * #attribute MagFactor: a float indicating the current x and y magnification ratio.
+ * void setMagFactor: sets the current x and y magnification ratio.
+ * @zoom_region: the index of the affected zoom region.
+ * @magX: the magnification factor in the x direction for the specified region.
+ * @magY: the magnification factor in the x direction for the specified region.
**/
- attribute float MagFactor;
+ oneway void setMagFactor (in short zoom_region, in float magX, in float magY);
/**
* #attribute SourceDisplay: a @string containing the X display name
/**
* oneway void setROI:
* Sets the region of interest for the magnifier.
+ * @zoom_region: the index of the affected zoom region.
* @x1: the minimum X coordinate of the ROI bounding box
* @x2: the maximum X coordinate of the ROI bounding box
* @y1: the minimum Y coordinate of the ROI bounding box
* @y2: the maximum Y coordinate of the ROI bounding box
**/
- oneway void setROI (in long x1, in long y1, in long x2, in long y2);
+ oneway void setROI (in short zoom_region,
+ in long x1, in long y1, in long x2, in long y2);
+
+ /**
+ * oneway void setROI:
+ * Sets the region of interest for the zoom region.
+ * If the zoom region was previously 'unmanaged', this associates
+ * it with the ROI.
+ * @zoom_region: the index of the affected zoom region.
+ * @x1: the minimum X coordinate of the ROI bounding box
+ * @x2: the maximum X coordinate of the ROI bounding box
+ * @y1: the minimum Y coordinate of the ROI bounding box
+ * @y2: the maximum Y coordinate of the ROI bounding box
+ **/
+ oneway void markDirty (in short zoom_region,
+ in long x1, in long y1, in long x2, in long y2);
+
+ /**
+ * oneway void markUnmanaged:
+ * Mark a zoom region as 'unmanaged', meaning that it should not
+ * attempt to get pixels from the source display but will have its
+ * pixels drawn by a client.
+ * @zoom_region: the index of the affected zoom region.
+ **/
+ oneway void markUnmanaged (in short zoom_region);
+
+ /**
+ * short createZoomRegion:
+ * Creates a new zoom region for the magnifier.
+ * The new region is initially unmanaged'.
+ * @zx: the scale factor in the x direction for the new zoom region
+ * @zy: the scale factor in the y direction for the new zoom region
+ * @x1: the minimum X coordinate of the zoomed area bounding box
+ * @x2: the maximum X coordinate of the zoomed area bounding box
+ * @y1: the minimum Y coordinate of the zoomed area bounding box
+ * @y2: the maximum Y coordinate of the zoomed area bounding box
+ **/
+ short createZoomRegion (in float zx, in float zy,
+ in long x1, in long y1,
+ in long x2, in long y2);
+
+ /**
+ * boolean getZoomRegionParams:
+ * Queries a specific zoom region for its parameters.
+ * returns: FALSE if the specified zoom region does not exist.
+ * @zoom_region: the index specifying which zoom region to query.
+ * @zx: the scale factor in the x direction for the new zoom region
+ * @zy: the scale factor in the y direction for the new zoom region
+ * @x1: the minimum X coordinate of the zoomed area bounding box
+ * @x2: the maximum X coordinate of the zoomed area bounding box
+ * @y1: the minimum Y coordinate of the zoomed area bounding box
+ * @y2: the maximum Y coordinate of the zoomed area bounding box
+ **/
+ boolean getZoomRegionParams (in short zoom_region,
+ out float zx, out float zy,
+ out long x1, out long y1,
+ out long x2, out long y2);
+
+ /**
+ * void resizeZoomRegion:
+ * Resizes the specified zoom region on the target display.
+ * @zoom_region: the index of the affected zoom region.
+ * @x1: the minimum X coordinate of the zoomed area bounding box
+ * @x2: the maximum X coordinate of the zoomed area bounding box
+ * @y1: the minimum Y coordinate of the zoomed area bounding box
+ * @y2: the maximum Y coordinate of the zoomed area bounding box
+ **/
+ oneway void resizeZoomRegion (in short zoom_region,
+ in long x1, in long y1,
+ in long x2, in long y2);
+
+ /**
+ * void destroyZoomRegion:
+ * Remove the specified zoom region from the magnifier.
+ **/
+ oneway void destroyZoomRegion (in short zoom_region);
+
+ /**
+ * void clearAllZoomRegions:
+ * Clears and destroys all currently defined zoom regions.
+ **/
+ void clearAllZoomRegions ();
/**
- * void exit:
+ * void exit:
* Unmap the current magnifier from the display.
**/
void exit ();
}
void
-magnifier_set_roi(int x, int y, int w, int h)
+magnifier_set_roi(int zoom_region, int x, int y, int w, int h)
{
Accessibility_Magnifier magnifier = get_magnifier();
if (magnifier)
Accessibility_Magnifier_setROI (magnifier,
- (const CORBA_long) x,
- (const CORBA_long) y,
- (const CORBA_long) x+w,
- (const CORBA_long) y+h,
- &ev);
+ (const CORBA_short) zoom_region,
+ (const CORBA_long) x,
+ (const CORBA_long) y,
+ (const CORBA_long) x+w,
+ (const CORBA_long) y+h,
+ &ev);
}
void
-magnifier_set_magnification (float mag_factor)
+magnifier_set_magnification (int zoom_region, float mag_factor_x, float mag_factor_y)
{
Accessibility_Magnifier magnifier = get_magnifier();
if (magnifier)
- Accessibility_Magnifier__set_MagFactor (magnifier,
- (const CORBA_short)
- ((short) mag_factor),
- &ev);
+ Accessibility_Magnifier_setMagFactor (magnifier,
+ (const CORBA_short) zoom_region,
+ ((CORBA_float) mag_factor_x),
+ ((CORBA_float) mag_factor_y),
+ &ev);
}
#endif /* __cplusplus */
Accessibility_Magnifier get_magnifier(void);
-void magnifier_set_roi (int x1, int y1, int x2, int y2);
-void magnifier_set_magnification (float mag_factor);
+void magnifier_set_roi (int zoom_region, int x1, int y1, int x2, int y2);
+void magnifier_set_magnification (int zoom_region, float mag_factor_x, float mag_factor_y);
#ifdef __cplusplus
}
else {
printf ("setting mag factor to %f\n", (float) atof (argv[1]));
- magnifier_set_magnification ((float) atof (argv[1]));
+ magnifier_set_magnification (0, (float) atof (argv[1]),
+ (float) atof (argv[1]));
}
sleep (4);
return 0;
}
void
-magnifier_set_roi(int x, int y, int w, int h)
+magnifier_set_roi(int zoom_region, int x, int y, int w, int h)
{
Accessibility_Magnifier magnifier = get_magnifier();
if (magnifier)
Accessibility_Magnifier_setROI (magnifier,
+ (const CORBA_short) zoom_region,
(const CORBA_long) x,
(const CORBA_long) y,
(const CORBA_long) x+w,
}
void
-magnifier_set_magnification (float mag_factor)
+magnifier_set_magnification (int zoom_region, float mag_factor_x, float mag_factor_y)
{
Accessibility_Magnifier magnifier = get_magnifier();
if (magnifier)
- Accessibility_Magnifier__set_MagFactor (magnifier,
- (const CORBA_short)
- ((short) mag_factor),
- &ev);
+ Accessibility_Magnifier_setMagFactor (magnifier,
+ (const CORBA_short) zoom_region,
+ (const CORBA_float) mag_factor_x,
+ (const CORBA_float) mag_factor_y,
+ &ev);
}
type = atoi((char*)&msg[1]);
switch (type){
case FACTOR :
- old_factor = data->factor;
- data->factor = get_num(msg);
- printf("FACTOR = %d\n",data->factor);
+ old_factor_x = data->factor_x;
+ data->factor_x = get_num(msg);
+ old_factor_y = data->factor_y;
+ data->factor_y = get_num(msg);
+ printf("FACTOR = %d\n",data->factor_x);
break;
case CONTRAST :
data->contrast = get_num(msg);
DisplayHeight(mag_data->target_display,screen_num),
0,
0,
- mag_data->factor,
- mag_data->factor,
+ mag_data->factor_x,
+ mag_data->factor_y,
GDK_INTERP_NEAREST);
gdk_pixbuf_render_to_drawable (scaled_image,
total_width = DisplayWidth (mag_data->source_display,screen_num);
total_height = DisplayHeight(mag_data->source_display,screen_num);
- x = mag_data->center.x - mag_data->mag_width/mag_data->factor/2;
- y = mag_data->center.y - mag_data->mag_height/mag_data->factor/2;
+ x = mag_data->center.x - mag_data->mag_width/mag_data->factor_x/2;
+ y = mag_data->center.y - mag_data->mag_height/mag_data->factor_y/2;
- if(mag_data->center.x < mag_data->mag_width/mag_data->factor/2)
+ if(mag_data->center.x < mag_data->mag_width/mag_data->factor_x/2)
x = 0;
- if(mag_data->center.x > (total_width - mag_data->mag_width/mag_data->factor/2))
- x = total_width - mag_data->mag_width/mag_data->factor;
- if(mag_data->center.y < mag_data->mag_height/mag_data->factor/2)
+ if(mag_data->center.x > (total_width - mag_data->mag_width/mag_data->factor_x/2))
+ x = total_width - mag_data->mag_width/mag_data->factor_x;
+ if(mag_data->center.y < mag_data->mag_height/mag_data->factor_y/2)
y = 0;
- if(mag_data->center.y > (total_height - mag_data->mag_height/mag_data->factor/2))
- y = total_height - mag_data->mag_height/mag_data->factor;
+ if(mag_data->center.y > (total_height - mag_data->mag_height/mag_data->factor_y/2))
+ y = total_height - mag_data->mag_height/mag_data->factor_y;
if(x < 0)
x = 0;
if(y < 0)
total_height,
total_width);
*/
- if(mag_data->factor != old_factor){
+ if(mag_data->factor_x != old_factor_x || mag_data->factor_y != old_factor_y){
g_object_unref((GObject *)image);
image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
- DisplayWidth (mag_data->target_display,screen_num)/mag_data->factor,
- DisplayHeight(mag_data->target_display,screen_num)/mag_data->factor);
+ DisplayWidth (mag_data->target_display,screen_num)/mag_data->factor_x,
+ DisplayHeight(mag_data->target_display,screen_num)/mag_data->factor_y);
/* yes, use target display above, since the size of the area grabbed depends on the target */
- old_factor = mag_data->factor;
+ old_factor_x = mag_data->factor_x;
+ old_factor_y = mag_data->factor_y;
}
get_root_image(image_root_window,
image,
};
static void
-rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap)
+rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap,
+ MagnifierData *mag_data)
{
- int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
- int bank=5; /* default fallback converter */
- Visual *v = cmap->visual;
-
+ int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
+ int bank=5; /* default fallback converter */
+ Visual *v = cmap->visual;
+ if (mag_data->fast_rgb_convert)
+ {
switch (v->class) {
/* I assume this is right for static & greyscale's too? */
case StaticGray:
/* always use the slow version */
break;
}
+ }
if (bank==5) {
convert_real_slow(image, pixels, rowstride, cmap, alpha);
}
}
-
-
-void get_root_image(Window src,GdkPixbuf *dest, int src_x, int src_y, MagnifierData *mag_data) {
+void get_root_image(Window src, GdkPixbuf *dest, int src_x, int src_y, MagnifierData *mag_data) {
XImage *image;
- int width = mag_data->mag_width/mag_data->factor;
- int height = mag_data->mag_height/mag_data->factor;
+ int width = mag_data->mag_width/mag_data->factor_x;
+ int height = mag_data->mag_height/mag_data->factor_y;
/* Get Image in ZPixmap format (packed bits). */
image = XGetImage (mag_data->source_display, src, src_x, src_y,
rgbconvert (image, gdk_pixbuf_get_pixels(dest),
gdk_pixbuf_get_rowstride(dest),
gdk_pixbuf_get_has_alpha(dest),
- x_cmap);
+ x_cmap,
+ mag_data);
+
+ /* would like to use GDK routine, but since we don't have multi-head
+ yet, we have to use X */
+
XDestroyImage (image);
}
GdkPixbuf* scaled_image;
Window image_root_window;
int screen_num;
-int old_factor;
+int old_factor_x;
+int old_factor_y;
xlib_colormap * x_cmap;
typedef struct _MagnifierData {
int mag_width;
int mag_height;
- int factor;
+ int factor_x;
+ int factor_y;
point center;
int follow_mouse;
int color_inverted;
+ int fast_rgb_convert;
int contrast;
GtkWidget *output_window;
void *source_display;
struct sockaddr_un mag_server = { AF_UNIX , "/tmp/magnifier_socket" };
+typedef struct {
+ GdkRectangle extents;
+ GdkRectangle roi;
+ float zoom_x;
+ float zoom_y;
+ int contrast;
+ gboolean is_managed;
+ gboolean is_dirty;
+} ZoomRegionData;
+
typedef struct {
gchar *target_display;
gchar *source_display;
int mouse_follow;
int invert_image;
float zoom_factor;
- int refresh_time;
+ int min_refresh_time;
int no_bonobo;
+ int fast_cmap_convert;
+ GList *zoom_regions;
} MagnifierOptions;
static MagnifierOptions global_options = { ":0.0",
0,
2.0,
200,
+ 0,
0
};
{"horizontal", 'h', POPT_ARG_NONE, &global_options.horizontal_split, 'h', "split screen horizontally (if target display = source display)", NULL},
{"dual-head", 'd', POPT_ARG_NONE, &global_options.dual_head, 'd', "dual-head display mode (maps magnifier to second display)", NULL},
{"mouse follow", 'm', POPT_ARG_NONE, &global_options.mouse_follow, 'm', "track mouse movements", NULL},
- {"refresh time", 'r', POPT_ARG_NONE, &global_options.refresh_time, 'r', "refresh time for mouse follow and idle, in ms", NULL},
+ {"refresh time", 'r', POPT_ARG_NONE, &global_options.min_refresh_time, 'r', "minimum refresh time for mouse follow and idle, in ms", NULL},
{"zoom (scale) factor", 'z', POPT_ARG_FLOAT, &global_options.zoom_factor, 'z', "zoom (scale) factor used to magnify source display", NULL},
/* {"invert image", 'i', POPT_ARG_NONE, &global_options.invert_image, 'i', "invert the image colormap", NULL}, */
+ {"fast-colormap-conversion", 'c', POPT_ARG_NONE, &global_options.fast_cmap_convert, 'c', "use faster colormap conversion algorithm (fails for 6 bit color)", NULL},
{"no-bonobo", '\0', POPT_ARG_NONE, &global_options.no_bonobo, '\0', "don't use bonobo for controls, use sockets", NULL},
{NULL, 0, 0, NULL, 0, 0}
};
global_options.mouse_follow;
magnifier->mag_data->color_inverted =
global_options.invert_image;
- magnifier->mag_data->factor =
+ magnifier->mag_data->factor_x =
(int) global_options.zoom_factor;
-
- /* TODO: enable fractional magnifications ? */
+ magnifier->mag_data->factor_y =
+ (int) global_options.zoom_factor;
+ /* TODO: enable fractional magnifications ? */
if (global_options.target_display) {
snprintf (env_string, (size_t) (ENV_STRING_MAX_SIZE-1), "DISPLAY=%s", global_options.target_display);
putenv (env_string);
gdk_window_set_functions(window->window, 0);
gdk_window_raise(window->window);
- gtk_timeout_add(global_options.refresh_time, display_image, magnifier->mag_data);
+ gtk_timeout_add(global_options.min_refresh_time, display_image, magnifier->mag_data);
obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1";
static void
impl_magnifier_set_roi (PortableServer_Servant servant,
+ const CORBA_short zoom_region,
const CORBA_long x1,
const CORBA_long y1,
const CORBA_long x2,
static void
impl_magnifier_set_mag_factor (PortableServer_Servant servant,
- const CORBA_float mag_factor,
+ const CORBA_short zoom_region,
+ const CORBA_float mag_factor_x,
+ const CORBA_float mag_factor_y,
CORBA_Environment *ev)
{
Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
- magnifier->mag_data->factor = (float) mag_factor;
+ magnifier->mag_data->factor_x = (float) mag_factor_x;
+ magnifier->mag_data->factor_y = (float) mag_factor_y;
+}
+
+static void
+impl_magnifier_mark_dirty (PortableServer_Servant servant,
+ const CORBA_short zoom_region,
+ CORBA_Environment *ev)
+{
+ Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
+}
+
+static void
+impl_magnifier_mark_unmanaged (PortableServer_Servant servant,
+ const CORBA_short zoom_region,
+ CORBA_Environment *ev)
+{
+ Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
+}
+
+static CORBA_short
+impl_magnifier_create_zoom_region (PortableServer_Servant servant,
+ const CORBA_float zx,
+ const CORBA_float zy,
+ const CORBA_long x1,
+ const CORBA_long y1,
+ const CORBA_long x2,
+ const CORBA_long y2,
+ CORBA_Environment *ev)
+{
+ Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
+ return -1;
+}
+
+static CORBA_boolean
+impl_magnifier_get_zoom_region_params (PortableServer_Servant _servant,
+ const CORBA_short zoom_region,
+ CORBA_float * zx,
+ CORBA_float * zy, CORBA_long * x1,
+ CORBA_long * y1, CORBA_long * x2,
+ CORBA_long * y2,
+ CORBA_Environment * ev)
+{
+ return CORBA_FALSE;
+}
+
+static void
+impl_magnifier_resize_zoom_region (PortableServer_Servant _servant,
+ const CORBA_short zoom_region,
+ const CORBA_long x1, const CORBA_long y1,
+ const CORBA_long x2, const CORBA_long y2,
+ CORBA_Environment * ev)
+{
+}
+
+static void
+impl_magnifier_destroy_zoom_region (PortableServer_Servant _servant,
+ const CORBA_short zoom_region,
+ CORBA_Environment * ev)
+{
+}
+
+static void
+impl_magnifier_clear_all_zoom_regions (PortableServer_Servant _servant,
+ CORBA_Environment * ev)
+{
}
static void
epv->_set_SourceDisplay = impl_magnifier_set_source_display;
epv->_set_TargetDisplay = impl_magnifier_set_target_display;
epv->setROI = impl_magnifier_set_roi;
- epv->_set_MagFactor = impl_magnifier_set_mag_factor;
+ epv->setMagFactor = impl_magnifier_set_mag_factor;
+ epv->markDirty = impl_magnifier_mark_dirty;
+ epv->markUnmanaged = impl_magnifier_mark_unmanaged;
+ epv->createZoomRegion = impl_magnifier_create_zoom_region;
+ epv->getZoomRegionParams = impl_magnifier_get_zoom_region_params;
+ epv->resizeZoomRegion = impl_magnifier_resize_zoom_region;
+ epv->destroyZoomRegion = impl_magnifier_destroy_zoom_region;
+ epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
epv->exit = impl_magnifier_exit;
}
magnifier_init (Magnifier *magnifier)
{
magnifier->mag_data = (MagnifierData *) g_new0 (MagnifierData, 1);
- magnifier->mag_data->factor = 2;
+ magnifier->mag_data->factor_x = 2;
+ magnifier->mag_data->factor_y = 2;
magnifier->mag_data->contrast = 0;
magnifier->mag_data->color_inverted = FALSE;
+ magnifier->mag_data->fast_rgb_convert = FALSE;
magnifier->mag_data->center.x = 0;
magnifier->mag_data->center.y = 0;
}