Compare commits

..

No commits in common. "c48b8d72da242e48b6e2f01dc6e011e8b88d8948" and "17b5068644ebafb3c50e89fe6b0d359df891302c" have entirely different histories.

7 changed files with 7 additions and 181 deletions

View File

@ -25,6 +25,7 @@ InstallDirRegKey HKLM "Software\Tom Butcher\Farm Control" "InstallDir"
RequestExecutionLevel admin
!define MUI_ABORTWARNING
!define MUI_BRANDINGTEXT "Farm Control v${VERSION}-b${BUILD_NUMBER} Installer"
!ifndef INSTALLER_ICON
!define INSTALLER_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
@ -42,8 +43,6 @@ UninstallIcon "${INSTALLER_ICON}"
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
!define MUI_BRANDINGTEXT "Farm Control v${VERSION}-b${BUILD_NUMBER} Installer"
Function .onInit
${If} ${Silent}
SetAutoClose true

View File

@ -28,40 +28,15 @@
done_uninstall:
!macroend
!macro fixShortcutWorkingDir SHORTCUT_PATH WORKING_DIR
Push $0
Push $1
Push $2
StrCpy $1 "${SHORTCUT_PATH}"
StrCpy $2 "${WORKING_DIR}"
InitPluginsDir
FileOpen $0 "$PLUGINSDIR\fix-shortcut.ps1" w
FileWrite $0 '$$s = (New-Object -COM WScript.Shell).CreateShortcut("'
FileWrite $0 $1
FileWrite $0 '")$\r$\n'
FileWrite $0 '$$s.WorkingDirectory = "'
FileWrite $0 $2
FileWrite $0 '"$\r$\n'
FileWrite $0 '$$s.Save()$\r$\n'
FileClose $0
ExecWait '"$SYSDIR\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File "$PLUGINSDIR\fix-shortcut.ps1"'
Delete "$PLUGINSDIR\fix-shortcut.ps1"
Pop $2
Pop $1
Pop $0
!macroend
!macro createDesktopShortcut
SetShellVarContext all
CreateShortCut "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin\launcher.exe" "" "$INSTDIR\bin\launcher.exe" 0 SW_SHOWNORMAL "" "Farm Control"
!insertmacro fixShortcutWorkingDir "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin"
CreateShortCut "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin\launcher.exe"
!macroend
!macro createStartMenuShortcut
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\Farm Control"
CreateShortCut "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin\launcher.exe" "" "$INSTDIR\bin\launcher.exe" 0 SW_SHOWNORMAL "" "Farm Control"
!insertmacro fixShortcutWorkingDir "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin"
CreateShortCut "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin\launcher.exe"
!macroend
!macro removeDesktopShortcut

View File

@ -277,38 +277,6 @@ if (existsSync(rceditSrc)) {
cpSync(rceditSrc, rceditDest, { recursive: true, force: true })
}
function patchNativeWrapperPath(nativeTsPath) {
if (!existsSync(nativeTsPath)) {
return
}
let source = readFileSync(nativeTsPath, 'utf8')
const needle =
'const nativeWrapperPath = join(process.cwd(), `libNativeWrapper.${suffix}`);'
const replacement =
'const nativeWrapperPath = join(dirname(process.execPath), `libNativeWrapper.${suffix}`);'
if (!source.includes(needle)) {
return
}
if (!source.includes('dirname')) {
source = source.replace(
'import { join } from "path";',
'import { dirname, join } from "path";'
)
}
source = source.replace(needle, replacement)
writeFileSync(nativeTsPath, source)
}
for (const distDir of ['dist', 'dist-macos-arm64', 'dist-win-x64']) {
patchNativeWrapperPath(
path.join(electrobunDir, distDir, 'api/bun/proc/native.ts')
)
}
const markerPath = path.join(electrobunDir, '.farmcontrol-electrobun-patched')
writeFileSync(markerPath, `patched-at=${new Date().toISOString()}\n`)

View File

