Skip to content

fix(macos): relaunch via 'open -n' on UI scale restart#2434

Merged
ten9876 merged 2 commits into
aethersdr:mainfrom
chibondking:fix/ui-scale-macos-restart
May 7, 2026
Merged

fix(macos): relaunch via 'open -n' on UI scale restart#2434
ten9876 merged 2 commits into
aethersdr:mainfrom
chibondking:fix/ui-scale-macos-restart

Conversation

@chibondking

Copy link
Copy Markdown
Collaborator

Summary

  • On macOS, applyUiScale() was restarting the app via QProcess::startDetached(applicationFilePath(), ...), which launches the raw binary inside the .app bundle directly. This bypasses Launch Services — the relaunched instance shows as a separate dock entry, loses the correct activation policy, and on notarized/sandboxed builds can fail entirely.
  • Fix walks up from the binary path (Foo.app/Contents/MacOS/Foo → Foo.app) and relaunches via open -n <bundle>. Falls back to direct exec when not running from a bundle (dev/CI builds).

Notes

The previously-noted "Retina DPR compounding" concern in #2432 was a misdiagnosis — QT_SCALE_FACTOR operates on Qt's logical pixel layer, which already sits above the Retina backing scale factor. There is no compounding visible to the user; the scale behaves correctly on Retina hardware without any adjustment.

Related

Completes the macOS leg of the UI Scale fix series started in #2432.

Test plan

  • macOS (.app bundle): change UI Scale, click Yes to restart — app relaunches as a single dock entry with normal activation (not a floating/unnamed window)
  • macOS (dev build, no bundle): same flow falls back to direct binary exec without errors
  • Linux / Windows: unaffected — #ifdef Q_OS_MAC guard ensures no behaviour change

🤖 Generated with Claude Code

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @chibondking — the bundle-walk + open -n approach is the right shape for this, and the .app suffix check with direct-exec fallback for dev builds is a nice touch. The diagnosis (startDetached on the inner Mach-O bypasses Launch Services / activation policy) matches what notarized macOS apps actually need.

One minor behavior asymmetry worth considering:

CLI arguments are silently dropped on the bundle path. The else branch and the non-macOS path both forward QCoreApplication::arguments().mid(1), but open -n <bundle> does not pass any of them through. Anyone launching AetherSDR with flags (e.g. a debug/log option, or a future workspace-file argument) would lose them across a UI-scale restart. open supports --args for exactly this:

QStringList openArgs = {"-n", d.absolutePath()};
const QStringList childArgs = QCoreApplication::arguments().mid(1);
if (!childArgs.isEmpty()) {
    openArgs << "--args";
    openArgs << childArgs;
}
QProcess::startDetached("open", openArgs);

Probably nobody hits this today, but it costs little to keep parity with the other two branches.

Everything else looks clean — narrow Q_OS_MAC guard, no behavior change for Linux/Windows, the comment explains the why, and the cdUp failure mode degrades gracefully into the dev-build fallback. The note about the Retina DPR concern from #2432 being a misdiagnosis is also useful context.

Not blocking on the --args suggestion.

@chibondking

Copy link
Copy Markdown
Collaborator Author

Good catch — applied in 5216ff6. CLI args are now forwarded via open --args when relaunching through the bundle.

chibondking and others added 2 commits May 6, 2026 19:48
QProcess::startDetached(applicationFilePath()) launches the raw binary
inside the .app bundle, bypassing Launch Services. On macOS this causes
the relaunched instance to appear as a separate dock entry and lose the
correct activation policy; on notarized or sandboxed builds it can fail
entirely.

Fix adds a Q_OS_MAC branch in applyUiScale() that walks up three path
components from the binary (Foo.app/Contents/MacOS/Foo → Foo.app) and
relaunches via 'open -n <bundle>'. Falls back to direct exec when not
running from a bundle (dev/CI builds).

The previously-noted "Retina DPR compounding" concern was a misdiagnosis:
QT_SCALE_FACTOR operates on Qt's logical pixel layer, which is below the
Retina backing scale factor — there is no compounding visible to the user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
'open -n <bundle>' was silently dropping any command-line arguments
passed to the original process. Forward them via 'open --args' to keep
parity with the Linux/Windows direct-exec path.
@ten9876 ten9876 force-pushed the fix/ui-scale-macos-restart branch from 5216ff6 to e1ff255 Compare May 7, 2026 02:48
@ten9876

ten9876 commented May 7, 2026

Copy link
Copy Markdown
Collaborator

Claude here — your branch was based off main before #2432 landed, so the main.cpp hunk became a duplicate of what's already on main (with a slightly different Qt API style). Rebased the branch onto current main and dropped that first commit so only the two macOS commits remain. Force-pushed back to your fork; CI should re-run shortly. The MainWindow.cpp relaunch fix is the real prize here, and it stands on its own cleanly.

73, Jeremy KK7GWY & Claude (AI dev partner)

@ten9876 ten9876 merged commit 8d2cd0f into aethersdr:main May 7, 2026
4 checks passed
@ten9876

ten9876 commented May 7, 2026

Copy link
Copy Markdown
Collaborator

Claude here — completes the UI Scale series with the right macOS-bundle relaunch pattern. The Launch Services route via 'open -n' is exactly what notarized/sandboxed builds need; the .app suffix check + direct-exec fallback keeps dev/CI builds working too. And the --args pass-through is a thoughtful detail. Thanks also for the Retina compounding clarification — agreed, QT_SCALE_FACTOR sits above the backing-store DPR. Merged.

73, Jeremy KK7GWY & Claude (AI dev partner)

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