mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
macos-option-as-alt config, handle alt-prefix for charCallback
This commit is contained in:
@ -142,6 +142,7 @@ const DerivedConfig = struct {
|
|||||||
confirm_close_surface: bool,
|
confirm_close_surface: bool,
|
||||||
mouse_interval: u64,
|
mouse_interval: u64,
|
||||||
macos_non_native_fullscreen: bool,
|
macos_non_native_fullscreen: bool,
|
||||||
|
macos_option_as_alt: bool,
|
||||||
|
|
||||||
pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig {
|
pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig {
|
||||||
var arena = ArenaAllocator.init(alloc_gpa);
|
var arena = ArenaAllocator.init(alloc_gpa);
|
||||||
@ -158,6 +159,7 @@ const DerivedConfig = struct {
|
|||||||
.confirm_close_surface = config.@"confirm-close-surface",
|
.confirm_close_surface = config.@"confirm-close-surface",
|
||||||
.mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms
|
.mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms
|
||||||
.macos_non_native_fullscreen = config.@"macos-non-native-fullscreen",
|
.macos_non_native_fullscreen = config.@"macos-non-native-fullscreen",
|
||||||
|
.macos_option_as_alt = config.@"macos-option-as-alt",
|
||||||
|
|
||||||
// Assignments happen sequentially so we have to do this last
|
// Assignments happen sequentially so we have to do this last
|
||||||
// so that the memory is captured from allocs above.
|
// so that the memory is captured from allocs above.
|
||||||
@ -985,7 +987,11 @@ pub fn preeditCallback(self: *Surface, preedit: ?u21) !void {
|
|||||||
try self.queueRender();
|
try self.queueRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn charCallback(self: *Surface, codepoint: u21) !void {
|
pub fn charCallback(
|
||||||
|
self: *Surface,
|
||||||
|
codepoint: u21,
|
||||||
|
mods: input.Mods,
|
||||||
|
) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
@ -1015,13 +1021,26 @@ pub fn charCallback(self: *Surface, codepoint: u21) !void {
|
|||||||
try self.io.terminal.scrollViewport(.{ .bottom = {} });
|
try self.io.terminal.scrollViewport(.{ .bottom = {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask our IO thread to write the data
|
|
||||||
var data: termio.Message.WriteReq.Small.Array = undefined;
|
var data: termio.Message.WriteReq.Small.Array = undefined;
|
||||||
const len = try std.unicode.utf8Encode(codepoint, &data);
|
|
||||||
|
// Prefix our data with ESC if we have alt pressed.
|
||||||
|
var i: u8 = 0;
|
||||||
|
if (mods.alt) alt: {
|
||||||
|
// On macOS, we have to opt-in to using alt because option
|
||||||
|
// by default is a unicode character sequence.
|
||||||
|
if (comptime builtin.target.isDarwin()) {
|
||||||
|
if (!self.config.macos_option_as_alt) break :alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[i] = 0x1b;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const len = try std.unicode.utf8Encode(codepoint, data[i..]);
|
||||||
_ = self.io_thread.mailbox.push(.{
|
_ = self.io_thread.mailbox.push(.{
|
||||||
.write_small = .{
|
.write_small = .{
|
||||||
.data = data,
|
.data = data,
|
||||||
.len = len,
|
.len = len + i,
|
||||||
},
|
},
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
|
|
||||||
|
@ -390,13 +390,23 @@ pub const Surface = struct {
|
|||||||
// We don't handle release events because we don't use them yet.
|
// We don't handle release events because we don't use them yet.
|
||||||
if (action != .press and action != .repeat) return;
|
if (action != .press and action != .repeat) return;
|
||||||
|
|
||||||
|
// If we're on macOS and we have macos-option-as-alt enabled,
|
||||||
|
// then we strip the alt modifier from the mods for translation.
|
||||||
|
const translate_mods = translate_mods: {
|
||||||
|
var translate_mods = mods;
|
||||||
|
if (self.app.config.@"macos-option-as-alt")
|
||||||
|
translate_mods.alt = false;
|
||||||
|
|
||||||
|
break :translate_mods translate_mods;
|
||||||
|
};
|
||||||
|
|
||||||
// Translate our key using the keymap for our localized keyboard layout.
|
// Translate our key using the keymap for our localized keyboard layout.
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
const result = try self.app.keymap.translate(
|
const result = try self.app.keymap.translate(
|
||||||
&buf,
|
&buf,
|
||||||
&self.keymap_state,
|
&self.keymap_state,
|
||||||
@intCast(keycode),
|
@intCast(keycode),
|
||||||
mods,
|
translate_mods,
|
||||||
);
|
);
|
||||||
|
|
||||||
// If we aren't composing, then we set our preedit to empty no matter what.
|
// If we aren't composing, then we set our preedit to empty no matter what.
|
||||||
@ -472,7 +482,7 @@ pub const Surface = struct {
|
|||||||
|
|
||||||
// Next, we want to call the char callback with each codepoint.
|
// Next, we want to call the char callback with each codepoint.
|
||||||
while (it.nextCodepoint()) |cp| {
|
while (it.nextCodepoint()) |cp| {
|
||||||
self.core_surface.charCallback(cp) catch |err| {
|
self.core_surface.charCallback(cp, mods) catch |err| {
|
||||||
log.err("error in char callback err={}", .{err});
|
log.err("error in char callback err={}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -481,7 +491,7 @@ pub const Surface = struct {
|
|||||||
|
|
||||||
pub fn charCallback(self: *Surface, cp_: u32) void {
|
pub fn charCallback(self: *Surface, cp_: u32) void {
|
||||||
const cp = std.math.cast(u21, cp_) orelse return;
|
const cp = std.math.cast(u21, cp_) orelse return;
|
||||||
self.core_surface.charCallback(cp) catch |err| {
|
self.core_surface.charCallback(cp, .{}) catch |err| {
|
||||||
log.err("error in char callback err={}", .{err});
|
log.err("error in char callback err={}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -597,7 +597,8 @@ pub const Surface = struct {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
core_win.charCallback(codepoint) catch |err| {
|
// TODO: mods
|
||||||
|
core_win.charCallback(codepoint, .{}) catch |err| {
|
||||||
log.err("error in char callback err={}", .{err});
|
log.err("error in char callback err={}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -1282,7 +1282,7 @@ pub const Surface = struct {
|
|||||||
};
|
};
|
||||||
var it = view.iterator();
|
var it = view.iterator();
|
||||||
while (it.nextCodepoint()) |cp| {
|
while (it.nextCodepoint()) |cp| {
|
||||||
self.core_surface.charCallback(cp) catch |err| {
|
self.core_surface.charCallback(cp, mods) catch |err| {
|
||||||
log.err("error in char callback err={}", .{err});
|
log.err("error in char callback err={}", .{err});
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@ -1390,7 +1390,7 @@ pub const Surface = struct {
|
|||||||
};
|
};
|
||||||
var it = view.iterator();
|
var it = view.iterator();
|
||||||
while (it.nextCodepoint()) |cp| {
|
while (it.nextCodepoint()) |cp| {
|
||||||
self.core_surface.charCallback(cp) catch |err| {
|
self.core_surface.charCallback(cp, .{}) catch |err| {
|
||||||
log.err("error in char callback err={}", .{err});
|
log.err("error in char callback err={}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -238,6 +238,19 @@ pub const Config = struct {
|
|||||||
/// animations.
|
/// animations.
|
||||||
@"macos-non-native-fullscreen": bool = false,
|
@"macos-non-native-fullscreen": bool = false,
|
||||||
|
|
||||||
|
/// If true, the Option key will be treated as Alt. This makes terminal
|
||||||
|
/// sequences expecting Alt to work properly, but will break Unicode
|
||||||
|
/// input sequences on macOS if you use them via the alt key. You may
|
||||||
|
/// set this to false to restore the macOS alt-key unicode sequences
|
||||||
|
/// but this will break terminal sequences expecting Alt to work.
|
||||||
|
///
|
||||||
|
/// Note that if an Option-sequence doesn't produce a printable
|
||||||
|
/// character, it will be treated as Alt regardless of this setting.
|
||||||
|
/// (i.e. alt+ctrl+a).
|
||||||
|
///
|
||||||
|
/// This does not work with GLFW builds.
|
||||||
|
@"macos-option-as-alt": bool = false,
|
||||||
|
|
||||||
/// This is set by the CLI parser for deinit.
|
/// This is set by the CLI parser for deinit.
|
||||||
_arena: ?ArenaAllocator = null,
|
_arena: ?ArenaAllocator = null,
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user