From 8d78e76a3ccd6317461e7521fd13f5b007b0fa2b Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 28 Jan 2026 10:01:15 +0100 Subject: [PATCH 01/10] fix: properly cleanup resources on macOS quit to prevent hanging --- assets/electron/template/app/src/index.js | 103 ++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index fa164ae..0bb36e9 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -286,6 +286,21 @@ app.setPath('userData', sessionDataPath) */ const clients = new Set() +/** + * @type {import('http').Server | null} + */ +let httpServer = null + +/** + * @type {import('ws').WebSocketServer | null} + */ +let wss = null + +/** + * @type {boolean} + */ +let isQuitting = false + /** * @param {string} message */ @@ -307,7 +322,8 @@ const dir = app.isPackaged ? join(metaDirname, './app') : './src/app' const createAppServer = (mainWindow, serveStatic = true) => { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { - const server = createServer() + httpServer = createServer() + const server = httpServer if (serveStatic) { server.on('request', (req, res) => { @@ -347,7 +363,7 @@ const createAppServer = (mainWindow, serveStatic = true) => { } try { - const wss = new WebSocketServer({ server }) + wss = new WebSocketServer({ server }) wss.on('connection', function connection(ws) { clients.add(ws) @@ -657,9 +673,53 @@ const createWindow = async () => { return mainWindow } +/** + * Cleanup all resources before quitting + */ +const cleanup = () => { + return new Promise((resolve) => { + console.log('Cleaning up resources...') + + // Close all WebSocket clients + for (const client of clients) { + try { + client.close() + } catch (e) { + console.error('Error closing WebSocket client:', e) + } + } + clients.clear() + + // Close WebSocket server + if (wss) { + try { + wss.close() + } catch (e) { + console.error('Error closing WebSocket server:', e) + } + wss = null + } + + // Close HTTP server + if (httpServer) { + httpServer.close(() => { + console.log('HTTP server closed') + httpServer = null + resolve() + }) + // Force resolve after timeout in case server doesn't close cleanly + setTimeout(resolve, 500) + } else { + resolve() + } + }) +} + const registerHandlers = async () => { - ipcMain.on('exit', (event, code) => { + ipcMain.on('exit', async (event, code) => { console.log('exit', code) + isQuitting = true + await cleanup() app.exit(code) }) } @@ -708,6 +768,39 @@ app.whenReady().then(async () => { }) }) -app.on('window-all-closed', async () => { - app.quit() +app.on('before-quit', (event) => { + if (!isQuitting) { + event.preventDefault() + isQuitting = true + cleanup().then(() => { + app.quit() + }) + } +}) + +app.on('will-quit', () => { + // Final cleanup - synchronous operations only + // Close any remaining WebSocket clients + for (const client of clients) { + try { + client.terminate() // Force close + } catch (e) { + // Ignore errors during final cleanup + } + } + clients.clear() +}) + +app.on('window-all-closed', () => { + // On macOS, apps typically stay open until explicitly quit + // But for games, we usually want to quit when the window is closed + if (process.platform !== 'darwin' || isQuitting) { + app.quit() + } else { + // On macOS, trigger the quit process which will run cleanup + isQuitting = true + cleanup().then(() => { + app.quit() + }) + } }) From b28979e81f6f72dec51ead8416b03c6bd5d62945 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Fri, 30 Jan 2026 00:02:05 +0100 Subject: [PATCH 02/10] added save screenshot handler --- .../app/src/handlers/steam/saveScreenshot.js | 65 +++++++++++++++++++ assets/electron/template/app/src/index.js | 4 ++ 2 files changed, 69 insertions(+) create mode 100644 assets/electron/template/app/src/handlers/steam/saveScreenshot.js diff --git a/assets/electron/template/app/src/handlers/steam/saveScreenshot.js b/assets/electron/template/app/src/handlers/steam/saveScreenshot.js new file mode 100644 index 0000000..8858101 --- /dev/null +++ b/assets/electron/template/app/src/handlers/steam/saveScreenshot.js @@ -0,0 +1,65 @@ +import { handleSteamRequest } from './utils.js' +import { writeFileSync, unlinkSync, mkdirSync } from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { randomUUID } from 'node:crypto' + +/** + * Save screenshot from base64 data URL to Steam library + * @param {Omit} client + * @param {Object} json + * @returns {Promise} The screenshot handle + */ +const saveScreenshotHandler = async (client, json) => { + const { body } = json + const { dataUrl, width, height } = body + + // Validate input + if (!dataUrl || typeof dataUrl !== 'string') { + throw new Error('dataUrl is required and must be a string') + } + + if (!dataUrl.startsWith('data:image/')) { + throw new Error('dataUrl must be a base64 data URL (data:image/...)') + } + + // Extract base64 data + const matches = dataUrl.match(/^data:image\/(\w+);base64,(.+)$/) + if (!matches) { + throw new Error('Invalid base64 data URL format') + } + + const [, format, base64Data] = matches + const buffer = Buffer.from(base64Data, 'base64') + + // Create temp file + const tempDir = join(tmpdir(), 'pipelab-screenshots') + mkdirSync(tempDir, { recursive: true }) + const tempPath = join(tempDir, `screenshot-${randomUUID()}.${format}`) + + try { + // Write to temp file + writeFileSync(tempPath, buffer) + + // Add to Steam library + const handle = client.screenshots.addScreenshotToLibrary(tempPath, null, width, height) + + return handle + } finally { + // Clean up temp file + try { + unlinkSync(tempPath) + } catch { + // Ignore cleanup errors + } + } +} + +/** + * @param {Object} json + * @param {import('ws').WebSocket} ws + * @param {Omit} client + */ +export default async (json, ws, client) => { + await handleSteamRequest(client, json, ws, saveScreenshotHandler) +} diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index 0bb36e9..e27f970 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -72,6 +72,7 @@ import steamInstallInfo from './handlers/steam/installInfo.js' import steamDownloadInfo from './handlers/steam/downloadInfo.js' import steamDownload from './handlers/steam/download.js' import steamDeleteItem from './handlers/steam/deleteItem.js' +import steamSaveScreenshot from './handlers/steam/saveScreenshot.js' // discord set activity import discordSetActivity from './handlers/discord/set-activity.js' @@ -528,6 +529,9 @@ const createAppServer = (mainWindow, serveStatic = true) => { case '/steam/workshop/delete-item': await steamDeleteItem(json, ws, client) break + case '/steam/screenshots/save': + await steamSaveScreenshot(json, ws, client) + break case '/discord/set-activity': await discordSetActivity(json, ws, mainWindow, rpc) break From 3965c0126a5e38b8d82693160c4b51318a41f266 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Fri, 30 Jan 2026 02:33:35 +0100 Subject: [PATCH 03/10] fixed screenshot code, there needs to be a little delay before deleting the file otherwise steam fails to copy it --- .../app/src/handlers/steam/saveScreenshot.js | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/assets/electron/template/app/src/handlers/steam/saveScreenshot.js b/assets/electron/template/app/src/handlers/steam/saveScreenshot.js index 8858101..193a9d7 100644 --- a/assets/electron/template/app/src/handlers/steam/saveScreenshot.js +++ b/assets/electron/template/app/src/handlers/steam/saveScreenshot.js @@ -1,5 +1,5 @@ import { handleSteamRequest } from './utils.js' -import { writeFileSync, unlinkSync, mkdirSync } from 'node:fs' +import { writeFileSync, unlinkSync, mkdirSync, rmdirSync } from 'node:fs' import { join } from 'node:path' import { tmpdir } from 'node:os' import { randomUUID } from 'node:crypto' @@ -37,22 +37,23 @@ const saveScreenshotHandler = async (client, json) => { mkdirSync(tempDir, { recursive: true }) const tempPath = join(tempDir, `screenshot-${randomUUID()}.${format}`) - try { - // Write to temp file - writeFileSync(tempPath, buffer) + // Write to temp file + writeFileSync(tempPath, buffer) - // Add to Steam library - const handle = client.screenshots.addScreenshotToLibrary(tempPath, null, width, height) + // Add to Steam library + const handle = client.screenshots.addScreenshotToLibrary(tempPath, null, width, height) - return handle - } finally { - // Clean up temp file + // Delete temp file after a delay to allow Steam to process it + setTimeout(() => { try { unlinkSync(tempPath) + rmdirSync(tempDir) } catch { // Ignore cleanup errors } - } + }, 5000) + + return handle } /** From 9e477059e6e943111bf5d1a3d8cdd2f114067161 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 01:44:31 +0100 Subject: [PATCH 04/10] WIP trying to fix window bug --- .../template/app/src/handlers/general/exit.js | 6 +- assets/electron/template/app/src/index.js | 146 ++++++++++++++---- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/assets/electron/template/app/src/handlers/general/exit.js b/assets/electron/template/app/src/handlers/general/exit.js index bcfe524..6ed3d89 100644 --- a/assets/electron/template/app/src/handlers/general/exit.js +++ b/assets/electron/template/app/src/handlers/general/exit.js @@ -1,9 +1,9 @@ -import { app } from 'electron' /** * @param {import('@pipelab/core').MakeInputOutput} json * @param {import('ws').WebSocket} ws + * @param {(exitCode?: number) => Promise} requestQuit */ -export default async (json, ws) => { +export default async (json, ws, requestQuit) => { /** * @type {import('@pipelab/core').MakeInputOutput} */ @@ -16,5 +16,5 @@ export default async (json, ws) => { } ws.send(JSON.stringify(engineResult)) - app.exit(json.body.code) + await requestQuit(json.body.code) } diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index a388c12..9c58981 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -332,6 +332,21 @@ let wss = null */ let isQuitting = false +/** + * @type {number} + */ +let requestedExitCode = 0 + +/** + * @type {Promise | null} + */ +let cleanupPromise = null + +/** + * @type {Promise | null} + */ +let quitPromise = null + /** * @param {string} message */ @@ -566,7 +581,7 @@ const createAppServer = (mainWindow, serveStatic = true) => { await discordSetActivity(json, ws, mainWindow, rpc) break case '/exit': - await exit(json, ws) + await exit(json, ws, requestQuit) break case '/window/fullscreen-state': // sent the other way around @@ -718,11 +733,14 @@ const createWindow = async () => { /** * Cleanup all resources before quitting */ -const cleanup = () => { - return new Promise((resolve) => { +const cleanup = async () => { + if (cleanupPromise) { + return cleanupPromise + } + + cleanupPromise = (async () => { console.log('Cleaning up resources...') - // Close all WebSocket clients for (const client of clients) { try { client.close() @@ -732,7 +750,6 @@ const cleanup = () => { } clients.clear() - // Close WebSocket server if (wss) { try { wss.close() @@ -742,27 +759,101 @@ const cleanup = () => { wss = null } - // Close HTTP server + if (rpc) { + try { + await rpc.clearActivity() + } catch (e) { + console.error('Error clearing Discord RPC activity:', e) + } + + try { + rpc.destroy() + } catch (e) { + console.error('Error destroying Discord RPC client:', e) + } + + rpc = undefined + } + + try { + protocol.unhandle('app') + } catch (e) { + console.error('Error unregistering app protocol:', e) + } + if (httpServer) { - httpServer.close(() => { - console.log('HTTP server closed') - httpServer = null - resolve() + const server = httpServer + httpServer = null + + await new Promise((resolve) => { + let isSettled = false + const done = () => { + if (!isSettled) { + isSettled = true + resolve() + } + } + + server.close(() => { + console.log('HTTP server closed') + done() + }) + + setTimeout(done, 500) }) - // Force resolve after timeout in case server doesn't close cleanly - setTimeout(resolve, 500) - } else { - resolve() } + })().finally(() => { + cleanupPromise = null + }) + + return cleanupPromise +} + +const hideAndDestroyAllWindows = () => { + for (const window of BrowserWindow.getAllWindows()) { + try { + if (process.platform === 'win32') { + window.setSkipTaskbar(true) + if (window.isVisible()) { + window.hide() + } + } + + if (!window.isDestroyed()) { + window.destroy() + } + } catch (e) { + console.error('Error destroying window during quit:', e) + } + } +} + +const requestQuit = async (exitCode = 0) => { + requestedExitCode = exitCode + process.exitCode = exitCode + + if (quitPromise) { + return quitPromise + } + + quitPromise = (async () => { + isQuitting = true + await cleanup() + hideAndDestroyAllWindows() + app.quit() + })().catch((error) => { + console.error('Error while quitting application:', error) + hideAndDestroyAllWindows() + app.quit() }) + + return quitPromise } const registerHandlers = async () => { ipcMain.on('exit', async (event, code) => { console.log('exit', code) - isQuitting = true - await cleanup() - app.exit(code) + await requestQuit(code) }) } @@ -874,16 +965,15 @@ app.whenReady().then(async () => { }) app.on('before-quit', (event) => { - if (!isQuitting) { + if (!quitPromise) { event.preventDefault() - isQuitting = true - cleanup().then(() => { - app.quit() - }) + void requestQuit(requestedExitCode) } }) app.on('will-quit', () => { + process.exitCode = requestedExitCode + // Final cleanup - synchronous operations only // Close any remaining WebSocket clients for (const client of clients) { @@ -897,15 +987,5 @@ app.on('will-quit', () => { }) app.on('window-all-closed', () => { - // On macOS, apps typically stay open until explicitly quit - // But for games, we usually want to quit when the window is closed - if (process.platform !== 'darwin' || isQuitting) { - app.quit() - } else { - // On macOS, trigger the quit process which will run cleanup - isQuitting = true - cleanup().then(() => { - app.quit() - }) - } + void requestQuit(requestedExitCode) }) From 5c4d55f59276a3768aee27f87d92ce55d17bb80f Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 01:47:47 +0100 Subject: [PATCH 05/10] WIP --- assets/electron/template/app/src/index.js | 45 +++++------------------ 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index 9c58981..99c2585 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -342,11 +342,6 @@ let requestedExitCode = 0 */ let cleanupPromise = null -/** - * @type {Promise | null} - */ -let quitPromise = null - /** * @param {string} message */ @@ -809,45 +804,23 @@ const cleanup = async () => { return cleanupPromise } -const hideAndDestroyAllWindows = () => { - for (const window of BrowserWindow.getAllWindows()) { - try { - if (process.platform === 'win32') { - window.setSkipTaskbar(true) - if (window.isVisible()) { - window.hide() - } - } - - if (!window.isDestroyed()) { - window.destroy() - } - } catch (e) { - console.error('Error destroying window during quit:', e) - } - } -} - const requestQuit = async (exitCode = 0) => { requestedExitCode = exitCode process.exitCode = exitCode - if (quitPromise) { - return quitPromise + if (isQuitting) { + return } - quitPromise = (async () => { - isQuitting = true + isQuitting = true + + try { await cleanup() - hideAndDestroyAllWindows() - app.quit() - })().catch((error) => { + } catch (error) { console.error('Error while quitting application:', error) - hideAndDestroyAllWindows() - app.quit() - }) + } - return quitPromise + app.quit() } const registerHandlers = async () => { @@ -965,7 +938,7 @@ app.whenReady().then(async () => { }) app.on('before-quit', (event) => { - if (!quitPromise) { + if (!isQuitting) { event.preventDefault() void requestQuit(requestedExitCode) } From 05f7641890885ca923d696bb23bdc2c4d7b1a3d2 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Wed, 25 Mar 2026 01:49:24 +0100 Subject: [PATCH 06/10] Made the implementation I had much simpler --- .../template/app/src/handlers/general/exit.js | 8 +-- assets/electron/template/app/src/index.js | 52 ++++++------------- 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/assets/electron/template/app/src/handlers/general/exit.js b/assets/electron/template/app/src/handlers/general/exit.js index 6ed3d89..f4f01e0 100644 --- a/assets/electron/template/app/src/handlers/general/exit.js +++ b/assets/electron/template/app/src/handlers/general/exit.js @@ -1,9 +1,10 @@ +import { app } from 'electron' + /** * @param {import('@pipelab/core').MakeInputOutput} json * @param {import('ws').WebSocket} ws - * @param {(exitCode?: number) => Promise} requestQuit */ -export default async (json, ws, requestQuit) => { +export default async (json, ws) => { /** * @type {import('@pipelab/core').MakeInputOutput} */ @@ -16,5 +17,6 @@ export default async (json, ws, requestQuit) => { } ws.send(JSON.stringify(engineResult)) - await requestQuit(json.body.code) + process.exitCode = json.body.code + app.quit() } diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index 99c2585..704903d 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -332,11 +332,6 @@ let wss = null */ let isQuitting = false -/** - * @type {number} - */ -let requestedExitCode = 0 - /** * @type {Promise | null} */ @@ -576,7 +571,7 @@ const createAppServer = (mainWindow, serveStatic = true) => { await discordSetActivity(json, ws, mainWindow, rpc) break case '/exit': - await exit(json, ws, requestQuit) + await exit(json, ws) break case '/window/fullscreen-state': // sent the other way around @@ -804,29 +799,11 @@ const cleanup = async () => { return cleanupPromise } -const requestQuit = async (exitCode = 0) => { - requestedExitCode = exitCode - process.exitCode = exitCode - - if (isQuitting) { - return - } - - isQuitting = true - - try { - await cleanup() - } catch (error) { - console.error('Error while quitting application:', error) - } - - app.quit() -} - const registerHandlers = async () => { - ipcMain.on('exit', async (event, code) => { + ipcMain.on('exit', (event, code) => { console.log('exit', code) - await requestQuit(code) + process.exitCode = code + app.quit() }) } @@ -940,25 +917,26 @@ app.whenReady().then(async () => { app.on('before-quit', (event) => { if (!isQuitting) { event.preventDefault() - void requestQuit(requestedExitCode) + isQuitting = true + cleanup() + .catch((error) => { + console.error('Error while quitting application:', error) + }) + .finally(() => { + app.quit() + }) } }) app.on('will-quit', () => { - process.exitCode = requestedExitCode - - // Final cleanup - synchronous operations only - // Close any remaining WebSocket clients for (const client of clients) { try { - client.terminate() // Force close - } catch (e) { - // Ignore errors during final cleanup - } + client.terminate() + } catch (e) {} } clients.clear() }) app.on('window-all-closed', () => { - void requestQuit(requestedExitCode) + app.quit() }) From c17e5ce7f9544d26714ada8dfee37d52abfce9ab Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Thu, 26 Mar 2026 17:52:59 +0100 Subject: [PATCH 07/10] removed unneeded change --- assets/electron/template/app/src/handlers/general/exit.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/assets/electron/template/app/src/handlers/general/exit.js b/assets/electron/template/app/src/handlers/general/exit.js index f4f01e0..bcfe524 100644 --- a/assets/electron/template/app/src/handlers/general/exit.js +++ b/assets/electron/template/app/src/handlers/general/exit.js @@ -1,5 +1,4 @@ import { app } from 'electron' - /** * @param {import('@pipelab/core').MakeInputOutput} json * @param {import('ws').WebSocket} ws @@ -17,6 +16,5 @@ export default async (json, ws) => { } ws.send(JSON.stringify(engineResult)) - process.exitCode = json.body.code - app.quit() + app.exit(json.body.code) } From cfdda90cba171124729d02c30d5b2e540dce42f3 Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Thu, 26 Mar 2026 17:57:00 +0100 Subject: [PATCH 08/10] reverted some changes --- assets/electron/template/app/src/index.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index 704903d..00a76c6 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -800,10 +800,11 @@ const cleanup = async () => { } const registerHandlers = async () => { - ipcMain.on('exit', (event, code) => { + ipcMain.on('exit', async (event, code) => { console.log('exit', code) - process.exitCode = code - app.quit() + isQuitting = true + await cleanup() + app.exit(code) }) } @@ -938,5 +939,15 @@ app.on('will-quit', () => { }) app.on('window-all-closed', () => { - app.quit() + // On macOS, apps typically stay open until explicitly quit + // But for games, we usually want to quit when the window is closed + if (process.platform !== 'darwin' || isQuitting) { + app.quit() + } else { + // On macOS, trigger the quit process which will run cleanup + isQuitting = true + cleanup().then(() => { + app.quit() + }) + } }) From 1ea169e8978f340790a056fed25a9a2e932ef19d Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Thu, 26 Mar 2026 19:40:48 +0100 Subject: [PATCH 09/10] disabled disable-direct-composition and enabled fullscreenable --- assets/electron/template/app/src/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index 00a76c6..2b528d2 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -276,7 +276,7 @@ let client console.log('config.enableSteamSupport', config.enableSteamSupport) if (config.enableSteamSupport) { app.commandLine.appendSwitch('in-process-gpu') - app.commandLine.appendSwitch('disable-direct-composition') + //app.commandLine.appendSwitch('disable-direct-composition') app.commandLine.appendSwitch('no-sandbox') // const isNecessary = steamworks.restartAppIfNecessary(config.steamGameId) @@ -627,6 +627,7 @@ const createWindow = async () => { width: config.width, height: config.height, fullscreen: config.fullscreen, + fullscreenable: true, frame: config.frame, transparent: config.transparent, alwaysOnTop: config.alwaysOnTop, From e47bc75432a557d78fee08c041e72d09cc54dc4e Mon Sep 17 00:00:00 2001 From: Ossama Jouini Date: Thu, 26 Mar 2026 20:14:26 +0100 Subject: [PATCH 10/10] Added support for set ignore mouse events --- .../window/set-ignore-mouse-events.js | 22 +++++++++++++++++++ assets/electron/template/app/src/index.js | 4 ++++ 2 files changed, 26 insertions(+) create mode 100644 assets/electron/template/app/src/handlers/window/set-ignore-mouse-events.js diff --git a/assets/electron/template/app/src/handlers/window/set-ignore-mouse-events.js b/assets/electron/template/app/src/handlers/window/set-ignore-mouse-events.js new file mode 100644 index 0000000..b499dcc --- /dev/null +++ b/assets/electron/template/app/src/handlers/window/set-ignore-mouse-events.js @@ -0,0 +1,22 @@ +/** + * @param {Object} json + * @param {string} json.correlationId + * @param {string} json.url + * @param {{ ignore: boolean, forward?: boolean }} json.body + * @param {import('ws').WebSocket} ws + * @param {import('electron').BrowserWindow} mainWindow + */ +export default async (json, ws, mainWindow) => { + const { ignore, forward } = json.body + + mainWindow.setIgnoreMouseEvents(ignore, { forward }) + + const result = { + correlationId: json.correlationId, + url: json.url, + body: { + success: true + } + } + ws.send(JSON.stringify(result)) +} diff --git a/assets/electron/template/app/src/index.js b/assets/electron/template/app/src/index.js index 2b528d2..1443a24 100644 --- a/assets/electron/template/app/src/index.js +++ b/assets/electron/template/app/src/index.js @@ -48,6 +48,7 @@ import windowSetY from './handlers/window/set-y.js' import windowShowDevTools from './handlers/window/show-dev-tools.js' import windowUnmaximize from './handlers/window/unmaximize.js' import windowSetFullscreen from './handlers/window/set-fullscreen.js' +import windowSetIgnoreMouseEvents from './handlers/window/set-ignore-mouse-events.js' // dialog import dialogFolder from './handlers/dialog/folder.js' @@ -495,6 +496,9 @@ const createAppServer = (mainWindow, serveStatic = true) => { case '/window/set-fullscreen': await windowSetFullscreen(json, ws, mainWindow) break + case '/window/set-ignore-mouse-events': + await windowSetIgnoreMouseEvents(json, ws, mainWindow) + break case '/engine': await engine(json, ws) break