fix #830: minimize instead of close option on macOS

pull/1541/head
antelle 2020-06-01 14:42:06 +02:00
parent a2194435e6
commit 2deb241ff2
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
9 changed files with 83 additions and 27 deletions

View File

@ -27,8 +27,9 @@ const AutoType = {
return;
}
Events.on('auto-type', e => this.handleEvent(e));
Events.on('main-window-blur', e => this.resetPendingEvent(e));
Events.on('main-window-will-close', e => this.resetPendingEvent(e));
Events.on('main-window-blur', e => this.mainWindowBlur(e));
Events.on('main-window-focus', e => this.mainWindowFocus(e));
Events.on('main-window-will-close', e => this.mainWindowWillClose(e));
Events.on('closed-open-view', e => this.processPendingEvent(e));
},
@ -258,6 +259,31 @@ const AutoType = {
});
},
mainWindowBlur() {
this.mainWindowBlurTimer = setTimeout(() => {
// macOS emits focus-blur-focus event in a row when triggering auto-type from minimized state
delete this.mainWindowBlurTimer;
this.resetPendingEvent();
if (this.selectEntryView) {
this.selectEntryView.emit('result', undefined);
}
}, Timeouts.AutoTypeWindowFocusAfterBlur);
},
mainWindowFocus() {
if (this.mainWindowBlurTimer) {
clearTimeout(this.mainWindowBlurTimer);
this.mainWindowBlurTimer = null;
}
},
mainWindowWillClose() {
this.resetPendingEvent();
if (this.selectEntryView) {
this.selectEntryView.emit('result', undefined);
}
},
resetPendingEvent() {
if (this.pendingEvent) {
this.pendingEvent = null;

View File

@ -208,9 +208,6 @@ const Launcher = {
minimizeApp() {
this.hideApp();
},
canMinimize() {
return false;
},
canDetectOsSleep() {
return false;
},

View File

@ -163,6 +163,7 @@ const Launcher = {
},
requestExit() {
const app = this.remoteApp();
app.setSkipBeforeQuitEvent();
if (this.restartPending) {
app.restartApp();
} else {
@ -189,15 +190,15 @@ const Launcher = {
clipboard.clear('selection');
}
},
quitOnRealQuitEventIfMinimizeOnQuitIsEnabled() {
return this.platform() === 'darwin';
},
minimizeApp() {
this.remoteApp().minimizeApp({
restore: Locale.menuRestoreApp.replace('{}', 'KeeWeb'),
quit: Locale.menuQuitApp.replace('{}', 'KeeWeb')
});
},
canMinimize() {
return process.platform !== 'darwin';
},
canDetectOsSleep() {
return process.platform !== 'linux';
},
@ -218,10 +219,10 @@ const Launcher = {
},
hideApp() {
const app = this.remoteApp();
if (this.canMinimize()) {
app.minimizeThenHideIfInTray();
} else {
if (this.platform() === 'darwin') {
app.hide();
} else {
app.minimizeThenHideIfInTray();
}
},
isAppFocused() {
@ -328,6 +329,9 @@ Events.on('app-ready', () =>
);
Launcher.remoteApp().on('remote-app-event', e => {
if (window.debugRemoteAppEvents) {
logger.debug('remote-app-event', e.name);
}
Events.emit(e.name, e.data);
});

View File

@ -6,6 +6,7 @@ const Timeouts = {
CheckWindowClosed: 300,
OtpFadeDuration: 10000,
AutoTypeAfterHide: 100,
AutoTypeWindowFocusAfterBlur: 500,
DropDownClickWait: 500,
RedrawInactiveWindow: 50,
PopupWaitTime: 1000,

View File

@ -90,6 +90,8 @@ class AppView extends View {
this.listenTo(Events, 'enter-full-screen', this.enterFullScreen);
this.listenTo(Events, 'leave-full-screen', this.leaveFullScreen);
this.listenTo(Events, 'import-csv-requested', this.showImportCsv);
this.listenTo(Events, 'launcher-before-quit', this.launcherBeforeQuit);
this.listenTo(UpdateModel, 'change:updateReady', this.updateApp);
window.onbeforeunload = this.beforeUnload.bind(this);
@ -334,6 +336,18 @@ class AppView extends View {
}
}
launcherBeforeQuit() {
// this is currently called only on macos
const event = {
fromBeforeQuit: true,
preventDefault() {}
};
const result = this.beforeUnload(event);
if (result !== false) {
Launcher.exit();
}
}
beforeUnload(e) {
const exitEvent = {
preventDefault() {
@ -342,12 +356,19 @@ class AppView extends View {
};
Events.emit('main-window-will-close', exitEvent);
if (exitEvent.prevented) {
Launcher.preventExit(e);
return;
return Launcher ? Launcher.preventExit(e) : false;
}
let minimizeInsteadOfClose = this.model.settings.minimizeOnClose;
if (e.fromBeforeQuit) {
if (Launcher.quitOnRealQuitEventIfMinimizeOnQuitIsEnabled()) {
minimizeInsteadOfClose = false;
}
}
if (this.model.files.hasDirtyFiles()) {
const exit = () => {
if (Launcher.canMinimize() && this.model.settings.minimizeOnClose) {
if (minimizeInsteadOfClose) {
Launcher.minimizeApp();
} else {
Launcher.exit();
@ -401,8 +422,7 @@ class AppView extends View {
Launcher &&
!Launcher.exitRequested &&
!Launcher.restartPending &&
Launcher.canMinimize() &&
this.model.settings.minimizeOnClose
minimizeInsteadOfClose
) {
Launcher.minimizeApp();
return Launcher.preventExit(e);

View File

@ -32,7 +32,6 @@ class AutoTypeSelectView extends View {
constructor(model) {
super(model);
this.initScroll();
this.listenTo(Events, 'main-window-blur', this.mainWindowBlur);
this.listenTo(Events, 'main-window-will-close', this.mainWindowWillClose);
this.listenTo(Events, 'keypress:auto-type', this.keyPressed);
this.setupKeys();
@ -209,13 +208,8 @@ class AutoTypeSelectView extends View {
this.showItemOptions(itemEl, e);
}
mainWindowBlur() {
this.cancelAndClose();
}
mainWindowWillClose(e) {
e.preventDefault();
this.cancelAndClose();
}
showItemOptions(itemEl, event) {

View File

@ -89,7 +89,7 @@ class SettingsGeneralView extends View {
devTools: Launcher && Launcher.devTools,
canAutoUpdate: Updater.enabled,
canAutoSaveOnClose: !!Launcher,
canMinimize: Launcher && Launcher.canMinimize(),
canMinimize: !!Launcher,
canDetectMinimize: !!Launcher,
canDetectOsSleep: Launcher && Launcher.canDetectOsSleep(),
canAutoType: AutoType.enabled,

View File

@ -116,6 +116,14 @@ app.on('activate', () => {
}
}
});
app.on('before-quit', e => {
if (process.platform === 'darwin') {
if (!app.skipBeforeQuitEvent) {
e.preventDefault();
emitRemoteEvent('launcher-before-quit');
}
}
});
app.on('will-quit', () => {
electron.globalShortcut.unregisterAll();
});
@ -174,6 +182,9 @@ app.minimizeThenHideIfInTray = function() {
app.getMainWindow = function() {
return mainWindow;
};
app.setSkipBeforeQuitEvent = () => {
app.skipBeforeQuitEvent = true;
};
app.setGlobalShortcuts = setGlobalShortcuts;
app.reqNative = reqNative;
app.showAndFocusMainWindow = showAndFocusMainWindow;
@ -274,10 +285,9 @@ function createMainWindow() {
}
function restoreMainWindow() {
// if (process.platform === 'darwin') {
// app.dock.show();
// mainWindow.show();
// }
if (process.platform === 'darwin' && !app.dock.isVisible()) {
app.dock.show();
}
if (mainWindow.isMinimized()) {
mainWindow.restore();
}
@ -294,6 +304,9 @@ function showAndFocusMainWindow() {
mainWindow.show();
}
mainWindow.focus();
if (process.platform === 'darwin' && !app.dock.isVisible()) {
app.dock.show();
}
}
function closeMainWindow() {

View File

@ -4,6 +4,7 @@ Release notes
`+` YubiKey integration in two modes: OATH and Challenge-Response
`+` configs are now encrypted with a key stored in keychain
`+` #1460: auto-type on double-clicking field labels
`+` #830: minimize instead of close option on macOS
`+` #557: Argon2 speed improvements in desktop apps
`+` #1503: ARM64 Windows support
`+` #1480: option to create a portable installation