Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

112 changes: 63 additions & 49 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,66 @@
## Next Windows release

Not released yet.

- When the second screen doesn't appear, the Windows Stream page says why and
what to do: the display driver isn't installed (run Setup again), Windows
couldn't verify the driver's signature, the driver stopped with an error
(with the Windows code: restart, then run Setup again), or the driver ran but
Windows added no screen. When Windows adds the screen but keeps the desktop
off it, the page says to choose Extend with Windows key + P or in Display
settings, and the next try waits 30 seconds for it. EternalMonitor does not
change the display layout itself. The display task no longer reports success
when the driver is missing or stopped with an error. After any failed attempt the support
diagnostics and **Copy logs** hold a display snapshot: the device state, the
graphics cards and the display paths Windows reports. The snapshot leaves out
the PC's name and the user's name; the rest of the log still contains them.
Before, every case read "no display appeared in time".
- The second screen has 30 seconds to appear instead of 10, while the iPad
shows the mirror. On some PCs Windows adds it only after more than 10 seconds,
and those connections stayed on the mirror.
- The second screen is drawn by the graphics card that drives the main screen,
whether or not **Match the iPad's resolution** is on. Before, the driver
chose the card with the most memory, which on laptops with Intel and NVIDIA
graphics drives no screen; in 0.3.1 diagnostics none of those laptops got the
second screen. A card Windows lists twice under one name, as on some
laptops, is still named when only its first listing drives a screen; when
two cards with one name could, the driver still chooses. When another app
installed the driver and the user or that app named a card, EternalMonitor
leaves that name alone. The log records which card the driver used.
- The second screen comes up at the iPad's resolution. Windows restores the
size it last saved for the second screen, and in 0.3.1 diagnostics 4 of the 5
PCs whose second screen appeared got a tiny, blurry 800×600 one. EternalMonitor
now sets the second screen's size itself, and only that display's: the
iPad's size, the sharpest size that fits when the driver doesn't offer it, or
1920×1080 while the iPad's size isn't known. The log records the size once.
- A PC set to **Mirror my screen** shows the first picture without waiting for
the virtual display to be turned off at startup. A slow or stuck display task
held it for up to 19 s in 0.3.1, and about 2 s on a healthy PC.
- Settings says that **Match the iPad's resolution** applies the next time the
second screen starts, when the iPad connects again. Before, changing it
seemed to do nothing.
- Running EternalMonitor-Setup.exe again repairs a virtual display driver that
Setup installed when none of its devices works, for example after the device
was removed in Device Manager. Working devices are never removed, and a
driver another app installed is left alone with a message saying so. Before,
Setup kept the existing driver and stopped with "Windows did not finish
installing the virtual display driver".
- Support diagnostics name Windows 11 from the build number. Windows 11 keeps
"Windows 10" in the registry, which earlier versions reported as the system.
## EternalMonitor v0.3.3

Released October 27, 2026. Install the Windows and iPad 0.3.3 updates together;
each still works with the other app on 0.3.1 or 0.3.2.

This release fixes **Second screen** on PCs where it didn't start, most often
laptops with Intel and NVIDIA graphics. The iPad then said **Your PC answered,
but no picture arrived**, and over USB the PC's screen blinked and Windows
played its connect and disconnect sounds every few seconds until the cable was
unplugged. Choosing **Mirror my screen** on the PC was the way around it.

### What changed

