Text Input not passing to X11 on Keypress in C

307 Views Asked by At

I've been attempting to hook up my BBC Micro to my Raspberry Pi and use it as a Keyboard over Serial TTY. I've found some great code on Github to forward Serial Keypresses to X11, but I can't seem to get it to work as I'd have hoped. I'm not great at C and had a go but sadly haven't got anywhere.

The below works in that it sends keypresses to X11 only when you press 'Return'. The trouble is, if you type 'ABCDE(RETURN)', it'll send 'ABCDE' to the X11 session and also hit the Return Key, you can't see what you've typed until you hit return. What i want it to do is send 'A' when i've pressed 'A', 'B' when i've hit B etc.

I think it seems to be holding everything in some kind of buffer (readbuf?) somehow controlled by the XFlush(dpy); at 112 flushing character input to X11, so moved that to 104 (didn't work), tried it at 53 and 155 in the hope that'd do the trick.

Any help at all would be greatly appreciated!

static int serialPort;
static Display *dpy;

static void xtest_key_press(unsigned char letter) {
  unsigned int shiftcode = XKeysymToKeycode(dpy, XStringToKeysym("Shift_L"));
  int upper = 0;
  int skip_lookup = 0;
  char s[2];
  s[0] = letter;
  s[1] = 0;
  KeySym sym = XStringToKeysym(s);
  KeyCode keycode;



  if (sym == 0) {
    sym = letter;
  }


  if (sym == '\n') {
    sym = XK_Return;
    skip_lookup = 1;

  } else if (sym == '\t') {
    sym = XK_Tab;
    skip_lookup = 1;
  }

  keycode = XKeysymToKeycode(dpy, sym);
  if (keycode == 0) {
    sym = 0xff00 | letter;
    keycode = XKeysymToKeycode(dpy, sym);

  }

  if (!skip_lookup) {
    // Here we try to determine if a keysym
    // needs a modifier key (shift), such as a
    // shifted letter or symbol.
    // The second keysym should be the shifted char
    KeySym *syms;
    int keysyms_per_keycode;
    syms = XGetKeyboardMapping(dpy, keycode, 1, &keysyms_per_keycode);
    int i = 0;
    for (i = 0; i <= keysyms_per_keycode; i++) {
      if (syms[i] == 0)
        break;

      if (i == 0 && syms[i] != letter)
        upper = 1;


    }
  }

  if (upper)
    XTestFakeKeyEvent(dpy, shiftcode, True, 0); 


  XTestFakeKeyEvent(dpy, keycode, True, 0); 
  XTestFakeKeyEvent(dpy, keycode, False, 0);

  if (upper)
    XTestFakeKeyEvent(dpy, shiftcode, False, 0);  



}

static void press_keys(char* string) {
  int len = strlen(string);
  int i = 0;
  for (i = 0; i < len; i++) {
    xtest_key_press(string[i]);
  }
  XFlush(dpy);
}


int sw_open_serial(const char *port) {
  serialPort = open(port, O_RDONLY);
  if (serialPort < 0) {
    fprintf(stderr, "Can't open serial port: %s\n", port);
    exit(-1);
  }

  return 0;
}

void sw_init() {

  int xtest_major_version = 0;
  int xtest_minor_version = 0;
  int dummy;


  /*
   * Open the display using the $DISPLAY environment variable to locate
   * the X server.  See Section 2.1.
   */
  if ((dpy = XOpenDisplay(NULL)) == NULL) {
    fprintf(stderr, "%s: can't open %s\en", "softwedge", XDisplayName(NULL));
    exit(1);
  }

  Bool success = XTestQueryExtension(dpy, &dummy, &dummy,
                     &xtest_major_version, &xtest_minor_version);
  if(success == False || xtest_major_version < 2 ||
     (xtest_major_version <= 2 && xtest_minor_version < 2))
  {
    fprintf(stderr,"XTEST extension not supported. Can't continue\n");
    exit(1);
  }

}


void sw_read_loop() {

  char readbuf[2];
  readbuf[1] = 0;

  while(read(serialPort, readbuf, 1) > 0) {
    if (readbuf[0] == 0x02 || readbuf[0] == 0x03) 
      continue;
    press_keys(readbuf);
  }
  // We're done now
  close(serialPort);
}
0

There are 0 best solutions below