in reply to Tk bind KeyPress KeyRelease Problem

I think you are running into the "automatic keyboard repeat" of the X windows system. (Probably the same idea on MSWindows). There are a couple of places to set these rates in Linux. One is the Option AutoRepeat in Xf86config, and the other is in /etc/X11/xkb/compat/norepeat ( on Slackware) where you can specify keys you don't want to repeat automatically.

Both of these will make it harder to let others use your script so, you may be better off try to figure out a way of circumventing the repeat in your program.

Off the top of my head, I thought this might work, but it fails too, but I think the idea is the right way to go. Somehow set a flag that the key is down, and then NOT start the function if it is set. Or maybe work out some flag which gets set when the function is first called, and prevents it from being started twice?

This dosn't work, but crudely tries to demonstrate the idea. Maybe someone smarter knows the trick?

#!/usr/bin/perl use warnings; use strict; use Tk; my $down = 0; my $mw = MainWindow->new; $mw->bind("<Key>", sub { &pressed } ); $mw->bind("<KeyRelease>", sub { &released } ); MainLoop; sub pressed{ if ($down == 1){return} else{print 'Key: ', ${Ev('K')}, " pressed\n"} $down = 1; } sub released{ print 'Key: ', ${Ev('K')}, " released\n"; $down = 0; }

I'm not really a human, but I play one on earth. flash japh

Replies are listed 'Best First'.
Re^2: Tk bind KeyPress KeyRelease Problem
by qumsieh (Scribe) on Sep 12, 2004 at 15:05 UTC
    This dosn't work, but crudely tries to demonstrate the idea. Maybe someone smarter knows the trick?

    It's a great idea, and the code works perfectly for me on WinXP. I don't feel like rebooting to linux, so I won't try it now. What do you mean by "doesn't (sic) work"?

      "What do you mean by "doesn't (sic) work"?

      Well I think the OP wanted to turn a key into a switch which is on as long as it is held down, and is off when it is released. The code I posted will still "repeat" on linux, ( I hav'nt tried it on Windows). That is if you hold the key down, you will get a succession of "pressed-released events". If the OP had a binding to 'release' , then he would be repeatedly starting-stopping.

      Just for fun, and because I think this could be useful in my "bag-o-tricks", I tried a few more things, but was still unsuccessful. For example:

      #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; $mw->bind("<Key>", sub { &pressed } ); $mw->bind("<KeyRelease>", sub { &released } ); MainLoop; sub pressed{ print 'Key: ', ${Ev('K')}, " pressed\n"; $mw->bind("<Key>", sub { } ); $mw->bind("<KeyRelease>", sub { } ); } sub released{ print 'Key: ', ${Ev('K')}, " released\n"; }
      This code above will break the "auto-repeat" of the X-windows, but I can't seem to find a way to "re-enable the key bindings" when the key is actually released. I tried adding timers, which watch the output, expecting a succession of "pressed" events, and if the output stops, then call the "stop_function".

      For example:

      #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; $mw->bind("<Key>", sub { &pressed } ); MainLoop; sub pressed{ print 'Key: ', ${Ev('K')}, " pressed\n"; $mw->bind("<Key>", sub { } ); $mw->bind("<KeyRelease>", sub {&pressed } ); }
      This will just print a succession of "pressed" as long as the key is held down, and will stop when the key is released. So I thought about opening a FH to \$tempvar, and writing the output to it, then have a timer, truncate FH after a time period. If the length($tempvar) == 0, then I know the key was released, and can call the stop_function. But the timers eluded me, because either I spawned multiple timers, or the timing of the timers was funky, and unusable. But as of now I think this is the only method that will work, but it depends on what the "internal repeat key rate" is on your system. So after all that, I figure, it would be better to take a different approach, like have 1 key to initiate, and a differently named key to stop. (Which is normally how it's done).

      I'm not really a human, but I play one on earth. flash japh
        Right now I have it set up where one key activates and another stops, and I guess I'll have to stick with that. I really thought this was some easy problem that I could easily find a fix for, but I guess not. Thanks, for the effort though. If I dream up anything magical, I'll let you guys know. As for my system, I'm on a school lab machine, so I don't know all of the specifics. Also, I'm normally an XP user and this is a linux/xwindows. I'm looking at a standard Dell package deal if that helps at all with type of keyboard and whatnot. Anyway, thanks again. -kfm-