summaryrefslogtreecommitdiffhomepage
path: root/app
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2018-03-05 19:15:22 +0100
committerAndrej Mihajlov <and@mullvad.net>2018-03-07 11:51:30 +0100
commit2de1c162aeb0214e6afd95c42655d0653ac28bff (patch)
tree01528270053780e3b2afc7fec41468c511f2077d /app
parent2bcd8c49e2ed3f59e3988540102f7cd58236a5a7 (diff)
downloadmullvadvpn-2de1c162aeb0214e6afd95c42655d0653ac28bff.tar.xz
mullvadvpn-2de1c162aeb0214e6afd95c42655d0653ac28bff.zip
Compute window position based on taskbar placement
Diffstat (limited to 'app')
-rw-r--r--app/main.js144
1 files changed, 109 insertions, 35 deletions
diff --git a/app/main.js b/app/main.js
index f097521c87..4d7dcd408a 100644
--- a/app/main.js
+++ b/app/main.js
@@ -3,7 +3,7 @@ import path from 'path';
import fs from 'fs';
import mkdirp from 'mkdirp';
import { log } from './lib/platform';
-import { app, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron';
+import electron, { app, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron';
import TrayIconManager from './lib/tray-icon-manager';
import ElectronSudo from 'electron-sudo';
import shellescape from 'shell-escape';
@@ -18,7 +18,6 @@ import uuid from 'uuid';
import type { TrayIconType } from './lib/tray-icon-manager';
const isDevelopment = (process.env.NODE_ENV === 'development');
-const isMacOS = (process.platform === 'darwin');
// The name for application directory used for
// scoping logs and user data in platform special folders
@@ -73,13 +72,15 @@ const appDelegate = {
// 1. https://github.com/electron/electron/issues/10118
// 2. https://github.com/electron/electron/pull/10191
_getLogsDirectory: () => {
- // macOS: ~/Library/Logs/{appname}
- if(isMacOS) {
+ switch(process.platform) {
+ case 'darwin':
+ // macOS: ~/Library/Logs/{appname}
return path.join(app.getPath('home'), 'Library/Logs', appDirectoryName);
+ default:
+ // Linux: ~/.config/{appname}/logs
+ // Windows: ~\AppData\Roaming\{appname}\logs
+ return path.join(app.getPath('userData'), 'logs');
}
- // Linux: ~/.config/{appname}/logs
- // Windows: ~\AppData\Roaming\{appname}\logs
- return path.join(app.getPath('userData'), 'logs');
},
onReady: async () => {
@@ -90,9 +91,8 @@ const appDelegate = {
appDelegate._pollForConnectionInfoFile();
});
- ipcMain.on('show-window', () => {
- appDelegate._showWindow(window, appDelegate._tray);
- });
+ ipcMain.on('show-window', () => appDelegate._showWindow(window, appDelegate._tray));
+ ipcMain.on('hide-window', () => window.hide());
window.loadURL('file://' + path.join(__dirname, 'index.html'));
window.on('close', () => {
@@ -138,13 +138,8 @@ const appDelegate = {
});
});
- // create tray icon on macOS
- if(isMacOS) {
- appDelegate._tray = appDelegate._createTray(window);
- } else {
- appDelegate._showWindow(window, null);
- }
-
+ // create tray icon
+ appDelegate._tray = appDelegate._createTray(window);
appDelegate._setAppMenu();
appDelegate._addContextMenu(window);
@@ -301,17 +296,32 @@ const appDelegate = {
}
};
- // setup window flags to mimic popover on macOS
- if(isMacOS) {
- const win = new BrowserWindow({
+ switch(process.platform) {
+ case 'darwin': {
+ // setup window flags to mimic popover on macOS
+ const appWindow = new BrowserWindow({
...options,
- height: contentHeight + 12, // 12 is the size of transparent area around arrow
+ // 12 is the size of transparent area around arrow
+ height: contentHeight + 12,
frame: false,
transparent: true
});
- win.setVisibleOnAllWorkspaces(true);
- return win;
- } else {
+
+ // make the window visible on all workspaces
+ appWindow.setVisibleOnAllWorkspaces(true);
+
+ return appWindow;
+ }
+
+ case 'win32':
+ // setup window flags to mimic an overlay window
+ return new BrowserWindow({
+ ...options,
+ frame: false,
+ transparent: true
+ });
+
+ default:
return new BrowserWindow(options);
}
},
@@ -395,17 +405,77 @@ const appDelegate = {
window.focus();
},
+ _getTrayPlacement: () => {
+ switch(process.platform) {
+ case 'darwin':
+ // macOS has menubar always placed at the top
+ return 'top';
+
+ case 'win32': {
+ // taskbar occupies some part of the screen excluded from work area
+ const primaryDisplay = electron.screen.getPrimaryDisplay();
+ const displaySize = primaryDisplay.size;
+ const workArea = primaryDisplay.workArea;
+
+ if(workArea.width < displaySize.width) {
+ return workArea.x > 0 ? 'left' : 'right';
+ } else if(workArea.height < displaySize.height) {
+ return workArea.y > 0 ? 'top' : 'bottom';
+ } else {
+ return 'none';
+ }
+ }
+
+ default:
+ return 'none';
+ }
+ },
+
_getWindowPosition: (window: BrowserWindow, tray: Tray): { x: number, y: number } => {
const windowBounds = window.getBounds();
const trayBounds = tray.getBounds();
- // center window horizontally below the tray icon
- const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2));
+ const primaryDisplay = electron.screen.getPrimaryDisplay();
+ const workArea = primaryDisplay.workArea;
+ const placement = appDelegate._getTrayPlacement();
+ const maxX = workArea.x + workArea.width - windowBounds.width;
+ const maxY = workArea.y + workArea.height - windowBounds.height;
- // position window vertically below the tray icon
- const y = Math.round(trayBounds.y + trayBounds.height);
+ let x = 0, y = 0;
+ switch(placement) {
+ case 'top':
+ x = trayBounds.x + (trayBounds.width - windowBounds.width) * 0.5;
+ y = trayBounds.y + trayBounds.height;
+ break;
- return { x, y };
+ case 'bottom':
+ x = trayBounds.x + (trayBounds.width - windowBounds.width) * 0.5;
+ y = trayBounds.y - windowBounds.height;
+ break;
+
+ case 'left':
+ x = trayBounds.x + trayBounds.width;
+ y = trayBounds.y + (trayBounds.height - windowBounds.height) * 0.5;
+ break;
+
+ case 'right':
+ x = trayBounds.x - windowBounds.width;
+ y = trayBounds.y + (trayBounds.height - windowBounds.height) * 0.5;
+ break;
+
+ case 'none':
+ x = workArea.x + (workArea.width - windowBounds.width) * 0.5;
+ y = workArea.y + (workArea.height - windowBounds.height) * 0.5;
+ break;
+ }
+
+ x = Math.min(Math.max(x, workArea.x), maxX);
+ y = Math.min(Math.max(y, workArea.y), maxY);
+
+ return {
+ x: Math.round(x),
+ y: Math.round(y)
+ };
},
_createTray: (window: BrowserWindow): Tray => {
@@ -413,20 +483,24 @@ const appDelegate = {
tray.setHighlightMode('never');
tray.on('click', () => appDelegate._toggleWindow(window, tray));
+ const trayIconManager = new TrayIconManager(tray, 'unsecured');
+
// setup NSEvent monitor to fix inconsistent window.blur
// see https://github.com/electron/electron/issues/8689
// $FlowFixMe: this module is only available on macOS
- const { NSEventMonitor, NSEventMask } = require('nseventmonitor');
- const trayIconManager = new TrayIconManager(tray, 'unsecured');
- const macEventMonitor = new NSEventMonitor();
- const eventMask = NSEventMask.leftMouseDown | NSEventMask.rightMouseDown;
+ if(process.platform === 'darwin') {
+ const { NSEventMonitor, NSEventMask } = require('nseventmonitor');
+ const macEventMonitor = new NSEventMonitor();
+ const eventMask = NSEventMask.leftMouseDown | NSEventMask.rightMouseDown;
+
+ window.on('show', () => macEventMonitor.start(eventMask, () => window.hide()));
+ window.on('hide', () => macEventMonitor.stop());
+ }
// add IPC handler to change tray icon from renderer
ipcMain.on('changeTrayIcon', (_: Event, type: TrayIconType) => trayIconManager.iconType = type);
// setup event handlers
- window.on('show', () => macEventMonitor.start(eventMask, () => window.hide()));
- window.on('hide', () => macEventMonitor.stop());
window.on('close', () => window.closeDevTools());
window.on('blur', () => !window.isDevToolsOpened() && window.hide());