Tcl /tk:关键事件队列溢出错误



我有一个关于Tcl/Tk(8.6版本,Ubuntu 14.04)的神秘问题。当我按下一个按钮(例如返回)一段时间并释放它时,程序不会对进一步的按键做出正确的反应:它忽略了一些按键,并产生错误的按键代码(通常是按键保持较长时间的那个,即使按下了其他一些按键)。如果事件处理程序花费一些时间(这里使用after模拟),则会出现问题。

这是我的脚本testKey.tcl:

proc keyHandler {keySym keyCode keySymNum} {
  puts "keyHandler (t=[clock clicks]): ($keySym) ($keyCode) ($keySymNum)"
  flush stdout
  if {$keySym == "Return"} { after 500 }
}
bind . <KeyPress> "keyHandler %K %k %N"

如果我用wish testKey.tcl运行脚本,将焦点移动到窗口并按下并按住Return键几秒钟,我一直得到这样的输出行

keyHandler (t=1474120548284090): (Return) (36) (65293)

在释放键后也会持续一段时间,我认为这是预期的行为。但是当这些输出结束时,按下更多的键(与Return不同)会导致错误的行为(忽略按键,传递错误的键代码)。

对我来说,似乎有些关键事件队列溢出。

我非常感谢任何帮助,谢谢!

编辑:我试图用一个普通的X11程序重现错误,我认为它与Tk主循环类似,但这里的效果是不可见的:
// modified from https://gist.github.com/javiercantero/7753445
// g++ -o xreadkeys xreadkeys.C -lX11
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
  Display *display;
  Window window;
  XEvent event;
  int s;
  /* open connection with the server */
  display = XOpenDisplay(NULL);
  if (display == NULL) {
    fprintf(stderr, "Cannot open displayn");
    exit(1);
  }
  s = DefaultScreen(display);
  /* create window */
  window = XCreateSimpleWindow(display, RootWindow(display, s), 
                   10, 10, 200, 200, 1,
                   BlackPixel(display, s), 
                   WhitePixel(display, s));
  /* select kind of events we are interested in */
  XSelectInput(display, window, KeyPressMask | KeyReleaseMask );
  /* map (show) the window */
  XMapWindow(display, window);
  /* event loop */
  long cnt = 0;
  while (1) {
    XNextEvent(display, &event);
    /* keyboard events */
    if (event.type == KeyPress) {
      printf( "KeyPress (%ld): %xn", cnt, event.xkey.keycode );
      /* exit on ESC key press */
      if ( event.xkey.keycode == 0x09 )
        break;
      /* Return */
      if (event.xkey.keycode == 0x24) {
        printf("Entern");
        for (int i = 0; i < 10000; i++)
          for (int j = 0; j < 40000; j++) {}
      }
    }
    else if (event.type == KeyRelease){
      printf( "KeyRelease (%ld): %xn", cnt, event.xkey.keycode );
    }
    cnt++;
  }
  /* close connection to server */
  XCloseDisplay(display);
  return 0;
}

(您可能需要为您的机器调整循环迭代的次数。)这难道不表明问题出在Tcl/Tk上吗?

Tk将在两种情况下使用相同的代码来处理事件,至少除非在一种情况下与输入法有奇怪的交互,而在另一种情况下没有。据我所知,键盘事件在运行Ubuntu的不同系统之间排队是相同的;这只是通常的X11键盘处理,KeyEvent通过GUI系统的事件队列传递。理论上,在Thinkpad的情况下,您可能会在服务器端填充缓冲区,而桌面系统的不同速度更能够跟上。也许…?

是的,我建议您编写代码来更快地为事件队列提供服务(我知道,这可能根本不是一件微不足道的事情),失败的根源最终在于Tcl/Tk没有负责的系统部分。

一位同事建议我运行im-config -a并选择"none"作为"active configuration",而不是之前的"ibus"(它产生一个包含行run_im none的文件~/.xinputrc)。如果我这样做,问题似乎在笔记本电脑上消失(重新启动X后),但到目前为止我不知道为什么。在我的PC上(问题没有发生),im-config -a将"missing"列为"active configuration"。

所以Donal Fellows关于"与输入法的奇怪交互"的预感似乎是正确的。你能详细解释一下你的评论吗?

我只是看到你可能还把"IME"指的是"输入法编辑器",所以你也是对的。

相关内容

  • 没有找到相关文章

最新更新