*
* (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
*
- * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2003 Sun Microsystems Inc.,
* Copyright 2001, 2002 Ximian, Inc.
*
* This library is free software; you can redistribute it and/or
static unsigned int mouse_button_mask =
Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
static unsigned int key_modifier_mask =
- Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | LockMask | ControlMask;
+ Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | LockMask | ControlMask | SPI_KEYMASK_NUMLOCK;
+static unsigned int _numlock_physical_mask = Mod2Mask; /* a guess, will be reset */
static GQuark spi_dec_private_quark = 0;
DEControllerPrivateData *priv =
g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
#ifdef SPI_XKB_DEBUG
- if (priv->xkb_latch_mask) fprintf (stderr, "unlatch pending! %x\n", mask);
+ if (priv->xkb_latch_mask) fprintf (stderr, "unlatch pending! %x\n",
+ priv->xkb_latch_mask);
#endif
priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask;
}
+static void
+spi_dec_clear_unlatch_pending (SpiDEController *controller)
+{
+ DEControllerPrivateData *priv =
+ g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+ priv->xkb_latch_mask = 0;
+}
+
static gboolean
spi_dec_button_update_and_emit (SpiDEController *controller,
guint mask_return)
fprintf (stderr, "MODIFIER CHANGE EVENT! %x to %x\n",
prev_mask, current_mask);
#endif
+
+ /* set bits for the virtual modifiers like NUMLOCK */
+ if (prev_mask & _numlock_physical_mask)
+ prev_mask |= SPI_KEYMASK_NUMLOCK;
+ if (current_mask & _numlock_physical_mask)
+ current_mask |= SPI_KEYMASK_NUMLOCK;
+
e.type = "keyboard:modifiers";
e.source = BONOBO_OBJREF (controller->registry->desktop);
e.detail1 = prev_mask & key_modifier_mask;
}
}
+#ifdef WE_NEED_UGRAB_MOUSE
static int
spi_dec_ungrab_mouse (gpointer data)
{
}
return FALSE;
}
+#endif
static void
spi_dec_init_mouse_listener (SpiRegistry *registry)
if (display)
{
- XGrabButton (display, AnyButton, AnyModifier,
+ if (XGrabButton (display, AnyButton, AnyModifier,
gdk_x11_get_default_root_xwindow (),
True, ButtonPressMask | ButtonReleaseMask,
- GrabModeSync, GrabModeAsync, None, None);
+ GrabModeSync, GrabModeAsync, None, None) != Success)
+ fprintf (stderr, "WARNING: could not grab mouse buttons!\n");
XSync (display, False);
#ifdef SPI_DEBUG
fprintf (stderr, "mouse buttons grabbed\n");
}
}
+/**
+ * Eventually we can use this to make the marshalling of mask types
+ * more sane, but for now we just use this to detect
+ * the use of 'virtual' masks such as Mumlock and convert them to
+ * system-specific mask values (i.e. ModMask).
+ *
+ **/
+static Accessibility_ControllerEventMask
+spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
+{
+ DEControllerPrivateData *priv;
+
+ if (mask == SPI_KEYMASK_NUMLOCK) {
+ mask = _numlock_physical_mask;
+ }
+ return mask;
+}
+
static DEControllerKeyListener *
spi_dec_key_listener_new (CORBA_Object l,
const Accessibility_KeySet *keys,
key_listener->listener.object = bonobo_object_dup_ref (l, ev);
key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
key_listener->keys = ORBit_copy_value (keys, TC_Accessibility_KeySet);
- key_listener->mask = mask;
+ key_listener->mask = spi_dec_translate_mask (mask);
key_listener->listener.typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
if (mode)
key_listener->mode = ORBit_copy_value (mode, TC_Accessibility_EventListenerMode);
int button = xbutton_event->button;
unsigned int mouse_button_state = xbutton_event->state;
-
+
switch (button)
{
case 1:
/* if client wants to consume this event, and XKB latch state was
* unset by this button event, we reset it
*/
- if (is_consumed && (xkb_mod_unlatch_occurred))
+ if (is_consumed && xkb_mod_unlatch_occurred)
spi_dec_set_unlatch_pending (controller, mouse_mask_state);
XAllowEvents (spi_get_display (),
&= ~(XkbAX_StickyKeysFBMask);
XkbChangeControls (display, priv->xkb_desc, &changes);
}
+ /* TODO: account for lock as well as latch */
XkbLatchModifiers (display,
XkbUseCoreKbd,
priv->pending_xkb_mod_relatch_mask,
g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
/* FIXME: should check for extension first! */
XTestGrabControl (spi_get_display (), True);
- priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
/* calls to device-specific implementations and routines go here */
/* register with: keyboard hardware code handler */
&priv->xkb_base_error_code, NULL, NULL);
if (priv->have_xkb)
{
+ priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
XkbSelectEvents (spi_get_display (),
XkbUseCoreKbd,
XkbStateNotifyMask, XkbStateNotifyMask);
+ _numlock_physical_mask = XkbKeysymToModifiers (spi_get_display (),
+ XK_Num_Lock);
}
+
gdk_window_add_filter (NULL, global_filter_fn, controller);
gdk_window_set_events (gdk_get_default_root_window (),
DEControllerKeyListener *listener,
CORBA_boolean is_system_global)
{
- if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFFFF)) &&
+ if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFF)) &&
spi_key_set_contains_key (listener->keys, key_event) &&
spi_eventtype_seq_contains_event (listener->listener.typeseq, key_event) &&
(is_system_global == listener->mode->global))
Accessibility_DeviceEvent key_event;
KeySym keysym;
const int cbuf_bytes = 20;
- char cbuf [cbuf_bytes];
-
- keysym = XLookupKeysym (x_key_event, 0);
+ char cbuf [cbuf_bytes+1];
+ int nbytes;
+
+ nbytes = XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL);
key_event.id = (CORBA_long)(keysym);
key_event.hw_code = (CORBA_short) x_key_event->keycode;
if (((XEvent *) x_key_event)->type == KeyPress)
{
- key_event.type = Accessibility_KEY_PRESSED;
+ key_event.type = Accessibility_KEY_PRESSED_EVENT;
}
else
{
- key_event.type = Accessibility_KEY_RELEASED;
+ key_event.type = Accessibility_KEY_RELEASED_EVENT;
}
key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
key_event.is_text = CORBA_FALSE;
key_event.event_string = CORBA_string_dup ("space");
break;
case XK_Tab:
-#ifdef SPI_KEYEVENT_DEBUG
- fprintf(stderr, "Tab\n");
-#endif
key_event.event_string = CORBA_string_dup ("Tab");
break;
case XK_BackSpace:
key_event.event_string = CORBA_string_dup ("Right");
break;
default:
- if (XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL) > 0)
+ if (nbytes > 0)
{
+ gunichar c;
+ cbuf[nbytes] = '\0'; /* OK since length is cbuf_bytes+1 */
key_event.event_string = CORBA_string_dup (cbuf);
- if (isgraph (keysym))
+ c = g_utf8_get_char_validated (cbuf, nbytes);
+ if ((c > 0) && g_unichar_isprint (c))
{
- key_event.is_text = CORBA_TRUE; /* FIXME: incorrect for some composed chars? */
+ key_event.is_text = CORBA_TRUE;
+ /* incorrect for some composed chars? */
}
}
else
key_event.timestamp = (CORBA_unsigned_long) x_key_event->time;
#ifdef SPI_KEYEVENT_DEBUG
fprintf (stderr,
- "Key %lu pressed (%c), modifiers %d\n",
- (unsigned long) keysym,
- keysym ? (int) keysym : '*',
- (int) x_key_event->state);
+ "Key %lu pressed (%c), modifiers %d; string=%s [%x] %s\n",
+ (unsigned long) keysym,
+ keysym ? (int) keysym : '*',
+ (int) x_key_event->state,
+ key_event.event_string,
+ key_event.event_string[0],
+ (key_event.is_text == CORBA_TRUE) ? "(text)" : "(not text)");
#endif
#ifdef SPI_DEBUG
fprintf (stderr, "%s%c",
next = l->next;
re_issue_grab = recv &&
-/* (recv->type == Accessibility_KEY_RELEASED) && - (?) */
(recv->modifiers & grab_mask->mod_mask) &&
(grab_mask->key_val == keycode_for_keysym (recv->id));
{
SpiDEController *controller =
SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
- DEControllerPrivateData *priv;
long key_synth_code;
- unsigned int slow_keys_delay;
- unsigned int press_time;
- unsigned int release_time;
+ KeySym keysym;
#ifdef SPI_DEBUG
fprintf (stderr, "synthesizing keystroke %ld, type %d\n",
{
DBG (-1, g_warning ("Error emitting keystroke"));
}
+ if (synth_type == Accessibility_KEY_SYM) {
+ keysym = keycode;
+ }
+ else {
+ keysym = XkbKeycodeToKeysym (spi_get_display (), keycode, 0, 0);
+ }
+ if (XkbKeysymToModifiers (spi_get_display (), keysym) == 0)
+ {
+ spi_dec_clear_unlatch_pending (controller);
+ }
}
/* Accessibility::DEController::generateMouseEvent */
const CORBA_char *eventName,
CORBA_Environment *ev)
{
- int button;
+ int button = 0;
gboolean error = FALSE;
Display *display = spi_get_display ();
#ifdef SPI_DEBUG
case '3':
button = 3;
break;
+ case '4':
+ button = 4;
+ break;
+ case '5':
+ button = 5;
+ break;
default:
error = TRUE;
}
device_event_controller->mouse_listeners = NULL;
device_event_controller->keygrabs_list = NULL;
- /*
- * TODO: fixme, this module makes the foolish assumptions that
- * registryd uses the same display as the apps, and that the
- * DISPLAY environment variable is set.
- */
- gdk_init (NULL, NULL);
-
private = g_new0 (DEControllerPrivateData, 1);
gettimeofday (&private->last_press_time, NULL);
gettimeofday (&private->last_release_time, NULL);
{
SpiDEController *retval = g_object_new (
SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
- DEControllerPrivateData *private;
retval->registry = SPI_REGISTRY (bonobo_object_ref (
BONOBO_OBJECT (registry)));
BONOBO_TYPE_FUNC_FULL (SpiDEController,
Accessibility_DeviceEventController,
PARENT_TYPE,
- spi_device_event_controller);
+ spi_device_event_controller)