diff --git a/packages/streamwall/src/main/StreamWindow.ts b/packages/streamwall/src/main/StreamWindow.ts index c024f14..2e89125 100644 --- a/packages/streamwall/src/main/StreamWindow.ts +++ b/packages/streamwall/src/main/StreamWindow.ts @@ -138,7 +138,10 @@ export default class StreamWindow extends EventEmitter { } createView() { - const { win } = this + const { + win, + config: { width, height }, + } = this assert(win != null, 'Window must be initialized') const { backgroundColor } = this.config const view = new WebContentsView({ @@ -159,11 +162,19 @@ export default class StreamWindow extends EventEmitter { ev.preventDefault() }) + // Hidden window used for loading the BrowserView before it's positioned in the wall + const offscreenWin = new BrowserWindow({ + width, + height, + show: false, + }) + const actor = createActor(viewStateMachine, { input: { id: viewId, view, win, + offscreenWin, }, }) @@ -277,9 +288,12 @@ export default class StreamWindow extends EventEmitter { newViews.set(view.getSnapshot().context.id, view) } for (const view of unusedViews) { - const contentView = view.getSnapshot().context.view + view.stop() + const { view: contentView, offscreenWin } = view.getSnapshot().context + offscreenWin.contentView.removeChildView(contentView) win.contentView.removeChildView(contentView) contentView.webContents.close() + offscreenWin.destroy() } this.views = newViews this.emitState() diff --git a/packages/streamwall/src/main/viewStateMachine.ts b/packages/streamwall/src/main/viewStateMachine.ts index e1330fd..3504ae8 100644 --- a/packages/streamwall/src/main/viewStateMachine.ts +++ b/packages/streamwall/src/main/viewStateMachine.ts @@ -21,11 +21,13 @@ const viewStateMachine = setup({ id: number view: WebContentsView win: BrowserWindow + offscreenWin: BrowserWindow }, context: {} as { id: number win: BrowserWindow + offscreenWin: BrowserWindow view: WebContentsView pos: ViewPos | null content: ViewContent | null @@ -83,20 +85,22 @@ const viewStateMachine = setup({ }, offscreenView: ({ context }) => { - const { view, win } = context - win.contentView.addChildView(view, 0) // Insert below background (so hidden by background) - const { width, height } = win.getBounds() + const { view, win, offscreenWin } = context + win.contentView.removeChildView(view) + offscreenWin.contentView.addChildView(view) + const { width, height } = offscreenWin.getBounds() view.setBounds({ x: 0, y: 0, width, height }) }, positionView: ({ context }) => { - const { pos, view, win } = context + const { pos, view, win, offscreenWin } = context if (!pos) { return } - win.contentView.addChildView(view, win.contentView.children.length - 2) // Insert below overlay but above background + offscreenWin.contentView.removeChildView(view) + win.contentView.addChildView(view, win.contentView.children.length - 1) // Insert below overlay but above background view.setBounds(pos) }, }, @@ -148,10 +152,11 @@ const viewStateMachine = setup({ }).createMachine({ id: 'view', initial: 'empty', - context: ({ input: { id, view, win } }) => ({ + context: ({ input: { id, view, win, offscreenWin } }) => ({ id, view, win, + offscreenWin, pos: null, content: null, options: null,