Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
- Introduced functions to validate the macOS dynamic library, ensuring it meets size and architecture requirements. - Updated build scripts to resolve target architecture dynamically and validate the generated dylib. - Enhanced the macOS window effects implementation to include traffic light positioning and improved error handling. - Refactored the dylib path resolution logic to support multiple potential locations for the library.
149 lines
3.9 KiB
JavaScript
149 lines
3.9 KiB
JavaScript
import { dlopen, FFIType } from 'bun:ffi'
|
|
import { existsSync, statSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
export const MAC_WINDOW_CORNER_RADIUS = 15
|
|
export const MAC_TRAFFIC_LIGHT_OFFSET = { x: 14, y: 12 }
|
|
|
|
const DYLIB_NAME = 'libMacWindowEffects.dylib'
|
|
const MIN_DYLIB_BYTES = 10_000
|
|
|
|
function resolveDylibPath() {
|
|
const candidates = new Set()
|
|
const moduleDir = path.dirname(fileURLToPath(import.meta.url))
|
|
|
|
candidates.add(path.join(moduleDir, DYLIB_NAME))
|
|
candidates.add(path.join(moduleDir, '../bun', DYLIB_NAME))
|
|
candidates.add(path.join(moduleDir, '../../bun', DYLIB_NAME))
|
|
candidates.add(path.join(process.cwd(), 'src/bun', DYLIB_NAME))
|
|
|
|
for (const execPath of [process.execPath, process.argv0].filter(Boolean)) {
|
|
const execDir = path.dirname(execPath)
|
|
candidates.add(
|
|
path.join(execDir, '../Resources/app/bun', DYLIB_NAME)
|
|
)
|
|
candidates.add(path.join(execDir, 'Resources/app/bun', DYLIB_NAME))
|
|
candidates.add(path.join(execDir, DYLIB_NAME))
|
|
}
|
|
|
|
for (const candidate of candidates) {
|
|
const resolved = path.resolve(candidate)
|
|
if (!existsSync(resolved)) {
|
|
continue
|
|
}
|
|
|
|
try {
|
|
if (statSync(resolved).size >= MIN_DYLIB_BYTES) {
|
|
return resolved
|
|
}
|
|
} catch {
|
|
// Ignore unreadable paths and keep searching.
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
function loadMacWindowEffectsLibrary() {
|
|
const dylibPath = resolveDylibPath()
|
|
if (!dylibPath) {
|
|
console.warn(
|
|
'macOS vibrancy: native effects library not found; using transparent window only.'
|
|
)
|
|
return null
|
|
}
|
|
|
|
try {
|
|
return {
|
|
path: dylibPath,
|
|
lib: dlopen(dylibPath, {
|
|
enableWindowVibrancy: {
|
|
args: [FFIType.ptr, FFIType.f64],
|
|
returns: FFIType.bool
|
|
},
|
|
ensureWindowShadow: {
|
|
args: [FFIType.ptr],
|
|
returns: FFIType.bool
|
|
},
|
|
setWindowCornerRadius: {
|
|
args: [FFIType.ptr, FFIType.f64],
|
|
returns: FFIType.bool
|
|
},
|
|
setWindowTrafficLightsPosition: {
|
|
args: [FFIType.ptr, FFIType.f64, FFIType.f64],
|
|
returns: FFIType.bool
|
|
},
|
|
setNativeWindowDragRegion: {
|
|
args: [FFIType.ptr, FFIType.f64, FFIType.f64],
|
|
returns: FFIType.bool
|
|
}
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.warn(
|
|
`macOS vibrancy: failed to load native effects library (${dylibPath}):`,
|
|
error
|
|
)
|
|
return null
|
|
}
|
|
}
|
|
|
|
function applyTrafficLightsPosition(lib, mainWindow, attempt = 0) {
|
|
const applied = lib.symbols.setWindowTrafficLightsPosition(
|
|
mainWindow.ptr,
|
|
MAC_TRAFFIC_LIGHT_OFFSET.x,
|
|
MAC_TRAFFIC_LIGHT_OFFSET.y
|
|
)
|
|
|
|
if (applied || attempt >= 10) {
|
|
return applied
|
|
}
|
|
|
|
setTimeout(() => applyTrafficLightsPosition(lib, mainWindow, attempt + 1), 50)
|
|
return false
|
|
}
|
|
|
|
export function applyMacOSWindowEffects(mainWindow) {
|
|
if (process.platform !== 'darwin' || !mainWindow?.ptr) {
|
|
return
|
|
}
|
|
|
|
const loaded = loadMacWindowEffectsLibrary()
|
|
if (!loaded) {
|
|
return
|
|
}
|
|
|
|
const { path: dylibPath, lib } = loaded
|
|
|
|
try {
|
|
const vibrancyEnabled = lib.symbols.enableWindowVibrancy(
|
|
mainWindow.ptr,
|
|
MAC_WINDOW_CORNER_RADIUS
|
|
)
|
|
const shadowEnabled = lib.symbols.ensureWindowShadow(mainWindow.ptr)
|
|
const trafficLightsScheduled = applyTrafficLightsPosition(lib, mainWindow)
|
|
|
|
mainWindow.on?.('resize', () => {
|
|
lib.symbols.setWindowCornerRadius(
|
|
mainWindow.ptr,
|
|
MAC_WINDOW_CORNER_RADIUS
|
|
)
|
|
lib.symbols.setWindowTrafficLightsPosition(
|
|
mainWindow.ptr,
|
|
MAC_TRAFFIC_LIGHT_OFFSET.x,
|
|
MAC_TRAFFIC_LIGHT_OFFSET.y
|
|
)
|
|
})
|
|
|
|
console.log(
|
|
`macOS vibrancy applied (dylib=${dylibPath}, vibrancy=${vibrancyEnabled}, shadow=${shadowEnabled}, trafficLights=${trafficLightsScheduled}, cornerRadius=${MAC_WINDOW_CORNER_RADIUS})`
|
|
)
|
|
} catch (error) {
|
|
console.warn(
|
|
'macOS vibrancy: failed to apply native window effects:',
|
|
error
|
|
)
|
|
}
|
|
}
|