如何在 Hammerspoon 中的监视器之间移动应用程序?

How to move an application between monitors in Hammerspoon?

在工作中,我有一个 3 显示器设置。我想将当前应用程序移动到具有键绑定的第二个或第三个监视器。怎么做?

我已经在 Reddit post here 中回答了这个问题,但如果有人遇到这个问题,这里是答案:

Hammerspoon API 没有提供执行此操作的显式函数,因此您必须使用自定义实现来实现此目的:

-- 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)

将上面的代码片段包装在一个函数中并将其绑定到一个热键应该会在您的不同显示器之间循环当前聚焦的应用程序。

screen 库有助于找到正确的 "display"。 allScreens 按照系统定义的相同顺序列出显示。 hs.window:moveToScreen 函数移动到给定屏幕,可以在其中设置 UUID。

以下代码适用于我。 点击 CTRL+ALT+CMD+ 3 将当前聚焦的 window 移动到显示 3,就像您在Dock 的选项菜单。

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))

我使用以下脚本在屏幕上循环聚焦window。

-- 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)

不完全是 OP 的答案,但将此留给其他也想循环浏览显示器并在每个屏幕上最大化的人:

local app = hs.window.focusedWindow()
app:moveToScreen(app:screen():next())
app:maximize()

您可以将其放入一个函数中并将其绑定到 Ctrl + Alt + n,如下所示:

function moveToNextScreen()
  local app = hs.window.focusedWindow()
  app:moveToScreen(app:screen():next())
  app:maximize()
end

hs.hotkey.bind({"ctrl", "alt"}, "n", moveToNextScreen)