2016-09-17 51 views
1

我有一個Tcl/Tk(版本8.6,Ubuntu 14.04)的神祕問題。當我按住一個按鈕(例如Return)一段時間並釋放它時,程序不再對按鍵進行適當的反應:它忽略了一些按鍵,並且它產生了錯誤的鍵碼(通常是鍵盤上的按鍵更長的時間,即使按了其他一些鍵)。如果事件處理程序需要一些時間(這裏使用after進行模擬),則會出現問題。tcl/tk:關鍵事件隊列溢出錯誤?

這裏是我的腳本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腳本,將焦點移動到窗口,按住返回鍵幾秒鐘,我不斷收到輸出線這樣的

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

也解除鍵,我認爲這是預期的行爲後的一段時間。但是,當這些輸出結束時,按下其他鍵(與返回不同)會導致錯誤的行爲(按鍵被忽略,錯誤的鍵碼被輸出)。

對我來說,看起來好像某些關鍵事件隊列溢出。

我非常感謝任何幫助,謝謝!

編輯:我試圖重現錯誤與普通的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嗎?

+0

我剛剛發現問題只出現在我的聯想ThinkPad T530。在我的臺式電腦上使用相同的Tk版本和相同的Ubuntu版本(從遠程訪問),它不會發生。任何想法可以找到問題的想法? – Ralf

+0

Thinkpad上的某個鍵盤驅動程序變得不快樂了?如果這是針對某些硬件的,那麼使用不同的系統配置尋找人(如我!)是很難的...... –

+1

我能夠在運行IME時複製問題。關閉IME並且問題消失。所以很可能是某種系統交互。 –

回答

2

在兩種情況下,Tk將使用相同的代碼來處理事件,至少除非在一種情況下與輸入法有奇怪的相互作用,而另一種情況則不存在。據我所知,鍵盤事件在運行Ubuntu的不同系統之間排隊相同;這只是通常的X11鍵盤處理,而KeyEvent則通過GUI系統的事件隊列傳遞。理論上講,你可能會在Thinkpad的服務器端填充緩衝區,而桌面系統的不同速度更能跟上。也許…?雖然是的,但我建議編寫代碼以更快速地服務事件隊列(根據我所知,這根本不是一件微不足道的事情),故障最終根植於Tcl/Tk系統的某些部分有責任。

+0

該效果在純X11程序中不會發生。我會用代碼擴展我的問題。 – Ralf

0

一個同事勸我跑im-config -a並選擇「無」「活性結構」而不是前面的「IBUS」(其產生的文件~/.xinputrc含有線run_im none)。如果我這樣做,問題似乎在筆記本電腦上消失(重新啓動X後),但到目前爲止,我不知道爲什麼。在我的PC上(問題沒有發生的地方),im-config -a列出「缺失」爲「主動配置」。

因此,Donal Fellows預測「與輸入法的奇怪交互」似乎是正確的。 @Donal Fellows:你能否詳細說明你的評論?

@Brad Lanam:我剛纔看到你可能也是用「IME」表示「輸入法編輯器」,所以你也是對的。

+1

如果ibus IME重新啓動,Tk將因分段故障而崩潰。我懷疑(即猜測)在這兩個程序中都存在各種關鍵處理假設,並且它們不能很好地協同工作。 –