Wait for browser process to acknowledge window manipulation IPC requests

We need to avoid using the  module for synchronous IPC on startup, but
in some cases, we need to know when our asynchronous IPC messages have taken
effect. Now,  methods like  and
return Promises that indicate when the message has been processed.
This commit is contained in:
Max Brunsfeld
2016-01-27 12:38:28 -08:00
parent d1b5e0e7e3
commit 32f5149196
6 changed files with 89 additions and 31 deletions

View File

@@ -1,5 +1,6 @@
_ = require 'underscore-plus'
{ipcRenderer, remote, shell, webFrame} = require 'electron'
ipcHelpers = require './ipc-helpers'
{Disposable} = require 'event-kit'
{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers'
@@ -26,26 +27,26 @@ class ApplicationDelegate
{width, height}
setWindowSize: (width, height) ->
remote.getCurrentWindow().setSize(width, height)
ipcHelpers.call('set-window-size', width, height)
getWindowPosition: ->
[x, y] = remote.getCurrentWindow().getPosition()
{x, y}
setWindowPosition: (x, y) ->
ipcRenderer.send("call-window-method", "setPosition", x, y)
ipcHelpers.call('set-window-position', x, y)
centerWindow: ->
ipcRenderer.send("call-window-method", "center")
ipcHelpers.call('center-window')
focusWindow: ->
ipcRenderer.send("call-window-method", "focus")
ipcHelpers.call('focus-window')
showWindow: ->
ipcRenderer.send("call-window-method", "show")
ipcHelpers.call('show-window')
hideWindow: ->
ipcRenderer.send("call-window-method", "hide")
ipcHelpers.call('hide-window')
reloadWindow: ->
ipcRenderer.send("call-window-method", "reload")

View File

@@ -519,16 +519,17 @@ class AtomEnvironment extends Model
# Restore the window to its previous dimensions and show it.
#
# Also restores the full screen and maximized state on the next tick to
# Restores the full screen and maximized state after the window has resized to
# prevent resize glitches.
displayWindow: ->
dimensions = @restoreWindowDimensions()
@show()
@focus()
setImmediate =>
@setFullScreen(true) if @workspace?.fullScreen
@maximize() if dimensions?.maximized and process.platform isnt 'darwin'
@restoreWindowDimensions().then (dimensions) =>
steps = [
@show(),
@focus()
]
steps.push(@setFullScreen(true)) if @workspace.fullScreen
steps.push(@maximize()) if dimensions?.maximized and process.platform isnt 'darwin'
Promise.all(steps)
# Get the dimensions of this window.
#
@@ -556,12 +557,14 @@ class AtomEnvironment extends Model
# * `width` The new width.
# * `height` The new height.
setWindowDimensions: ({x, y, width, height}) ->
steps = []
if width? and height?
@setSize(width, height)
steps.push(@setSize(width, height))
if x? and y?
@setPosition(x, y)
steps.push(@setPosition(x, y))
else
@center()
steps.push(@center())
Promise.all(steps)
# Returns true if the dimensions are useable, false if they should be ignored.
# Work around for https://github.com/atom/atom-shell/issues/473
@@ -594,8 +597,7 @@ class AtomEnvironment extends Model
dimensions = @state.windowDimensions
unless @isValidDimensions(dimensions)
dimensions = @getDefaultWindowDimensions()
@setWindowDimensions(dimensions)
dimensions
@setWindowDimensions(dimensions).then -> dimensions
storeWindowDimensions: ->
dimensions = @getWindowDimensions()

View File

@@ -3,6 +3,7 @@ ApplicationMenu = require './application-menu'
AtomProtocolHandler = require './atom-protocol-handler'
AutoUpdateManager = require './auto-update-manager'
StorageFolder = require '../storage-folder'
ipcHelpers = require '../ipc-helpers'
{BrowserWindow, Menu, app, dialog, ipcMain, shell} = require 'electron'
fs = require 'fs-plus'
path = require 'path'
@@ -261,6 +262,24 @@ class AtomApplication
@promptForPath "folder", (selectedPaths) ->
event.sender.send(responseChannel, selectedPaths)
ipcHelpers.respondTo 'set-window-size', (win, width, height) ->
win.setSize(width, height)
ipcHelpers.respondTo 'set-window-position', (win, x, y) ->
win.setPosition(x, y)
ipcHelpers.respondTo 'center-window', (win) ->
win.center()
ipcHelpers.respondTo 'focus-window', (win) ->
win.focus()
ipcHelpers.respondTo 'show-window', (win) ->
win.show()
ipcHelpers.respondTo 'hide-window', (win) ->
win.hide()
ipcMain.on 'did-cancel-window-unload', =>
@quitting = false

View File

@@ -23,11 +23,11 @@ module.exports = ({blobStore}) ->
enablePersistence: true
})
atom.displayWindow()
atom.startEditorWindow()
atom.displayWindow().then ->
atom.startEditorWindow()
# Workaround for focus getting cleared upon window creation
windowFocused = ->
window.removeEventListener('focus', windowFocused)
setTimeout (-> document.querySelector('atom-workspace').focus()), 0
window.addEventListener('focus', windowFocused)
# Workaround for focus getting cleared upon window creation
windowFocused = ->
window.removeEventListener('focus', windowFocused)
setTimeout (-> document.querySelector('atom-workspace').focus()), 0
window.addEventListener('focus', windowFocused)

40
src/ipc-helpers.js Normal file
View File

@@ -0,0 +1,40 @@
var ipcRenderer = null
var ipcMain = null
var BrowserWindow = null
exports.call = function (methodName, ...args) {
if (!ipcRenderer) {
ipcRenderer = require('electron').ipcRenderer
}
var responseChannel = getResponseChannel(methodName)
return new Promise(function (resolve) {
ipcRenderer.on(responseChannel, function (event, result) {
ipcRenderer.removeAllListeners(responseChannel)
resolve(result)
})
ipcRenderer.send(methodName, ...args)
})
}
exports.respondTo = function (methodName, callback) {
if (!ipcMain) {
var electron = require('electron')
ipcMain = electron.ipcMain
BrowserWindow = electron.BrowserWindow
}
var responseChannel = getResponseChannel(methodName)
ipcMain.on(methodName, function (event, ...args) {
var browserWindow = BrowserWindow.fromWebContents(event.sender)
var result = callback(browserWindow, ...args)
event.sender.send(responseChannel, result)
})
}
function getResponseChannel (methodName) {
return 'ipc-helpers-' + methodName + '-response'
}