@ -36,7 +36,6 @@ if (!existsSync(launcherPath)) {
}
const child = spawn(launcherPath, [], {
cwd: dirname(launcherPath),
detached: true,
stdio: 'ignore',
windowsHide: true

View File

@ -1,19 +1,9 @@
import { chdirSync } from 'node:fs'
import { dirname } from 'node:path'
import {
captureLaunchUrl,
closeSingleInstanceServer,
ensureSingleInstanceLock
} from '../desktop/single-instance.js'
if (process.platform === 'win32') {
try {
chdirSync(dirname(process.execPath))
} catch {
// Best effort; some launchers may not allow changing directory.
}
}
const launchUrl = captureLaunchUrl()
const gotSingleInstanceLock = await ensureSingleInstanceLock({ launchUrl })

View File

@ -5,10 +5,6 @@ import {
MAC_TRAFFIC_LIGHT_OFFSET
} from './macos-window-effects.js'
import { sendToRenderer, setMessageSender } from './notify.js'
import {
clampWindowToWorkArea,
isWindowWorkAreaMaximized
} from './windows-work-area.js'
const isMacOS = process.platform === 'darwin'
const isWindows = process.platform === 'win32'
@ -171,20 +167,12 @@ function syncWindowsWebviewLayout(window) {
window.setSize(width, height)
}
function handleWindowsWindowChange(window) {
if (clampWindowToWorkArea(window)) {
syncWindowsWebviewLayout(window)
}
broadcastWindowState()
}
function applyWindowsStartupWindowState(window) {
if (!window) return
setTimeout(() => {
window.maximize?.()
handleWindowsWindowChange(window)
syncWindowsWebviewLayout(window)
setTimeout(() => syncWindowsWebviewLayout(window), 0)
setTimeout(() => syncWindowsWebviewLayout(window), 100)
setTimeout(broadcastWindowState, 100)
@ -193,13 +181,9 @@ function applyWindowsStartupWindowState(window) {
function setupWindowEvents(window) {
// Electrobun emits resize/focus, not Electron's maximize/fullscreen events.
const onWindowChange = isWindows
? () => handleWindowsWindowChange(window)
: broadcastWindowState
window.on?.('resize', onWindowChange)
window.on?.('resize', broadcastWindowState)
window.on?.('focus', broadcastWindowState)
window.on?.('move', onWindowChange)
window.on?.('move', broadcastWindowState)
}
export function setupMainWindowMessaging(window = mainWindow) {
@ -330,9 +314,7 @@ export function getWindowState() {
return {
isFullScreen: mainWindow.isFullScreen?.() ?? false,
isMaximized: isWindows
? isWindowWorkAreaMaximized(mainWindow)
: (mainWindow.isMaximized?.() ?? false)
isMaximized: mainWindow.isMaximized?.() ?? false
}
}
@ -349,10 +331,6 @@ export function handleWindowControl(action) {
} else {
mainWindow.maximize?.()
}
if (isWindows) {
handleWindowsWindowChange(mainWindow)
}
break
case 'fullscreen':
if (mainWindow.isFullScreen?.()) {

View File

@ -1,83 +0,0 @@
import { Screen } from 'electrobun/bun'
const FRAME_TOLERANCE_PX = 4
function framesMatch(a, b, tolerance = FRAME_TOLERANCE_PX) {
return (
Math.abs(a.x - b.x) <= tolerance &&
Math.abs(a.y - b.y) <= tolerance &&
Math.abs(a.width - b.width) <= tolerance &&
Math.abs(a.height - b.height) <= tolerance
)
}
function getFrameCenter(frame) {
return {
x: frame.x + frame.width / 2,
y: frame.y + frame.height / 2
}
}
function getDisplayForFrame(frame) {
const { x, y } = getFrameCenter(frame)
const displays = Screen.getAllDisplays()
const match = displays.find(({ bounds }) => {
return (
x >= bounds.x &&
x < bounds.x + bounds.width &&
y >= bounds.y &&
y < bounds.y + bounds.height
)
})
return match ?? Screen.getPrimaryDisplay()
}
function frameCoversMonitor(frame, bounds) {
return (
frame.x <= bounds.x + FRAME_TOLERANCE_PX &&
frame.y <= bounds.y + FRAME_TOLERANCE_PX &&
frame.x + frame.width >= bounds.x + bounds.width - FRAME_TOLERANCE_PX &&
frame.y + frame.height >= bounds.y + bounds.height - FRAME_TOLERANCE_PX
)
}
export function isWindowWorkAreaMaximized(window) {
if (!window?.getFrame) {
return false
}
const frame = window.getFrame()
const { workArea } = getDisplayForFrame(frame)
return framesMatch(frame, workArea)
}
export function clampWindowToWorkArea(window) {
if (!window?.getFrame || !window?.setFrame) {
return false
}
if (window.isFullScreen?.()) {
return false
}
const frame = window.getFrame()
if (!frame.width || !frame.height) {
return false
}
const display = getDisplayForFrame(frame)
const { bounds, workArea } = display
if (framesMatch(frame, workArea)) {
return false
}
if (!frameCoversMonitor(frame, bounds)) {
return false
}
window.setFrame(workArea.x, workArea.y, workArea.width, workArea.height)
return true
}