launcher-tauri: run on windows and macOS & new features - #1
Merged
Merged
Conversation
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.
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.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The launcher only built on Linux.
blueris BlueZ over D-Bus and sat in plain [dependencies], solibdbus-syswas 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:
Now 76/76 on Windows, clean under cargo check for aarch64-apple-darwin.