Skip to content

Commit

Permalink
feat: Remember window size and position
Browse files Browse the repository at this point in the history
  • Loading branch information
gmaclennan committed Sep 19, 2019
1 parent c3796db commit cca4bc7
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 1 deletion.
12 changes: 11 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var menuTemplate = require('./src/main/menu')
var createServer = require('./src/main/server.js')
var createTileServer = require('./src/main/tile-server.js')
var logger = require('./src/log')
var windowStateKeeper = require('./src/main/window-state')

var installStatsIndex = require('./src/main/osm-stats')
var TileImporter = require('./src/main/tile-importer')
Expand Down Expand Up @@ -90,8 +91,17 @@ function openWindow () {
var APP_NAME = app.getName()
var INDEX = 'file://' + path.join(__dirname, './index.html')
var SPLASH = 'file://' + path.join(__dirname, './splash.html')
var mainWindowState = windowStateKeeper({
defaultWidth: 1000,
defaultHeight: 800
})

if (!win) {
win = new BrowserWindow({
x: mainWindowState.x,
y: mainWindowState.y,
width: mainWindowState.width,
height: mainWindowState.height,
title: APP_NAME,
show: false,
alwaysOnTop: false,
Expand All @@ -101,6 +111,7 @@ function openWindow () {
nodeIntegration: true
}
})
mainWindowState.manage(win)
splash = new BrowserWindow({
width: 810,
height: 610,
Expand Down Expand Up @@ -221,7 +232,6 @@ function notifyReady (done) {
setTimeout(() => {
var IS_TEST = process.env.NODE_ENV === 'test'
if (IS_TEST) win.setSize(1000, 800, false)
else win.maximize()
if (argv.debug) win.webContents.openDevTools()
splash.destroy()
win.show()
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"electron-is-dev": "^1.0.1",
"electron-log": "^3.0.8",
"electron-squirrel-startup": "^1.0.0",
"electron-store": "^5.0.0",
"end-of-stream": "^1.1.0",
"fs-copy-file-sync": "^1.0.1",
"glob": "^7.1.2",
Expand Down
203 changes: 203 additions & 0 deletions src/main/window-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
'use strict'

const electron = require('electron')
const Store = require('electron-store')

const store = new Store({ name: 'window-position' })

const defaults = {
maximize: true,
fullscreen: true,
defaultWidth: 800,
defaultHeight: 600,
isMaximized: true
}

/**
* Store window size and position and restore it when the user restarts
* Adapted from https://github.com/mawie81/electron-window-state (MIT License)
*/
module.exports = function (options) {
const screen = electron.screen || electron.remote.screen
let state
let winRef
let stateChangeTimer
const eventHandlingDelay = 100
const config = Object.assign(defaults, options)

function isNormal (win) {
return !win.isMaximized() && !win.isMinimized() && !win.isFullScreen()
}

function hasBounds () {
return (
state &&
Number.isInteger(state.x) &&
Number.isInteger(state.y) &&
Number.isInteger(state.width) &&
state.width > 0 &&
Number.isInteger(state.height) &&
state.height > 0
)
}

function resetStateToDefault () {
const displayBounds = screen.getPrimaryDisplay().bounds

// Reset state to default values on the primary display
state = {
width: config.defaultWidth || 800,
height: config.defaultHeight || 600,
x: 0,
y: 0,
displayBounds
}
}

function windowWithinBounds (bounds) {
return (
state.x >= bounds.x &&
state.y >= bounds.y &&
state.x + state.width <= bounds.x + bounds.width &&
state.y + state.height <= bounds.y + bounds.height
)
}

function ensureWindowVisibleOnSomeDisplay () {
const visible = screen.getAllDisplays().some(display => {
return windowWithinBounds(display.bounds)
})

if (!visible) {
// Window is partially or fully not visible now.
// Reset it to safe defaults.
return resetStateToDefault()
}
}

function validateState () {
const isValid =
state && (hasBounds() || state.isMaximized || state.isFullScreen)
if (!isValid) {
state = null
return
}

if (hasBounds() && state.displayBounds) {
ensureWindowVisibleOnSomeDisplay()
}
}

function updateState (win) {
win = win || winRef
if (!win) {
return
}
// Don't throw an error when window was closed
try {
const winBounds = win.getBounds()
if (isNormal(win)) {
state.x = winBounds.x
state.y = winBounds.y
state.width = winBounds.width
state.height = winBounds.height
}
state.isMaximized = win.isMaximized()
state.isFullScreen = win.isFullScreen()
state.displayBounds = screen.getDisplayMatching(winBounds).bounds
} catch (err) {}
}

function saveState (win) {
// Update window state only if it was provided
if (win) {
updateState(win)
}

// Save state
try {
store.set('state', state)
} catch (err) {
// Don't care
}
}

function stateChangeHandler () {
// Handles both 'resize' and 'move'
clearTimeout(stateChangeTimer)
stateChangeTimer = setTimeout(updateState, eventHandlingDelay)
}

function closeHandler () {
updateState()
}

function closedHandler () {
// Unregister listeners and save state
unmanage()
saveState()
}

function manage (win) {
if (config.maximize && state.isMaximized) {
win.maximize()
}
if (config.fullScreen && state.isFullScreen) {
win.setFullScreen(true)
}
win.on('resize', stateChangeHandler)
win.on('move', stateChangeHandler)
win.on('close', closeHandler)
win.on('closed', closedHandler)
winRef = win
}

function unmanage () {
if (winRef) {
winRef.removeListener('resize', stateChangeHandler)
winRef.removeListener('move', stateChangeHandler)
clearTimeout(stateChangeTimer)
winRef.removeListener('close', closeHandler)
winRef.removeListener('closed', closedHandler)
winRef = null
}
}

// Load previous state
try {
state = store.get('state', defaults)
} catch (err) {
// Don't care
}

// Check state validity
validateState()

return {
get x () {
return state.x
},
get y () {
return state.y
},
get width () {
return state.width
},
get height () {
return state.height
},
get displayBounds () {
return state.displayBounds
},
get isMaximized () {
return state.isMaximized
},
get isFullScreen () {
return state.isFullScreen
},
saveState,
unmanage,
manage,
resetStateToDefault
}
}

0 comments on commit cca4bc7

Please sign in to comment.