私は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
でスクリプトを実行し、ウィンドウを押しにフォーカスを移動し、数秒間Returnキーを押したままにすると、私はこのような出力ラインを取得しておきます私が期待される振る舞いだと思うキーを、解除した後しばらくの間も
keyHandler (t=1474120548284090): (Return) (36) (65293)
。しかし、これらの出力が終了すると、Returnキーとは別のキーを押すと、誤った動作になります(キーの押下は無視され、間違ったキーコードが渡されます)。
私にとって、キーイベントキューがオーバーフローしたように見えます。
ご協力いただきありがとうございます。
編集:私はTkのメインループに同じようなことをすると仮定し、プレーンX11プログラムでエラーを再現してみましたが、ここでは効果は表示されません。
// 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にあることを示していませんか?
私はこの問題がLenovo ThinkPad T530でのみ発生することを発見しました。同じTkバージョンとデスクトップPCの同じUbuntuバージョン(リモートからアクセス)では、それは起こらない。問題がどこに置かれたのか? – Ralf
ThinkPadのキーボード・ドライバーで何かが不幸になってしまった?それがハードウェアに特有のものであれば、私のような人たちをさまざまなシステム構成で探し出すのはかなり難しいです... –
IMEを実行して問題を再現することができました。 IMEを無効にして、問題が解決します。システムのやりとりのようなものでしょう。 –