Versions: FPC 3.2.0 beta rev 43824, Linux Ubuntu 18.04 64-bit with KDE-Plasma-Desktop, Windows 7 32-bit.
I please need a Linux expert for reading special key-codes in FPC console programs (and maybe for "Konsole" terminal from KDE-Desktop).
I'm adapting a bunch of FPC console programs from Windows to Linux. Since about 35 years I used these 2 functions to read from the keyboard in my console programs:
program Test1; // read Keyboard via Unit CRT
{$mode objfpc}{$H+}
uses crt;
type Taste = 0..511; // Scan-Code for a key
function checkTaste: Taste;
{checks for a key, but does not wait. Result: 0 = no key pressed /
1..255 = normal ASCII-Code / 257..511 = extended Scan-Code}
var b: byte;
begin
if not KeyPressed then exit(0);
b:=byte(ReadKey); if b <> 0 then exit(b);
b:=byte(ReadKey); exit(b+256);
end;
function readTaste: Taste;
{waits for a key, until one has been pressed. Result is as checkTaste()}
var t: Taste;
begin
repeat t:=checkTaste;
until t <> 0;
readTaste:=t;
end;
var t: Taste;
begin
writeln('FPC-Version: ', {$I %FPCVERSION%}, ' / To exit press "x"');
repeat t:=readTaste;
if t < 256 then
begin
write(HexStr(t,2)); // show Hex-Code of ASCII-char
if t > 32 then write('=', chr(t), ' ') else write(' ');
end
else write('*', HexStr(t and $FF,2), ' '); // show extended Scan-Code
until t = ord('x');
writeln;
end.
They worked perfect on all Windows versions I ever had (at last Windows 7) including every special key-codes with SHIFT/CTRL/ALT and including our 7 German special characters (Ä Ö Ü ä ö ü ß) which send a 1-Byte-Code in CP850 (which was perfect for German Windows consoles) and so all programs were "designed" simple to handle all printable chars in vars of type "char".
But on Linux - as often - there are problems: most keys work, but I found 5 keys, which do not work:
- END-key: sends 3 keys = "F" and "[" and <ESC>
- CTRL-PgUp and CTRL-PgDn: send nothing (on Windows they work perfect)
- CTRL-LeftArrow and CTRL-RightArrow: send wrong Scancodes *44 and *43 (which belong to <F10> and <F9>)
After some research I found unit "keyboard" as an alternative and created a little demo program:
program Test2; // read Keyboard via Unit keyboard
{$mode objfpc}{$H+}
uses keyboard;
var k,t: TKeyEvent;
RK: TKeyRecord absolute k;
RT: TKeyRecord absolute t;
begin
InitKeyBoard;
writeln('FPC-Version: ' + {$I %FPCVERSION%});
writeln('"scan"=Scancode, "code"=ASCII-Code of printable chars / To exit press "x"');
repeat
k:=GetKeyEvent; {waits for a key}
write('scan=', HexStr(hi(RK.KeyCode),2), ' code=', HexStr(lo(RK.KeyCode),2),
' shift=', HexStr(RK.ShiftState,2), ' flags=', HexStr(RK.Flags,2), '':2);
t:=TranslateKeyEvent(k);
write('scan=', HexStr(hi(RT.KeyCode),2), ' code=', HexStr(lo(RT.KeyCode),2),
' shift=', HexStr(RT.ShiftState,2), ' flags=', HexStr(RT.Flags,2), '':2);
write('"', KeyEventToString(t), '" ');
case GetKeyEventFlags(t) of
kbASCII: write('ASCII');
kbUniCode: write('Unicode');
kbFnKey: write('Function');
kbPhys: write('Physical');
kbReleased: write('Released');
end; {case}
writeln;
until GetKeyEventChar(t) = 'x';
DoneKeyBoard;
end.
But unfortunately that caused as many new problems as it solved:
- END-key and CTRL-LeftArrow / CTRL-RightArrow: now work correct
- CTRL-PgUp and CTRL-PgDn: again send nothing
- 7 German special characters: now send 2 "keys" with it's UTF8-Code, e.g. "Ä"=C384 (requires additional effort to "catch" and convert them to 1-Byte-Codes in CP850, without danger to "hang" if an expected 2nd Code does not come)
- ESC-key: must always pressed twice! (which is "unusable" in my eyes)
Above tests I made with the "Konsole" terminal from KDE-Desktop. I tried another "Virtual Console", which can be evoked via CTRL-ALT-F2 .. CTRL-ALT-F6. "Test1" shows 4 wrong key codes, but in "Test2"
all 5 problem-keys work correctly! So it's proof, that CTRL-PgUp and CTRL-PgDn can generally work on Linux.
But those "Virtual Consoles" have so big and many disadvantages, that they are "unusable" for most purposes:
- a "Virtual Console" covers a
complete screen. They are not resizeable. Even if you have 2 screens, both show always the same. So it's impossible, to see any other window from other applications at the same time, e.g. to read something from there and to operate the console at the same time - and vice versa.
- there is no mouse possible in a "Virtual Console" e.g. to mark/select/copy something into the clipboard or to have a convenient context menu
- and uncountable more disadvantages
- and above noted problems with 7 German special characters and the ESC-key (to press twice) exist also.
I spent more time and found out, that "Konsole" terminal from KDE-Desktop has configurable "Key bindings" (see screenshot1). Default is "Standard (XFree 4)". I tried the 2 others ("Linux console" and "Solaris console"), which made some difference, but:
- CTRL-PgUp and CTRL-PgDn: again send nothing (in both Tests)
- CTRL-LeftArrow and CTRL-RightArrow: now send completely wrong codes (in both tests)
So the "Key binding" had an influence and so I tried to "Edit" a newly created one (see screenshot2, it shows the "definition" of CTRL-PgDn). But I did not understand how this should work, and all what I tried, made either no difference or "killed" the changed key totally.
Question: is there someone who knows how to operate this dialog? And do you think, it can make CTRL-PgUp and CTRL-PgDn working? If yes, please what must I do?
Because my keyboard is old (via PS/2) I organized a new one (via USB) but the results were the same.
In the "System Settings" of KDE-Plasma / Hardware / Input Devices / Hardware / you can select 1 of "hundreds" of different keyboard models (see screenshot3). I tried another one but the results were the same.
I spent more time and in
https://www.freepascal.org/docs-html/current/rtl/keyboard/kbdunix.html I found:
The terminal emulation of the Linux kernel is ... configurable. On the Linux console, the Free Pascal keyboard unit tries to implement full functionality.
Users of applications using the keyboard unit should expect the following:
- Full functionality on the Linux console. It must be the bare console, SSH into another machine will kill the full functionality.
- Limited functionality otherwise.
Notes about Linux full functionality:
- ... Unlike what you're used to with other Unix software, escape works as you intuitively expect, it generates the keycode for an escape key without a delay.
The limited functionality does include these quirks:
- Escape must be pressed two times before it has effect
- <a long list of more quirks>
I don't really understand, in which cases "full functionality" applies and when "limited functionality" applies. From my understanding, I should have "full functionality", because I don't use SSH into another machine. But obviously I have "limited functionality", because ESC has to be pressed twice. Can somebody please explain this? Is it anyhow possible, to "switch" from "limited functionality" to "full functionality", so that ESC must only pressed once?
At that point I decided to stop for now and ask you for help. I'm a beginner on Linux.
I attached above 2 Test-programs, so that you can easy experiment with them, if you want.
Sorry that this post got so long. But I wanted to give you as many infos as I have.
Thanks a lot in advance for your attention.