mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
modifyOtherKeys state 2 should send sequences for all chars
See: https://github.com/mitchellh/ghostty/issues/242#issuecomment-1678268533 Quoted: @hovsater OKAY! I've consulted _the source_, i.e. `xterm`. None of the other reference material was illuminating and there is so much conflicting implementation out there and so very few terminals actually support `modifyOtherKeys`. I believe I've figured it out. I believe that `C-S-h` is only supported via `modifyOtherKeys` state 2. iTerm emits it for state 1 but I think this is a mistake and I can't get any other terminal to do it, including `xterm`. Here is my test script on Linux: ``` printf "\x1b[>4;1m" # change to "2" for state 2 showkey -a ``` With state 1, I couldn't get any terminal to output anything for `C-S-h`. **But with state 2, xterm outputs: ** `CSI 27;6;72~`. One thing to note is 72 is `H` (uppercase), so in even this case, iTerm appears to be sending the wrong code or `dte -K` is outputting the wrong case (less likely I think). When I launch `dte` (the full editor), it only requests `modifyOtherKeys` state 1. So, with only `modifyOtherKeys` support, it shouldn't get access to `C-S-h`. Note that I couldn't get any terminal on macOS to show the same sequences as xterm under any circumstance. I also cracked open the `xterm` source and I only eyeballed it but I believe this is not sending the sequences under state 1: https://sourcegraph.com/github.com/ThomasDickey/xterm-snapshots@c2b36af8d216926b8931c6f9cebefd69228e437c/-/blob/input.c?L579 **I could be very wrong, I'm not confident.** Every implementation (and there are only few) seems different and the behaviors are not consistent at all. Hence, I'm falling back to `xterm`, but even then I could be reading the source wrong. But when I ran `xterm` manually I could only get `C-S-h` to show up in state 2.
This commit is contained in:
@ -1008,6 +1008,7 @@ pub fn charCallback(
|
||||
// Critical area
|
||||
const critical: struct {
|
||||
alt_esc_prefix: bool,
|
||||
modify_other_keys: bool,
|
||||
} = critical: {
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
@ -1024,11 +1025,38 @@ pub fn charCallback(
|
||||
|
||||
break :critical .{
|
||||
.alt_esc_prefix = self.io.terminal.modes.alt_esc_prefix,
|
||||
.modify_other_keys = self.io.terminal.modes.modify_other_keys,
|
||||
};
|
||||
};
|
||||
|
||||
// Where we're going to write any data. Any data we write has to
|
||||
// fit into the fixed size array so we just define it up front.
|
||||
var data: termio.Message.WriteReq.Small.Array = undefined;
|
||||
|
||||
// In modify other keys state 2, we send the CSI 27 sequence
|
||||
// for any char with a modifier. Ctrl sequences like Ctrl+A
|
||||
// are handled in keyCallback and should never have reached this
|
||||
// point.
|
||||
if (critical.modify_other_keys and !mods.empty()) {
|
||||
for (input.function_keys.modifiers, 2..) |modset, code| {
|
||||
if (!mods.equal(modset)) continue;
|
||||
|
||||
const resp = try std.fmt.bufPrint(
|
||||
&data,
|
||||
"\x1B[27;{};{}~",
|
||||
.{ code, codepoint },
|
||||
);
|
||||
_ = self.io_thread.mailbox.push(.{
|
||||
.write_small = .{
|
||||
.data = data,
|
||||
.len = @intCast(resp.len),
|
||||
},
|
||||
}, .{ .forever = {} });
|
||||
try self.io_thread.wakeup.notify();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix our data with ESC if we have alt pressed.
|
||||
var i: u8 = 0;
|
||||
if (mods.alt) alt: {
|
||||
|
Reference in New Issue
Block a user