From 7adb0214b225207f7d8c8477f8c39f18c935230f Mon Sep 17 00:00:00 2001 From: FreeTeaspoon <76246708+FreeTeaspoon@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:31:36 +0800 Subject: [PATCH] Support extended function key shortcut labels --- .../Shortcuts/KeyboardShortcutManager.swift | 24 +++++++++++++++++++ .../Shortcuts/ShortcutCoreTests.swift | 20 ++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/Snapzy/Services/Shortcuts/KeyboardShortcutManager.swift b/Snapzy/Services/Shortcuts/KeyboardShortcutManager.swift index c6b08c4e..1d777caa 100644 --- a/Snapzy/Services/Shortcuts/KeyboardShortcutManager.swift +++ b/Snapzy/Services/Shortcuts/KeyboardShortcutManager.swift @@ -212,6 +212,14 @@ struct ShortcutConfig: Equatable, Codable { case kVK_F10: return "F10" case kVK_F11: return "F11" case kVK_F12: return "F12" + case kVK_F13: return "F13" + case kVK_F14: return "F14" + case kVK_F15: return "F15" + case kVK_F16: return "F16" + case kVK_F17: return "F17" + case kVK_F18: return "F18" + case kVK_F19: return "F19" + case kVK_F20: return "F20" case kVK_Space: return "Space" case kVK_Return: return "↩" case kVK_Tab: return "⇥" @@ -319,6 +327,22 @@ extension ShortcutConfig { return Self.unicodeScalarString(Int(NSF11FunctionKey)) case kVK_F12: return Self.unicodeScalarString(Int(NSF12FunctionKey)) + case kVK_F13: + return Self.unicodeScalarString(Int(NSF13FunctionKey)) + case kVK_F14: + return Self.unicodeScalarString(Int(NSF14FunctionKey)) + case kVK_F15: + return Self.unicodeScalarString(Int(NSF15FunctionKey)) + case kVK_F16: + return Self.unicodeScalarString(Int(NSF16FunctionKey)) + case kVK_F17: + return Self.unicodeScalarString(Int(NSF17FunctionKey)) + case kVK_F18: + return Self.unicodeScalarString(Int(NSF18FunctionKey)) + case kVK_F19: + return Self.unicodeScalarString(Int(NSF19FunctionKey)) + case kVK_F20: + return Self.unicodeScalarString(Int(NSF20FunctionKey)) case kVK_ForwardDelete: return Self.unicodeScalarString(Int(NSDeleteFunctionKey)) case kVK_Home: diff --git a/SnapzyTests/Services/Shortcuts/ShortcutCoreTests.swift b/SnapzyTests/Services/Shortcuts/ShortcutCoreTests.swift index 3b46ca47..0e6529ee 100644 --- a/SnapzyTests/Services/Shortcuts/ShortcutCoreTests.swift +++ b/SnapzyTests/Services/Shortcuts/ShortcutCoreTests.swift @@ -36,17 +36,37 @@ final class ShortcutCoreTests: XCTestCase { XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_ANSI_A)), "A") XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_ANSI_0)), "0") XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_F12)), "F12") + XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_F13)), "F13") + XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_F14)), "F14") + XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_F20)), "F20") XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_LeftArrow)), "\u{2190}") XCTAssertEqual(ShortcutConfig.keyCodeToString(UInt32(kVK_ANSI_Slash)), "/") XCTAssertEqual(ShortcutConfig.keyCodeToString(9999), "?") } + func testShortcutConfigDisplayParts_includeFnWithExtendedFunctionKeys() { + let f13 = ShortcutConfig( + keyCode: UInt32(kVK_F13), + modifiers: ShortcutConfig.functionCarbonModifier + ) + let f14 = ShortcutConfig( + keyCode: UInt32(kVK_F14), + modifiers: ShortcutConfig.functionCarbonModifier + ) + + XCTAssertEqual(f13.displayParts, ["fn", "F13"]) + XCTAssertEqual(f13.displayString, "fn F13") + XCTAssertEqual(f14.displayParts, ["fn", "F14"]) + } + func testShortcutConfigMenuKeyEquivalent_mapsSpecialKeys() { XCTAssertEqual(ShortcutConfig(keyCode: UInt32(kVK_Space), modifiers: 0).menuKeyEquivalent, " ") XCTAssertEqual(ShortcutConfig(keyCode: UInt32(kVK_Return), modifiers: 0).menuKeyEquivalent, "\r") XCTAssertEqual(ShortcutConfig(keyCode: UInt32(kVK_Tab), modifiers: 0).menuKeyEquivalent, "\t") XCTAssertEqual(ShortcutConfig(keyCode: UInt32(kVK_Escape), modifiers: 0).menuKeyEquivalent, "\u{1B}") XCTAssertNotNil(ShortcutConfig(keyCode: UInt32(kVK_F1), modifiers: 0).menuKeyEquivalent) + XCTAssertNotNil(ShortcutConfig(keyCode: UInt32(kVK_F13), modifiers: 0).menuKeyEquivalent) + XCTAssertNotNil(ShortcutConfig(keyCode: UInt32(kVK_F20), modifiers: 0).menuKeyEquivalent) } func testShortcutConfigMenuModifierFlags_convertCarbonModifiers() {