From 6d282f59a99ad303c83b3b7d1db139ca8d4817e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 29 May 2025 15:01:43 +0200 Subject: [PATCH 1/2] Correct documentation for left/right super key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The super key maps to ⌘ for the USB driver, but for the VNC driver ⌘ is produced by left/right Alt, so we can't promise that leftSuper/rightSuper produces ⌘. --- bootcommand/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootcommand/config.go b/bootcommand/config.go index e5b13be67..417309688 100644 --- a/bootcommand/config.go +++ b/bootcommand/config.go @@ -64,7 +64,7 @@ const PackerKeyDefault = 100 * time.Millisecond // // - ` ` - Simulates pressing the shift key. // -// - ` ` - Simulates pressing the ⌘ or Windows key. +// - ` ` - Simulates pressing the super key. // // - ` ` - Adds a 1, 5 or 10 second pause before // sending any additional keys. This is useful if you have to generally From 81531cc0f6f3b4126bf8bc7cf506bc2ebae80a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 29 May 2025 14:54:46 +0200 Subject: [PATCH 2/2] Add bootcommand mappings for left/right command and option keys When automating macOS systems it's convenient to refer to the keys by their natural names, and for the VNC driver none of the existing special keys mapped to option, so this enables boot commands using the option key. --- bootcommand/boot_command.go | 66 ++++++++++++++++++++++----------- bootcommand/boot_command.pigeon | 2 + bootcommand/config.go | 4 ++ bootcommand/usb_driver.go | 6 +++ bootcommand/vnc_driver.go | 6 +++ 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/bootcommand/boot_command.go b/bootcommand/boot_command.go index 5fbfeee66..108ff8d9f 100644 --- a/bootcommand/boot_command.go +++ b/bootcommand/boot_command.go @@ -601,18 +601,42 @@ var g = &grammar{ }, &litMatcher{ pos: position{line: 71, col: 11, offset: 1678}, + val: "leftcommand", + ignoreCase: true, + want: "\"leftCommand\"i", + }, + &litMatcher{ + pos: position{line: 71, col: 28, offset: 1695}, + val: "rightcommand", + ignoreCase: true, + want: "\"rightCommand\"i", + }, + &litMatcher{ + pos: position{line: 71, col: 46, offset: 1713}, + val: "leftoption", + ignoreCase: true, + want: "\"leftOption\"i", + }, + &litMatcher{ + pos: position{line: 71, col: 62, offset: 1729}, + val: "rightoption", + ignoreCase: true, + want: "\"rightOption\"i", + }, + &litMatcher{ + pos: position{line: 73, col: 11, offset: 1832}, val: "left", ignoreCase: true, want: "\"left\"i", }, &litMatcher{ - pos: position{line: 71, col: 21, offset: 1688}, + pos: position{line: 73, col: 21, offset: 1842}, val: "right", ignoreCase: true, want: "\"right\"i", }, &litMatcher{ - pos: position{line: 71, col: 32, offset: 1699}, + pos: position{line: 73, col: 32, offset: 1853}, val: "menu", ignoreCase: true, want: "\"menu\"i", @@ -622,9 +646,9 @@ var g = &grammar{ }, { name: "NonZeroDigit", - pos: position{line: 73, col: 1, offset: 1708}, + pos: position{line: 75, col: 1, offset: 1862}, expr: &charClassMatcher{ - pos: position{line: 73, col: 16, offset: 1723}, + pos: position{line: 75, col: 16, offset: 1877}, val: "[1-9]", ranges: []rune{'1', '9'}, ignoreCase: false, @@ -633,9 +657,9 @@ var g = &grammar{ }, { name: "Digit", - pos: position{line: 74, col: 1, offset: 1729}, + pos: position{line: 76, col: 1, offset: 1883}, expr: &charClassMatcher{ - pos: position{line: 74, col: 9, offset: 1737}, + pos: position{line: 76, col: 9, offset: 1891}, val: "[0-9]", ranges: []rune{'0', '9'}, ignoreCase: false, @@ -644,48 +668,48 @@ var g = &grammar{ }, { name: "TimeUnit", - pos: position{line: 75, col: 1, offset: 1743}, + pos: position{line: 77, col: 1, offset: 1897}, expr: &choiceExpr{ - pos: position{line: 75, col: 13, offset: 1755}, + pos: position{line: 77, col: 13, offset: 1909}, alternatives: []interface{}{ &litMatcher{ - pos: position{line: 75, col: 13, offset: 1755}, + pos: position{line: 77, col: 13, offset: 1909}, val: "ns", ignoreCase: false, want: "\"ns\"", }, &litMatcher{ - pos: position{line: 75, col: 20, offset: 1762}, + pos: position{line: 77, col: 20, offset: 1916}, val: "us", ignoreCase: false, want: "\"us\"", }, &litMatcher{ - pos: position{line: 75, col: 27, offset: 1769}, + pos: position{line: 77, col: 27, offset: 1923}, val: "µs", ignoreCase: false, want: "\"µs\"", }, &litMatcher{ - pos: position{line: 75, col: 34, offset: 1777}, + pos: position{line: 77, col: 34, offset: 1931}, val: "ms", ignoreCase: false, want: "\"ms\"", }, &litMatcher{ - pos: position{line: 75, col: 41, offset: 1784}, + pos: position{line: 77, col: 41, offset: 1938}, val: "s", ignoreCase: false, want: "\"s\"", }, &litMatcher{ - pos: position{line: 75, col: 47, offset: 1790}, + pos: position{line: 77, col: 47, offset: 1944}, val: "m", ignoreCase: false, want: "\"m\"", }, &litMatcher{ - pos: position{line: 75, col: 53, offset: 1796}, + pos: position{line: 77, col: 53, offset: 1950}, val: "h", ignoreCase: false, want: "\"h\"", @@ -696,11 +720,11 @@ var g = &grammar{ { name: "_", displayName: "\"whitespace\"", - pos: position{line: 77, col: 1, offset: 1802}, + pos: position{line: 79, col: 1, offset: 1956}, expr: &zeroOrMoreExpr{ - pos: position{line: 77, col: 19, offset: 1820}, + pos: position{line: 79, col: 19, offset: 1974}, expr: &charClassMatcher{ - pos: position{line: 77, col: 19, offset: 1820}, + pos: position{line: 79, col: 19, offset: 1974}, val: "[ \\n\\t\\r]", chars: []rune{' ', '\n', '\t', '\r'}, ignoreCase: false, @@ -710,11 +734,11 @@ var g = &grammar{ }, { name: "EOF", - pos: position{line: 79, col: 1, offset: 1832}, + pos: position{line: 81, col: 1, offset: 1986}, expr: ¬Expr{ - pos: position{line: 79, col: 8, offset: 1839}, + pos: position{line: 81, col: 8, offset: 1993}, expr: &anyMatcher{ - line: 79, col: 9, offset: 1840, + line: 81, col: 9, offset: 1994, }, }, }, diff --git a/bootcommand/boot_command.pigeon b/bootcommand/boot_command.pigeon index 982e8f98d..35aef33ab 100644 --- a/bootcommand/boot_command.pigeon +++ b/bootcommand/boot_command.pigeon @@ -68,6 +68,8 @@ SpecialKey = "bs"i / "del"i / "enter"i / "esc"i / "f10"i / "f11"i / "f12"i / "return"i / "tab"i / "up"i / "down"i / "spacebar"i / "insert"i / "home"i / "end"i / "pageUp"i / "pageDown"i / "leftAlt"i / "leftCtrl"i / "leftShift"i / "rightAlt"i / "rightCtrl"i / "rightShift"i / "leftSuper"i / "rightSuper"i + / "leftCommand"i / "rightCommand"i / "leftOption"i / "rightOption"i + // left/right must go last, to not take priority over {left/right}Foo / "left"i / "right"i / "menu"i NonZeroDigit = [1-9] diff --git a/bootcommand/config.go b/bootcommand/config.go index 417309688..39001f874 100644 --- a/bootcommand/config.go +++ b/bootcommand/config.go @@ -66,6 +66,10 @@ const PackerKeyDefault = 100 * time.Millisecond // // - ` ` - Simulates pressing the super key. // +// - ` ` - Simulates pressing the ⌘ key. +// +// - ` ` - Simulates pressing the ⌥ key. +// // - ` ` - Adds a 1, 5 or 10 second pause before // sending any additional keys. This is useful if you have to generally // wait for the UI to update before typing more. diff --git a/bootcommand/usb_driver.go b/bootcommand/usb_driver.go index a49168d26..f42ec9ef2 100644 --- a/bootcommand/usb_driver.go +++ b/bootcommand/usb_driver.go @@ -73,6 +73,12 @@ func NewUSBDriver(send SendUsbScanCodes, interval time.Duration) *usbDriver { "leftsuper": key.CodeLeftGUI, "rightsuper": key.CodeRightGUI, "spacebar": key.CodeSpacebar, + + // https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf + "leftcommand": key.CodeLeftGUI, + "rightcommand": key.CodeRightGUI, + "leftoption": key.CodeLeftAlt, + "rightoption": key.CodeRightAlt, } scancodeIndex := make(map[string]key.Code) diff --git a/bootcommand/vnc_driver.go b/bootcommand/vnc_driver.go index 8823897d8..e0119e865 100644 --- a/bootcommand/vnc_driver.go +++ b/bootcommand/vnc_driver.go @@ -78,6 +78,12 @@ func NewVNCDriver(c VNCKeyEvent, interval time.Duration) *vncDriver { sMap["tab"] = 0xFF09 sMap["up"] = 0xFF52 + // Verified against the built-in VNC server on macOS + sMap["leftcommand"] = 0xFFE9 + sMap["rightcommand"] = 0xFFEA + sMap["leftoption"] = 0xFFE7 + sMap["rightoption"] = 0xFFE8 + return &vncDriver{ c: c, interval: keyInterval,