electron#BrowserWindowConstructorOptions TypeScript Examples
The following examples show how to use
electron#BrowserWindowConstructorOptions.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.ts From TidGi-Desktop with Mozilla Public License 2.0 | 6 votes |
private async handleCreateBasicWindow(windowName: WindowNames, windowConfig: BrowserWindowConstructorOptions): Promise<BrowserWindow> {
const newWindow = new BrowserWindow(windowConfig);
this.windows[windowName] = newWindow;
const unregisterContextMenu = await this.menuService.initContextMenuForWindowWebContents(newWindow.webContents);
newWindow.on('closed', () => {
this.windows[windowName] = undefined;
unregisterContextMenu();
});
let webContentLoadingPromise: Promise<void> | undefined;
if (windowName === WindowNames.main) {
// handle window show and Webview/browserView show
webContentLoadingPromise = new Promise<void>((resolve) => {
newWindow.once('ready-to-show', async () => {
const mainWindow = this.get(WindowNames.main);
if (mainWindow === undefined) return;
const { wasOpenedAsHidden } = app.getLoginItemSettings();
if (!wasOpenedAsHidden) {
mainWindow.show();
}
// ensure redux is loaded first
// if not, redux might not be able catch changes sent from ipcMain
if (!mainWindow.webContents.isLoading()) {
return resolve();
}
mainWindow.webContents.once('did-stop-loading', () => {
resolve();
});
});
});
}
await this.updateWindowBackground(newWindow);
// This loading will wait for a while
await newWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
await webContentLoadingPromise;
return newWindow;
}
Example #2
Source File: app-window.ts From kliveide with MIT License | 5 votes |
/**
* Gets the options this window should be created
* @param savedWindowState
* @returns
*/
getWindowOptions(
savedWindowState: any,
showWindow: boolean
): BrowserWindowConstructorOptions {
const windowOptions: BrowserWindowConstructorOptions = {
x: savedWindowState.x,
y: savedWindowState.y,
width: savedWindowState.width,
height: savedWindowState.height,
minWidth: this.minimumWidth,
minHeight: this.minimumHeight,
show: showWindow,
// --- This fixes subpixel aliasing on Windows
// --- See https://github.com/atom/atom/commit/683bef5b9d133cb194b476938c77cc07fd05b972
backgroundColor: "#fff",
webPreferences: {
webSecurity: false,
devTools: process.env.NODE_ENV === "production" ? false : true,
contextIsolation: true,
preload: path.join(__dirname, "preload.bundled.js"),
},
acceptFirstMouse: true,
icon: path.join(__dirname, "icons/spectnet-logo.png"),
};
// --- Additional options depending on the host platform
if (__DARWIN__) {
windowOptions.frame = true;
} else if (__WIN32__) {
windowOptions.frame = true;
} else if (__LINUX__) {
windowOptions.icon = path.join(__dirname, "icons/spectnet-logo.png");
}
return windowOptions;
}
Example #3
Source File: window.ts From SideQuest with MIT License | 5 votes |
private createWindow(state?: WindowState) {
const [windowState, hasMultipleDisplays] = this.restoreWindowState(state);
const isMaximized = windowState.mode === 'maximized';
const showAfterSetup = isMaximized;
const options: BrowserWindowConstructorOptions = {
width: windowState.width,
height: windowState.height,
x: windowState.x,
y: windowState.y,
minWidth: 800,
minHeight: 480,
show: !showAfterSetup,
frame: false,
webPreferences: {
webviewTag: true,
nodeIntegration: true,
contextIsolation: false,
},
};
this._window = new BrowserWindow(options);
// (Electron 4 regression): when running on multiple displays where the target display
// to open the window has a larger resolution than the primary display, the window will not size
// correctly unless we set the bounds again
const isMacintosh = process.platform === 'darwin';
if (isMacintosh && hasMultipleDisplays) {
const hasAllBoundsValues = [windowState.width, windowState.height, windowState.x, windowState.y].every(
value => typeof value === 'number'
);
if (hasAllBoundsValues) {
this._window.setBounds({
width: windowState.width,
height: windowState.height,
x: windowState.x,
y: windowState.y,
});
}
}
if (isMaximized) {
this._window.maximize();
if (!this._window.isVisible()) {
this._window.show();
}
}
}
Example #4
Source File: window.ts From noteworthy with GNU Affero General Public License v3.0 | 5 votes |
constructor(name: string, options: BrowserWindowConstructorOptions = {}, stateOptions: windowStateKeeper.Options = {}){
this.name = name;
this.options = options;
this.stateOptions = stateOptions;
}
Example #5
Source File: window.ts From noteworthy with GNU Affero General Public License v3.0 | 5 votes |
options: BrowserWindowConstructorOptions;
Example #6
Source File: main.ts From WowUp with GNU General Public License v3.0 | 4 votes |
function createWindow(): BrowserWindow {
if (win) {
win.destroy();
}
// Main object for managing window state
// Initialize with a window name and default size
const mainWindowManager = windowStateManager("main", {
width: WINDOW_DEFAULT_WIDTH,
height: WINDOW_DEFAULT_HEIGHT,
});
const windowOptions: BrowserWindowConstructorOptions = {
width: mainWindowManager.width,
height: mainWindowManager.height,
x: mainWindowManager.x,
y: mainWindowManager.y,
minWidth: WINDOW_MIN_WIDTH,
minHeight: WINDOW_MIN_HEIGHT,
center: mainWindowManager.centered === true,
transparent: false,
resizable: true,
backgroundColor: getBackgroundColor(),
title: "WowUp",
titleBarStyle: "hidden",
webPreferences: {
preload: join(__dirname, "preload.js"),
nodeIntegration: true,
contextIsolation: false,
allowRunningInsecureContent: argv.serve,
webSecurity: false,
additionalArguments: [
`--log-path=${LOG_PATH}`,
`--user-data-path=${app.getPath("userData")}`,
`--base-bg-color=${getBackgroundColor()}`,
],
webviewTag: true,
},
show: false,
};
if (platform.isWin || platform.isLinux) {
windowOptions.frame = false;
}
// Attempt to fix the missing icon issue on Ubuntu
if (platform.isLinux) {
windowOptions.icon = join(__dirname, "assets", WOWUP_LOGO_FILENAME);
}
// Create the browser window.
win = new BrowserWindow(windowOptions);
appUpdater.init(win);
initializeIpcHandlers(win);
initializeStoreIpcHandlers();
pushEvents.on(PUSH_NOTIFICATION_EVENT, (data) => {
win.webContents.send(IPC_PUSH_NOTIFICATION, data);
});
// Keep track of window state
mainWindowManager.monitorState(win);
win.on("blur", () => {
win.webContents.send("blur");
});
win.on("focus", () => {
win.webContents.send("focus");
});
win.webContents.userAgent = USER_AGENT;
win.webContents.on("will-attach-webview", (evt, webPreferences) => {
log.debug("will-attach-webview");
webPreferences.additionalArguments = [`--log-path=${LOG_PATH}`];
webPreferences.contextIsolation = true;
webPreferences.plugins = false;
webPreferences.webgl = false;
});
win.webContents.on("did-attach-webview", (evt, webContents) => {
webContents.session.setUserAgent(webContents.userAgent);
webContents.on("preload-error", (evt) => {
log.error("[webview] preload-error", evt);
});
webContents.on("did-fail-provisional-load", (evt) => {
log.error("[webview] did-fail-provisional-load", evt);
});
webContents.session.setPermissionRequestHandler((contents, permission, callback) => {
log.warn("setPermissionRequestHandler", permission);
return callback(false);
});
webContents.session.setPermissionCheckHandler((contents, permission, origin) => {
if (["background-sync"].includes(permission)) {
return true;
}
log.warn("setPermissionCheckHandler", permission, origin);
return false;
});
webContents.on("did-fail-load", (evt, code, desc, url) => {
log.error("[webview] did-fail-load", code, desc, url);
setTimeout(() => {
log.error("[webview] reload");
webContents.reload();
}, 2000);
});
webContents.on("will-navigate", (evt, url) => {
log.debug("[webview] will-navigate", url);
if (webContents.getURL() === url) {
log.debug(`[webview] reload detected`);
} else {
evt.preventDefault(); // block the webview from navigating at all
}
});
// webview allowpopups must be enabled for any link to work
// https://www.electronjs.org/docs/latest/api/webview-tag#allowpopups
webContents.setWindowOpenHandler((details) => {
log.debug("[webview] setWindowOpenHandler");
win.webContents.send("webview-new-window", details); // forward this new window to the app for processing
return { action: "deny" };
});
});
win.webContents.on("zoom-changed", (evt, zoomDirection) => {
sendEventToContents(win, "zoom-changed", zoomDirection);
});
// See https://www.electronjs.org/docs/api/web-contents#event-render-process-gone
win.webContents.on("render-process-gone", (evt, details) => {
log.error("webContents render-process-gone");
log.error(details);
// If something killed the process, quit
if (details.reason === "killed") {
win?.destroy();
app.quit();
return;
}
// If process crashes too quickly, kill the app
const crashTime = Date.now();
if (crashTime - lastCrash < 5000) {
log.error("Crash loop detected");
win?.destroy();
app.quit();
return;
}
lastCrash = crashTime;
log.info("Restarting main window");
});
// See https://www.electronjs.org/docs/api/web-contents#event-unresponsive
win.webContents.on("unresponsive", () => {
log.error("webContents unresponsive");
});
// See https://www.electronjs.org/docs/api/web-contents#event-responsive
win.webContents.on("responsive", () => {
log.error("webContents responsive");
});
win.once("ready-to-show", () => {
if (canStartHidden()) {
return;
}
// win.webContents.session.setPermissionRequestHandler((contents, permission, callback) => {
// log.warn("win setPermissionRequestHandler", permission);
// return callback(false);
// });
// win.webContents.session.setPermissionCheckHandler((contents, permission, origin) => {
// log.warn("win setPermissionCheckHandler", permission, origin);
// return false;
// });
win.show();
});
win.once("show", () => {
// win.webContents.openDevTools();
if (mainWindowManager.isFullScreen) {
win.setFullScreen(true);
} else if (mainWindowManager.isMaximized) {
win.maximize();
}
appUpdater.checkForUpdates().catch((e) => console.error(e));
win.on("show", () => {
win?.webContents?.send(IPC_WINDOW_RESUME);
});
});
win.on("close", (e) => {
if (appIsQuitting || preferenceStore.get(COLLAPSE_TO_TRAY_PREFERENCE_KEY) !== "true") {
pushEvents.removeAllListeners(PUSH_NOTIFICATION_EVENT);
return;
}
e.preventDefault();
win.hide();
win.setSkipTaskbar(true);
if (platform.isMac) {
app.setBadgeCount(0);
app.dock.hide();
}
});
win.once("closed", () => {
win = null;
});
win.on("maximize", () => {
win?.webContents?.send(IPC_WINDOW_MAXIMIZED);
});
win.on("unmaximize", () => {
win?.webContents?.send(IPC_WINDOW_UNMAXIMIZED);
});
win.on("minimize", () => {
win?.webContents?.send(IPC_WINDOW_MINIMIZED);
});
win.on("enter-full-screen", () => {
win?.webContents?.send(IPC_WINDOW_ENTER_FULLSCREEN);
});
win.on("leave-full-screen", () => {
win?.webContents?.send(IPC_WINDOW_LEAVE_FULLSCREEN);
});
win.webContents.on("did-fail-load", () => {
log.info("did-fail-load");
if (loadFailCount < 5) {
loadFailCount += 1;
loadMainUrl(win).catch((e) => log.error(e));
} else {
log.error(`Failed to load too many times, exiting`);
app.quit();
}
});
log.info(`Loading app URL: ${Date.now() - startedAt}ms`);
if (argv.serve) {
require("electron-reload")(__dirname, {
electron: require(join(__dirname, "..", "node_modules", "electron")),
});
win.loadURL("http://localhost:4200").catch((e) => log.error(e));
} else {
loadMainUrl(win).catch((e) => log.error(e));
}
return win;
}
Example #7
Source File: setupViewEventHandlers.ts From TidGi-Desktop with Mozilla Public License 2.0 | 4 votes |
function handleNewWindow(
nextUrl: string,
newWindowContext: INewWindowContext,
disposition: 'default' | 'new-window' | 'foreground-tab' | 'background-tab' | 'save-to-disk' | 'other',
parentWebContents: Electron.WebContents,
):
| {
action: 'deny';
}
| {
action: 'allow';
overrideBrowserWindowOptions?: Electron.BrowserWindowConstructorOptions | undefined;
} {
const nextDomain = extractDomain(nextUrl);
// open external url in browser
if (nextDomain !== undefined && (disposition === 'foreground-tab' || disposition === 'background-tab')) {
logger.debug('handleNewWindow() openExternal', { nextUrl, nextDomain, disposition });
void shell.openExternal(nextUrl).catch((error) => logger.error(`handleNewWindow() openExternal error ${(error as Error).message}`, error));
return {
action: 'deny',
};
}
const workspaceService = container.get<IWorkspaceService>(serviceIdentifier.Workspace);
logger.debug('handleNewWindow()', { newWindowContext });
const { view, workspace, sharedWebPreferences } = newWindowContext;
const currentUrl = view.webContents.getURL();
/** Conditions are listed by order of priority
if global.forceNewWindow = true
or regular new-window event
or if in Google Drive app, open Google Docs files internally https://github.com/atomery/webcatalog/issues/800
the next external link request will be opened in new window */
const clickOpenNewWindow = newWindowContext.meta.forceNewWindow || disposition === 'new-window' || disposition === 'default';
/** App tries to open external link using JS
nextURL === 'about:blank' but then window will redirect to the external URL
https://github.com/quanglam2807/webcatalog/issues/467#issuecomment-569857721 */
const isExternalLinkUsingJS = nextDomain === null && (disposition === 'foreground-tab' || disposition === 'background-tab');
if (clickOpenNewWindow || isExternalLinkUsingJS) {
// https://gist.github.com/Gvozd/2cec0c8c510a707854e439fb15c561b0
// if 'new-window' is triggered with Cmd+Click
// options is undefined
// https://github.com/atomery/webcatalog/issues/842
const browserViewMetaData: IBrowserViewMetaData = {
isPopup: true,
...(JSON.parse(
decodeURIComponent(sharedWebPreferences?.additionalArguments?.[1]?.replace(MetaDataChannel.browserViewMetaData, '') ?? '{}'),
) as IBrowserViewMetaData),
};
logger.debug(`handleNewWindow() ${newWindowContext.meta.forceNewWindow ? 'forceNewWindow' : 'disposition'}`, {
browserViewMetaData,
disposition,
nextUrl,
nextDomain,
});
newWindowContext.meta.forceNewWindow = false;
const metadataConfig = {
additionalArguments: [
`${MetaDataChannel.browserViewMetaData}${WindowNames.newWindow}`,
`${MetaDataChannel.browserViewMetaData}${encodeURIComponent(JSON.stringify(browserViewMetaData))}`,
],
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
};
const windowWithBrowserViewState = windowStateKeeper({
file: 'window-state-open-in-new-window.json',
path: SETTINGS_FOLDER,
defaultWidth: windowDimension[WindowNames.main].width,
defaultHeight: windowDimension[WindowNames.main].height,
});
let newOptions: BrowserWindowConstructorOptions = {
x: windowWithBrowserViewState.x,
y: windowWithBrowserViewState.y,
width: windowWithBrowserViewState.width,
height: windowWithBrowserViewState.height,
webPreferences: metadataConfig,
autoHideMenuBar: true,
};
if (isExternalLinkUsingJS) {
newOptions = { ...newOptions, show: false };
}
parentWebContents.once('did-create-window', (childWindow) => {
childWindow.setMenuBarVisibility(false);
childWindow.webContents.setWindowOpenHandler((details: Electron.HandlerDetails) =>
handleNewWindow(details.url, newWindowContext, details.disposition, parentWebContents),
);
childWindow.webContents.once('will-navigate', async (_event, url) => {
// if the window is used for the current app, then use default behavior
let appUrl = (await workspaceService.get(workspace.id))?.homeUrl;
if (appUrl === undefined) {
throw new Error(`Workspace ${workspace.id} not existed, or don't have homeUrl setting`);
}
appUrl = await getLocalHostUrlWithActualIP(appUrl);
if (isInternalUrl(url, [appUrl, currentUrl])) {
childWindow.show();
} else {
// if not, open in browser
_event.preventDefault();
void shell.openExternal(url);
childWindow.close();
}
});
windowWithBrowserViewState.manage(childWindow);
const menuService = container.get<IMenuService>(serviceIdentifier.MenuService);
void menuService.initContextMenuForWindowWebContents(view.webContents).then((unregisterContextMenu) => {
childWindow.webContents.on('destroyed', () => {
unregisterContextMenu();
});
});
});
return {
action: 'allow',
overrideBrowserWindowOptions: newOptions,
};
}
return { action: 'allow' };
}
Example #8
Source File: index.ts From TidGi-Desktop with Mozilla Public License 2.0 | 4 votes |
public async open<N extends WindowNames>(
windowName: N,
meta: WindowMeta[N] = {} as WindowMeta[N],
config?: {
recreate?: boolean | ((windowMeta: WindowMeta[N]) => boolean);
},
): Promise<void> {
const { recreate = false } = config ?? {};
const existedWindow = this.get(windowName);
// update window meta
await this.setWindowMeta(windowName, meta);
const existedWindowMeta = await this.getWindowMeta(windowName);
if (existedWindow !== undefined) {
if (recreate === true || (typeof recreate === 'function' && existedWindowMeta !== undefined && recreate(existedWindowMeta))) {
existedWindow.close();
} else {
return existedWindow.show();
}
}
// create new window
let windowWithBrowserViewConfig: Partial<BrowserWindowConstructorOptions> = {};
let windowWithBrowserViewState: windowStateKeeperState | undefined;
const isWindowWithBrowserView = windowName === WindowNames.main || windowName === WindowNames.menuBar;
if (isWindowWithBrowserView) {
windowWithBrowserViewState = windowStateKeeper({
file: windowName === WindowNames.main ? 'window-state-main-window.json' : 'window-state-menubar.json',
path: SETTINGS_FOLDER,
defaultWidth: windowDimension[WindowNames.main].width,
defaultHeight: windowDimension[WindowNames.main].height,
});
windowWithBrowserViewConfig = {
x: windowWithBrowserViewState.x,
y: windowWithBrowserViewState.y,
width: windowWithBrowserViewState.width,
height: windowWithBrowserViewState.height,
};
}
const windowConfig: BrowserWindowConstructorOptions = {
...windowDimension[windowName],
...windowWithBrowserViewConfig,
resizable: true,
maximizable: true,
minimizable: true,
fullscreenable: true,
autoHideMenuBar: false,
titleBarStyle: (await this.preferenceService.get('titleBar')) ? 'default' : 'hidden',
alwaysOnTop:
windowName === WindowNames.menuBar ? await this.preferenceService.get('menuBarAlwaysOnTop') : await this.preferenceService.get('alwaysOnTop'),
webPreferences: {
devTools: !isTest,
nodeIntegration: false,
webSecurity: false,
allowRunningInsecureContent: true,
contextIsolation: true,
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
additionalArguments: [
`${MetaDataChannel.browserViewMetaData}${windowName}`,
`${MetaDataChannel.browserViewMetaData}${encodeURIComponent(JSON.stringify(meta))}`,
],
},
parent: isWindowWithBrowserView ? undefined : this.get(WindowNames.main),
};
let newWindow: BrowserWindow;
if (windowName === WindowNames.menuBar) {
this.mainWindowMenuBar = await this.handleAttachToMenuBar(windowConfig);
if (this.mainWindowMenuBar.window === undefined) {
throw new Error('MenuBar failed to create window.');
}
newWindow = this.mainWindowMenuBar.window;
} else {
newWindow = await this.handleCreateBasicWindow(windowName, windowConfig);
if (isWindowWithBrowserView) {
this.registerMainWindowListeners(newWindow);
// calling this to redundantly setBounds BrowserView
// after the UI is fully loaded
// if not, BrowserView mouseover event won't work correctly
// https://github.com/atomery/webcatalog/issues/812
await this.workspaceViewService.realignActiveWorkspace();
} else {
newWindow.setMenuBarVisibility(false);
}
}
windowWithBrowserViewState?.manage(newWindow);
}
Example #9
Source File: index.ts From TidGi-Desktop with Mozilla Public License 2.0 | 4 votes |
private async handleAttachToMenuBar(windowConfig: BrowserWindowConstructorOptions): Promise<Menubar> {
// setImage after Tray instance is created to avoid
// "Segmentation fault (core dumped)" bug on Linux
// https://github.com/electron/electron/issues/22137#issuecomment-586105622
// https://github.com/atomery/translatium/issues/164
const tray = new Tray(nativeImage.createEmpty());
// icon template is not supported on Windows & Linux
tray.setImage(MENUBAR_ICON_PATH);
const menuBar = menubar({
index: MAIN_WINDOW_WEBPACK_ENTRY,
tray,
activateWithApp: false,
preloadWindow: true,
tooltip: i18n.t('Menu.TidGiMenuBar'),
browserWindow: mergeDeep(windowConfig, {
show: false,
minHeight: 100,
minWidth: 250,
}),
});
menuBar.on('after-create-window', () => {
if (menuBar.window !== undefined) {
menuBar.window.on('focus', () => {
const view = menuBar.window?.getBrowserView();
if (view?.webContents !== undefined) {
view.webContents.focus();
}
});
menuBar.window.removeAllListeners('close');
menuBar.window.on('close', (event) => {
event.preventDefault();
menuBar.hideWindow();
});
}
});
// https://github.com/maxogden/menubar/issues/120
menuBar.on('after-hide', () => {
if (process.platform === 'darwin') {
menuBar.app.hide();
}
});
return await new Promise<Menubar>((resolve) => {
menuBar.on('ready', async () => {
// right on tray icon
menuBar.tray.on('right-click', () => {
// TODO: restore updater options here
const contextMenu = Menu.buildFromTemplate([
{
label: i18n.t('ContextMenu.OpenTidGi'),
click: async () => await this.open(WindowNames.main),
},
{
label: i18n.t('ContextMenu.OpenTidGiMenuBar'),
click: async () => await menuBar.showWindow(),
},
{
type: 'separator',
},
{
label: i18n.t('ContextMenu.About'),
click: async () => await this.open(WindowNames.about),
},
{ type: 'separator' },
{
label: i18n.t('ContextMenu.Preferences'),
click: async () => await this.open(WindowNames.preferences),
},
{
label: i18n.t('ContextMenu.Notifications'),
click: async () => await this.open(WindowNames.notifications),
},
{ type: 'separator' },
{
label: i18n.t('ContextMenu.Quit'),
click: () => {
menuBar.app.quit();
},
},
]);
menuBar.tray.popUpContextMenu(contextMenu);
});
// right click on window content
if (menuBar.window?.webContents !== undefined) {
const unregisterContextMenu = await this.menuService.initContextMenuForWindowWebContents(menuBar.window.webContents);
menuBar.on('after-close', () => {
unregisterContextMenu();
});
}
resolve(menuBar);
});
});
}