From 4fd5dbe695a6600bda1f3fa4a9d071421eaae9c6 Mon Sep 17 00:00:00 2001 From: olcxja Date: Sat, 26 Sep 2026 14:31:10 +0200 Subject: [PATCH] fix launching shortcuts --- src/main.js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/main.js b/src/main.js index 3c5af33..f66d261 100644 --- a/src/main.js +++ b/src/main.js @@ -1,7 +1,7 @@ 'use strict' const { app } = require('electron') -const { ensureDirs } = require('./paths') +const { ensureDirs, DIRS } = require('./paths') const i18n = require('./i18n') const wines = require('./wines') const { registerIpc } = require('./ipc') @@ -27,13 +27,29 @@ let autoQuitWhenDone = false // headless boot: quit after that game exits const getWindow = () => win // --- single instance --------------------------------------------------------- +// Diagnostics: the shortcut handoff path is invisible otherwise (a failing +// handoff just "does nothing" for the user). Everything lands in a small +// trace file next to the launcher data so problems are reproducible. +function trace(msg) { + try { + const file = path.join(DIRS.DATA, 'instance-trace.log') + // keep the trace tiny: drop it once it grows past ~64 KiB + try { + if (fs.existsSync(file) && fs.statSync(file).size > 64 * 1024) fs.rmSync(file, { force: true }) + } catch {} + fs.appendFileSync(file, `${new Date().toISOString()} ${msg}\n`) + } catch {} +} + // A second launcher invocation (e.g. a desktop shortcut with --launch ) // hands its arguments to the running instance and exits immediately. const gotLock = app.requestSingleInstanceLock() +trace(`boot argv=${process.argv.slice(1).join(' ')} gotLock=${gotLock}`) if (!gotLock) { app.quit() } else { app.on('second-instance', (e, argv) => { + trace(`second-instance argv=${argv.join(' ')}`) const id = parseLaunchId(argv) lastHandoffAt = Date.now() if (id) launchGame(id) @@ -49,7 +65,16 @@ let lastHandoffAt = 0 function parseLaunchId(argv) { const args = Array.isArray(argv) ? argv : process.argv const i = args.indexOf('--launch') - if (i !== -1 && args[i + 1]) return args[i + 1] + if (i !== -1) { + // Chromium injects its own flags into the second instance's argv and they + // can land BETWEEN --launch and the value (e.g. `--launch + // --allow-file-access-from-files 1790414564627`), so skip anything that + // looks like a flag and take the first non-flag token. + for (let j = i + 1; j < args.length; j++) { + if (!args[j].startsWith('--')) return args[j] + } + return null + } const eq = args.find(a => a.startsWith('--launch=')) return eq ? eq.slice('--launch='.length) : null } @@ -169,8 +194,10 @@ function wireWindow(w) { let gamesService = null async function launchGame(id) { + trace(`launchGame ${id} serviceReady=${!!gamesService}`) if (!gamesService) return const res = await gamesService.start(getWindow(), id) + trace(`launchGame ${id} result=${JSON.stringify(res).slice(0, 200)}`) if (res.ok) { rebuildTrayMenu() // headless boot: when the auto-started game finishes and nothing else is