mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Merge pull request #1088 from mitchellh/kitty-mods
macos: proper event when sided mod released with other side pressed
This commit is contained in:
@ -905,10 +905,32 @@ extension Ghostty {
|
|||||||
// but this is super cheap and flagsChanged isn't that common.
|
// but this is super cheap and flagsChanged isn't that common.
|
||||||
let mods = Ghostty.ghosttyMods(event.modifierFlags)
|
let mods = Ghostty.ghosttyMods(event.modifierFlags)
|
||||||
|
|
||||||
// If the key that pressed this is active, its a press, else release
|
// If the key that pressed this is active, its a press, else release.
|
||||||
var action = GHOSTTY_ACTION_RELEASE
|
var action = GHOSTTY_ACTION_RELEASE
|
||||||
if (mods.rawValue & mod != 0) { action = GHOSTTY_ACTION_PRESS }
|
if (mods.rawValue & mod != 0) {
|
||||||
|
// If the key is pressed, its slightly more complicated, because we
|
||||||
|
// want to check if the pressed modifier is the correct side. If the
|
||||||
|
// correct side is pressed then its a press event otherwise its a release
|
||||||
|
// event with the opposite modifier still held.
|
||||||
|
let sidePressed: Bool
|
||||||
|
switch (event.keyCode) {
|
||||||
|
case 0x3C:
|
||||||
|
sidePressed = event.modifierFlags.rawValue & UInt(NX_DEVICERSHIFTKEYMASK) != 0;
|
||||||
|
case 0x3E:
|
||||||
|
sidePressed = event.modifierFlags.rawValue & UInt(NX_DEVICERCTLKEYMASK) != 0;
|
||||||
|
case 0x3D:
|
||||||
|
sidePressed = event.modifierFlags.rawValue & UInt(NX_DEVICERALTKEYMASK) != 0;
|
||||||
|
case 0x36:
|
||||||
|
sidePressed = event.modifierFlags.rawValue & UInt(NX_DEVICERCMDKEYMASK) != 0;
|
||||||
|
default:
|
||||||
|
sidePressed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sidePressed) {
|
||||||
|
action = GHOSTTY_ACTION_PRESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keyAction(action, event: event)
|
keyAction(action, event: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,11 @@ fn kitty(
|
|||||||
var seq: KittySequence = .{
|
var seq: KittySequence = .{
|
||||||
.key = entry.code,
|
.key = entry.code,
|
||||||
.final = entry.final,
|
.final = entry.final,
|
||||||
.mods = KittyMods.fromInput(all_mods),
|
.mods = KittyMods.fromInput(
|
||||||
|
self.event.action,
|
||||||
|
self.event.key,
|
||||||
|
all_mods,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (self.kitty_flags.report_events) {
|
if (self.kitty_flags.report_events) {
|
||||||
@ -596,12 +600,27 @@ const KittyMods = packed struct(u8) {
|
|||||||
num_lock: bool = false,
|
num_lock: bool = false,
|
||||||
|
|
||||||
/// Convert an input mods value into the CSI u mods value.
|
/// Convert an input mods value into the CSI u mods value.
|
||||||
pub fn fromInput(mods: key.Mods) KittyMods {
|
pub fn fromInput(
|
||||||
|
action: key.Action,
|
||||||
|
k: key.Key,
|
||||||
|
mods: key.Mods,
|
||||||
|
) KittyMods {
|
||||||
|
// Annoying boolean logic, but according to the Kitty spec:
|
||||||
|
// "When both left and right control keys are pressed and one is
|
||||||
|
// released, the release event must again have the modifier bit reset"
|
||||||
|
// In other words, we allow a modifier if it is set AND the action
|
||||||
|
// is NOT a release. Or if the action is a release, then the key being
|
||||||
|
// released must not be the associated modifier key.
|
||||||
|
const shift = mods.shift and (action != .release or (k != .left_shift and k != .right_shift));
|
||||||
|
const alt = mods.alt and (action != .release or (k != .left_alt and k != .right_alt));
|
||||||
|
const ctrl = mods.ctrl and (action != .release or (k != .left_control and k != .right_control));
|
||||||
|
const super = mods.super and (action != .release or (k != .left_super and k != .right_super));
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.shift = mods.shift,
|
.shift = shift,
|
||||||
.alt = mods.alt,
|
.alt = alt,
|
||||||
.ctrl = mods.ctrl,
|
.ctrl = ctrl,
|
||||||
.super = mods.super,
|
.super = super,
|
||||||
.caps_lock = mods.caps_lock,
|
.caps_lock = mods.caps_lock,
|
||||||
.num_lock = mods.num_lock,
|
.num_lock = mods.num_lock,
|
||||||
};
|
};
|
||||||
@ -982,6 +1001,27 @@ test "kitty: ctrl with all flags" {
|
|||||||
try testing.expectEqualStrings("[57442;5u", actual[1..]);
|
try testing.expectEqualStrings("[57442;5u", actual[1..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "kitty: ctrl release with ctrl mod set" {
|
||||||
|
var buf: [128]u8 = undefined;
|
||||||
|
var enc: KeyEncoder = .{
|
||||||
|
.event = .{
|
||||||
|
.action = .release,
|
||||||
|
.key = .left_control,
|
||||||
|
.mods = .{ .ctrl = true },
|
||||||
|
.utf8 = "",
|
||||||
|
},
|
||||||
|
.kitty_flags = .{
|
||||||
|
.disambiguate = true,
|
||||||
|
.report_events = true,
|
||||||
|
.report_alternates = true,
|
||||||
|
.report_all = true,
|
||||||
|
.report_associated = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const actual = try enc.kitty(&buf);
|
||||||
|
try testing.expectEqualStrings("[57442;1:3u", actual[1..]);
|
||||||
|
}
|
||||||
|
|
||||||
test "kitty: delete" {
|
test "kitty: delete" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user