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

时间:2016-09-17 14:14:58

标签: tcl tk

我对Tcl / Tk(版本8.6,Ubuntu 14.04)有一个神秘的问题。当我按下按钮(例如Return)一段时间并将其释放时,程序不再对进一步的按键操作做出正确的反应:它忽略了一些按键操作并产生错误的键码(通常是键盘中的键码)更长时间,即使按下了其他一些键)。如果事件处理程序需要一些时间(此处使用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 display\n");
    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): %x\n", cnt, event.xkey.keycode );
      /* exit on ESC key press */
      if ( event.xkey.keycode == 0x09 )
        break;
      /* Return */
      if (event.xkey.keycode == 0x24) {
        printf("Enter\n");
        for (int i = 0; i < 10000; i++)
          for (int j = 0; j < 40000; j++) {}
      }
    }
    else if (event.type == KeyRelease){
      printf( "KeyRelease (%ld): %x\n", cnt, event.xkey.keycode );
    }
    cnt++;
  }
  /* close connection to server */
  XCloseDisplay(display);
  return 0;
}

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

2 个答案:

答案 0 :(得分:2)

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

虽然是,我建议编写代码以更快地为事件队列提供服务(这可能不是一件微不足道的事情,我知道)故障最终根植于Tcl / Tk没有的系统部分责任。

答案 1 :(得分:0)

一位同事建议我运行im-config -a并选择&#34; none&#34; as&#34;活跃配置&#34;而不是早期的&#34; ibus&#34; (生成包含行~/.xinputrc)的文件run_im none。如果我这样做,问题似乎在笔记本电脑上消失(重启X后),但到目前为止我不明白为什么。在我的电脑上(问题没有发生),列出了im-config -a&#34;缺少&#34; as&#34;活跃配置&#34;。

所以看起来Donal Fellows在与输入法&#34;的奇怪交互中踌躇满志。是对的。 @Donal Fellows:你能详细说明你的评论吗?

@Brad Lanam:我只是看到你可能也意味着&#34;输入法编辑器&#34;通过&#34; IME&#34;,所以你也是对的。