build: recompile dist after display_control fail-fast fix
This commit is contained in:
51
dist/main/system_handlers.js
vendored
51
dist/main/system_handlers.js
vendored
@@ -360,32 +360,46 @@ function registerSystemHandlers() {
|
|||||||
}
|
}
|
||||||
return { success: false, error: 'Unknown action' };
|
return { success: false, error: 'Unknown action' };
|
||||||
});
|
});
|
||||||
// 6. Set Display Layout (Displayplacer)
|
// 6. Set Display Layout
|
||||||
// Auto-detects connected displays via `displayplacer list` when no explicit configStr is given.
|
// Primary path: display_control (native CoreGraphics, no external deps).
|
||||||
// mirror: secondary display(s) mirror the primary.
|
// Build from scripts/display_control.m via scripts/build-display-control.sh on a Mac.
|
||||||
// extend: displays shown side-by-side; un-mirrors if currently mirrored.
|
// Commit the resulting resources/bin/display_control binary to the repo.
|
||||||
|
// Fallback: displayplacer (requires: brew install displayplacer on each venue Mac).
|
||||||
|
// Also supports per-device configStr override (displayplacer format).
|
||||||
electron_1.ipcMain.handle('native:set-display-layout', async (event, { mode, configStr }) => {
|
electron_1.ipcMain.handle('native:set-display-layout', async (event, { mode, configStr }) => {
|
||||||
if (os.platform() !== 'darwin')
|
if (os.platform() !== 'darwin')
|
||||||
return { success: false, error: 'Display control only supported on macOS' };
|
return { success: false, error: 'Display control only supported on macOS' };
|
||||||
// Try bundled binary first; fall back to common Homebrew/system locations.
|
// Primary: display_control — native CoreGraphics, no Homebrew dependency.
|
||||||
// Install on a dev/venue Mac via: brew install displayplacer
|
// Derived from OSIT MasterKey app (LegacyUtilities.m). No configStr support needed —
|
||||||
const _bin_candidates = electron_1.app.isPackaged
|
// CoreGraphics auto-detects all connected displays.
|
||||||
|
const dc_bin = electron_1.app.isPackaged
|
||||||
|
? path.join(process.resourcesPath, 'bin', 'display_control')
|
||||||
|
: path.join(__dirname, '../../resources/bin/display_control');
|
||||||
|
if (fs.existsSync(dc_bin) && !configStr) {
|
||||||
|
if (mode !== 'mirror' && mode !== 'extend') {
|
||||||
|
return { success: false, error: `Unsupported display mode: ${mode}` };
|
||||||
|
}
|
||||||
|
return await runExec(`"${dc_bin}" ${mode}`);
|
||||||
|
}
|
||||||
|
// Fallback: displayplacer — required when display_control binary is not built yet,
|
||||||
|
// or when a per-device configStr override is set (displayplacer-format string from event_device.data_json).
|
||||||
|
// Install: brew install displayplacer
|
||||||
|
const _dp_candidates = electron_1.app.isPackaged
|
||||||
? [path.join(process.resourcesPath, 'bin', 'displayplacer')]
|
? [path.join(process.resourcesPath, 'bin', 'displayplacer')]
|
||||||
: [
|
: [
|
||||||
path.join(__dirname, '../../resources/bin/displayplacer'),
|
path.join(__dirname, '../../resources/bin/displayplacer'),
|
||||||
'/opt/homebrew/bin/displayplacer', // Apple Silicon Homebrew
|
'/opt/homebrew/bin/displayplacer', // Apple Silicon Homebrew
|
||||||
'/usr/local/bin/displayplacer', // Intel Homebrew
|
'/usr/local/bin/displayplacer', // Intel Homebrew
|
||||||
];
|
];
|
||||||
const binPath = _bin_candidates.find(p => fs.existsSync(p)) ?? _bin_candidates[0];
|
const dpPath = _dp_candidates.find(p => fs.existsSync(p)) ?? _dp_candidates[0];
|
||||||
// Explicit config string always takes priority — allows manual override per device.
|
// Explicit configStr takes priority — allows manual per-device override.
|
||||||
if (configStr) {
|
if (configStr) {
|
||||||
return await runExec(`"${binPath}" ${configStr}`);
|
return await runExec(`"${dpPath}" ${configStr}`);
|
||||||
}
|
}
|
||||||
// Auto-detect: `displayplacer list` emits a ready-to-run command line at the bottom.
|
// Auto-detect via `displayplacer list`.
|
||||||
// We parse the quoted display strings from that line and modify them for the requested mode.
|
const list_result = await runExec(`"${dpPath}" list`);
|
||||||
const list_result = await runExec(`"${binPath}" list`);
|
|
||||||
if (!list_result.success || !list_result.stdout) {
|
if (!list_result.success || !list_result.stdout) {
|
||||||
return { success: false, error: `displayplacer list failed: ${list_result.error ?? 'no output'}` };
|
return { success: false, error: `displayplacer not available. Build display_control from scripts/build-display-control.sh or run: brew install displayplacer` };
|
||||||
}
|
}
|
||||||
// The command line looks like: displayplacer "id:xxx res:... origin:(0,0) ..." "id:yyy ..."
|
// The command line looks like: displayplacer "id:xxx res:... origin:(0,0) ..." "id:yyy ..."
|
||||||
const cmd_line = list_result.stdout.split('\n').find(l => l.trim().startsWith('displayplacer "'));
|
const cmd_line = list_result.stdout.split('\n').find(l => l.trim().startsWith('displayplacer "'));
|
||||||
@@ -402,22 +416,19 @@ function registerSystemHandlers() {
|
|||||||
return { success: false, error: 'Could not parse primary display ID from displayplacer output' };
|
return { success: false, error: 'Could not parse primary display ID from displayplacer output' };
|
||||||
}
|
}
|
||||||
const primary_id = primary_id_match[1];
|
const primary_id = primary_id_match[1];
|
||||||
// Primary display unchanged; secondary display(s) get mirror_of_display:<primary_id>.
|
|
||||||
const mirror_args = display_strings.map((s, i) => {
|
const mirror_args = display_strings.map((s, i) => {
|
||||||
if (i === 0)
|
if (i === 0)
|
||||||
return `"${s}"`;
|
return `"${s}"`;
|
||||||
const without_existing_mirror = s.replace(/\s*mirror_of_display:\S+/g, '').trim();
|
const without_existing_mirror = s.replace(/\s*mirror_of_display:\S+/g, '').trim();
|
||||||
return `"${without_existing_mirror} mirror_of_display:${primary_id}"`;
|
return `"${without_existing_mirror} mirror_of_display:${primary_id}"`;
|
||||||
}).join(' ');
|
}).join(' ');
|
||||||
return await runExec(`"${binPath}" ${mirror_args}`);
|
return await runExec(`"${dpPath}" ${mirror_args}`);
|
||||||
}
|
}
|
||||||
if (mode === 'extend') {
|
if (mode === 'extend') {
|
||||||
const any_mirrored = display_strings.some(s => /\bmirror_of_display:\S+/.test(s));
|
const any_mirrored = display_strings.some(s => /\bmirror_of_display:\S+/.test(s));
|
||||||
if (!any_mirrored) {
|
if (!any_mirrored) {
|
||||||
// Already extended — re-apply current layout to ensure it is active.
|
return await runExec(`"${dpPath}" ${display_strings.map(s => `"${s}"`).join(' ')}`);
|
||||||
return await runExec(`"${binPath}" ${display_strings.map(s => `"${s}"`).join(' ')}`);
|
|
||||||
}
|
}
|
||||||
// Remove mirror keys and compute side-by-side origins from each display's resolution.
|
|
||||||
let x_offset = 0;
|
let x_offset = 0;
|
||||||
const extend_args = display_strings.map((s) => {
|
const extend_args = display_strings.map((s) => {
|
||||||
const without_mirror = s.replace(/\s*mirror_of_display:\S+/g, '').trim();
|
const without_mirror = s.replace(/\s*mirror_of_display:\S+/g, '').trim();
|
||||||
@@ -427,7 +438,7 @@ function registerSystemHandlers() {
|
|||||||
x_offset += width;
|
x_offset += width;
|
||||||
return `"${updated}"`;
|
return `"${updated}"`;
|
||||||
}).join(' ');
|
}).join(' ');
|
||||||
return await runExec(`"${binPath}" ${extend_args}`);
|
return await runExec(`"${dpPath}" ${extend_args}`);
|
||||||
}
|
}
|
||||||
return { success: false, error: `Unsupported display mode: ${mode}` };
|
return { success: false, error: `Unsupported display mode: ${mode}` };
|
||||||
});
|
});
|
||||||
|
|||||||
2
dist/main/system_handlers.js.map
vendored
2
dist/main/system_handlers.js.map
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user