Skip to content

macOS desktop app window stays above normal windowed apps and will not yield focus (bare Mach-O, not a .app bundle) #10078

Description

@steinybot

Summary

On macOS, a Perry-compiled desktop app's window stays above a normal windowed app and does not go behind it when that app is clicked. Observed over a Chrome window: clicking Chrome does not bring it in front of the Perry window. Behavior over native-fullscreen apps is inconsistent. Some become active when clicked, some do not. The behavior is not universal across all apps.

Environment

  • Perry 0.5.1531 (local build)
  • macOS, Darwin 25.6.0, arm64
  • Native macOS target (perry-ui-macos)

Steps to reproduce

  1. Compile a minimal macOS UI app: perry compile app.ts -o myapp.
  2. Run ./myapp. A window opens and comes to the front.
  3. With a normal windowed app such as Chrome, click it.
  4. It does not come in front. The Perry window stays on top.

Expected

Clicking another app brings that app in front of the Perry window, like any normal macOS app.

Suspected cause

Perry's macOS desktop output is a bare Mach-O executable, not a .app bundle. It embeds a minimal Info.plist as a __TEXT,__info_plist section (crates/perry/src/commands/compile/link/build_and_run.rs: "Perry's direct desktop output is a Mach-O executable, not a .app bundle") and sets the activation policy to Regular at runtime (crates/perry-ui-macos/src/app.rs, setActivationPolicy). A non-bundled process registered this way is not fully known to LaunchServices, so macOS does not reliably reorder its window when another app activates. That fits the inconsistency: the window stays over normal windowed apps but native-fullscreen apps on their own Space are affected differently.

It is not a window-level issue. The main window is at normal level (0). The only setLevel path is gated on the App() level option, which this app does not pass.

Fix confirmed for the windowed case

Wrapping the same binary in a minimal .app bundle makes the window yield normally when another app is clicked:

myapp.app/
  Contents/
    Info.plist            # CFBundleExecutable, CFBundleIdentifier, CFBundlePackageType=APPL
    MacOS/myapp

Suggested fix

Emit a real .app bundle for the macOS target. Perry already builds bundles for iOS, tvOS, watchOS, and visionOS (crates/perry/src/commands/compile/bundle_apple.rs), so the machinery exists.

Separately, for automated or headless runs such as Geisterhand, add an agent launch mode (LSUIElement or accessory activation) so a driven app does not take the foreground.

Scope

macOS desktop apps built with Perry. The exact behavior varies with the other app's window state (normal window vs native fullscreen).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions