Skip to content

launcher-tauri: run on windows and macOS & new features - #1

Merged
Hyphaed merged 3 commits into
Hyphaed:gb/launcher-taurifrom
psnwd:pr-566
Sep 11, 2026
Merged

Hyphaed merged 3 commits into
Hyphaed:gb/launcher-taurifrom
psnwd:pr-566

Conversation

@psnwd

@psnwd psnwd commented Sep 11, 2026

Copy link
Copy Markdown

The launcher only built on Linux. bluer is BlueZ over D-Bus and sat in plain [dependencies], so libdbus-sys was pulled in on every target and its build script failed looking for pkg-config. Gate it behind Linux and give bluetooth.rs a backend per platform instead: WinRT device enumeration on Windows, IOBluetooth on macOS, and an explicit unsupported error elsewhere. Where a platform has no app-facing call for something -- connect/disconnect on Windows, removing a pairing on macOS -- say so rather than offer a button that does nothing.

Report adapter state through a new bluetooth_adapter_state command. A missing adapter and a switched-off one both yield an empty device list, so the panel now tells them apart. Listing devices no longer goes through the Linux helper that calls set_powered(true): asking whether the radio is on must not be what turns it on.

Emulator discovery hardcoded _Build/linux/install, so Launch could never find the binary on another OS.

The folder browser showed canonicalize()'s verbatim ?\C:\Users\name form, and a drive root has no parent, so there was no way to reach another drive. Trim the prefix and add a This PC level above the drive roots, which is also where the picker now opens on Windows.

Write the supervisor's launch spec with tempfile rather than a predictable /tmp path: the spec names a binary the supervisor then executes, so a pre-created path was a way for another local account to choose it. Record the play start before handing off, since both processes read-modify-write the same playtime.json and the supervisor's matching stop can fire immediately when a game crashes on launch.

Test suite was 67/72 on Windows, not the 70/72 the branch reported:

  • The ini fixtures are byte-exact, but nothing pinned their line endings, so core.autocrlf checked them out as CRLF against an LF writer.
  • build_args asserted a POSIX separator for a path built by Path::join.
  • bvh_stub_enabled defaulted to true while its own doc comment says off, and was written unconditionally -- so a Qt-written Kyty.ini could never round-trip, and every file this launcher touched gained a key the Qt launcher knows nothing about.

Now 76/76 on Windows, clean under cargo check for aarch64-apple-darwin.

The launcher only built on Linux. `bluer` is BlueZ over D-Bus and sat in
plain [dependencies], so `libdbus-sys` was pulled in on every target and
its build script failed looking for pkg-config. Gate it behind Linux and
give bluetooth.rs a backend per platform instead: WinRT device
enumeration on Windows, IOBluetooth on macOS, and an explicit unsupported
error elsewhere. Where a platform has no app-facing call for something --
connect/disconnect on Windows, removing a pairing on macOS -- say so
rather than offer a button that does nothing.

Report adapter state through a new bluetooth_adapter_state command. A
missing adapter and a switched-off one both yield an empty device list,
so the panel now tells them apart. Listing devices no longer goes through
the Linux helper that calls set_powered(true): asking whether the radio
is on must not be what turns it on.

Emulator discovery hardcoded _Build/linux/install, so Launch could never
find the binary on another OS.

The folder browser showed canonicalize()'s verbatim \?\C:\Users\name
form, and a drive root has no parent, so there was no way to reach
another drive. Trim the prefix and add a This PC level above the drive
roots, which is also where the picker now opens on Windows.

Write the supervisor's launch spec with tempfile rather than a
predictable /tmp path: the spec names a binary the supervisor then
executes, so a pre-created path was a way for another local account to
choose it. Record the play start before handing off, since both processes
read-modify-write the same playtime.json and the supervisor's matching
stop can fire immediately when a game crashes on launch.

Test suite was 67/72 on Windows, not the 70/72 the branch reported:

- The ini fixtures are byte-exact, but nothing pinned their line endings,
  so core.autocrlf checked them out as CRLF against an LF writer.
- build_args asserted a POSIX separator for a path built by Path::join.
- bvh_stub_enabled defaulted to true while its own doc comment says off,
  and was written unconditionally -- so a Qt-written Kyty.ini could never
  round-trip, and every file this launcher touched gained a key the Qt
  launcher knows nothing about.

Now 76/76 on Windows, clean under cargo check for aarch64-apple-darwin.
@psnwd psnwd changed the title launcher-tauri: run on windows and macos launcher-tauri: run on windows and macOS Sep 11, 2026
Backing out of a game opened from Home dumped the user in the Library
grid. The detail pane lives inside Library, so "up one level" meant the
grid -- right when the grid is where you came from, wrong when Home's
"View details" jumped straight past it. Track which view opened the pane
and return there. handleBack now reads `view` directly rather than
calling setSelectedGamePath inside a setView updater, which fired a side
effect during the update.