- The iPad shows the PC's main screen as soon as it connects, while the second
screen starts. Once Windows adds it, the PC switches to it; if it shows no
picture within 5 seconds, the iPad goes back to the mirror. Windows now gets
up to 30 seconds to add it, not 10; if it never does, the mirror stays. Either way the PC says the second screen
didn't start, and later connections mirror until you click **Try again**,
restart the stream or change the mode.
- The PC turns the second screen on or off at most once every 10 seconds and
keeps it on for 10 seconds after the iPad leaves, so a quick reconnect reuses
it. The screen no longer blinks in a loop.
- The PC tries to start the second screen on the graphics card that drives the
main screen. Before, the driver chose the card with the most memory, which on
Intel + NVIDIA laptops drives no screen. This should help those laptops; if
the second screen still doesn't start, **Mirror my screen** works. The driver
still chooses when two cards share a name, when the PC can't write the
driver's settings, or when another app installed the driver and chose a card.
- With **Match the iPad's resolution** on, as it is by default, the second
screen starts at the iPad's resolution instead of a small, blurry 800×600.
When the driver doesn't offer that size, it uses the largest one that fits.
- When the second screen doesn't appear, the PC's Stream page says why and what
to do: run Setup again, restart the PC, or choose Extend with Windows key + P.
Running Setup again repairs a display driver Setup installed whose device
was removed or stopped working.
- The first picture arrives sooner on NVIDIA and Intel graphics, especially on
a still second screen. **Mirror my screen** no longer waits
for the second screen to turn off at startup.
- After two attempts in a row where the PC answered but sent no picture, the
iPad stops reconnecting and says to choose **Mirror my screen** on the PC
(**Main display (mirror)** in 0.3.1). **Try again** starts over. This also
ends the blinking with PCs still on 0.3.1 or 0.3.2.
- The iPad shows a **Support ID** in Settings > Diagnostics, with **Copy
Support ID**, and feedback emails include it. PC Settings says **Match the
iPad's resolution** applies the next time the second screen starts.
- After a failed attempt, the support diagnostics and **Copy logs** hold a
display snapshot: why the second screen didn't start, and the graphics cards
and displays Windows reports. The snapshot leaves out the PC's name and the
user's name; the rest of the log still contains them. Diagnostics name
Windows 11 correctly.

### What to test

On a laptop with Intel and NVIDIA graphics, choose **Second screen** and connect
the iPad over Wi-Fi, then over USB. The PC's screen should appear at once, then
the second screen a few seconds later, at the iPad's resolution (or the largest
size that fits) while **Match the iPad's resolution** is on. If the second
screen doesn't come up, the iPad should keep the PC's screen with no blinking or
connect sounds, and the PC should say why. Send the PC's **Copy logs** text with
the time; it includes the PC's name.

With the iPad on 0.3.3 and a PC on 0.3.2 whose second screen fails, the iPad
should stop after two tries and say to choose **Mirror my screen**.

## EternalMonitor v0.3.2

Expand Down
2 changes: 1 addition & 1 deletion host/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "eternal-host"
version = "0.3.2"
version = "0.3.3"
edition = "2021"

