99 ipcMain,
1010 nativeImage,
1111 nativeTheme,
12+ screen,
1213} = require ( "electron" ) ;
1314const path = require ( "path" ) ;
1415const fs = require ( "fs" ) ;
@@ -1785,10 +1786,31 @@ function log(msg) {
17851786 } catch ( _ ) { }
17861787}
17871788
1788- function createWindow ( ) {
1789+ /** Windows: resolve before the first show() or the taskbar often keeps a blank/generic icon. */
1790+ async function resolveBrowserWindowIcon ( ) {
1791+ const fallback = nativeImageFromAppIcon ( ) ;
1792+ if ( process . platform !== "win32" || ! app . isPackaged ) return fallback ;
1793+ const iconPaths = [ resolveAppIconIcoPath ( ) , process . execPath ] . filter (
1794+ ( p ) => p && ( p === process . execPath || fs . existsSync ( p ) ) ,
1795+ ) ;
1796+ for ( const p of iconPaths ) {
1797+ for ( const size of [ "large" , "normal" ] ) {
1798+ try {
1799+ const img = await app . getFileIcon ( p , { size } ) ;
1800+ if ( ! img . isEmpty ( ) ) return img ;
1801+ } catch ( e ) {
1802+ try {
1803+ log ( `getFileIcon(${ p } , ${ size } ): ${ e ?. message || e } ` ) ;
1804+ } catch ( _ ) { }
1805+ }
1806+ }
1807+ }
1808+ return fallback ;
1809+ }
1810+
1811+ async function createWindow ( ) {
17891812 const appPath = app . getAppPath ( ) ;
17901813 const distPath = path . join ( appPath , "dist" ) ;
1791- const windowIcon = nativeImageFromAppIcon ( ) ;
17921814 const indexHtml = path . join ( distPath , "index.html" ) ;
17931815
17941816 if ( ! isDev && ! fs . existsSync ( indexHtml ) ) {
@@ -1797,6 +1819,13 @@ function createWindow() {
17971819 return ;
17981820 }
17991821
1822+ const windowIcon = await resolveBrowserWindowIcon ( ) ;
1823+ if ( process . platform === "win32" && app . isPackaged && ( ! windowIcon || windowIcon . isEmpty ( ) ) ) {
1824+ try {
1825+ log ( "warn: taskbar icon: resolveBrowserWindowIcon returned empty" ) ;
1826+ } catch ( _ ) { }
1827+ }
1828+
18001829 // NSIS close-app uses PRODUCT_NAME (package.json → build.productName). The window title must
18011830 // match that string, not a URL — otherwise the installer cannot find/close the running app.
18021831 // Keep in sync with app/package.json "build.productName".
@@ -1816,37 +1845,21 @@ function createWindow() {
18161845 show : false ,
18171846 } ) ;
18181847
1819- // Windows: nativeImage.createFromPath(.exe) often returns an empty image; shell-extracted icons work for the taskbar.
1820- if ( process . platform === "win32" && app . isPackaged ) {
1821- const iconPaths = [ resolveAppIconIcoPath ( ) , process . execPath ] . filter (
1822- ( p ) => p && ( p === process . execPath || fs . existsSync ( p ) ) ,
1823- ) ;
1824- void ( async ( ) => {
1825- for ( const p of iconPaths ) {
1826- try {
1827- const img = await app . getFileIcon ( p , { size : "large" } ) ;
1828- if ( mainWindow . isDestroyed ( ) ) return ;
1829- if ( ! img . isEmpty ( ) ) {
1830- mainWindow . setIcon ( img ) ;
1831- return ;
1832- }
1833- } catch ( e ) {
1834- try {
1835- log ( `getFileIcon(${ p } ): ${ e ?. message || e } ` ) ;
1836- } catch ( _ ) { }
1837- }
1848+ mainWindow . once ( "ready-to-show" , ( ) => {
1849+ // Edge-to-edge without WS_MAXIMIZE: on Windows, maximize() can interact badly with shell icons
1850+ // and some system shortcuts (e.g. Print Screen); filling the work area matches prior "fullscreen" intent.
1851+ try {
1852+ if ( process . platform === "win32" ) {
1853+ const wa = screen . getPrimaryDisplay ( ) . workArea ;
1854+ mainWindow . setBounds ( wa ) ;
1855+ } else {
1856+ mainWindow . maximize ( ) ;
18381857 }
1858+ } catch ( _ ) {
18391859 try {
1840- log ( "warn: taskbar icon: getFileIcon found no usable image" ) ;
1860+ mainWindow . maximize ( ) ;
18411861 } catch ( _ ) { }
1842- } ) ( ) ;
1843- }
1844-
1845- mainWindow . once ( "ready-to-show" , ( ) => {
1846- // Fill the display work area by default (fresh install, after update, new window).
1847- try {
1848- mainWindow . maximize ( ) ;
1849- } catch ( _ ) { }
1862+ }
18501863 mainWindow . show ( ) ;
18511864 } ) ;
18521865
@@ -1907,7 +1920,11 @@ app.whenReady().then(() => {
19071920 return net . fetch ( pathToFileURL ( resolved ) . toString ( ) ) ;
19081921 } ) ;
19091922 }
1910- createWindow ( ) ;
1923+ createWindow ( ) . catch ( ( e ) => {
1924+ try {
1925+ log ( `createWindow: ${ e ?. message || e } ` ) ;
1926+ } catch ( _ ) { }
1927+ } ) ;
19111928 setupAutoUpdater ( ) ;
19121929} ) ;
19131930
@@ -1917,5 +1934,11 @@ app.on("window-all-closed", () => {
19171934} ) ;
19181935
19191936app . on ( "activate" , ( ) => {
1920- if ( BrowserWindow . getAllWindows ( ) . length === 0 ) createWindow ( ) ;
1937+ if ( BrowserWindow . getAllWindows ( ) . length === 0 ) {
1938+ createWindow ( ) . catch ( ( e ) => {
1939+ try {
1940+ log ( `createWindow (activate): ${ e ?. message || e } ` ) ;
1941+ } catch ( _ ) { }
1942+ } ) ;
1943+ }
19211944} ) ;
0 commit comments