Skip to main content
Glama
non-overlapping-engine.js12.8 kB
#!/usr/bin/env node /** * Enhanced Non-Overlapping Layout Engine for MOOM MCP * Implements best practices for professional window management */ const { execSync } = require('child_process'); class NonOverlappingLayoutEngine { constructor() { this.displays = this.getDisplayInfo(); this.snapTolerance = 10; // Pixels for edge snapping this.minWindowSize = { width: 400, height: 300 }; // Minimum viable window size } /** * Get display information using displayplacer */ getDisplayInfo() { try { const output = execSync('displayplacer list', { encoding: 'utf8' }); return this.parseDisplayOutput(output); } catch (error) { console.error('Error getting display info:', error.message); return []; } } /** * Parse displayplacer output */ parseDisplayOutput(output) { const displays = []; const lines = output.split('\n'); let currentDisplay = {}; for (const line of lines) { if (line.includes('Persistent screen id:')) { if (currentDisplay.id) displays.push(currentDisplay); currentDisplay = { id: line.split(': ')[1] }; } else if (line.includes('Type:')) { currentDisplay.type = line.split(': ')[1]; } else if (line.includes('Resolution:')) { const res = line.match(/(\d+)x(\d+)/); if (res) { currentDisplay.width = parseInt(res[1]); currentDisplay.height = parseInt(res[2]); } } else if (line.includes('Origin:')) { const origin = line.match(/\((-?\d+),(-?\d+)\)/); if (origin) { currentDisplay.x = parseInt(origin[1]); currentDisplay.y = parseInt(origin[2]); } } else if (line.includes('Main Display: Yes')) { currentDisplay.isMain = true; } } if (currentDisplay.id) displays.push(currentDisplay); return displays; } /** * Create grid-based zones for non-overlapping layouts */ createGridZones(display, columns = 2, rows = 2) { const menuBarHeight = 25; // Account for macOS menu bar const availableHeight = display.height - menuBarHeight; const zoneWidth = Math.floor(display.width / columns); const zoneHeight = Math.floor(availableHeight / rows); const zones = []; for (let row = 0; row < rows; row++) { for (let col = 0; col < columns; col++) { zones.push({ x: display.x + (col * zoneWidth), y: display.y + menuBarHeight + (row * zoneHeight), width: zoneWidth, height: zoneHeight, id: `zone_${row}_${col}` }); } } return zones; } /** * Snap windows to edges and prevent overlap */ snapToEdges(window, allWindows, display) { const snapped = { ...window }; // Snap to display edges if (Math.abs(snapped.x - display.x) < this.snapTolerance) { snapped.x = display.x; } if (Math.abs(snapped.y - display.y) < this.snapTolerance) { snapped.y = display.y + 25; // Menu bar } if (Math.abs((snapped.x + snapped.width) - (display.x + display.width)) < this.snapTolerance) { snapped.x = display.x + display.width - snapped.width; } if (Math.abs((snapped.y + snapped.height) - (display.y + display.height)) < this.snapTolerance) { snapped.y = display.y + display.height - snapped.height; } // Snap to other windows for (const otherWindow of allWindows) { if (otherWindow.app === window.app) continue; // Snap to right edge of other window if (Math.abs(snapped.x - (otherWindow.x + otherWindow.width)) < this.snapTolerance) { snapped.x = otherWindow.x + otherWindow.width; } // Snap to left edge of other window if (Math.abs((snapped.x + snapped.width) - otherWindow.x) < this.snapTolerance) { snapped.x = otherWindow.x - snapped.width; } // Snap to bottom edge of other window if (Math.abs(snapped.y - (otherWindow.y + otherWindow.height)) < this.snapTolerance) { snapped.y = otherWindow.y + otherWindow.height; } // Snap to top edge of other window if (Math.abs((snapped.y + snapped.height) - otherWindow.y) < this.snapTolerance) { snapped.y = otherWindow.y - snapped.height; } } return snapped; } /** * Check for window overlaps and resolve them */ resolveOverlaps(windows) { const resolved = [...windows]; for (let i = 0; i < resolved.length; i++) { for (let j = i + 1; j < resolved.length; j++) { if (this.windowsOverlap(resolved[i], resolved[j])) { // Resolve overlap by adjusting the second window resolved[j] = this.adjustWindowToAvoidOverlap(resolved[j], resolved[i]); } } } return resolved; } /** * Check if two windows overlap */ windowsOverlap(window1, window2) { return !(window1.x + window1.width <= window2.x || window2.x + window2.width <= window1.x || window1.y + window1.height <= window2.y || window2.y + window2.height <= window1.y); } /** * Adjust window position to avoid overlap */ adjustWindowToAvoidOverlap(windowToMove, fixedWindow) { const adjusted = { ...windowToMove }; // Try moving to the right if (fixedWindow.x + fixedWindow.width + adjusted.width <= fixedWindow.display?.width) { adjusted.x = fixedWindow.x + fixedWindow.width; return adjusted; } // Try moving down if (fixedWindow.y + fixedWindow.height + adjusted.height <= fixedWindow.display?.height) { adjusted.y = fixedWindow.y + fixedWindow.height; return adjusted; } // Try moving to the left if (fixedWindow.x - adjusted.width >= 0) { adjusted.x = fixedWindow.x - adjusted.width; return adjusted; } // Try moving up if (fixedWindow.y - adjusted.height >= 25) { // Menu bar adjusted.y = fixedWindow.y - adjusted.height; return adjusted; } return adjusted; } /** * Professional Coding Layout - Zero Overlap Guaranteed */ createProfessionalCodingLayout() { const mainDisplay = this.displays.find(d => d.isMain) || this.displays[0]; const rightDisplay = this.displays.find(d => d.x > 0 && !d.isMain); // Create precise grid zones const zones = this.createGridZones(mainDisplay, 5, 2); // 5x2 grid for flexibility const layout = { name: "Professional Non-Overlapping Coding", windows: [ { app: "Visual Studio Code", display: mainDisplay, x: zones[0].x, // Left 3 columns y: zones[0].y, width: zones[0].width * 3, // 60% of width height: zones[0].height * 2 // Full height }, { app: "Safari", display: mainDisplay, x: zones[3].x, // Right 2 columns, top y: zones[3].y, width: zones[3].width * 2, // 40% of width height: zones[3].height // 50% of height }, { app: "iTerm", display: mainDisplay, x: zones[8].x, // Right 2 columns, bottom y: zones[8].y, width: zones[8].width * 2, // 40% of width height: zones[8].height // 50% of height } ] }; // Add Claude to right display if available if (rightDisplay) { layout.windows.push({ app: "Claude", display: rightDisplay, x: rightDisplay.x + 50, y: rightDisplay.y + 50, width: rightDisplay.width - 100, height: rightDisplay.height - 100 }); } // Apply snapping and overlap resolution layout.windows = this.resolveOverlaps( layout.windows.map(w => this.snapToEdges(w, layout.windows, w.display || mainDisplay)) ); return layout; } /** * Ultimate Multi-Monitor Layout - Perfect Distribution */ createUltimateMultiMonitorLayout() { const mainDisplay = this.displays.find(d => d.isMain) || this.displays[0]; const leftDisplay = this.displays.find(d => d.x < 0); const rightDisplay = this.displays.find(d => d.x > 0 && !d.isMain); const layout = { name: "Ultimate Multi-Monitor Non-Overlapping", windows: [] }; // Main display: VSCode full screen layout.windows.push({ app: "Visual Studio Code", display: mainDisplay, x: mainDisplay.x, y: mainDisplay.y + 25, width: mainDisplay.width, height: mainDisplay.height - 50 }); // Left display: Browser and Terminal split if (leftDisplay) { const leftZones = this.createGridZones(leftDisplay, 1, 2); layout.windows.push({ app: "Safari", display: leftDisplay, x: leftZones[0].x, y: leftZones[0].y, width: leftZones[0].width, height: leftZones[0].height }); layout.windows.push({ app: "iTerm", display: leftDisplay, x: leftZones[1].x, y: leftZones[1].y, width: leftZones[1].width, height: leftZones[1].height }); } // Right display: Claude if (rightDisplay) { layout.windows.push({ app: "Claude", display: rightDisplay, x: rightDisplay.x + 25, y: rightDisplay.y + 50, width: rightDisplay.width - 50, height: rightDisplay.height - 75 }); } return layout; } /** * Generate AppleScript with overlap prevention */ generateNonOverlappingScript(layout) { let script = `-- ${layout.name} - Non-Overlapping Layout Engine\n`; script += `-- Generated with overlap prevention and edge snapping\n\n`; for (const window of layout.windows) { script += `-- Position ${window.app} (${window.width}x${window.height} at ${window.x},${window.y})\n`; script += `tell application "${window.app}"\n`; script += ` activate\n`; script += ` delay 0.5\n`; script += `end tell\n\n`; script += `tell application "System Events"\n`; script += ` tell process "${this.getProcessName(window.app)}"\n`; script += ` set frontmost to true\n`; script += ` try\n`; script += ` -- Ensure window is visible and sized correctly\n`; script += ` set position of front window to {${window.x}, ${window.y}}\n`; script += ` set size of front window to {${window.width}, ${window.height}}\n`; script += ` -- Verify no overlap occurred\n`; script += ` on error\n`; script += ` -- Fallback to Moom zone assignment\n`; script += ` end try\n`; script += ` end tell\n`; script += `end tell\n\n`; script += `delay 0.3\n\n`; } script += `-- Verify layout and return to primary app\n`; script += `tell application "Visual Studio Code" to activate\n`; return script; } /** * Get process name mapping */ getProcessName(appName) { const processMap = { "Visual Studio Code": "Code", "iTerm": "iTerm2", "Safari": "Safari", "Claude": "Claude" }; return processMap[appName] || appName; } /** * Validate layout for overlaps */ validateLayout(layout) { const issues = []; for (let i = 0; i < layout.windows.length; i++) { for (let j = i + 1; j < layout.windows.length; j++) { if (this.windowsOverlap(layout.windows[i], layout.windows[j])) { issues.push(`Overlap detected: ${layout.windows[i].app} and ${layout.windows[j].app}`); } } // Check minimum size const window = layout.windows[i]; if (window.width < this.minWindowSize.width || window.height < this.minWindowSize.height) { issues.push(`Window too small: ${window.app} (${window.width}x${window.height})`); } } return { valid: issues.length === 0, issues: issues }; } } module.exports = NonOverlappingLayoutEngine; // CLI usage if (require.main === module) { const engine = new NonOverlappingLayoutEngine(); console.log('🎯 Non-Overlapping Layout Engine'); console.log('================================'); const layout = engine.createProfessionalCodingLayout(); const validation = engine.validateLayout(layout); console.log(`Layout: ${layout.name}`); console.log(`Valid: ${validation.valid ? '✅' : '❌'}`); if (!validation.valid) { console.log('Issues found:'); validation.issues.forEach(issue => console.log(` - ${issue}`)); } console.log('\nGenerated AppleScript:'); console.log('====================='); console.log(engine.generateNonOverlappingScript(layout)); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/itrimble/moom-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server