Ensure window stays on screen after external monitor removed.

This commit is contained in:
Patrick FIc
2025-05-15 15:19:15 -07:00
parent cd5ddc4fa1
commit eab52bf8c1
4 changed files with 118 additions and 5 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "bodyshop-desktop",
"version": "0.0.1-alpha.10",
"version": "0.0.1-alpha.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bodyshop-desktop",
"version": "0.0.1-alpha.10",
"version": "0.0.1-alpha.11",
"hasInstallScript": true,
"dependencies": {
"@apollo/client": "^3.13.6",

View File

@@ -1,6 +1,6 @@
{
"name": "bodyshop-desktop",
"version": "0.0.1-alpha.11",
"version": "0.0.1-alpha.13",
"description": "Shop Management System Partner",
"main": "./out/main/index.js",
"author": "Convenient Brands, LLC",

View File

@@ -33,6 +33,7 @@ import {
isKeepAliveTaskInstalled,
setupKeepAliveTask,
} from "./setup-keep-alive-task";
import ensureWindowOnScreen from "./util/ensureWindowOnScreen";
Sentry.init({
dsn: "https://ba41d22656999a8c1fd63bcb7df98650@o492140.ingest.us.sentry.io/4509074139447296",
@@ -56,11 +57,14 @@ function createWindow(): void {
y: number | undefined;
};
// Validate window position is on screen
const { validX, validY } = ensureWindowOnScreen(x, y, width, height);
const mainWindow = new BrowserWindow({
width,
height,
x,
y,
x: validX,
y: validY,
show: false, // Start hidden, show later if not keep-alive
minWidth: 600,
minHeight: 400,

View File

@@ -0,0 +1,109 @@
import { screen } from "electron";
function ensureWindowOnScreen(
x: number | undefined,
y: number | undefined,
windowWidth: number,
windowHeight: number,
): { validX: number | undefined; validY: number | undefined } {
// If no coordinates stored, let Electron position window automatically
if (x === undefined || y === undefined) {
return { validX: undefined, validY: undefined };
}
const displays = screen.getAllDisplays();
// Minimum visible pixels required on each edge to be considered "visible enough"
const MIN_VISIBLE = 50; // Ensure at least 50px from each edge is visible
// Try to find a display where the window would be almost fully visible
for (const display of displays) {
const { bounds } = display;
// Check if window is mostly within this display
if (
x + MIN_VISIBLE >= bounds.x &&
x + windowWidth - MIN_VISIBLE <= bounds.x + bounds.width &&
y + MIN_VISIBLE >= bounds.y &&
y + windowHeight - MIN_VISIBLE <= bounds.y + bounds.height
) {
// Window is adequately visible on this display
return { validX: x, validY: y };
}
}
// If window isn't adequately visible on any display, try to adjust it to fit the closest display
const closestDisplay = findClosestDisplay(displays, x, y);
const { bounds } = closestDisplay;
// Adjust position to ensure window is fully on screen
let adjustedX = x;
let adjustedY = y;
// Adjust horizontal position if needed
if (x < bounds.x) {
adjustedX = bounds.x;
} else if (x + windowWidth > bounds.x + bounds.width) {
adjustedX = bounds.x + bounds.width - windowWidth;
}
// Adjust vertical position if needed
if (y < bounds.y) {
adjustedY = bounds.y;
} else if (y + windowHeight > bounds.y + bounds.height) {
adjustedY = bounds.y + bounds.height - windowHeight;
}
// If adjustments keep window on screen, use adjusted position
if (
adjustedX >= bounds.x &&
adjustedX + windowWidth <= bounds.x + bounds.width &&
adjustedY >= bounds.y &&
adjustedY + windowHeight <= bounds.y + bounds.height
) {
return { validX: adjustedX, validY: adjustedY };
}
// If all else fails, center on primary display
const primaryDisplay = screen.getPrimaryDisplay();
const primaryBounds = primaryDisplay.bounds;
return {
validX: Math.floor(
primaryBounds.x + (primaryBounds.width - windowWidth) / 2,
),
validY: Math.floor(
primaryBounds.y + (primaryBounds.height - windowHeight) / 2,
),
};
}
// Helper function to find the closest display to a point
function findClosestDisplay(
displays: Electron.Display[],
x: number,
y: number,
): Electron.Display {
let closestDisplay = displays[0];
let shortestDistance = Number.MAX_VALUE;
for (const display of displays) {
const { bounds } = display;
// Calculate distance to center of display
const displayCenterX = bounds.x + bounds.width / 2;
const displayCenterY = bounds.y + bounds.height / 2;
const distance = Math.sqrt(
Math.pow(x - displayCenterX, 2) + Math.pow(y - displayCenterY, 2),
);
if (distance < shortestDistance) {
shortestDistance = distance;
closestDisplay = display;
}
}
return closestDisplay;
}
export default ensureWindowOnScreen;