v1.8.7: fix Ctrl+key for non-Latin keyboard layouts

- Replace Cyrillic char bindings (tkinter rejects them) with keycode dispatch
- <Control-Key> handler routes by physical keycode (67=C, 86=V, etc.)
- Works with Russian, Ukrainian, and any other keyboard layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-02-24 04:19:23 -05:00
parent 0d3c433bac
commit 8285e33555
2 changed files with 23 additions and 8 deletions

View File

@@ -224,14 +224,8 @@ class TerminalWidget(tk.Frame):
self._text.bind("<Control-Shift-C>", self._on_copy)
self._text.bind("<Control-Shift-V>", self._on_ctrl_v)
self._text.bind("<<Paste>>", lambda e: "break")
# Russian keyboard layout: Cyrillic equivalents (Windows)
self._text.bind("<Control-\u0441>", self._on_ctrl_c) # с
self._text.bind("<Control-\u043c>", self._on_ctrl_v) # м (Ctrl+V → м)
self._text.bind("<Control-\u0432>", self._on_ctrl_d) # в (Ctrl+D → в)
self._text.bind("<Control-\u0434>", self._on_ctrl_l) # д (Ctrl+L → д)
self._text.bind("<Control-\u044f>", self._on_ctrl_z) # я (Ctrl+Z → я)
self._text.bind("<Control-Shift-\u0421>", self._on_copy) # С (Shift)
self._text.bind("<Control-Shift-\u041c>", self._on_ctrl_v) # М (Shift)
# Handle Ctrl+key by keycode — works with ANY keyboard layout
self._text.bind("<Control-Key>", self._on_ctrl_key)
# ── Mouse bindings ──
self._text.bind("<Button-1>", self._on_mouse_press)
@@ -703,6 +697,27 @@ class TerminalWidget(tk.Frame):
return "break"
# ── Ctrl+Key by keycode — works with any keyboard layout ──
_CTRL_KEYCODE_MAP = {
67: '_on_ctrl_c', # C
86: '_on_ctrl_v', # V
68: '_on_ctrl_d', # D
76: '_on_ctrl_l', # L
90: '_on_ctrl_z', # Z
}
def _on_ctrl_key(self, event):
"""Route Ctrl+key by physical keycode (layout-independent)."""
handler_name = self._CTRL_KEYCODE_MAP.get(event.keycode)
if handler_name:
# Check if Shift is also held
if event.state & 0x1 and event.keycode == 67:
return self._on_copy(event)
if event.state & 0x1 and event.keycode == 86:
return self._on_ctrl_v(event)
return getattr(self, handler_name)(event)
return None # let other bindings handle it
# ── Ctrl+C: copy or SIGINT (double-press within 1.5s) ──
def _on_ctrl_c(self, event):
if event.state & 0x1: # Shift held → Ctrl+Shift+C → copy