Skip to content

Instantly share code, notes, and snippets.

@rbreaves
Created October 28, 2025 16:01
Show Gist options
  • Select an option

  • Save rbreaves/4fb528638e29511e980cafe56f59c1d7 to your computer and use it in GitHub Desktop.

Select an option

Save rbreaves/4fb528638e29511e980cafe56f59c1d7 to your computer and use it in GitHub Desktop.
Reset Workflow for 3 monitors - macOS
// pre-reqs - homebrew, displayplacer
// brew install displayplacer
//
// How To Run
// osascript -l JavaScript ~/move_to_three_monitors.jxa
ObjC.import('stdlib')
const se = Application('System Events')
const app = Application.currentApplication()
app.includeStandardAdditions = true
// --- read displayplacer output ---
function getDisplayplacerOrigins() {
const output = app.doShellScript("displayplacer list | grep 'origin'")
// Correct regex: origin:(x,y)
const matches = [...output.matchAll(/origin:\(([-\d]+),([-\d]+)\)/g)]
return matches.map(m => ({ x: parseInt(m[1]), y: parseInt(m[2]) }))
}
// --- classify monitors dynamically ---
function classifyDisplays(coords) {
let left = coords[0], right = coords[0], main = coords[0]
coords.forEach(c => {
if (c.x < left.x) left = c
if (c.x > right.x) right = c
if (c.x === 0 && c.y === 0) main = c
})
return { left, right, main }
}
const coords = getDisplayplacerOrigins()
if (coords.length === 0) {
console.log("⚠️ Could not parse displayplacer output.")
$.exit(1)
}
const { left, right, main } = classifyDisplays(coords)
// --- log what we detected ---
console.log(`Left: (${left.x},${left.y}) | Main: (${main.x},${main.y}) | Right: (${right.x},${right.y})`)
// --- helpers ---
function moveApp(names, dest, label) {
names.forEach(n => {
try {
const proc = se.processes.byName(n)
proc.windows().forEach(w => {
try { w.position = [dest.x, dest.y]; console.log(`Moved ${n} to the ${label}`); } catch (e) {}
})
} catch (e) {}
})
}
function moveByExactTitle(titleExact, dest, label) {
se.processes().forEach(proc => {
try {
proc.windows().forEach(w => {
const title = w.name()
if (title === titleExact) {
try { w.position = [dest.x, dest.y]; console.log(`Moved ${n} to the ${label}`); } catch (e) {}
}
})
} catch (e) {}
})
}
// --- Move Vivaldi Snapshot ---
moveApp(['Vivaldi Snapshot'], right, "right")
// moveByExactTitle('Vivaldi Snapshot', right, "right")
// --- Move Microsoft Teams ---
moveApp(['Microsoft Teams'], left, "left")
// moveByExactTitle('Microsoft Teams', left, "left")
// --- Everything else -> main monitor ---
se.processes().forEach(proc => {
const name = proc.name().toLowerCase()
// console.log(name);
// Skip known app families
const isVivaldi =
name === "vivaldi snapshot"
const isTeams =
name.startsWith("microsoft teams") || name === "msteams"
if (!isVivaldi && !isTeams) {
try {
proc.windows().forEach(w => { w.position = [main.x, main.y] })
} catch (e) {}
}
})
console.log(`Moved everything else to the center.`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment