does XkbSetMap affect XTestFakeKeyEvent?

2012-10-24 Thread Daiki Ueno
Hi,

I'm currently looking into Caribou (an on-screen keyboard software)[1]
and found that its keysym replacement logic does not work reliably[2].

That code basically does the following:

(1) assign a keysym to some unused keycode (like keycode 246, which
XF86WLAN is assigned here) with XkbSetMap
(2) send key press event using XTestFakeKeyEvent to get the keysym typed

Is this supposed to work?  After (1), I could type the new keysym with
physical keyboard, but couldn't with XTestFakeKeyEvent.  If I change the
mapping with XChangeKeyboardMapping instead of XkbSetMap, it seems to
work with both physical and virtual keyboard.

I'm attaching a test program which changes keysym mapping on 'a' key
(keycode 38) on US keyboard and then send key press.

The original code can be found at:

http://git.gnome.org/browse/caribou/tree/libcaribou/xadapter.vala#n148
http://git.gnome.org/browse/at-spi2-core/tree/registryd/deviceeventcontroller.c#n286

Footnotes: 
[1]  http://live.gnome.org/Caribou
[2]  https://bugzilla.gnome.org/show_bug.cgi?id=673547

Regards,
-- 
Daiki Ueno
/* This program does:
 *
 * (1) change keysym mapping 'a' -> 'b'
 * (2) wait a second to allow typing 'a' from physical keyboard
 * (3) emit key press/release event, with XTestFakeKeyEvent
 * (4) change keysym mapping 'b' -> 'a'
 */

#include 
#include 
#include 
#include 

Display *display;
XkbDescRec *xkb;

static Bool
replace_keycode (unsigned int keycode, unsigned int *keysym)
{
  unsigned int offset;
  XkbMapChangesRec changes;
  XkbChangesRec _changes;
  unsigned int old_keysym;
  Bool retval;

  if (xkb->min_key_code > keycode ||
  keycode > xkb->max_key_code)
return False;

  if (keysym == NULL)
return False;

  offset = xkb->map->key_sym_map[keycode].offset;
  old_keysym = xkb->map->syms[offset];
  xkb->map->syms[offset] = *keysym;

#if USE_XKB
  changes.changed = XkbKeySymsMask;
  changes.first_key_sym = keycode;
  changes.num_key_syms = xkb->map->key_sym_map[keycode].width;

  XkbChangeMap (display, xkb, &changes);
  XSync (display, False);
#else
  XChangeKeyboardMapping (display,
  keycode,
  xkb->map->key_sym_map[keycode].width,
  &xkb->map->syms[offset],
  1);
  XSync (display, False);
#endif

  *keysym = old_keysym;

  return True;
}

int
main (void)
{
  int opcode, event_base, error_base, major_version, minor_version;
  unsigned int keycode;
  unsigned int keysym;

  display = XOpenDisplay (NULL);

  if (!XTestQueryExtension(display, &event_base, &error_base,
   &major_version, &minor_version))
{
  g_printerr ("XTest extension is not available\n");
  exit (1);
}

  if (!XkbQueryExtension(display, &opcode, &event_base, &error_base,
 &major_version, &minor_version))
{
  g_printerr ("Xkb extension is not available\n");
  exit (1);
}

  xkb = XkbGetMap (display, XkbAllComponentsMask, XkbUseCoreKbd);

  keycode = 38; /* keycode for 'a' key */
  keysym = 0x62;/* keysym for 'b' */

  printf ("initial %X\n", XkbKeycodeToKeysym (display, keycode, 0, 0));
  replace_keycode (keycode, &keysym);
  printf ("replaced %X - type 'a'\n", XkbKeycodeToKeysym (display, keycode, 0, 
0));
  sleep (1);
  XTestFakeKeyEvent (display, keycode, True, 20);
  XSync (display, False);
  printf ("key pressed %X\n", XkbKeycodeToKeysym (display, keycode, 0, 0));
  XTestFakeKeyEvent (display, keycode, False, 20);
  XSync (display, False);
  printf ("key released %X\n", XkbKeycodeToKeysym (display, keycode, 0, 0));
  replace_keycode (keycode, &keysym);
  printf ("replaced %X\n", XkbKeycodeToKeysym (display, keycode, 0, 0));

  return 0;
}

/* Local Variables:  */
/* compile-command: "gcc -DUSE_XKB test-xkb-xtest.c -o test-xkb-xtest 
`pkg-config gobject-2.0 x11 xtst --cflags --libs`" */
/* End:  */
___
xorg@lists.x.org: X.Org support
Archives: http://lists.freedesktop.org/archives/xorg
Info: http://lists.x.org/mailman/listinfo/xorg
Your subscription address: arch...@mail-archive.com

Re: does XkbSetMap affect XTestFakeKeyEvent?

2012-10-24 Thread Daiki Ueno
Daiki Ueno  writes:

> (1) assign a keysym to some unused keycode (like keycode 246, which
> XF86WLAN is assigned here) with XkbSetMap
> (2) send key press event using XTestFakeKeyEvent to get the keysym typed
>
> Is this supposed to work?  After (1), I could type the new keysym with
> physical keyboard, but couldn't with XTestFakeKeyEvent.  If I change the
> mapping with XChangeKeyboardMapping instead of XkbSetMap, it seems to
> work with both physical and virtual keyboard.

Sorry for the noise.
It was solved by setting xkb->device_spec when calling XkbSetMap.

Regards,
-- 
Daiki Ueno
___
xorg@lists.x.org: X.Org support
Archives: http://lists.freedesktop.org/archives/xorg
Info: http://lists.x.org/mailman/listinfo/xorg
Your subscription address: arch...@mail-archive.com