[dependencies]
Expand Down
6 changes: 3 additions & 3 deletions host/tests/gui_snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ fn feedback_and_star(shared: &SharedControl, dir: &std::path::Path, results: &mu
window.get_by_label("Copy message").click();
window.step();
let copied = copied_text(&window).expect("Copy message copies");
assert!(copied.starts_with("To: hello@sideband.studio\nSubject: EternalMonitor 0.3.2 for Windows: Something I like"), "{copied}");
assert!(copied.starts_with("To: hello@sideband.studio\nSubject: EternalMonitor 0.3.3 for Windows: Something I like"), "{copied}");
assert!(copied.contains("Drawing on the iPad in Krita feels great."));
assert!(copied.contains("Setup: Second screen, USB, iPad 2420 × 1668 at 120 Hz"));
assert!(!copied.contains("Test iPad Pro") && !copied.contains("192.0.2.10"));
Expand All @@ -885,7 +885,7 @@ fn feedback_and_star(shared: &SharedControl, dir: &std::path::Path, results: &mu
let url = opened_url(&window).expect("Open in my email app opens a mailto link");
assert!(
url.starts_with(
"mailto:hello@sideband.studio?subject=EternalMonitor%200.3.2%20for%20Windows"
"mailto:hello@sideband.studio?subject=EternalMonitor%200.3.3%20for%20Windows"
),
"{url}"
);
Expand All @@ -902,7 +902,7 @@ fn feedback_and_star(shared: &SharedControl, dir: &std::path::Path, results: &mu
let copied = copied_text(&window).unwrap();
// The subject keeps the kind and version, for sorting mail.
assert!(
copied.contains("Subject: EternalMonitor 0.3.2 for Windows: Something I like"),
copied.contains("Subject: EternalMonitor 0.3.3 for Windows: Something I like"),
"{copied}"
);
assert!(
Expand Down
Binary file modified host/tests/snapshots/feedback-ask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/feedback-panel-long-minimum.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/feedback-panel-long.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/feedback-panel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/pairing-qr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/performance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/settings-about.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/sidebar-star-hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/sidebar-star-thanks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/sidebar-star.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/software-and-display-task-failure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/stream-connected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/update-banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified host/tests/snapshots/update-popup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
114 changes: 55 additions & 59 deletions ios/TESTFLIGHT_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,63 @@
# EternalMonitor 0.3.2: What to Test
# EternalMonitor 0.3.3: What to Test

Released October 22, 2026. Install the Windows and iPad 0.3.2 updates together;
an iPad on 0.3.1 still works with the Windows changes.
Released October 27, 2026. Install the Windows and iPad 0.3.3 updates together;
each still works with the other app on 0.3.1 or 0.3.2.

This release fixes **Second screen** on PCs where it didn't start, most often
laptops with Intel and NVIDIA graphics. The iPad then said **Your PC answered,
but no picture arrived**, and over USB the PC's screen blinked and Windows
played its connect and disconnect sounds every few seconds until the cable was
unplugged. Choosing **Mirror my screen** on the PC was the way around it.

### What changed

- Apple Pencil lands under the tip when another monitor sits left of or above
the main display, a cancelled stroke resumes instead of dropping, and Pencil
works as a mouse if Windows cannot create its pen device.
- The iPad can fill its whole screen: choose **Picture: Fill** in Settings or
tap the arrows next to the settings button. Fill trims the edges of the PC
picture that don't fit; **Fit** still shows all of it, with bars.
- Plain-language messages in both apps say what happened and what to do, with
**Try again**, **Search again** or **Open Settings**. The iPad looks for PCs
as soon as it opens and spots a pairing code or router address typed as the
PC's address. The PC's Stream page asks **Use the iPad as** (**Mirror my
screen** or **Second screen**) and says why the picture paused while Windows
withholds the screen.
- Windows updates itself: **Update now** checks the installer's SHA-256,
installs it and reopens EternalMonitor, waiting for streaming to stop or for
**Stop and update**. The iPad says when the PC is updating and when a new
TestFlight build is ready. Both apps say which one to update when versions
differ. A popup recommends each new version, and the PC says when the iPad
app is outdated.
- The PC window opens on graphics drivers that crashed 0.3.1 at startup. If
the host can't start or stops unexpectedly, it names the error and log file,
and a helper process reports the crash and tries to turn the second screen
off. Opening EternalMonitor again brings the running window to the front.
- EternalMonitor no longer opens a black console window next to the app.
- A USB connection stays up when the stream restarts. Capture blocked by the
lock screen or a display change retries by itself. A hung or missing display
task no longer stalls the stream. At quit, EternalMonitor tries to turn the
second screen off even while Windows' display task is slow, and if it can't,
a helper process tries again.
- PC audio starts cleanly and survives a large packet. With no iPad connected
the PC stops encoding its screen.
- The installer allows display traffic on work or school networks and names
the Windows version needed on older Windows. With VoiceOver on, the iPad's
stream controls stay until you hide them.
- Logs collapse repeated lines and keep their last lines at quit. A Known
issues page and the setup guide's tables list every message and what to do.
- **Send feedback** in both apps writes an email to the studio with the app
versions and setup filled in; nothing is sent until you press Send. The iPad
attaches its Diagnostics report, which you can remove, and problem cards
offer **Report this problem**. Without an email app, **Copy message** works
instead. After a few long sessions each app asks once how it's going, and
the PC sidebar has a card for starring EternalMonitor on GitHub.
- The iPad shows the PC's main screen as soon as it connects, while the second
screen starts. Once Windows adds it, the PC switches to it; if it shows no
picture within 5 seconds, the iPad goes back to the mirror. Windows now gets
up to 30 seconds to add it, not 10; if it never does, the mirror stays. Either way the PC says the second screen
didn't start, and later connections mirror until you click **Try again**,
restart the stream or change the mode.
- The PC turns the second screen on or off at most once every 10 seconds and
keeps it on for 10 seconds after the iPad leaves, so a quick reconnect reuses
it. The screen no longer blinks in a loop.
- The PC tries to start the second screen on the graphics card that drives the
main screen. Before, the driver chose the card with the most memory, which on
Intel + NVIDIA laptops drives no screen. This should help those laptops; if
the second screen still doesn't start, **Mirror my screen** works. The driver
still chooses when two cards share a name, when the PC can't write the
driver's settings, or when another app installed the driver and chose a card.
- With **Match the iPad's resolution** on, as it is by default, the second
screen starts at the iPad's resolution instead of a small, blurry 800×600.
When the driver doesn't offer that size, it uses the largest one that fits.
- When the second screen doesn't appear, the PC's Stream page says why and what
to do: run Setup again, restart the PC, or choose Extend with Windows key + P.
Running Setup again repairs a display driver Setup installed whose device
was removed or stopped working.
- The first picture arrives sooner on NVIDIA and Intel graphics, especially on
a still second screen. **Mirror my screen** no longer waits
for the second screen to turn off at startup.
- After two attempts in a row where the PC answered but sent no picture, the
iPad stops reconnecting and says to choose **Mirror my screen** on the PC
(**Main display (mirror)** in 0.3.1). **Try again** starts over. This also
ends the blinking with PCs still on 0.3.1 or 0.3.2.
- The iPad shows a **Support ID** in Settings > Diagnostics, with **Copy
Support ID**, and feedback emails include it. PC Settings says **Match the
iPad's resolution** applies the next time the second screen starts.
- After a failed attempt, the support diagnostics and **Copy logs** hold a
display snapshot: why the second screen didn't start, and the graphics cards
and displays Windows reports. The snapshot leaves out the PC's name and the
user's name; the rest of the log still contains them. Diagnostics name
Windows 11 correctly.

### What to test

On a PC where 0.3.1 closed right after opening, install this build: the window
should appear, or a message should name the error and log file. Send that file
with the time.

On a PC with 0.3.1, download the 0.3.2 installer and run it over 0.3.1;
0.3.1's banner only offers **View release**. From 0.3.2 on, **Update now**
installs a later build in place: once one is out, click it, approve the
prompt, and check that the new version opens, once while streaming with
**Stop and update**. On the iPad, tap **Open TestFlight** from the banner.

With a second monitor left of the main display, touch each corner of the iPad
picture with Apple Pencil; the pointer should be under the tip. Repeat with the
extended iPad display and with 125% scaling.
On a laptop with Intel and NVIDIA graphics, choose **Second screen** and connect
the iPad over Wi-Fi, then over USB. The PC's screen should appear at once, then
the second screen a few seconds later, at the iPad's resolution (or the largest
size that fits) while **Match the iPad's resolution** is on. If the second
screen doesn't come up, the iPad should keep the PC's screen with no blinking or
connect sounds, and the PC should say why. Send the PC's **Copy logs** text with
the time; it includes the PC's name.

Tap **Send feedback** in Settings on the iPad and click it in the PC's sidebar:
check the email it writes, and tell us what you think.
With the iPad on 0.3.3 and a PC on 0.3.2 whose second screen fails, the iPad
should stop after two tries and say to choose **Mirror my screen**.
4 changes: 2 additions & 2 deletions ios/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ targets:
PRODUCT_BUNDLE_IDENTIFIER: com.eternal.monitor
TARGETED_DEVICE_FAMILY: "2"
SUPPORTS_XR: "NO"
MARKETING_VERSION: "0.3.2"
CURRENT_PROJECT_VERSION: "7"
MARKETING_VERSION: "0.3.3"
CURRENT_PROJECT_VERSION: "8"
DEVELOPMENT_TEAM: "9X79V37Q89"
CODE_SIGN_STYLE: Automatic
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
Expand Down
2 changes: 1 addition & 1 deletion proto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "eternal-wire"
version = "0.3.2"
version = "0.3.3"
edition = "2021"

[dependencies]
Expand Down
Loading