Ensure window stays on screen after external monitor removed.
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "bodyshop-desktop",
|
"name": "bodyshop-desktop",
|
||||||
"version": "0.0.1-alpha.10",
|
"version": "0.0.1-alpha.11",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "bodyshop-desktop",
|
"name": "bodyshop-desktop",
|
||||||
"version": "0.0.1-alpha.10",
|
"version": "0.0.1-alpha.11",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.13.6",
|
"@apollo/client": "^3.13.6",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bodyshop-desktop",
|
"name": "bodyshop-desktop",
|
||||||
"version": "0.0.1-alpha.11",
|
"version": "0.0.1-alpha.13",
|
||||||
"description": "Shop Management System Partner",
|
"description": "Shop Management System Partner",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "Convenient Brands, LLC",
|
"author": "Convenient Brands, LLC",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
isKeepAliveTaskInstalled,
|
isKeepAliveTaskInstalled,
|
||||||
setupKeepAliveTask,
|
setupKeepAliveTask,
|
||||||
} from "./setup-keep-alive-task";
|
} from "./setup-keep-alive-task";
|
||||||
|
import ensureWindowOnScreen from "./util/ensureWindowOnScreen";
|
||||||
|
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: "https://ba41d22656999a8c1fd63bcb7df98650@o492140.ingest.us.sentry.io/4509074139447296",
|
dsn: "https://ba41d22656999a8c1fd63bcb7df98650@o492140.ingest.us.sentry.io/4509074139447296",
|
||||||
@@ -56,11 +57,14 @@ function createWindow(): void {
|
|||||||
y: number | undefined;
|
y: number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Validate window position is on screen
|
||||||
|
const { validX, validY } = ensureWindowOnScreen(x, y, width, height);
|
||||||
|
|
||||||
const mainWindow = new BrowserWindow({
|
const mainWindow = new BrowserWindow({
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
x,
|
x: validX,
|
||||||
y,
|
y: validY,
|
||||||
show: false, // Start hidden, show later if not keep-alive
|
show: false, // Start hidden, show later if not keep-alive
|
||||||
minWidth: 600,
|
minWidth: 600,
|
||||||
minHeight: 400,
|
minHeight: 400,
|
||||||
|
|||||||
109
src/main/util/ensureWindowOnScreen.ts
Normal file
109
src/main/util/ensureWindowOnScreen.ts
Normal 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;
|
||||||
Reference in New Issue
Block a user