Ver Fonte

- Fixed kitty input mode accidently broken by win32 input mode implementation
- Fixed Shift+Tab behavior under win32 input mode
- Fixed Del key behavior in win32 input mode
- Fixed Alt+non_latin_letters and Ctrl+arrows in legacy mode

Ivan Sorokin há 6 dias atrás
pai
commit
3da92b35a9
1 ficheiros alterados com 47 adições e 20 exclusões
  1. 47 20
      packages/rtl-console/src/unix/keyboard.pp

+ 47 - 20
packages/rtl-console/src/unix/keyboard.pp

@@ -2313,6 +2313,20 @@ var
       if (p_idx <= 5) and (st <> '') then
         Val(st, params[p_idx], code);
 
+      // For non-printable command keys, we must ignore any character code provided
+      // by the terminal (like #127 for Del) and force it to 0. This ensures the
+      // application interprets the key event as a command (via its scancode)
+      // rather than as a character to be printed.
+      case params[0] of // Check Virtual Key Code (wVirtualKeyCode)
+        // Function keys F1-F12
+        $70..$7B,
+        // Arrow keys (Left, Up, Right, Down)
+        $25..$28,
+        // Navigation keys (PgUp, PgDn, End, Home, Ins, Del)
+        $21..$24, $2D, $2E:
+          params[2] := 0; // Force UnicodeChar to be 0
+      end;
+
       // 2. Process only key down and repeat events (param[3] must be non-zero)
       if params[3] = 0 then exit; // Ignore key up events completely for now.
                                   // The sequence is considered "handled".
@@ -2669,6 +2683,34 @@ begin
           {save char later use }
           store[arrayind]:=ch;
           inc(arrayind);
+
+          // If we detect a pattern for a complex parameterized sequence (ESC [ <digit>),
+          // which is common for win32-input-mode and Kitty, we switch from a non-blocking
+          // to a blocking read. This ensures we read the entire sequence even if it
+          // arrives in chunks with micro-delays.
+          if
+            (arrayind = 4) and
+            (store[0]=#27) and
+            (store[1]='[') and
+            (store[2] in ['0'..'9']) and
+            ((store[3] in ['0'..'9']) or (store[3] = ';')) and
+            (not ((store[2] = '1') and (store[3] = ';'))) // skip for legacy seqs like ESC[1;something
+          then
+          begin
+            // Enter blocking read loop with a safety break
+            while (arrayind < 31) do
+            begin
+              // This is a blocking read, it will wait for the next character
+              ch := ttyRecvChar;
+              store[arrayind] := ch;
+              inc(arrayind);
+              // Check for known terminators for win32, kitty, xterm, and other CSI sequences.
+              if (ch = '_') or (ch = 'u') or (ch = '~') or (ch in ['A'..'Z']) or (ch in ['a'..'z']) then
+                break; // Exit this inner blocking loop
+            end;
+            break; // We have the full sequence, so exit the outer `while syskeypressed` loop
+          end;
+
           if arrayind >= 31 then break;
           {check tree for maching sequence}
           if assigned(NPT) then
@@ -2696,28 +2738,12 @@ begin
           if (arrayind>3) and not (ch in [';',':','0'..'9']) and (ch <> '_') then break; {end of escape sequence}
         end;
 
-        // If we detect what looks like a parameterized CSI sequence (ESC [ digit ...), which is very likely a
-        // win32-input-mode sequence, enter a blocking read loop to fetch the rest of it until the terminator `_` is found.
-        // This avoids depending on timings/timeouts and distinguishes it from simple sequences like arrow keys (ESC [ A).
-        if (arrayind > 2) and (store[0]=#27) and (store[1]='[') and (store[2] in ['0'..'9']) and (store[arrayind-1] <> '_') then
-        begin
-          repeat
-            ch := ttyRecvChar; // This is a blocking read
-            if arrayind < 31 then
-            begin
-              store[arrayind]:=ch;
-              inc(arrayind);
-            end;
-          until (ch = '_') or (arrayind >= 31);
-        end;
-
         ch := store[arrayind-1];
 
         if (ch = '_') and (arrayind > 2) and (store[0]=#27) and (store[1]='[') then
         begin
           DecodeAndPushWin32Key(store, arrayind);
-          FoundNPT := RootNPT;
-          arrayind := 0;
+          exit;
         end else
         if (arrayind>3) then
           if (ch = 'u'  )   { for sure kitty keys  or }
@@ -3021,15 +3047,16 @@ begin {main}
       exit;
     end;
   SysGetEnhancedKeyEvent:=NilEnhancedKeyEvent;
-  // FAST PATH for pre-constructed events from ReadKey's Alt+UTF8 logic
   MyKey:=ReadKey;
-  // FAST PATH for pre-constructed events from ReadKey's Alt+UTF8 logic OR win32-input-mode
-  if (MyKey.ShiftState <> []) and (MyKey.VirtualScanCode <> 0) then
+
+  // FAST PATH for pre-constructed events from ReadKey's Alt+UTF8 logic
+  if (MyKey.ShiftState <> []) and (Ord(MyKey.UnicodeChar) > 0) and (Ord(MyKey.UnicodeChar) <> Ord(MyKey.AsciiChar)) then
   begin
     SysGetEnhancedKeyEvent := MyKey;
     LastShiftState := MyKey.ShiftState;
     exit;
   end;
+
   MyChar:=MyKey.AsciiChar;
   MyUniChar:=MyKey.UnicodeChar;
   MyScan:=MyKey.VirtualScanCode shr 8;