duncs / clusterssh

Cluster SSH - Cluster Admin Via SSH
https://github.com/duncs/clusterssh/wiki
896 stars 79 forks source link

Issue with dead keys #87

Open shneyderO opened 7 years ago

shneyderO commented 7 years ago

Hello,

I figured out, that cluster SSH has an issue with dead keys. The characters like á, è, ´, `, etc not appearing in the server windows, when they are entered in the main window. This issue appears on all keyboard layouts with dead keys support. It makes impossible even to enter such characters as "´", which is often necessary when one uses shell.

After some investigation, I found why it happens. The problem is in ClusterSSH.pm in sub key_event. Cluster SSH reading the KeyPress and KeyRelease events from Tk widget and forwarding them like X events to the server windows. Unfortunately Tk events and X events are not quite equal. To generate the character like "á"(aacute), user should press "´"(dead_acute), press "a", after that release "a" and release "´". If you'll test this with xev, you will see the next sequence of X events:

KeyPress event
keycode 21 (keysym 0xfe51, dead_acute) XmbLookupString gives 2 bytes: (c2 b4) "´"

KeyPress event keycode 38 (keysym 0x61, a) XmbLookupString gives 1 bytes: (61) "a"

KeyPress event keycode 0
XmbLookupString gives 2 bytes: (c3 a1) "á"

KeyRelease event keycode 38 (keysym 0x61, a) XLookupString gives 1 bytes: (61) "a"

KeyRelease event keycode 21 (keysym 0xfe51, dead_acute), XLookupString gives 2 bytes: (c2 b4) "´"

Unfortunately you won't have same result if you are reading the Key events from Tk widget. In this case you'll get only:

Pressed Keycode:0, Keysym(dec): 225, Keysym: aacute Released Keycode:38, Keysym(dec): 97, Keysym: a Released Keycode:21, Keysym(dec): 65105, Keysym: dead_acute

With Perl Tk widgets, which are Cluster SSH using, you'll get even less:

KeyPress - Keycode: 0, Keysym(dec): 0 Keysym: 0 KeyRelease - Keycode: 21, Keysym(dec): 65105 Keysym: dead_acute KeyRelease - Keycode: 38, Keysym(dec): 97 Keysym: a

As you can see, in the Perl version keysym in the KeyPress event is 0. Even if it supposed to be 225(aacute). This is actually the sequence of events which ClusterSSH sending to server windows when user trying to enter the "aacute" symbol. And this is why the symbol is not appearing there.

As a fix for this issue, I could imagine to verify a value of keysym in the KeyPress callback. You can figure out what character user entered by examining a $Tk::event->A, which is representing an UNICODE character corresponding to the event. In our example case it would be "\x{e1}" and after that send to the server windows a correct sequens of X events.

Here are the wish and Perl scripts which you can use to see events captured by Tk widgets:

!/usr/bin/env wish

tk useinputmethods 1 entry .value -width 26 -relief sunken -textvariable value grid .value -padx 1m -pady 1m bind .value {puts "Pressed Keycode:%k, Keysym(dec): %N, Keysym: %K"} bind .value {puts "Released Keycode:%k, Keysym(dec): %N, Keysym: %K"}

!/usr/bin/perl

use Tk; use strict; sub key_event { my $event = $Tk::event->T; my $keycode = $Tk::event->k; my $keysymdec = $Tk::event->N; my $keysym = $Tk::event->K; print ("$event - Keycode: ", $keycode, ", Keysym(dec): ".$keysymdec, " Keysym: ".$keysym, "\n"); } my $top = new MainWindow; my $entry=$top->Entry(); $entry->pack; $entry->bind( '', sub { &key_event } ); $entry->bind( '', sub { &key_event } ); MainLoop;

Best regards, Alex

duncs commented 7 years ago

Thank you for the example code - this has long been a problem with ClusterSSH - I will investigate and see if I can sort it for the next version