Returning to Home also landed on the TopBar's Search icon. FocusNav
remembers each view's last focused element, and the TopBar is in every
view, so leaving Home through its Search icon recorded that icon as
Home's focus for good. Mark the bar as chrome and skip remembering it.

Game folders reached the emulator as `\?\F:\Games`: scanner canonicalizes
each one to dedupe spellings, and on Windows that returns the verbatim
form, which then became the `--game` argument, the key in playtime.json
and the path shown in the UI. Trim it with the same helper the folder
browser uses.

The console cleared itself on every launch, so the output explaining why
a run just died was destroyed by the next attempt. Keep it, separated per
run, until the user clears it or closes the app.

Session logs are now written to `logs/session-YYYYMMDD-HHMMSS.log`, one
per launch, headed with the game and full argv, newest 20 kept. Both
launch paths feed it: the in-app reader tees each line it streams, and
the supervisor redirects the child's output into it. The Console page can
open the folder, so reporting a crash means attaching a file. Timestamps
are UTC -- a filename that shifts with the reader's timezone is not
stable to sort or cite.

That folder is `<config>/Kyty/Launcher/` rather than Tauri's
`app_data_dir()`, which names it after the bundle identifier
(`io.github.kytyps5.launcher`). Fine for a folder nobody opens; not fine
now that the app tells people to fetch a log out of it. Kyty.ini already
lives in `<config>/Kyty/`. Existing data is moved across on first run.

The emulator's own console window is suppressed on Windows, with no
setting: its output is already captured twice over, and a user who wants
a live terminal picks the External terminal launch mode, which is what
that mode is for.

Also: text selection off outside real text entry (this is a gamepad
dashboard, and dragging across a game title only ever left a stray
highlight), and the 1px hover underline on toggles is gone -- row-based
toggles carry no inline caption, so it rendered as a dash floating under
the switch.
The Audio page only ever offered "System default" on Windows: audio.rs
shelled out to pactl, which does not exist there, so enumeration returned
nothing every time. Enumerate through WinRT device enumeration instead
(AudioRender/AudioCapture, skipping disabled endpoints); Linux keeps the
pactl path.

Input devices are now listed and selectable too, symmetric with output:
PULSE_SOURCE alongside PULSE_SINK, both re-applied at startup since a
process environment variable does not survive a relaunch. That is enough
on Linux, where the emulator inherits this process's environment.

Windows has no per-process routing a launcher can apply to a child it did
not write, and kyty_emulator exposes no audio flags, so selecting a device
there cannot move a game's audio. The page says so and points at the
Volume mixer rather than offering a control that quietly does nothing.

The library filter flyout could only be dismissed by the button that
opened it. Close it on a click anywhere else, on pointerdown so it is gone
before the click lands, with the trigger exempt -- otherwise its own
toggle would immediately reopen what the outside handler just closed.

The top bar's back button sat flush in the window corner while the window
controls opposite it had a 10px gutter, and a fixed-height button in a
stretch row rode the top edge with the spare 4px below it.

Profile settings: deleting a profile fired on the first click of a trash
icon, with no confirmation and no undo. It now asks in place, the same
two-step GameDetail already uses for removing save data. The list, the
field that creates a profile and the preferences belonging to the active
profile ran together unlabelled, so the create row read as one more
profile entry -- headings and a rule separate them. "New profile" on an
empty field silently did nothing, which reads as broken rather than as a
refusal; it is disabled instead. Escape now abandons a rename, which
previously could only be committed. The avatar circle was a 14-line
inline style repeated per row, unable to carry hover or focus and already
drifted from ProfileView's own copy; it is one class now.
@psnwd psnwd changed the title launcher-tauri: run on windows and macOS launcher-tauri: run on windows and macOS & new features Sep 11, 2026
@Hyphaed
Hyphaed merged commit 021652a into Hyphaed:gb/launcher-tauri Sep 11, 2026
Hyphaed added a commit that referenced this pull request Sep 11, 2026
…tion

Swap src/launcher-tauri wholesale for fork/gb/launcher-tauri (merged PR #1),
which independently fixed the same cross-platform build/runtime issues and
was verified 76/76 on real Windows CI. Our own from-scratch build and PR#1
turned out to be two unrelated implementations of the same app; reconciling
file-by-file is not viable (every file conflicts as add/add, including the
entire UI). Every non-launcher-tauri file (engine, kernel, graphics, tests)
is untouched.

Follow-up commits reapply gb/new-ui-squashed's own launcher-tauri polish
work (cursor-hide fix, exit-confirm page, close-on-launch default, etc.)
against this new base, plus whatever the fix-those-reported-issues session
found that PR#1 doesn't already cover.
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