feat(desktop): launch from the applications list (folio-style)

- launch-keynctr.sh: builds renderer/electron main if missing, exports
  KEYNCTR_ENABLE_GPU=1 (software rendering dies 'GPU process isn't
  usable' on this Hyprland box), execs bundled electron with
  --class=keynectr for WM_CLASS grouping.
- keynctr.desktop installed at ~/.local/share/applications/ (validated,
  icon = public/icon.png, categories Utility, StartupWMClass keynectr).
- requestSingleInstanceLock: second launch focuses the existing window
  (app.exit(0) in the doomed instance) instead of a duplicate shell
  fighting the vault.
Verified via gtk-launch: 'keynectr | Keynctr' window maps; second
gtk-launch keeps exactly 1 window.
This commit is contained in:
Avi 2026-09-30 09:35:25 -05:00
commit fac4ba3cde
2 changed files with 42 additions and 0 deletions

View file

@ -1002,6 +1002,24 @@ if (process.platform === 'linux') {
app.setDesktopName('keynectr.desktop');
}
// Launched from the applications list a second time? Focus the existing
// window instead of starting a duplicate app (two Electron shells would
// each spawn their own backend and fight over the vault file).
const gotInstanceLock = app.requestSingleInstanceLock();
if (!gotInstanceLock) {
// Hard exit: app.quit() is async and would let the rest of this module
// (whenReady → backend spawn) run in the doomed second instance.
app.exit(0);
} else {
app.on('second-instance', () => {
const [window] = BrowserWindow.getAllWindows();
if (window) {
if (window.isMinimized()) window.restore();
window.focus();
}
});
}
app.whenReady().then(() => {
protocol.handle('app', (request) => {
const { pathname } = new URL(request.url);