[MM-58357] Account for monitor scale factor when creating the window from saved bounds (#3045) (#3057)

(cherry picked from commit 9bc0270a13)

Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com>
This commit is contained in:
Mattermost Build 2024-06-10 17:01:32 +03:00 committed by GitHub
parent 6eab211e41
commit af3b1d262e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 8 deletions

View file

@ -179,7 +179,7 @@ export function validateArgs(data: Args) {
}
// validate bounds_info.json
export function validateBoundsInfo(data: SavedWindowState) {
export function validateBoundsInfo(data: SavedWindowState | null) {
return validateAgainstSchema(data, boundsInfoSchema);
}

View file

@ -104,7 +104,7 @@ describe('main/windows/mainWindow', () => {
BrowserWindow.mockImplementation(() => baseWindow);
fs.readFileSync.mockImplementation(() => '{"x":400,"y":300,"width":1280,"height":700,"maximized":false,"fullscreen":false}');
path.join.mockImplementation(() => 'anyfile.txt');
screen.getDisplayMatching.mockImplementation(() => ({bounds: {x: 0, y: 0, width: 1920, height: 1080}}));
screen.getDisplayMatching.mockImplementation(() => ({scaleFactor: 1, bounds: {x: 0, y: 0, width: 1920, height: 1080}}));
isInsideRectangle.mockReturnValue(true);
Validator.validateBoundsInfo.mockImplementation((data) => data);
ContextMenu.mockImplementation(() => ({
@ -129,6 +129,20 @@ describe('main/windows/mainWindow', () => {
}));
});
it('should set scaled window size using bounds read from file', () => {
screen.getDisplayMatching.mockImplementation(() => ({scaleFactor: 2, bounds: {x: 0, y: 0, width: 1920, height: 1080}}));
const mainWindow = new MainWindow();
mainWindow.init();
expect(BrowserWindow).toHaveBeenCalledWith(expect.objectContaining({
x: 400,
y: 300,
width: 640,
height: 350,
maximized: false,
fullscreen: false,
}));
});
it('should set default window size when failing to read bounds from file', () => {
fs.readFileSync.mockImplementation(() => 'just a bunch of garbage');
const mainWindow = new MainWindow();

View file

@ -45,7 +45,7 @@ const ALT_MENU_KEYS = ['Alt+F', 'Alt+E', 'Alt+V', 'Alt+H', 'Alt+W', 'Alt+P'];
export class MainWindow extends EventEmitter {
private win?: BrowserWindow;
private savedWindowState?: SavedWindowState;
private savedWindowState?: Partial<SavedWindowState>;
private ready: boolean;
private isResizing: boolean;
private lastEmittedBounds?: Electron.Rectangle;
@ -89,6 +89,7 @@ export class MainWindow extends EventEmitter {
spellcheck: typeof Config.useSpellChecker === 'undefined' ? true : Config.useSpellChecker,
},
});
log.debug('main window options', windowOptions);
if (process.platform === 'linux') {
windowOptions.icon = path.join(path.resolve(app.getAppPath(), 'assets'), 'linux', 'app_icon.png');
@ -245,25 +246,34 @@ export class MainWindow extends EventEmitter {
return os.platform() === 'darwin' || (os.platform() === 'win32' && Utils.isVersionGreaterThanOrEqualTo(os.release(), '6.2'));
};
private getSavedWindowState = () => {
let savedWindowState: any;
private getSavedWindowState = (): Partial<SavedWindowState> => {
try {
savedWindowState = JSON.parse(fs.readFileSync(boundsInfoPath, 'utf-8'));
let savedWindowState: SavedWindowState | null = JSON.parse(fs.readFileSync(boundsInfoPath, 'utf-8'));
savedWindowState = Validator.validateBoundsInfo(savedWindowState);
if (!savedWindowState) {
throw new Error('Provided bounds info file does not validate, using defaults instead.');
}
const matchingScreen = screen.getDisplayMatching(savedWindowState);
log.debug('matching screen for main window', matchingScreen);
if (!(matchingScreen && (isInsideRectangle(matchingScreen.bounds, savedWindowState) || savedWindowState.maximized))) {
throw new Error('Provided bounds info are outside the bounds of your screen, using defaults instead.');
}
// We check for the monitor's scale factor when we want to set these bounds
// This is due to a long running Electron issue: https://github.com/electron/electron/issues/10862
return {
...savedWindowState,
width: Math.floor(savedWindowState.width / matchingScreen.scaleFactor),
height: Math.floor(savedWindowState.height / matchingScreen.scaleFactor),
};
} catch (e) {
log.error(e);
// Follow Electron's defaults, except for window dimensions which targets 1024x768 screen resolution.
savedWindowState = {width: DEFAULT_WINDOW_WIDTH, height: DEFAULT_WINDOW_HEIGHT};
return {
width: DEFAULT_WINDOW_WIDTH,
height: DEFAULT_WINDOW_HEIGHT,
};
}
return savedWindowState;
};
private saveWindowState = (file: string, window: BrowserWindow) => {
@ -273,6 +283,7 @@ export class MainWindow extends EventEmitter {
fullscreen: window.isFullScreen(),
};
try {
log.debug('saving window state', windowState);
fs.writeFileSync(file, JSON.stringify(windowState));
} catch (e) {
// [Linux] error happens only when the window state is changed before the config dir is created.