From ad50233222c2c248ca31ddc9697c97d4177fc2dc Mon Sep 17 00:00:00 2001 From: Pete Miller Date: Wed, 1 Nov 2017 22:50:25 -0700 Subject: [PATCH] Hide windows until they are either rendered or a timeout expires Fix #8121 --- app/browser/reducers/windowsReducer.js | 57 +++++++++++++++++++++++--- app/browser/windows.js | 21 ++++++++++ js/actions/appActions.js | 10 +++++ js/constants/appConstants.js | 1 + js/entry.js | 6 ++- 5 files changed, 88 insertions(+), 7 deletions(-) diff --git a/app/browser/reducers/windowsReducer.js b/app/browser/reducers/windowsReducer.js index d93fbc4fa45..31c03fd0ed5 100644 --- a/app/browser/reducers/windowsReducer.js +++ b/app/browser/reducers/windowsReducer.js @@ -35,6 +35,8 @@ const appDispatcher = require('../../../js/dispatcher/appDispatcher') const isDarwin = platformUtil.isDarwin() const isWindows = platformUtil.isWindows() +const TIMEOUT_WINDOW_SHOW_MS = 5000 + // TODO cleanup all this createWindow crap function isModal (browserOpts) { // this needs some better checks @@ -108,7 +110,6 @@ const setMaximized = (state, browserOpts, immutableWindowState) => { function windowDefaults (state) { return { - show: false, width: state.getIn(['defaultWindowParams', 'width']) || state.get('defaultWindowWidth'), height: state.getIn(['defaultWindowParams', 'height']) || state.get('defaultWindowHeight'), x: state.getIn(['defaultWindowParams', 'x']) || undefined, @@ -245,7 +246,52 @@ const createWindow = (state, action) => { const toolbarUserInterfaceScale = getSetting(settings.TOOLBAR_UI_SCALE) setImmediate(() => { - const win = new BrowserWindow(Object.assign(windowProps, browserOpts, {disposition: frameOpts.disposition})) + // normally macOS will open immediately-created windows from fullscreen + // parent windows as fullscreen + // but since we are showing the window async, we will set the window + // fullscreen once it is ready to be shown + // (browserOpts.fullscreen may already be set when loading from saved state, + // so this just sets it for other scenarios) + if (isDarwin && parentWindow && parentWindow.isFullScreen()) { + windowProps.fullscreen = true + } + + const defaultArgs = { + // hide the window until the window reports that it is rendered + show: false, + fullscreenable: true + } + const enforcedArgs = { + disposition: frameOpts.disposition + } + const windowArgs = Object.assign( + defaultArgs, + windowProps, + browserOpts, + enforcedArgs + ) + // remember if the window should be opened fullscreen once it is rendered + // and remove the fullscreen property for now + // (otherwise the window will be shown immediately by the OS / muon) + let shouldFullscreen = false + if (!windowArgs.show && windowArgs.fullscreen) { + windowArgs.fullscreen = false + shouldFullscreen = true + } + const win = new BrowserWindow(windowArgs) + // let the windowReady handler know to set the window to fullscreen + win.__shouldFullscreen = shouldFullscreen + if (!windowArgs.show) { + // the window is hidden until render, but we'll check to see + // if it is shown in a timeout as if the window errors it won't send + // the message to ask to be shown + // in those cases, we want to still show it, so that the user can find the error message + setTimeout(() => { + if (win && !win.isDestroyed() && !win.isVisible()) { + win.show() + } + }, TIMEOUT_WINDOW_SHOW_MS) + } let restoredImmutableWindowState = action.get('restoredState') initWindowCacheState(win.id, restoredImmutableWindowState) @@ -308,10 +354,6 @@ const createWindow = (state, action) => { } }) - win.on('ready-to-show', () => { - win.show() - }) - win.loadURL(appUrlUtil.getBraveExtIndexHTML()) }) @@ -330,6 +372,9 @@ const windowsReducer = (state, action, immutableAction) => { case appConstants.APP_WINDOW_READY: windows.windowReady(action.get('windowId')) break + case appConstants.APP_WINDOW_RENDERED: + windows.windowRendered(action.get('windowId')) + break case appConstants.APP_TAB_UPDATED: if (immutableAction.getIn(['changeInfo', 'pinned']) != null) { setImmediate(() => { diff --git a/app/browser/windows.js b/app/browser/windows.js index 5971c659c4b..cac1007c381 100644 --- a/app/browser/windows.js +++ b/app/browser/windows.js @@ -317,6 +317,27 @@ const api = { }) }, + windowRendered: (windowId) => { + setImmediate(() => { + const win = currentWindows[windowId] + if (win && !win.isDestroyed() && !win.isVisible()) { + // window is hidden by default until we receive 'ready' message, + // so show it now + win.show() + if (win.__shouldFullscreen) { + // this timeout helps with an issue that + // when a user is loading from state, and + // has many full screen windows and non fullscreen windows + // the non fullscreen windows can get opened on top of the fullscreen + // spaces because macOS has switched away from the desktop space + setTimeout(() => { + win.setFullScreen(true) + }, 100) + } + } + }) + }, + closeWindow: (windowId) => { let win = api.getWindow(windowId) try { diff --git a/js/actions/appActions.js b/js/actions/appActions.js index b81a533cc6c..f30e6b54244 100644 --- a/js/actions/appActions.js +++ b/js/actions/appActions.js @@ -48,6 +48,16 @@ const appActions = { }) }, + windowRendered: function (windowId) { + dispatch({ + actionType: appConstants.APP_WINDOW_RENDERED, + windowId, + queryInfo: { + windowId + } + }) + }, + closeWindow: function (windowId) { dispatch({ actionType: appConstants.APP_CLOSE_WINDOW, diff --git a/js/constants/appConstants.js b/js/constants/appConstants.js index 4a4a2e4a189..6fec46fee43 100644 --- a/js/constants/appConstants.js +++ b/js/constants/appConstants.js @@ -7,6 +7,7 @@ const _ = null const appConstants = { APP_NEW_WINDOW: _, APP_WINDOW_READY: _, + APP_WINDOW_RENDERED: _, APP_CLOSE_WINDOW: _, APP_WINDOW_CLOSED: _, APP_WINDOW_CREATED: _, diff --git a/js/entry.js b/js/entry.js index 59f34edeb65..50a53b678d5 100644 --- a/js/entry.js +++ b/js/entry.js @@ -86,9 +86,13 @@ ipc.on(messages.INITIALIZE_WINDOW, (e, mem) => { windowStore.state = newState generateTabs(newState, message.frames, windowValue.id) appActions.windowReady(windowValue.id, windowValue) - ReactDOM.render(, document.getElementById('appContainer')) + ReactDOM.render(, document.getElementById('appContainer'), fireOnReactRender.bind(null, windowValue)) }) +const fireOnReactRender = (windowValue) => { + appActions.windowRendered(windowValue.id) +} + const generateTabs = (windowState, frames, windowId) => { const activeFrameKey = windowState.get('activeFrameKey')