diff --git a/electron.js b/electron.js index 9ad294b85..a0b1f109f 100644 --- a/electron.js +++ b/electron.js @@ -29,7 +29,7 @@ app.on('ready', async () => { if (await sqlInit.isDbInitialized()) { await sqlInit.dbReady; - await windowService.createMainWindow(); + await windowService.createMainWindow(app); tray.createTray(); } diff --git a/src/services/window.js b/src/services/window.js index 89a0a0aa1..f99f374ff 100644 --- a/src/services/window.js +++ b/src/services/window.js @@ -44,7 +44,7 @@ ipcMain.on('create-extra-window', (event, arg) => { createExtraWindow(arg.notePath, arg.hoistedNoteId); }); -async function createMainWindow() { +async function createMainWindow(app) { const windowStateKeeper = require('electron-window-state'); // should not be statically imported const mainWindowState = windowStateKeeper({ @@ -81,6 +81,18 @@ async function createMainWindow() { mainWindow.on('closed', () => mainWindow = null); configureWebContents(mainWindow.webContents, spellcheckEnabled); + + app.on('second-instance', () => { + // Someone tried to run a second instance, we should focus our window. + // see www.js "requestSingleInstanceLock" for the rest of this logic with explanation + if (mainWindow) { + if (mainWindow.isMinimized()) { + mainWindow.restore(); + } + + mainWindow.focus(); + } + }); } function configureWebContents(webContents, spellcheckEnabled) { diff --git a/src/www b/src/www index c17ae0412..8571f921e 100644 --- a/src/www +++ b/src/www @@ -38,6 +38,21 @@ if (!semver.satisfies(process.version, ">=10.5.0")) { let httpServer; async function startTrilium() { + /** + * The intended behavior is to detect when a second instance is running, in that case open the old instance + * instead of the new one. This is complicated by the fact that it is possible to run multiple instances of Trilium + * if port and data dir is configured separately. This complication is the source of the following weird usage. + * + * The line below makes sure that the "second-instance" (process in window.js) is fired. Normally it returns a boolean + * indicating whether another instance is running or not, but we ignore that and kill the app only based on the port conflict. + * + * A bit weird is that "second-instance" is triggered also on the valid usecases (different port/data dir) and + * focuses the existing window. But the new process is start as well and will steal the focus too, it will win, because + * its startup is slower than focusing the existing process/window. So in the end it works out without having + * to do complex evaluation. + */ + require("electron").app.requestSingleInstanceLock(); + const usedPort = await port; const usedHost = await host;