X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=registryd%2Fdeviceeventcontroller.c;h=609deeac759a3a41476bc5a481a911d03d77c655;hb=5e9de4f03f0c4406e3479d50a012901e87642210;hp=8fe64e4536ed372fe4690610a2486e5d420429aa;hpb=306430033b38ba2dad70cd93964abbf7803f9d72;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 8fe64e4..609deea 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -1,8 +1,8 @@ -/* - * AT-SPI - Assistive Technology Service Provider Interface +/* AT-SPI - Assistive Technology Service Provider Interface + * * (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 @@ -26,12 +26,13 @@ #include #undef SPI_XKB_DEBUG -#define SPI_DEBUG +#undef SPI_DEBUG #undef SPI_KEYEVENT_DEBUG #include #include #include +#include #include #include @@ -59,7 +60,8 @@ static unsigned int mouse_mask_state = 0; 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; @@ -95,17 +97,17 @@ typedef struct { } DEControllerKeyListener; typedef struct { - unsigned int last_press_keycode; - unsigned int last_release_keycode; - struct timeval last_press_time; - struct timeval last_release_time; - int have_xkb; - int xkb_major_extension_opcode; - int xkb_base_event_code; - int xkb_base_error_code; - unsigned int xkb_latch_mask; - unsigned int pending_xkb_mod_relatch_mask; - XkbDescPtr xkb_desc; + unsigned int last_press_keycode; + unsigned int last_release_keycode; + struct timeval last_press_time; + struct timeval last_release_time; + int have_xkb; + int xkb_major_extension_opcode; + int xkb_base_event_code; + int xkb_base_error_code; + unsigned int xkb_latch_mask; + unsigned int pending_xkb_mod_relatch_mask; + XkbDescPtr xkb_desc; } DEControllerPrivateData; static void spi_controller_register_with_devices (SpiDEController *controller); @@ -179,128 +181,262 @@ spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2) } } -static gint poll_count = 0; - +static void +spi_dec_set_unlatch_pending (SpiDEController *controller, unsigned mask) +{ + 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", + 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_poll_mouse_moved (gpointer data) +spi_dec_button_update_and_emit (SpiDEController *controller, + guint mask_return) { - SpiRegistry *registry = SPI_REGISTRY (data); - SpiDEController *controller = registry->de_controller; CORBA_Environment ev; Accessibility_Event e; Accessibility_DeviceEvent mouse_e; - Window root_return, child_return; - int win_x_return,win_y_return; - int x, y; - int poll_count_modulus = 10; - unsigned int mask_return; gchar event_name[24]; - gboolean is_consumed; - Display *display = spi_get_display (); + gboolean is_consumed = FALSE; - if (display != NULL) - XQueryPointer(display, DefaultRootWindow (display), - &root_return, &child_return, - &x, &y, - &win_x_return, &win_y_return, &mask_return); - - if (mask_return != mouse_mask_state) { - if ((mask_return & mouse_button_mask) != - (mouse_mask_state & mouse_button_mask)) { - int button_number = 0; - if (!(mask_return & Button1Mask) && - (mouse_mask_state & Button1Mask)) { - button_number = 1; - } else if (!(mask_return & Button2Mask) && - (mouse_mask_state & Button2Mask)) { - button_number = 2; - } else if (!(mask_return & Button3Mask) && - (mouse_mask_state & Button3Mask)) { - button_number = 3; - } else if (!(mask_return & Button4Mask) && - (mouse_mask_state & Button1Mask)) { - button_number = 4; - } else if (!(mask_return & Button5Mask) && - (mouse_mask_state & Button5Mask)) { - button_number = 5; - } - if (button_number) { + if ((mask_return & mouse_button_mask) != + (mouse_mask_state & mouse_button_mask)) + { + int button_number = 0; + gboolean is_down = False; + + if (!(mask_return & Button1Mask) && + (mouse_mask_state & Button1Mask)) + { + mouse_mask_state &= ~Button1Mask; + button_number = 1; + } + else if ((mask_return & Button1Mask) && + !(mouse_mask_state & Button1Mask)) + { + mouse_mask_state |= Button1Mask; + button_number = 1; + is_down = True; + } + else if (!(mask_return & Button2Mask) && + (mouse_mask_state & Button2Mask)) + { + mouse_mask_state &= ~Button2Mask; + button_number = 2; + } + else if ((mask_return & Button2Mask) && + !(mouse_mask_state & Button2Mask)) + { + mouse_mask_state |= Button2Mask; + button_number = 2; + is_down = True; + } + else if (!(mask_return & Button3Mask) && + (mouse_mask_state & Button3Mask)) + { + mouse_mask_state &= ~Button3Mask; + button_number = 3; + } + else if ((mask_return & Button3Mask) && + !(mouse_mask_state & Button3Mask)) + { + mouse_mask_state |= Button3Mask; + button_number = 3; + is_down = True; + } + else if (!(mask_return & Button4Mask) && + (mouse_mask_state & Button4Mask)) + { + mouse_mask_state &= ~Button4Mask; + button_number = 4; + } + else if ((mask_return & Button4Mask) && + !(mouse_mask_state & Button4Mask)) + { + mouse_mask_state |= Button4Mask; + button_number = 4; + is_down = True; + } + else if (!(mask_return & Button5Mask) && + (mouse_mask_state & Button5Mask)) + { + mouse_mask_state &= ~Button5Mask; + button_number = 5; + } + else if ((mask_return & Button5Mask) && + !(mouse_mask_state & Button5Mask)) + { + mouse_mask_state |= Button5Mask; + button_number = 5; + is_down = True; + } + if (button_number) { #ifdef SPI_DEBUG - fprintf (stderr, "Button %d Released\n", - button_number); + fprintf (stderr, "Button %d %s\n", + button_number, (is_down) ? "Pressed" : "Released"); #endif - snprintf (event_name, 22, "mouse:button:%dr", button_number); - /* TODO: distinguish between physical and - * logical buttons - */ - mouse_e.type = Accessibility_BUTTON_RELEASED_EVENT; - mouse_e.id = button_number; - mouse_e.hw_code = button_number; - mouse_e.modifiers = (CORBA_unsigned_short) - mouse_mask_state; - mouse_e.timestamp = 0; - mouse_e.event_string = ""; - mouse_e.is_text = CORBA_FALSE; - is_consumed = - spi_controller_notify_mouselisteners (controller, - &mouse_e, - &ev); - e.type = event_name; - e.source = BONOBO_OBJREF (registry->desktop); - e.detail1 = last_mouse_pos->x; - e.detail2 = last_mouse_pos->y; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - if (!is_consumed) - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), - &e, - &ev); - } + snprintf (event_name, 22, "mouse:button:%d%c", button_number, + (is_down) ? 'p' : 'r'); + /* TODO: distinguish between physical and + * logical buttons + */ + mouse_e.type = (is_down) ? + Accessibility_BUTTON_PRESSED_EVENT : + Accessibility_BUTTON_RELEASED_EVENT; + mouse_e.id = button_number; + mouse_e.hw_code = button_number; + mouse_e.modifiers = (CORBA_unsigned_short) mouse_mask_state; + mouse_e.timestamp = 0; + mouse_e.event_string = ""; + mouse_e.is_text = CORBA_FALSE; + is_consumed = + spi_controller_notify_mouselisteners (controller, + &mouse_e, + &ev); + e.type = event_name; + e.source = BONOBO_OBJREF (controller->registry->desktop); + e.detail1 = last_mouse_pos->x; + e.detail2 = last_mouse_pos->y; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + if (!is_consumed) + { + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), + &e, + &ev); } - if ((mask_return & key_modifier_mask) != - (mouse_mask_state & key_modifier_mask)) { -#ifdef SPI_DEBUG - fprintf (stderr, "MODIFIER CHANGE EVENT!\n"); + else + spi_dec_set_unlatch_pending (controller, mask_return); + } + return TRUE; + } + else + { + return FALSE; + } +} + + +static guint +spi_dec_mouse_check (SpiDEController *controller, + int *x, int *y, gboolean *moved) +{ + Accessibility_Event e; + CORBA_Environment ev; + int win_x_return,win_y_return; + unsigned int mask_return; + Window root_return, child_return; + Display *display = spi_get_display (); + + if (display != NULL) + XQueryPointer(display, DefaultRootWindow (display), + &root_return, &child_return, + x, y, + &win_x_return, &win_y_return, &mask_return); + /* + * Since many clients grab the pointer, and X goes an automatic + * pointer grab on mouse-down, we often must detect mouse button events + * by polling rather than via a button grab. + * The while loop (rather than if) is used since it's possible that + * multiple buttons have changed state since we last checked. + */ + if (mask_return != mouse_mask_state) + { + while (spi_dec_button_update_and_emit (controller, mask_return)); + } + + if (*x != last_mouse_pos->x || *y != last_mouse_pos->y) + { + e.type = "mouse:abs"; + e.source = BONOBO_OBJREF (controller->registry->desktop); + e.detail1 = *x; + e.detail2 = *y; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), + &e, + &ev); + e.type = "mouse:rel"; + e.source = BONOBO_OBJREF (controller->registry->desktop); + e.detail1 = *x - last_mouse_pos->x; + e.detail2 = *y - last_mouse_pos->y; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + last_mouse_pos->x = *x; + last_mouse_pos->y = *y; + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), + &e, + &ev); + *moved = True; + } + else + { + *moved = False; + } + + return mask_return; +} + +static void +spi_dec_emit_modifier_event (SpiDEController *controller, guint prev_mask, + guint current_mask) +{ + Accessibility_Event e; + CORBA_Environment ev; + +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "MODIFIER CHANGE EVENT! %x to %x\n", + prev_mask, current_mask); #endif - e.type = "keyboard:modifiers"; - e.source = BONOBO_OBJREF (registry->desktop); - e.detail1 = mouse_mask_state; - e.detail2 = mask_return; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), - &e, - &ev); - } - mouse_mask_state = mask_return; - } - if (poll_count++ == poll_count_modulus) { - poll_count = 0; - e.type = "mouse:abs"; - e.source = BONOBO_OBJREF (registry->desktop); - e.detail1 = x; - e.detail2 = y; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), - &e, - &ev); - } - if (x != last_mouse_pos->x || y != last_mouse_pos->y) { - e.type = "mouse:rel"; - e.source = BONOBO_OBJREF (registry->desktop); - e.detail1 = x - last_mouse_pos->x; - e.detail2 = y - last_mouse_pos->y; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - last_mouse_pos->x = x; - last_mouse_pos->y = y; - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), - &e, - &ev); - return TRUE; - } - return FALSE; + + /* 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; + e.detail2 = current_mask & key_modifier_mask; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), + &e, + &ev); +} + +static gboolean +spi_dec_poll_mouse_moved (gpointer data) +{ + SpiRegistry *registry = SPI_REGISTRY (data); + SpiDEController *controller = registry->de_controller; + 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)) + { + spi_dec_emit_modifier_event (controller, mouse_mask_state, mask_return); + mouse_mask_state = mask_return; + } + + return moved; } static gboolean @@ -327,6 +463,7 @@ spi_dec_poll_mouse_moving (gpointer data) } } +#ifdef WE_NEED_UGRAB_MOUSE static int spi_dec_ungrab_mouse (gpointer data) { @@ -338,6 +475,7 @@ spi_dec_ungrab_mouse (gpointer data) } return FALSE; } +#endif static void spi_dec_init_mouse_listener (SpiRegistry *registry) @@ -347,10 +485,11 @@ 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"); @@ -358,6 +497,24 @@ spi_dec_init_mouse_listener (SpiRegistry *registry) } } +/** + * 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, @@ -370,7 +527,7 @@ spi_dec_key_listener_new (CORBA_Object l, 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); @@ -685,7 +842,6 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, gchar event_name[24]; gboolean is_consumed = FALSE; gboolean xkb_mod_unlatch_occurred; - DEControllerPrivateData *priv; XButtonEvent *xbutton_event = (XButtonEvent *) xevent; int button = xbutton_event->button; @@ -710,6 +866,7 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, mouse_button_state |= Button5Mask; break; } + last_mouse_pos->x = ((XButtonEvent *) xevent)->x_root; last_mouse_pos->y = ((XButtonEvent *) xevent)->y_root; @@ -732,18 +889,27 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, mouse_e.timestamp = (CORBA_unsigned_long) xbutton_event->time; mouse_e.event_string = ""; mouse_e.is_text = CORBA_FALSE; - is_consumed = spi_controller_notify_mouselisteners (controller, &mouse_e, &ev); - - e.type = CORBA_string_dup (event_name); - e.source = BONOBO_OBJREF (controller->registry->desktop); - e.detail1 = last_mouse_pos->x; - e.detail2 = last_mouse_pos->y; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), - &e, - &ev); + if ((mouse_button_state & mouse_button_mask) != + (mouse_mask_state & mouse_button_mask)) + { + if ((mouse_mask_state & key_modifier_mask) != + (mouse_button_state & key_modifier_mask)) + spi_dec_emit_modifier_event (controller, + mouse_mask_state, mouse_button_state); + mouse_mask_state = mouse_button_state; + is_consumed = + spi_controller_notify_mouselisteners (controller, &mouse_e, &ev); + e.type = CORBA_string_dup (event_name); + e.source = BONOBO_OBJREF (controller->registry->desktop); + e.detail1 = last_mouse_pos->x; + e.detail2 = last_mouse_pos->y; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), + &e, + &ev); + } xkb_mod_unlatch_occurred = (xevent->type == ButtonPress || xevent->type == ButtonRelease); @@ -752,10 +918,7 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, * unset by this button event, we reset it */ if (is_consumed && xkb_mod_unlatch_occurred) - { - priv = g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); - priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask; - } + spi_dec_set_unlatch_pending (controller, mouse_mask_state); XAllowEvents (spi_get_display (), (is_consumed) ? SyncPointer : ReplayPointer, @@ -785,12 +948,24 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) if (xevent->type == priv->xkb_base_event_code) { XkbAnyEvent * xkb_ev = (XkbAnyEvent *) xevent; + /* ugly but probably necessary...*/ + XSynchronize (spi_get_display (), TRUE); if (xkb_ev->xkb_type == XkbStateNotify) { XkbStateNotifyEvent *xkb_snev = (XkbStateNotifyEvent *) xkb_ev; - priv->xkb_latch_mask = xkb_snev->latched_mods; + /* check the mouse, to catch mouse events grabbed by + * another client; in case we should revert this XKB delatch + */ + if (!priv->pending_xkb_mod_relatch_mask) + { + int x, y; + gboolean moved; + spi_dec_mouse_check (controller, &x, &y, &moved); + } + /* we check again, since the previous call may have + changed this flag */ if (priv->pending_xkb_mod_relatch_mask) { unsigned int feedback_mask; @@ -811,6 +986,7 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) &= ~(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, @@ -828,9 +1004,14 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) #endif priv->pending_xkb_mod_relatch_mask = 0; } + else + { + priv->xkb_latch_mask = xkb_snev->latched_mods; + } } else DBG (2, g_warning ("XKB event %d\n", xkb_ev->xkb_type)); + XSynchronize (spi_get_display (), FALSE); } return GDK_FILTER_CONTINUE; @@ -856,8 +1037,8 @@ spi_controller_register_with_devices (SpiDEController *controller) { DEControllerPrivateData *priv = (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); - - priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd); + /* FIXME: should check for extension first! */ + XTestGrabControl (spi_get_display (), True); /* calls to device-specific implementations and routines go here */ /* register with: keyboard hardware code handler */ @@ -869,10 +1050,14 @@ spi_controller_register_with_devices (SpiDEController *controller) &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 (), @@ -969,7 +1154,7 @@ spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event, 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)) @@ -1070,18 +1255,19 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) 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; @@ -1091,9 +1277,6 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) 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: @@ -1166,12 +1349,16 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) 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 @@ -1183,10 +1370,13 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) 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", @@ -1224,7 +1414,6 @@ spi_controller_update_key_grabs (SpiDEController *controller, 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)); @@ -1648,9 +1837,7 @@ impl_generate_keyboard_event (PortableServer_Servant servant, SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant)); 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", @@ -1665,7 +1852,8 @@ impl_generate_keyboard_event (PortableServer_Servant servant, /* TODO: implement keystring mode also */ gdk_error_trap_push (); - + key_synth_code = keycode; + switch (synth_type) { case Accessibility_KEY_PRESS: @@ -1692,6 +1880,16 @@ impl_generate_keyboard_event (PortableServer_Servant servant, { 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 */ @@ -1702,7 +1900,7 @@ impl_generate_mouse_event (PortableServer_Servant servant, const CORBA_char *eventName, CORBA_Environment *ev) { - int button; + int button = 0; gboolean error = FALSE; Display *display = spi_get_display (); #ifdef SPI_DEBUG @@ -1724,6 +1922,12 @@ impl_generate_mouse_event (PortableServer_Servant servant, case '3': button = 3; break; + case '4': + button = 4; + break; + case '5': + button = 5; + break; default: error = TRUE; } @@ -1816,20 +2020,12 @@ spi_device_event_controller_init (SpiDEController *device_event_controller) 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); g_object_set_qdata (G_OBJECT (device_event_controller), spi_dec_private_quark, private); - spi_controller_register_with_devices (device_event_controller); } @@ -1868,7 +2064,6 @@ spi_device_event_controller_new (SpiRegistry *registry) { SpiDEController *retval = g_object_new ( SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL); - DEControllerPrivateData *private; retval->registry = SPI_REGISTRY (bonobo_object_ref ( BONOBO_OBJECT (registry))); @@ -1881,4 +2076,4 @@ spi_device_event_controller_new (SpiRegistry *registry) BONOBO_TYPE_FUNC_FULL (SpiDEController, Accessibility_DeviceEventController, PARENT_TYPE, - spi_device_event_controller); + spi_device_event_controller)