Просмотр исходного кода

electron: assign ids to windows

Brendan Allan 4 дней назад
Родитель
Сommit
1f95d8a4ca

+ 7 - 1
packages/desktop-electron/src/main/ipc.ts

@@ -4,7 +4,7 @@ import type { IpcMainEvent, IpcMainInvokeEvent } from "electron"
 
 
 import type { InitStep, ServerReadyData, SqliteMigrationProgress, TitlebarTheme, WslConfig } from "../preload/types"
 import type { InitStep, ServerReadyData, SqliteMigrationProgress, TitlebarTheme, WslConfig } from "../preload/types"
 import { getStore } from "./store"
 import { getStore } from "./store"
-import { setTitlebar } from "./windows"
+import { getWindowId, setTitlebar } from "./windows"
 
 
 const pickerFilters = (ext?: string[]) => {
 const pickerFilters = (ext?: string[]) => {
   if (!ext || ext.length === 0) return undefined
   if (!ext || ext.length === 0) return undefined
@@ -151,6 +151,12 @@ export function registerIpcHandlers(deps: Deps) {
 
 
   ipcMain.handle("get-window-count", () => BrowserWindow.getAllWindows().length)
   ipcMain.handle("get-window-count", () => BrowserWindow.getAllWindows().length)
 
 
+  ipcMain.handle("get-window-id", (event: IpcMainInvokeEvent) => {
+    const win = BrowserWindow.fromWebContents(event.sender)
+    if (!win) return null
+    return getWindowId(win) ?? null
+  })
+
   ipcMain.handle("get-window-focused", (event: IpcMainInvokeEvent) => {
   ipcMain.handle("get-window-focused", (event: IpcMainInvokeEvent) => {
     const win = BrowserWindow.fromWebContents(event.sender)
     const win = BrowserWindow.fromWebContents(event.sender)
     return win?.isFocused() ?? false
     return win?.isFocused() ?? false

+ 32 - 0
packages/desktop-electron/src/main/windows.ts

@@ -1,3 +1,4 @@
+import { randomInt } from "node:crypto"
 import windowState from "electron-window-state"
 import windowState from "electron-window-state"
 import { app, BrowserWindow, nativeImage, nativeTheme } from "electron"
 import { app, BrowserWindow, nativeImage, nativeTheme } from "electron"
 import { dirname, join } from "node:path"
 import { dirname, join } from "node:path"
@@ -12,6 +13,9 @@ type Globals = {
 const root = dirname(fileURLToPath(import.meta.url))
 const root = dirname(fileURLToPath(import.meta.url))
 
 
 let backgroundColor: string | undefined
 let backgroundColor: string | undefined
+const ids = new WeakMap<BrowserWindow, string>()
+const used = new Set<string>()
+let seen = false
 
 
 export function setBackgroundColor(color: string) {
 export function setBackgroundColor(color: string) {
   backgroundColor = color
   backgroundColor = color
@@ -21,6 +25,10 @@ export function getBackgroundColor(): string | undefined {
   return backgroundColor
   return backgroundColor
 }
 }
 
 
+export function getWindowId(win: BrowserWindow) {
+  return ids.get(win)
+}
+
 function iconsDir() {
 function iconsDir() {
   return app.isPackaged ? join(process.resourcesPath, "icons") : join(root, "../../resources/icons")
   return app.isPackaged ? join(process.resourcesPath, "icons") : join(root, "../../resources/icons")
 }
 }
@@ -88,6 +96,7 @@ export function createMainWindow(globals: Globals) {
       sandbox: false,
       sandbox: false,
     },
     },
   })
   })
+  track(win)
 
 
   state.manage(win)
   state.manage(win)
   loadWindow(win, "index.html")
   loadWindow(win, "index.html")
@@ -161,3 +170,26 @@ function wireZoom(win: BrowserWindow) {
     win.webContents.setZoomFactor(1)
     win.webContents.setZoomFactor(1)
   })
   })
 }
 }
+
+function track(win: BrowserWindow) {
+  const id = nextId()
+  ids.set(win, id)
+  win.once("closed", () => {
+    used.delete(id)
+  })
+}
+
+function nextId() {
+  if (!seen) {
+    seen = true
+    used.add("main")
+    return "main"
+  }
+
+  while (true) {
+    const id = String(randomInt(100_000, 1_000_000))
+    if (used.has(id)) continue
+    used.add(id)
+    return id
+  }
+}

+ 1 - 0
packages/desktop-electron/src/preload/index.ts

@@ -29,6 +29,7 @@ const api: ElectronAPI = {
   storeLength: (name) => ipcRenderer.invoke("store-length", name),
   storeLength: (name) => ipcRenderer.invoke("store-length", name),
 
 
   getWindowCount: () => ipcRenderer.invoke("get-window-count"),
   getWindowCount: () => ipcRenderer.invoke("get-window-count"),
+  getWindowId: () => ipcRenderer.invoke("get-window-id"),
   onSqliteMigrationProgress: (cb) => {
   onSqliteMigrationProgress: (cb) => {
     const handler = (_: unknown, progress: SqliteMigrationProgress) => cb(progress)
     const handler = (_: unknown, progress: SqliteMigrationProgress) => cb(progress)
     ipcRenderer.on("sqlite-migration-progress", handler)
     ipcRenderer.on("sqlite-migration-progress", handler)

+ 1 - 0
packages/desktop-electron/src/preload/types.ts

@@ -37,6 +37,7 @@ export type ElectronAPI = {
   storeLength: (name: string) => Promise<number>
   storeLength: (name: string) => Promise<number>
 
 
   getWindowCount: () => Promise<number>
   getWindowCount: () => Promise<number>
+  getWindowId: () => Promise<string | null>
   onSqliteMigrationProgress: (cb: (progress: SqliteMigrationProgress) => void) => () => void
   onSqliteMigrationProgress: (cb: (progress: SqliteMigrationProgress) => void) => () => void
   onMenuCommand: (cb: (id: string) => void) => () => void
   onMenuCommand: (cb: (id: string) => void) => () => void
   onDeepLink: (cb: (urls: string[]) => void) => () => void
   onDeepLink: (cb: (urls: string[]) => void) => () => void