Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove buggy window repositioning #1248

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 2 additions & 20 deletions src/main/Core/BrowserWindow/BrowserWindowModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ import {
MacOsBrowserWindowConstructorOptionsProvider,
VibrancyProvider,
WindowsBrowserWindowConstructorOptionsProvider,
defaultWindowSize,
} from "./BrowserWindowConstructorOptionsProvider";
import { BrowserWindowCreator } from "./BrowserWindowCreator";
import { BrowserWindowToggler } from "./BrowserWindowToggler";
import { WindowBoundsMemory } from "./WindowBoundsMemory";
import { sendToBrowserWindow } from "./sendToBrowserWindow";

export class BrowserWindowModule {
Expand All @@ -36,8 +34,6 @@ export class BrowserWindowModule {
const assetPathResolver = dependencyRegistry.get("AssetPathResolver");
const ipcMain = dependencyRegistry.get("IpcMain");

const windowBoundsMemory = new WindowBoundsMemory(dependencyRegistry.get("Screen"), {});

const appIconFilePathResolver = new AppIconFilePathResolver(nativeTheme, assetPathResolver, operatingSystem);

const defaultBrowserWindowOptions = new DefaultBrowserWindowConstructorOptionsProvider(
Expand Down Expand Up @@ -67,13 +63,7 @@ export class BrowserWindowModule {

browserWindow.setVisibleOnAllWorkspaces(settingsManager.getValue("window.visibleOnAllWorkspaces", false));

const browserWindowToggler = new BrowserWindowToggler(
operatingSystem,
app,
browserWindow,
defaultWindowSize,
settingsManager,
);
const browserWindowToggler = new BrowserWindowToggler(operatingSystem, app, browserWindow);

eventEmitter.emitEvent("browserWindowCreated", { browserWindow });

Expand All @@ -83,13 +73,11 @@ export class BrowserWindowModule {
browserWindowToggler,
browserWindow,
dependencyRegistry.get("SettingsManager"),
windowBoundsMemory,
);

BrowserWindowModule.registerEvents(
browserWindow,
dependencyRegistry.get("EventSubscriber"),
windowBoundsMemory,
vibrancyProvider,
backgroundMaterialProvider,
browserWindowToggler,
Expand All @@ -108,22 +96,18 @@ export class BrowserWindowModule {
browserWindowToggler: BrowserWindowToggler,
browserWindow: BrowserWindow,
settingsManager: SettingsManager,
windowBoundsMemory: WindowBoundsMemory,
) {
const shouldHideWindowOnBlur = () =>
settingsManager
.getValue("window.hideWindowOn", BrowserWindowModule.DefaultHideWindowOnOptions)
.includes("blur");

browserWindow.on("blur", () => shouldHideWindowOnBlur() && browserWindowToggler.hide());
browserWindow.on("moved", () => windowBoundsMemory.saveWindowBounds(browserWindow));
browserWindow.on("resized", () => windowBoundsMemory.saveWindowBounds(browserWindow));
}

private static registerEvents(
browserWindow: BrowserWindow,
eventSubscriber: EventSubscriber,
windowBoundsMemory: WindowBoundsMemory,
vibrancyProvider: VibrancyProvider,
backgroundMaterialProvider: BackgroundMaterialProvider,
browserWindowToggler: BrowserWindowToggler,
Expand All @@ -147,9 +131,7 @@ export class BrowserWindowModule {
}
});

eventSubscriber.subscribe("hotkeyPressed", () =>
browserWindowToggler.toggle(windowBoundsMemory.getBoundsNearestToCursor()),
);
eventSubscriber.subscribe("hotkeyPressed", () => browserWindowToggler.toggle());

eventSubscriber.subscribe("settingUpdated", ({ key, value }: { key: string; value: unknown }) => {
sendToBrowserWindow(browserWindow, `settingUpdated[${key}]`, { value });
Expand Down
80 changes: 12 additions & 68 deletions src/main/Core/BrowserWindow/BrowserWindowToggler.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { SettingsManager } from "@Core/SettingsManager";
import type { OperatingSystem } from "@common/Core";
import type { App, BrowserWindow, Rectangle, Size } from "electron";
import type { App, BrowserWindow } from "electron";
import { describe, expect, it, vi } from "vitest";
import { BrowserWindowToggler } from "./BrowserWindowToggler";

Expand Down Expand Up @@ -61,20 +60,15 @@ describe(BrowserWindowToggler, () => {

const {
browserWindow,
centerMock,
focusMock,
isFocusedMock,
isVisibleMock,
restoreMock,
setBoundsMock,
showMock,
webContentsSendMock,
} = createBrowserWindow({ isFocused: false, isVisible: true });

const defaultSize = <Size>{ width: 100, height: 200 };
const settingsManager = <SettingsManager>{};

new BrowserWindowToggler(operatingSystem, app, browserWindow, defaultSize, settingsManager).toggle();
new BrowserWindowToggler(operatingSystem, app, browserWindow).toggle();

expect(isVisibleMock).toHaveBeenCalledOnce();
expect(isFocusedMock).toHaveBeenCalledOnce();
Expand All @@ -89,8 +83,6 @@ describe(BrowserWindowToggler, () => {
expect(showMock).toHaveBeenCalledOnce();
expect(focusMock).toHaveBeenCalledOnce();
expect(webContentsSendMock).toHaveBeenCalledWith("windowFocused");
expect(setBoundsMock).toHaveBeenCalledWith(defaultSize);
expect(centerMock).toHaveBeenCalledOnce();
};

testShowAndFocus({ operatingSystem: "Windows" });
Expand All @@ -101,94 +93,49 @@ describe(BrowserWindowToggler, () => {
it("should show and focus the window if its hidden, re-centering it and resizing it to the default size", () => {
const { app, showMock: appShowMock } = createApp();

const {
browserWindow,
centerMock,
focusMock,
isVisibleMock,
restoreMock,
setBoundsMock,
showMock,
webContentsSendMock,
} = createBrowserWindow({ isFocused: false, isVisible: false });

const defaultSize = <Size>{ width: 100, height: 200 };
const settingsManager = <SettingsManager>{};
const { browserWindow, focusMock, isVisibleMock, restoreMock, showMock, webContentsSendMock } =
createBrowserWindow({ isFocused: false, isVisible: false });

new BrowserWindowToggler("Windows", app, browserWindow, defaultSize, settingsManager).toggle();
new BrowserWindowToggler("Windows", app, browserWindow).toggle();

expect(isVisibleMock).toHaveBeenCalledOnce();
expect(appShowMock).toHaveBeenCalledOnce();
expect(restoreMock).toHaveBeenCalledOnce();
expect(showMock).toHaveBeenCalledOnce();
expect(focusMock).toHaveBeenCalledOnce();
expect(webContentsSendMock).toHaveBeenCalledWith("windowFocused");
expect(setBoundsMock).toHaveBeenCalledWith(defaultSize);
expect(centerMock).toHaveBeenCalledOnce();
});

it("should show and focus the window if its hidden, repositioning it with the given bounds", () => {
const { app, showMock: appShowMock } = createApp();

const {
browserWindow,
focusMock,
isVisibleMock,
restoreMock,
setBoundsMock,
showMock,
webContentsSendMock,
centerMock,
} = createBrowserWindow({ isFocused: false, isVisible: false });

const defaultSize = <Size>{ width: 100, height: 200 };
const bounds = <Rectangle>{ x: 10, y: 20, width: 30, height: 40 };

const getValueMock = vi.fn().mockReturnValue(false);
const settingsManager = <SettingsManager>{ getValue: (k, d) => getValueMock(k, d) };
const { browserWindow, focusMock, isVisibleMock, restoreMock, showMock, webContentsSendMock } =
createBrowserWindow({ isFocused: false, isVisible: false });

new BrowserWindowToggler("Windows", app, browserWindow, defaultSize, settingsManager).toggle(bounds);
new BrowserWindowToggler("Windows", app, browserWindow).toggle();

expect(isVisibleMock).toHaveBeenCalledOnce();
expect(appShowMock).toHaveBeenCalledOnce();
expect(restoreMock).toHaveBeenCalledOnce();
expect(showMock).toHaveBeenCalledOnce();
expect(focusMock).toHaveBeenCalledOnce();
expect(webContentsSendMock).toHaveBeenCalledWith("windowFocused");
expect(setBoundsMock).toHaveBeenCalledWith(bounds);
expect(centerMock).not.toHaveBeenCalled();
});

it("should show and focus the window if its hidden, repositioning it with the given bounds and re-centering it if alwaysCenter is set to true", () => {
const { app, showMock: appShowMock } = createApp();

const {
browserWindow,
centerMock,
focusMock,
isVisibleMock,
restoreMock,
setBoundsMock,
showMock,
webContentsSendMock,
} = createBrowserWindow({ isFocused: false, isVisible: false });
const { browserWindow, focusMock, isVisibleMock, restoreMock, showMock, webContentsSendMock } =
createBrowserWindow({ isFocused: false, isVisible: false });

const defaultSize = <Size>{ width: 100, height: 200 };
const bounds = <Rectangle>{ x: 10, y: 20, width: 30, height: 40 };

const getValueMock = vi.fn().mockReturnValue(true);
const settingsManager = <SettingsManager>{ getValue: (k, d) => getValueMock(k, d) };

new BrowserWindowToggler("Windows", app, browserWindow, defaultSize, settingsManager).toggle(bounds);
new BrowserWindowToggler("Windows", app, browserWindow).toggle();

expect(isVisibleMock).toHaveBeenCalledOnce();
expect(appShowMock).toHaveBeenCalledOnce();
expect(restoreMock).toHaveBeenCalledOnce();
expect(showMock).toHaveBeenCalledOnce();
expect(focusMock).toHaveBeenCalledOnce();
expect(webContentsSendMock).toHaveBeenCalledWith("windowFocused");
expect(setBoundsMock).toHaveBeenCalledWith(bounds);
expect(centerMock).toHaveBeenCalledOnce();
});

it("should hide the window if it is visible and focussed", () => {
Expand All @@ -200,10 +147,7 @@ describe(BrowserWindowToggler, () => {
isVisible: true,
});

const defaultSize = <Size>{ width: 100, height: 200 };
const settingsManager = <SettingsManager>{};

new BrowserWindowToggler(operatingSystem, app, browserWindow, defaultSize, settingsManager).toggle();
new BrowserWindowToggler(operatingSystem, app, browserWindow).toggle();

expect(isVisibleMock).toHaveBeenCalledOnce();
expect(isFocusedMock).toHaveBeenCalledOnce();
Expand Down
25 changes: 4 additions & 21 deletions src/main/Core/BrowserWindow/BrowserWindowToggler.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import type { SettingsManager } from "@Core/SettingsManager";
import type { OperatingSystem } from "@common/Core";
import type { App, BrowserWindow, Rectangle, Size } from "electron";
import type { App, BrowserWindow } from "electron";

export class BrowserWindowToggler {
public constructor(
private readonly operatingSystem: OperatingSystem,
private readonly app: App,
private readonly browserWindow: BrowserWindow,
private readonly defaultSize: Size,
private readonly settingsManager: SettingsManager,
) {}

public toggle(bounds?: Rectangle): void {
public toggle(): void {
if (this.isVisibleAndFocused()) {
this.hide();
} else {
this.showAndFocus(bounds);
this.showAndFocus();
}
}

Expand All @@ -37,7 +34,7 @@ export class BrowserWindowToggler {
this.browserWindow.hide();
}

public showAndFocus(bounds?: Rectangle): void {
public showAndFocus(): void {
if (typeof this.app.show === "function") {
this.app.show();
}
Expand All @@ -49,21 +46,7 @@ export class BrowserWindowToggler {
this.browserWindow.restore();
}

this.repositionWindow(bounds);

this.browserWindow.focus();
this.browserWindow.webContents.send("windowFocused");
}

private repositionWindow(bounds?: Rectangle): void {
this.browserWindow.setBounds(bounds ?? this.defaultSize);

if (!bounds || this.alwaysCenter()) {
this.browserWindow.center();
}
}

private alwaysCenter(): boolean {
return this.settingsManager.getValue("window.alwaysCenter", false);
}
}
66 changes: 0 additions & 66 deletions src/main/Core/BrowserWindow/WindowBoundsMemory.test.ts

This file was deleted.

30 changes: 0 additions & 30 deletions src/main/Core/BrowserWindow/WindowBoundsMemory.ts

This file was deleted.