Add support for tvOS input#65
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1c59d721b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if now >= state.deadline { | ||
| keyboardShortcutStates[slot] = nil |
There was a problem hiding this comment.
Don't resuppress held shortcut buttons after timeout
When a user holds only one button from the text-input chord, such as the default Y button for an in-game hold action, the state is cleared as soon as the delay expires. On the next sample the still-held button starts a new shortcut state, so the button is suppressed again; the stream sees brief repeated taps instead of a continuous hold. After the timeout for an incomplete chord, keep that partial press in a pass-through state until all involved buttons are released.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Indeed, Tested in FH6. Could you make sure that if only part of the shortcut is held, the button continues behaving like a normal held button until it’s released? At the moment, it might be sent as repeated taps.
| if shortcutButtons == textInputTriggerSequence.asSet() { | ||
| notifyControllerKeyboardShortcut() |
There was a problem hiding this comment.
Honor the hold delay before opening text entry
For the common case where the full chord is pressed together, this branch calls notifyControllerKeyboardShortcut() immediately instead of waiting for textInputTriggerDelayMs. That makes the new hold-delay setting ineffective and still lets quick accidental chord presses open the Apple TV keyboard, contrary to the setting description that the buttons must be held for the configured duration.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
We should apply the configured hold delay after the full shortcut is pressed? A quick press of the shortcut shouldn’t open the keyboard.
|
Hi @omgitsalexl Could you please run the SwiftLint, swiftformat on the branch while I test. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dad7c125ad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let shortcutGraceWindow = UInt64(textInputTriggerDelayMs) * 1_000_000 | ||
| let shortcutButtons = physicalKeyboardShortcutButtons(on: controller) | ||
| if var state = keyboardShortcutStates[slot] { | ||
| state.pendingButtons.formUnion(shortcutButtons) |
There was a problem hiding this comment.
Don't merge sequential shortcut taps into a chord
When a user taps one configured shortcut button, releases it, and then taps another before the delay expires, this line keeps the released button in pendingButtons. At the timeout, keyboardShortcutReplayButtons(for: state.pendingButtons) replays every accumulated button as one chord, so with the default Options+Y shortcut the stream receives a synthetic Options+Y tap instead of the two separate game inputs. Clear or replay the released partial before unioning later presses.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
We should preserve separate button presses here. If someone taps Y and then Options, the game should receive two individual taps rather than one combined shortcut.
| guard let (usage, requiresShift) = Self.usageForCharacter(character) else { | ||
| inputLog.info("Skipping unsupported replay character: \(String(character), privacy: .public)") | ||
| continue |
There was a problem hiding this comment.
Don't submit text after dropping unsupported characters
When the Apple TV keyboard returns characters outside this hard-coded HID map (for example accented letters, CJK IME output, or emoji), this path silently skips them; replaySubmittedText still appends Return afterward, so the remote game/chat can receive a truncated or empty submission. Either reject/disable sending when any character is unmapped, or use an input path that preserves the full String.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
This I couldn't test yet but maybe you can validate the text before sending it? If it contains unsupported characters, keep the keyboard open and show an error instead of sending incomplete text.
Also, please avoid writing the character to logs since it could be part of a password.
|
@omgitsalexl I didn't get the chance to test in a game where I need to type which I will do in sometime, need to look for a game where I can input. But did high level testing and noticed that the review comments from the bots are valid. Also, maybe the UI overlay for the text input could be styled a bit better, like centre the text, etc. Also, after entering the text, and clicking on "done" closes the entire overlay, and I was never able to "send" it. |
|
Codex: |
|
I really appreciate the thorough review! I had only tested it myself in a very specific manner, inputting server details mostly. Regarding the done button vs a send button: pressing done closes the window and sends input at the same time. I could definitely make this more clear to the user. The Codex bot does indeed have some good points as well, and yours regarding the potential logging issues. I'll take all these into account and try to get it cleaned up! |
When streaming certain games, they require text input from the user to continue (e.g. Inputting a password to join a dedicated server in Enshrouded, Palworld, or other games). This pull request adds the ability to pull up the tvOS native keyboard, receive input, and then play this input back to the stream as a sequence of characters.
There are settings added to allow customizing the shortcut keys to pull up the native keyboard, and to adjust the hold time needed to display the keyboard; to help prevent crossover between games that may have the same button sequence.