At work I have a 3 monitor setup. I would like to move the current application to a second or a third monitor with a key binding. How to do that?
6 Answers
I use the following script to cycle the focused window through the screens.
-- bind hotkey hs.hotkey.bind({'alt', 'ctrl', 'cmd'}, 'n', function() -- get the focused window local win = hs.window.focusedWindow() -- get the screen where the focused window is displayed, a.k.a. current screen local screen = win:screen() -- compute the unitRect of the focused window relative to the current screen -- and move the window to the next screen setting the same unitRect win:move(win:frame():toUnitRect(screen:frame()), screen:next(), true, 0) end) Comments
The screen library helps finding the right "display". allScreens lists the displays in the same order as they are defined by the system. The hs.window:moveToScreen function moves to a given screen, where it's possible to set the UUID.
The following code works for me. Hitting CTRL+ALT+CMD+ 3 moves the currently focused window to display 3, same as if you would choose "Display 3" in the Dock's Option menu.
function moveWindowToDisplay(d) return function() local displays = hs.screen.allScreens() local win = hs.window.focusedWindow() win:moveToScreen(displays[d], false, true) end end hs.hotkey.bind({"ctrl", "alt", "cmd"}, "1", moveWindowToDisplay(1)) hs.hotkey.bind({"ctrl", "alt", "cmd"}, "2", moveWindowToDisplay(2)) hs.hotkey.bind({"ctrl", "alt", "cmd"}, "3", moveWindowToDisplay(3)) 1 Comment
Not exactly the answer to OP but leaving this here for others who also want to cycle through monitors and maximize on each screen:
local app = hs.window.focusedWindow() app:moveToScreen(app:screen():next()) app:maximize() You can put this in a function and bind it to Ctrl + Alt + n like so:
function moveToNextScreen() local app = hs.window.focusedWindow() app:moveToScreen(app:screen():next()) app:maximize() end hs.hotkey.bind({"ctrl", "alt"}, "n", moveToNextScreen) Comments
I've answered this in Reddit post here, but in case anyone comes across this question here's the answer:
The Hammerspoon API doesn't provide an explicit function for doing this, so you gotta roll out with a custom implementation to achieve this:
-- Get the focused window, its window frame dimensions, its screen frame dimensions, -- and the next screen's frame dimensions. local focusedWindow = hs.window.focusedWindow() local focusedScreenFrame = focusedWindow:screen():frame() local nextScreenFrame = focusedWindow:screen():next():frame() local windowFrame = focusedWindow:frame() -- Calculate the coordinates of the window frame in the next screen and retain aspect ratio windowFrame.x = ((((windowFrame.x - focusedScreenFrame.x) / focusedScreenFrame.w) * nextScreenFrame.w) + nextScreenFrame.x) windowFrame.y = ((((windowFrame.y - focusedScreenFrame.y) / focusedScreenFrame.h) * nextScreenFrame.h) + nextScreenFrame.y) windowFrame.h = ((windowFrame.h / focusedScreenFrame.h) * nextScreenFrame.h) windowFrame.w = ((windowFrame.w / focusedScreenFrame.w) * nextScreenFrame.w) -- Set the focused window's new frame dimensions focusedWindow:setFrame(windowFrame) Wrapping the snippet above in a function and binding it to a hotkey should cycle the currently focused application across your different monitors.
Comments
Another way to move the window around is to use the directional move functions, e.g. win:moveOneScreenEast() and the like (there's one function for each direction). I find it useful to bind arrow keys to effect mnemonic keyboard shortcuts.
hs.hotkey.bind({'alt', 'ctrl', 'cmd'}, 'Right', function() local win = hs.window.focusedWindow() win:moveOneScreenEast(false, true, 0.5) end) hs.hotkey.bind({'alt', 'ctrl', 'cmd'}, 'Left', function() local win = hs.window.focusedWindow() win:moveOneScreenWest(false, true, 0.5) end) Reference: http://hammerspoon.org/docs/hs.window.html#moveOneScreenEast
Comments
Other answers to date seem to all be limited to moving windows, not complete applications as the question asks. Below is what I use, bound to a key combo using hs.hotkey.bind() as others note.
local function moveAppWindow() -- Move visible windows - including popups, modals, floating - from same screen as -- focused window. (Only standard windows misses those apps that annoyingly start -- as popups.) local focusedWindow = hs.window.focusedWindow() local focusedApp = focusedWindow:application() if focusedApp then local screens = hs.screen.allScreens() if #screens > 1 then local windows = focusedApp:allWindows() local initialScreen = focusedWindow:screen() local destinationScreen = nextScreen(initialScreen) for _, w in ipairs(windows) do if w:screen() == initialScreen and w:isVisible() then w:moveToScreen(destinationScreen, true, true) end end else focusedWindow:centerOnScreen(nil, true) end end end