Skip to content

Instantly share code, notes, and snippets.

@sapjax
Created July 16, 2026 01:23
Show Gist options
  • Select an option

  • Save sapjax/bacd8db9b10ae18971ee7baca3401e4c to your computer and use it in GitHub Desktop.

Select an option

Save sapjax/bacd8db9b10ae18971ee7baca3401e4c to your computer and use it in GitHub Desktop.
phoenix config
const WINDOW_MODIFIERS = ['alt'];
const FRAME_TOLERANCE = 12;
const TRAVERSAL_EXCLUDED_APP_NAMES = ['otty'];
let windowTraversal;
function focusedNormalWindow() {
const window = Window.focused();
if (!window || !window.isNormal()) {
Phoenix.log('No focused normal window.');
return undefined;
}
return window;
}
function windowsAtTopOfStack(focusedWindow) {
return [focusedWindow].concat(
Window.recent().filter((window) => {
return (
window.isNormal() &&
window.isVisible() &&
!window.isEqual(focusedWindow)
);
})
);
}
function splitFrames(screen) {
const frame = screen.flippedVisibleFrame();
const leftWidth = Math.floor(frame.width / 2);
return {
left: {
x: frame.x,
y: frame.y,
width: leftWidth,
height: frame.height,
},
right: {
x: frame.x + leftWidth,
y: frame.y,
width: frame.width - leftWidth,
height: frame.height,
},
};
}
function framesMatch(first, second) {
return (
Math.abs(first.x - second.x) <= FRAME_TOLERANCE &&
Math.abs(first.y - second.y) <= FRAME_TOLERANCE &&
Math.abs(first.width - second.width) <= FRAME_TOLERANCE &&
Math.abs(first.height - second.height) <= FRAME_TOLERANCE
);
}
function topWindowOnOtherSide(focusedWindow, windows) {
const screen = focusedWindow.screen();
if (!screen) {
return undefined;
}
const frames = splitFrames(screen);
const focusedFrame = focusedWindow.frame();
let otherFrame;
if (framesMatch(focusedFrame, frames.left)) {
otherFrame = frames.right;
} else if (framesMatch(focusedFrame, frames.right)) {
otherFrame = frames.left;
} else {
return undefined;
}
return windows.find((window) => {
return (
!window.isEqual(focusedWindow) &&
framesMatch(window.frame(), otherFrame)
);
});
}
function resetWindowTraversal() {
windowTraversal = undefined;
}
function isExcludedFromTraversal(window) {
const app = window.app();
const appName = app && app.name();
return (
appName &&
TRAVERSAL_EXCLUDED_APP_NAMES.indexOf(appName.toLowerCase()) !== -1
);
}
function traverseWindowStack(direction) {
const focusedWindow = focusedNormalWindow();
if (!focusedWindow) {
resetWindowTraversal();
return;
}
const stack = windowsAtTopOfStack(focusedWindow);
const fixedWindow = topWindowOnOtherSide(focusedWindow, stack);
const fixedHash = fixedWindow ? fixedWindow.hash() : null;
const focusedHash = focusedWindow.hash();
const eligibleWindows = stack.filter((window) => {
if (window.isEqual(focusedWindow)) {
return true;
}
return (
(!fixedWindow || !window.isEqual(fixedWindow)) &&
!isExcludedFromTraversal(window)
);
});
const windowsByHash = Object.create(null);
const currentOrder = [];
eligibleWindows.forEach((window) => {
const hash = window.hash();
windowsByHash[String(hash)] = window;
currentOrder.push(hash);
});
if (currentOrder.length < 2) {
Phoenix.log('There is no other visible normal window to focus.');
resetWindowTraversal();
return;
}
const canContinue =
windowTraversal &&
windowTraversal.focusedHash === focusedHash &&
windowTraversal.fixedHash === fixedHash;
let order;
if (canContinue) {
order = windowTraversal.order.filter((hash) => {
return windowsByHash[String(hash)];
});
currentOrder.forEach((hash) => {
if (order.indexOf(hash) === -1) {
order.push(hash);
}
});
} else {
order = currentOrder;
}
const currentIndex = order.indexOf(focusedHash);
const targetIndex = (currentIndex + direction + order.length) % order.length;
const targetWindow = windowsByHash[String(order[targetIndex])];
if (!targetWindow || targetWindow.isEqual(focusedWindow)) {
Phoenix.log('Could not find the next window in the stack.');
resetWindowTraversal();
return;
}
if (!targetWindow.setFrame(focusedWindow.frame()) || !targetWindow.focus()) {
Phoenix.log('Could not replace or focus the next window.');
resetWindowTraversal();
return;
}
windowTraversal = {
order,
focusedHash: targetWindow.hash(),
fixedHash,
};
}
// Alt + 1: maximise the focused window on its current screen.
Key.on('1', WINDOW_MODIFIERS, () => {
resetWindowTraversal();
const window = focusedNormalWindow();
if (window) {
window.maximise();
}
});
// Alt + 2: tile the top two windows in the global app/window stack.
// The focused window is always placed on the left.
Key.on('2', WINDOW_MODIFIERS, () => {
resetWindowTraversal();
const focusedWindow = focusedNormalWindow();
if (!focusedWindow) {
return;
}
const windows = windowsAtTopOfStack(focusedWindow);
if (windows.length < 2) {
Phoenix.log('There is no second visible normal window in the stack.');
return;
}
const screen = focusedWindow.screen();
if (!screen) {
Phoenix.log('The focused window is not on an available screen.');
return;
}
const frames = splitFrames(screen);
windows[0].setFrame(frames.left);
windows[1].setFrame(frames.right);
windows[0].focus();
});
// Alt + L: replace the focused window with the next window in the stack.
Key.on('l', WINDOW_MODIFIERS, () => {
traverseWindowStack(1);
});
// Alt + H: replace the focused window with the previous window in the stack.
Key.on('h', WINDOW_MODIFIERS, () => {
traverseWindowStack(-1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment