Skip to content

Stop the iPad's no-picture reconnect loop and say to mirror - #99

Merged
whoisaldo merged 5 commits into
mainfrom
fix/ipad-no-picture
Oct 27, 2026
Merged

whoisaldo merged 5 commits into
mainfrom
fix/ipad-no-picture

Conversation

@whoisaldo

@whoisaldo whoisaldo commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

PCs on 0.3.1 and 0.3.2 in Second screen mode can answer the iPad and then take longer than its 10 s first-frame timeout to send a picture. The iPad gave up and showed "Your PC answered, but no picture arrived". Over USB the PC connects the cable again a second later, so the attempts never ended and the PC's screen blinked about every 11 s. Mirror mode works. #97 fixes new PCs; this makes the iPad behave well with the PCs already out there. iPad only: no change to host/ or proto/.

Changes

Message. The no-picture card now reads:

Your PC answered, but no picture arrived
The PC's second screen didn't start. On the PC, choose Mirror my screen (called Main display (mirror) in version 0.3.1), then try again. If it already mirrors, click Restart on the PC first.

If the PC answered at the same Wi-Fi address earlier in the same series of attempts and then goes silent while EternalMonitor restarts on it, the card keeps this message instead of switching to "Your PC didn't answer" (or the router-address card). An answer from the same PC over the cable keeps that Wi-Fi address. A different PC starts a new series. A silent cable keeps "Your PC didn't answer over the cable", since the cable doesn't say which PC is at its other end.

Retry stop. NoPictureStreak counts attempts in a row that one PC answered and that ended without a picture: the timeout fired, or the PC closed or failed the connection first. A PC on 0.3.1 closes the cable a few seconds after it answers, when its second screen restarts the stream, so that close counts too. The count belongs to the PC by the pairing token it gives in its answer: the PC keeps it across restarts and gives it over Wi-Fi and the cable. Two PCs count separately even when they have the same name, and one PC that moves between Wi-Fi and the cable counts on. A PC with pairing off gives no token and counts by its name (or its address if it gives none). With pairing on, renaming a PC keeps its count and resetting its pairing starts a new one. At NoPictureStreak.limit = 2 the iPad ends the reconnect cycle and, over USB, stops taking the cable (as a manual Disconnect does) and leaves the card with Try again up. Unlike a manual Disconnect, the cable stays stopped when the app comes back to the foreground. At the limit the cable close no longer starts the automatic Wi-Fi fallback either; Try again resumes it, and connecting over Wi-Fi by hand still works. Two gives a PC that was only slow once another attempt; a second failure means it fails the same way each time, and with the PC's 1 s redial that is about 22 s of blinking (8 s on 0.3.1's cable) instead of an endless loop. Try again (and Connect USB) starts a new count; a first frame clears it. Attempts the PC never answered don't count, so Wi-Fi blips, unplugged cables and PC restarts that do send a picture reconnect as before.

Diagnostics. The timeout now says goodbye with ByeReason.error (3), which both sides already define, so the PC logs reason=Error rather than UserDisconnect. The iPad logs Disconnect state=connecting reason=error. The [timeout] line and First frame decoded successfully now end with session_id=N ms_since_start=N ms_since_accept=N. The original wording stays first, so existing searches still match.

Support ID. Settings > Diagnostics shows the installation_id that automatic uploads use, labelled Support ID, with a Copy Support ID button. The diagnostics export has Support ID: … as its second line, and the feedback email puts it first in the details. The export's Launch: id is a different id and is unchanged.

SETUP.md and the PC quickstart describe the new card. SETUP.md also mentions the Support ID.

Tests

  • ConnectionProblemTests: the card text, counting up to the limit and resetting it, counting by the PC's pairing token (two PCs with one name apart, one PC renamed or moved counting on) with the name as the fallback when pairing is off, and keeping the message when a PC that answered goes silent at its address, including after the same PC answered over the cable.
  • NoPictureTimeoutTests (new, fake UDP PC): the timeout sends the error goodbye and logs session_id and timings; the first-frame line does too; the cycle stops after two no-picture timeouts and Try again starts a new count; a single slow attempt still reconnects and streams; a PC that answered keeps the no-picture message while it is silent.
  • USBLinkFailureTests: two no-picture timeouts over a real FramedLink pause the cable, the PC's next cable connection is refused, and Try again accepts it again. A PC that answers and then closes (or fails) the cable before the timeout, as 0.3.1 does, stops at the limit too, while cables that end before an answer don't count. The stop outlasts backgrounding and foregrounding. Two PCs with the same name on the cable count separately, and a silent cable doesn't reset or inherit a count. A PC that answered over Wi-Fi and then over the cable, silent at its Wi-Fi address afterwards, keeps the no-picture message.
  • FeedbackTests, SupportDiagnosticsTests: where the Support ID appears and that it equals the upload's installation_id.

Local run on Xcode 16.4 with an iPad Pro 11-inch (M4) on iOS 18.6, the CI configuration: scripts/test_ios.sh -only-testing:EternalMonitorTests ran 260 tests with 0 failures, and -only-testing:EternalMonitorUITests/ConnectScreenTests ran 8 with 0 failures.

PCs on 0.3.1 and 0.3.2 in Second screen mode can take longer than the
iPad's 10 s first-frame timeout to send a picture. The iPad gave up, and
over USB the PC connected the cable again a second later, so the attempts
never ended and the PC's screen blinked with each one.

- The no-picture card now says the PC's second screen didn't start and
  to choose Mirror my screen on the PC, then try again.
- After two no-picture timeouts in a row at the same PC, the iPad ends
  the reconnect cycle and stops taking the cable until Try again. Try
  again starts a new count; a first frame clears it.
- A PC that answered earlier in the series and is silent while it
  restarts keeps the no-picture card instead of "didn't answer".
- The timeout says goodbye with the error reason instead of the user
  one, and the timeout and first-frame lines carry session_id and the
  time since the attempt started and since the PC accepted it.
Settings > Diagnostics shows the installation_id that automatic uploads
use, labelled Support ID, with a Copy button. The diagnostics export and
the feedback email put it near the top, so a message can be matched to
the iPad's uploaded diagnostics. The export's Launch id is a different
id and stays as it is.
A PC on 0.3.1 closes the cable a few seconds after it answers, before the
connect timeout, so the no-picture count never grew and the loop went on.
An attempt the PC answered now counts when it ends without a picture,
whether the timeout fires or the PC closes or fails the connection first.

The count belongs to the PC by the name it answers with, so two PCs on
one cable no longer add up, and a silent cable keeps its own advice. A
cable stopped this way stays stopped when the app comes back to the
foreground, until Try again or Connect USB.
…i address

Two PCs with the same name no longer share a count: the streak follows
the pairing token the PC gives when it answers, and falls back to the
name only when pairing is off. An answer over the cable keeps the
address where the same PC last answered over Wi-Fi.
@whoisaldo
whoisaldo marked this pull request as ready for review October 27, 2026 03:43
@whoisaldo
whoisaldo merged commit 9aba66f into main Oct 27, 2026
6 checks passed
@whoisaldo whoisaldo mentioned this pull request Oct 27, 2026
3 of 4 tasks
@whoisaldo
whoisaldo deleted the fix/ipad-no-picture branch October 27, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants