1

In Perl/Tk, it is possible to bind an event like this:

$mw->bind('<KeyPress-W>', sub{print "W is pressed";});

Is is possible to get this information the other direction? Can I make a call like "get the status of a key" or "check if W is pressed"?

It would not be reacting directly to the event.

Of course, there is the possibility to populate variables for the various events, but I want to know if there is such a method.

capfan
  • 817
  • 10
  • 26
  • You could bind an event which sets a control flag within your program, but otherwise I'm not aware of another method. – rutter Sep 26 '13 at 22:17

1 Answers1

3

Perl/Tk does not provide such functionality. So you would have to track the events yourself. Note that there are the Any-KeyPress and Any-KeyRelease events, so you don't have to create a binding for every key:

$mw->bind("<Any-KeyPress>" => sub {
    warn $_[0]->XEvent->K; # prints keysym
});

If you're on X11, then using the X11::Protocol module (which can be used within a Perl/Tk script) and calling the QueryKeymap method would give you the actually pressed keycodes. Here's a little script which demonstrates this:

use strict;
use X11::Protocol;

# Get the keycode-to-keysym mapping. Being lazy, I just parse
# the output of xmodmap -pke. The "real" approach would be to
# use X11 functions like GetKeyboardMapping() and the
# X11::Keysyms module.
my %keycode_to_keysym;
{
    open my $fh, "-|", "xmodmap", "-pke" or die $!;
    while(<$fh>) {
        chomp;
        if (m{^keycode\s+(\d+)\s*=(?:\s*(\S+))?}) {
            if (defined $2) {
                $keycode_to_keysym{$1} = $2;
            }
        } else {
            warn "Cannot parse $_";
        }
    }
}

my $x11 = X11::Protocol->new;
while(1) {
    my $keyvec = $x11->QueryKeymap;
    for my $bit (0 .. 32*8-1) {
        if (vec $keyvec, $bit, 1) {
            warn "Active key: keycode $bit, keysym $keycode_to_keysym{$bit}\n";
        }
    }
    sleep 1;
}
Slaven Rezic
  • 4,571
  • 14
  • 12