mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-17 14:04:52 +02:00
Also transmit key events when broadcasting
This commit is contained in:
@@ -9,7 +9,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
|||||||
|
|
||||||
from kitty.cli import parse_args
|
from kitty.cli import parse_args
|
||||||
from kitty.cli_stub import BroadcastCLIOptions
|
from kitty.cli_stub import BroadcastCLIOptions
|
||||||
from kitty.key_encoding import RELEASE, key_defs as K
|
from kitty.key_encoding import RELEASE, encode_key_event, key_defs as K
|
||||||
from kitty.rc.base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION
|
from kitty.rc.base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION
|
||||||
from kitty.remote_control import create_basic_command, encode_send
|
from kitty.remote_control import create_basic_command, encode_send
|
||||||
from kitty.typing import KeyEventType
|
from kitty.typing import KeyEventType
|
||||||
@@ -48,12 +48,17 @@ class Broadcast(Handler):
|
|||||||
if key_event.key is K['TAB']:
|
if key_event.key is K['TAB']:
|
||||||
self.write_broadcast_text('\t')
|
self.write_broadcast_text('\t')
|
||||||
self.write('\t')
|
self.write('\t')
|
||||||
|
return
|
||||||
elif key_event.key is K['BACKSPACE']:
|
elif key_event.key is K['BACKSPACE']:
|
||||||
self.write_broadcast_text('\177')
|
self.write_broadcast_text('\177')
|
||||||
self.write('\x08\x1b[X')
|
self.write('\x08\x1b[X')
|
||||||
|
return
|
||||||
elif key_event.key is K['ENTER']:
|
elif key_event.key is K['ENTER']:
|
||||||
self.write_broadcast_text('\r')
|
self.write_broadcast_text('\r')
|
||||||
self.print('')
|
self.print('')
|
||||||
|
return
|
||||||
|
ek = encode_key_event(key_event)
|
||||||
|
self.write_broadcast_data('kitty-key:' + ek)
|
||||||
|
|
||||||
def write_broadcast_text(self, text: str) -> None:
|
def write_broadcast_text(self, text: str) -> None:
|
||||||
self.write_broadcast_data('base64:' + standard_b64encode(text.encode('utf-8')).decode('ascii'))
|
self.write_broadcast_data('base64:' + standard_b64encode(text.encode('utf-8')).decode('ascii'))
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ class Loop:
|
|||||||
def _on_apc(self, apc: str) -> None:
|
def _on_apc(self, apc: str) -> None:
|
||||||
if apc.startswith('K'):
|
if apc.startswith('K'):
|
||||||
try:
|
try:
|
||||||
k = decode_key_event(apc)
|
k = decode_key_event(apc[1:])
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|||||||
39
kitty/key_encoding.py
generated
39
kitty/key_encoding.py
generated
@@ -417,6 +417,10 @@ def symbolic_name(glfw_name: str) -> str:
|
|||||||
return glfw_name[9:].replace('_', ' ')
|
return glfw_name[9:].replace('_', ' ')
|
||||||
|
|
||||||
|
|
||||||
|
def glfw_key_name(symbolic_name: str) -> str:
|
||||||
|
return 'GLFW_KEY_' + symbolic_name.replace(' ', '_')
|
||||||
|
|
||||||
|
|
||||||
def update_encoding() -> None:
|
def update_encoding() -> None:
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -492,9 +496,9 @@ del key_name, enc
|
|||||||
|
|
||||||
|
|
||||||
def decode_key_event(text: str) -> KeyEvent:
|
def decode_key_event(text: str) -> KeyEvent:
|
||||||
typ = type_map[text[1]]
|
typ = type_map[text[0]]
|
||||||
mods = mod_map[text[2]]
|
mods = mod_map[text[1]]
|
||||||
key = key_rmap[text[3:5]]
|
key = key_rmap[text[2:4]]
|
||||||
return KeyEvent(typ, mods, key)
|
return KeyEvent(typ, mods, key)
|
||||||
|
|
||||||
|
|
||||||
@@ -503,3 +507,32 @@ def encode_key_event(key_event: KeyEvent) -> str:
|
|||||||
mods = rmod_map[key_event.mods]
|
mods = rmod_map[key_event.mods]
|
||||||
key = ENCODING[key_event.key.replace('_', ' ')]
|
key = ENCODING[key_event.key.replace('_', ' ')]
|
||||||
return typ + mods + key
|
return typ + mods + key
|
||||||
|
|
||||||
|
|
||||||
|
class WindowSystemKeyEvent(NamedTuple):
|
||||||
|
code: int
|
||||||
|
mods: int
|
||||||
|
action: int
|
||||||
|
|
||||||
|
|
||||||
|
def decode_key_event_as_window_system_key(text: str) -> Optional[WindowSystemKeyEvent]:
|
||||||
|
k = decode_key_event(text)
|
||||||
|
glfw_name = glfw_key_name(k.key)
|
||||||
|
glfw_code = getattr(defines, glfw_name, None)
|
||||||
|
if glfw_code is None:
|
||||||
|
return None
|
||||||
|
action = defines.GLFW_PRESS
|
||||||
|
if k.type is RELEASE:
|
||||||
|
action = defines.GLFW_RELEASE
|
||||||
|
elif k.type is REPEAT:
|
||||||
|
action = defines.GLFW_REPEAT
|
||||||
|
mods = 0
|
||||||
|
if k.mods & CTRL:
|
||||||
|
mods |= defines.GLFW_MOD_CONTROL
|
||||||
|
if k.mods & ALT:
|
||||||
|
mods |= defines.GLFW_MOD_ALT
|
||||||
|
if k.mods & SUPER:
|
||||||
|
mods |= defines.GLFW_MOD_SUPER
|
||||||
|
if k.mods & SHIFT:
|
||||||
|
mods |= defines.GLFW_MOD_SHIFT
|
||||||
|
return WindowSystemKeyEvent(glfw_code, mods, action)
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import sys
|
|||||||
from typing import TYPE_CHECKING, Dict, Generator, List, Optional
|
from typing import TYPE_CHECKING, Dict, Generator, List, Optional
|
||||||
|
|
||||||
from kitty.config import parse_send_text_bytes
|
from kitty.config import parse_send_text_bytes
|
||||||
|
from kitty.key_encoding import (
|
||||||
|
WindowSystemKeyEvent, decode_key_event_as_window_system_key
|
||||||
|
)
|
||||||
|
from kitty.keys import interpret_key_event
|
||||||
|
|
||||||
from .base import (
|
from .base import (
|
||||||
MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError,
|
MATCH_TAB_OPTION, MATCH_WINDOW_OPTION, ArgsType, Boss, MatchError,
|
||||||
@@ -142,13 +146,20 @@ Do not send text to the active window, even if it is one of the matched windows.
|
|||||||
data = q.encode('utf-8')
|
data = q.encode('utf-8')
|
||||||
elif encoding == 'base64':
|
elif encoding == 'base64':
|
||||||
data = base64.standard_b64decode(q)
|
data = base64.standard_b64decode(q)
|
||||||
|
elif encoding == 'kitty-key':
|
||||||
|
data = decode_key_event_as_window_system_key(q)
|
||||||
else:
|
else:
|
||||||
raise TypeError(f'Invalid encoding for send-text data: {encoding}')
|
raise TypeError(f'Invalid encoding for send-text data: {encoding}')
|
||||||
exclude_active = payload_get('exclude_active')
|
exclude_active = payload_get('exclude_active')
|
||||||
for window in windows:
|
for window in windows:
|
||||||
if window is not None:
|
if window is not None:
|
||||||
if not exclude_active or window is not boss.active_window:
|
if not exclude_active or window is not boss.active_window:
|
||||||
window.write_to_child(data)
|
if isinstance(data, WindowSystemKeyEvent):
|
||||||
|
kdata = interpret_key_event(data.code, 0, data.mods, window, data.action)
|
||||||
|
if kdata:
|
||||||
|
window.write_to_child(kdata)
|
||||||
|
else:
|
||||||
|
window.write_to_child(data)
|
||||||
|
|
||||||
|
|
||||||
send_text = SendText()
|
send_text = SendText()
|
||||||
|
|||||||
Reference in New Issue
Block a user