Skip to content

Detect Minecraft windows from any launcher, and stop the overlay covering everything - #1

Open
ParalelSt wants to merge 3 commits into
programmerstevie:mainfrom
ParalelSt:main
Open

Detect Minecraft windows from any launcher, and stop the overlay covering everything#1
ParalelSt wants to merge 3 commits into
programmerstevie:mainfrom
ParalelSt:main

Conversation

@ParalelSt

Copy link
Copy Markdown

What's broken

The window picker never finds the game when it's launched from Prism Launcher or
MultiMC. On my machine, Beta 1.8.1 running under Prism reports itself as:

owner="Prism Launcher: b1.8.1"   bundle=com.azul.zulu.java   854x508

WindowFinder matched only windows whose owning app name or title contained
"minecraft", and Prism renames the game process to the instance name — so
there is no "minecraft" anywhere to match. The window is never listed.

Two things made this hard to diagnose:

  1. A permission failure looked identical to a missing window. When
    SCShareableContent throws -3801 (Screen Recording declined), the catch
    returned [], and the UI said "No Minecraft window found. Make sure Minecraft
    is running in windowed mode."
    That points at the game when the real problem is
    a permission the app never got.

  2. App translocation. Opening the release straight from Downloads makes macOS
    run it from a randomized read-only path that changes every launch, so TCC can
    never persist a Screen Recording grant — and the prompt may never appear at
    all. This is what I hit; the app was silently blind with no way to tell why.

What this changes

Detection — scored heuristic instead of a substring match. Strong signals:
"minecraft" in the title/app name, or a JVM bundle identifier (Minecraft is a Java
app whatever launcher starts it, which is what catches renamed instances). Weak
signals (launcher keywords, classic 854x480 geometry, on-screen) only affect
ranking and can never qualify a window alone — a launcher's own window carries the
same name as the game window it spawned. Browsers/chat/editors score negative so a
wiki tab titled "Minecraft Wiki" doesn't outrank the game.

Windows are now ranked, not filtered, with a "Show all windows" fallback, so a
window the heuristic misses is still selectable. Also dropped
onScreenWindowsOnly: true — a window on another Space isn't "on screen" and was
being excluded for that reason alone.

Permissions — permission denial and translocation are reported distinctly, each
with an actionable button. Uses CGPreflightScreenCaptureAccess /
CGRequestScreenCaptureAccess rather than relying on SCShareableContent to
prompt implicitly, which is unreliable for a menu-bar-only .accessory app.
Translocation is a warning, not a hard stop — if capture works anyway the app stays
usable.

Overlay focus — addresses the "overlay stays on top of all windows in that
workspace" glitch from the 0.1.0 release notes. The overlay now shows only while
the captured app is frontmost, so the one-Space-per-Minecraft workaround isn't
needed. Activating this app deliberately doesn't force it visible, otherwise
opening the menu panel would drag the overlay over whatever you were using.

Also fixed along the way: picking a second window without stopping first
orphaned the previous overlay window (nothing left referencing it, so stop()
couldn't close it) while its stream kept writing frames into the new overlay's
view; and stop() awaited before detaching the stream, so a stop in flight could
null out a stream a subsequent start had already installed.

Testing

Verified on macOS 26.6 (arm64) against Minecraft Beta 1.8.1 under Prism Launcher:
the window is detected, the overlay renders correctly, and it hides and reappears
with Minecraft's focus.

The scoring is value-based (WindowFinder.score(appName:title:bundleID:frame:isOnScreen:))
so it can be exercised directly. I ran 16 cases covering the real captured window
data plus regressions — Prism/MultiMC/official launcher windows detected; Prism's
own launcher window, browser tabs titled "Minecraft Wiki", #minecraft chat
channels, maximized non-game windows and unrelated Java apps all rejected.

Three commits, each building independently, so they can be taken separately.

The window filter only matched windows whose owning app name or title
contained "minecraft". That misses the common case: Prism Launcher and
MultiMC rename the game process to the *instance* name, so a Beta 1.8.1
instance reports itself as:

    owner="Prism Launcher: b1.8.1"  bundle=com.azul.zulu.java  854x508

There is no "minecraft" anywhere in that, so the game was never found and
the app was unusable with those launchers.

Replace the substring match with a scored heuristic. Strong signals are
"minecraft" in the title or app name, and a JVM bundle identifier — the
last of which is what catches renamed instances, since Minecraft is a Java
app whatever launcher starts it. Launcher keywords, the classic 854x480
geometry and on-screen state are weak signals that only affect ranking;
they can never qualify a window on their own, because a launcher's own
window carries the same name as the game window it spawned and any 16:9
window would otherwise look like a game.

Browsers, chat clients and editors score strongly negative: a wiki tab or a
channel named #minecraft would otherwise outrank the actual game.

Windows are now listed ranked rather than filtered, with the full list
available as a fallback, so a window the heuristic misses can still be
picked manually.

Also stop passing onScreenWindowsOnly: true. A window on another Space is
not "on screen", so a running game could be excluded for that reason alone.

Since the picker stays on screen while a capture runs, selecting a second
window now tears the first one down. Previously it orphaned the old overlay
window with nothing left holding a reference to it, and left the old stream
writing its frames into the new overlay's view. Detach the stream in stop()
before suspending, too, so a stop still in flight cannot null out a stream
that a subsequent start has already installed.
A Screen Recording denial was swallowed and returned as an empty window
list, so the UI reported "No Minecraft window found. Make sure Minecraft is
running in windowed mode." That sends users to check the game when the
actual problem is a permission the app never obtained — the two states were
indistinguishable.

Surface them separately, and address two ways the permission silently never
gets granted in the first place:

- The app relied on SCShareableContent to raise the prompt implicitly.
  That is unreliable for a menu-bar-only (.accessory) app. Use
  CGPreflightScreenCaptureAccess to read the current grant and
  CGRequestScreenCaptureAccess to raise the prompt explicitly.

- macOS runs quarantined, unsigned apps from a randomized read-only path
  (app translocation), which is where the app lands when opened straight
  from Downloads. Because that path changes every launch, TCC can never
  persist a grant, so the app stays permanently blind with no indication
  why. Detect it and tell the user to move the app to Applications.

Translocation is reported as a warning rather than a hard stop, and the
window picker stays reachable throughout: if capture happens to work
anyway, the app remains fully usable.

Also show the version in the panel header. Copies of this app accumulate,
and without it there is no way to tell which build is running.
The overlay window is .floating, which puts it above every normal window on
its Space. Since its visibility never changed, it covered whatever the user
switched to, and the documented workaround was to give Minecraft a Space of
its own.

Track the owning app's activation and show the overlay only while that app
is frontmost. The overlay now behaves like part of Minecraft rather than a
permanent floating layer, and the separate-Space workaround is unnecessary.

Activating this app is deliberately not treated as "show": opening the menu
bar panel makes this app frontmost, and forcing the overlay visible there
would drag it on top of whatever the user was actually working in. Leaving
visibility untouched keeps it correct in both directions.

When the captured window reports no owning process there is nothing to
follow, so the overlay stays on top as before — say so in the status text
rather than quietly not doing what the app advertises.

Also document the permission and translocation traps in SETUP.md, describe
the new window picker, and record that this tracking is app-level rather
than window-level.
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.

1 participant