Last active
December 17, 2025 15:54
-
-
Save WardsParadox/9b300ca4a67cf5414a180bd060854fff to your computer and use it in GitHub Desktop.
Rectangle move to next window as applescript instead, Fully references Rectangle code for screendetection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- AppleScript to move focused window to the next screen | |
| use framework "Foundation" | |
| use framework "AppKit" | |
| use scripting additions | |
| on run | |
| moveWindowToNextScreen() | |
| end run | |
| on moveWindowToNextScreen() | |
| -- Get all screens | |
| set allScreens to current application's NSScreen's screens() | |
| set screenCount to allScreens's |count|() | |
| if screenCount < 2 then | |
| display notification "Only one screen detected" with title "Move Window" | |
| return | |
| end if | |
| -- Get main screen height for coordinate conversion (Cocoa uses bottom-left origin) | |
| set mainScreen to (allScreens's objectAtIndex:0) | |
| set mainFrame to mainScreen's frame() | |
| set mainHeight to (item 2 of item 2 of mainFrame) as real | |
| -- Get the frontmost application and its focused window | |
| tell application "System Events" | |
| set frontApp to first application process whose frontmost is true | |
| try | |
| set frontWindow to first window of frontApp | |
| set {winX, winY} to position of frontWindow | |
| set {winWidth, winHeight} to size of frontWindow | |
| on error | |
| display notification "No window found" with title "Move Window" | |
| return | |
| end try | |
| end tell | |
| -- Window center in System Events coordinates (origin top-left) | |
| set windowCenterX to winX + (winWidth / 2) | |
| set windowCenterY to winY + (winHeight / 2) | |
| -- Build list of screens with their frames converted to System Events coordinates | |
| set screenFrames to {} | |
| repeat with i from 0 to (screenCount - 1) | |
| set currentScreen to (allScreens's objectAtIndex:i) | |
| set screenFrame to currentScreen's frame() | |
| set visibleFrame to currentScreen's visibleFrame() | |
| -- Cocoa frame coordinates | |
| set frameX to (item 1 of item 1 of screenFrame) as real | |
| set frameY to (item 2 of item 1 of screenFrame) as real | |
| set frameW to (item 1 of item 2 of screenFrame) as real | |
| set frameH to (item 2 of item 2 of screenFrame) as real | |
| -- Cocoa visible frame coordinates | |
| set visX to (item 1 of item 1 of visibleFrame) as real | |
| set visY to (item 2 of item 1 of visibleFrame) as real | |
| set visW to (item 1 of item 2 of visibleFrame) as real | |
| set visH to (item 2 of item 2 of visibleFrame) as real | |
| -- Convert Y coordinates from Cocoa (bottom-left origin) to System Events (top-left origin) | |
| -- For full frame: top Y in SE coords = mainHeight - (cocoaY + cocoaHeight) | |
| set screenTopY to mainHeight - (frameY + frameH) | |
| -- For visible frame: need to convert the visible area's top position | |
| set visibleTopY to mainHeight - (visY + visH) | |
| set end of screenFrames to {screenIndex:i, x:frameX, y:screenTopY, width:frameW, height:frameH, visX:visX, visY:visibleTopY, visW:visW, visH:visH} | |
| end repeat | |
| -- Sort screens by X coordinate (left to right) | |
| set sortedScreens to sortScreensByX(screenFrames) | |
| -- Find which screen contains the window center | |
| set currentScreenPos to 0 | |
| repeat with i from 1 to count of sortedScreens | |
| set scr to item i of sortedScreens | |
| set scrLeft to (x of scr) | |
| set scrRight to scrLeft + (width of scr) | |
| set scrTop to (y of scr) | |
| set scrBottom to scrTop + (height of scr) | |
| if windowCenterX � scrLeft and windowCenterX < scrRight and windowCenterY � scrTop and windowCenterY < scrBottom then | |
| set currentScreenPos to i | |
| exit repeat | |
| end if | |
| end repeat | |
| -- Fallback: if no screen found, find by X only | |
| if currentScreenPos = 0 then | |
| repeat with i from 1 to count of sortedScreens | |
| set scr to item i of sortedScreens | |
| if windowCenterX � (x of scr) and windowCenterX < ((x of scr) + (width of scr)) then | |
| set currentScreenPos to i | |
| exit repeat | |
| end if | |
| end repeat | |
| end if | |
| -- Final fallback | |
| if currentScreenPos = 0 then set currentScreenPos to 1 | |
| -- Calculate next screen (wrap around) | |
| set nextScreenPos to currentScreenPos + 1 | |
| if nextScreenPos > (count of sortedScreens) then set nextScreenPos to 1 | |
| set targetScreen to item nextScreenPos of sortedScreens | |
| set sourceScreen to item currentScreenPos of sortedScreens | |
| -- Calculate relative position of window on current screen's visible area | |
| set relX to (winX - (x of sourceScreen)) / (width of sourceScreen) | |
| set relY to (winY - (y of sourceScreen)) / (height of sourceScreen) | |
| -- Calculate new position on target screen (maintaining relative position) | |
| set newX to (x of targetScreen) + (relX * (width of targetScreen)) | |
| set newY to (y of targetScreen) + (relY * (height of targetScreen)) | |
| -- Ensure window fits within target screen's visible area | |
| set targetVisLeft to (visX of targetScreen) | |
| set targetVisTop to (visY of targetScreen) | |
| set targetVisRight to targetVisLeft + (visW of targetScreen) | |
| set targetVisBottom to targetVisTop + (visH of targetScreen) | |
| if newX < targetVisLeft then set newX to targetVisLeft | |
| if newY < targetVisTop then set newY to targetVisTop | |
| if (newX + winWidth) > targetVisRight then | |
| set newX to targetVisRight - winWidth | |
| end if | |
| if (newY + winHeight) > targetVisBottom then | |
| set newY to targetVisBottom - winHeight | |
| end if | |
| -- Move the window | |
| tell application "System Events" | |
| tell frontApp | |
| set position of first window to {newX as integer, newY as integer} | |
| end tell | |
| end tell | |
| end moveWindowToNextScreen | |
| on sortScreensByX(screenList) | |
| set sortedList to screenList | |
| repeat with i from 1 to (count of sortedList) - 1 | |
| repeat with j from 1 to (count of sortedList) - i | |
| if (x of item j of sortedList) > (x of item (j + 1) of sortedList) then | |
| set temp to item j of sortedList | |
| set item j of sortedList to item (j + 1) of sortedList | |
| set item (j + 1) of sortedList to temp | |
| end if | |
| end repeat | |
| end repeat | |
| return sortedList | |
| end sortScreensByX |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment