hammerspoon
hammerspoon copied to clipboard
hs.spaces.moveWindowToSpace does not work on macOS 15.0 Sequoia
It simply returns true without actually moving the window.
It does, if that happens to be the number of the current space. Otherwise it should output
nil target space ID 3 does not refer to a user space.
On x86 Sonoma 14.7:
Showing all available spaces hs.spaces.allSpaces() outputs smth like this for me:["3A6BED5A-AB1C-8E9F-E898-3B421BF1F35B"] = { 1, 81, 83 }.
So the second space has the id 81 on my current installation.
Using hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 81) moves the window, to the second space (while I am on the first) and outputs true. Works as designed.
What OS version are you on?
I can replicate the issue on my OS Sequoia 15.0.1 (24A348)
I've tried both shortcut and cli to move a focused window from Id 1 to Id2. The window blinked and remains without really going to desktop id 2.
Logs are,
2024-10-07 11:29:53: -- Lazy extension loading enabled
2024-10-07 11:29:53: -- Loading ~/.hammerspoon/init.lua
2024-10-07 11:29:53: -- Loading extension: logger
2024-10-07 11:29:53: -- Loading extension: hotkey
2024-10-07 11:29:53: 11:29:53 hotkey: Enabled hotkey ⌃⇧1
2024-10-07 11:29:53: hotkey: Enabled hotkey ⌃⇧2
2024-10-07 11:29:53: hotkey: Enabled hotkey ⌃⇧3
2024-10-07 11:29:53: hotkey: Enabled hotkey ⌃⇧4
2024-10-07 11:29:53: hotkey: Enabled hotkey ⌃⇧5
2024-10-07 11:29:53: hotkey: Enabled hotkey ⌃⇧6
2024-10-07 11:29:53: -- Done.
2024-10-07 11:30:04: 11:30:04 WindowMove: Hotkey pressed: ctrl + shift + 2
2024-10-07 11:30:04: WindowMove: Attempting to move window to Desktop 2
2024-10-07 11:30:04: -- Loading extension: spaces
2024-10-07 11:30:04: -- Loading extension: application
2024-10-07 11:30:04: WindowMove: UUID: 1D51D562-4807-ABEA-57D3-DF5D9BD2EFF9
2024-10-07 11:30:04: WindowMove: Index: 1, Name: Desktop 1
2024-10-07 11:30:04: WindowMove: Index: 2, Name: Desktop 2
2024-10-07 11:30:04: WindowMove: Found spaceId for Desktop 2: 2
2024-10-07 11:30:04: -- Loading extension: window
2024-10-07 11:30:04: WindowMove: Moving window hs.spaces.moveWindowToSpace does not work on macOS 15.0 Sequoia · Issue #3698 · Hammerspoon/hammerspoon - Google Chrome – Ben (Personal) to spaceId 2
2024-10-07 11:30:07: 11:30:07 WindowMove: Hotkey pressed: ctrl + shift + 3
2024-10-07 11:30:07: WindowMove: Attempting to move window to Desktop 3
2024-10-07 11:30:07: WindowMove: UUID: 1D51D562-4807-ABEA-57D3-DF5D9BD2EFF9
2024-10-07 11:30:07: WindowMove: Index: 1, Name: Desktop 1
2024-10-07 11:30:07: WindowMove: Index: 2, Name: Desktop 2
2024-10-07 11:30:07: WindowMove: UUID: 7985EF1E-B2B7-C0CF-BC29-0CD90FBCB3D8
2024-10-07 11:30:07: WindowMove: Index: 1, Name: Desktop 1
2024-10-07 11:30:07: WindowMove: Index: 2, Name: Desktop 2
2024-10-07 11:30:07: 11:30:07 ** Warning:WindowMove: Space not found: Desktop 3
2024-10-07 11:30:07: 11:30:07 ** Warning:WindowMove: Space not found: Desktop 3
2024-10-07 11:30:07: -- Loading extension: alert
2024-10-07 11:30:10: 11:30:10 WindowMove: Hotkey pressed: ctrl + shift + 1
2024-10-07 11:30:10: WindowMove: Attempting to move window to Desktop 1
2024-10-07 11:30:10: WindowMove: UUID: 1D51D562-4807-ABEA-57D3-DF5D9BD2EFF9
2024-10-07 11:30:10: WindowMove: Index: 1, Name: Desktop 1
2024-10-07 11:30:10: WindowMove: Found spaceId for Desktop 1: 1
2024-10-07 11:30:10: WindowMove: Moving window hs.spaces.moveWindowToSpace does not work on macOS 15.0 Sequoia · Issue #3698 · Hammerspoon/hammerspoon - Google Chrome – Ben (Personal) to spaceId 1
> hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 2)
true
> hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 3)
nil target space ID 3 does not refer to a user space
What OS version are you on?
I am currently on 15.0.1 Sequoia but the issue happens since 15.0 (as per the title).
Sorry if my logs weren't clear enough. Regardless of whether I was moving it to the current space or not, it will always return true. In the following example, I was always in the first space:
2024-10-07 09:37:36: Welcome to the Hammerspoon Console!
You can run any Lua code in here.
2024-10-07 09:37:36: -- Lazy extension loading enabled
2024-10-07 09:37:36: -- Loading ~/.hammerspoon/init.lua
2024-10-07 09:37:36: -- Loading extension: hotkey
2024-10-07 09:37:36: 09:37:36 hotkey: Enabled hotkey ⌘⌃⌥W
2024-10-07 09:37:36: -- Done.
2024-10-07 09:38:18: -- Loading extension: spaces
> hs.spaces.allSpaces()
{
["37D8832A-2D66-02CA-B9F7-8F30A301B230"] = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
}
2024-10-07 09:38:31: -- Loading extension: window
> hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 5)
true
> hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 6)
true
> hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 6)
true
> hs.spaces.moveWindowToSpace(hs.window.focusedWindow(), 5)
true
I can confirm the same behavior, it is always returning true, still nothing happens. It started after upgrading to Sequoia.
> hs.spaces.moveWindowToSpace(hs.application.get("kitty"):mainWindow(), hs.spaces.focusedSpace())
true
They discussed here already. It seems like there's no good option to make it work https://github.com/Hammerspoon/hammerspoon/issues/3636
They discussed here already. It seems like there's no good option to make it work #3636
@marcelja Thanks for bringing this to my attention! The comment here https://github.com/Hammerspoon/hammerspoon/issues/3636#issuecomment-2384239506 seems to have done the trick for me.
I tried to modify provided script to suit my needs, namely moving unfocused window to current space, hack is not sufficient for this behavior, for me it's still open issue.
I've tried everything as inspired by code here and was unable to make it work.
my original config reads
-- Set up the logger
local log = hs.logger.new('WindowMover', 'info')
-- Function to get spaceId by space name
function getSpaceIdByName(spaceName)
local spaceNames = hs.spaces.missionControlSpaceNames()
for uuid, desktops in pairs(spaceNames) do
log.i("UUID: " .. uuid) -- Log the UUID
for index, name in pairs(desktops) do
log.i("Index: " .. index .. ", Name: " .. tostring(name)) -- Log the index and name
if name == spaceName then
log.i("Found spaceId for " .. spaceName .. ": " .. index)
return index
end
end
end
log.w("Space not found: " .. spaceName)
return nil
end
-- Function to move focused window to a specific space
function moveFocusedWindowToSpace(spaceNumber)
local spaceName = "Desktop " .. spaceNumber
log.i("Attempting to move window to " .. spaceName)
local spaceId = getSpaceIdByName(spaceName)
if spaceId then
local focusedWindow = hs.window.focusedWindow()
if focusedWindow then
log.i("Moving window " .. focusedWindow:title() .. " to spaceId " .. spaceId)
hs.spaces.moveWindowToSpace(focusedWindow:id(), spaceId)
else
log.w("No focused window")
hs.alert.show("No focused window")
end
else
log.w("Space not found: " .. spaceName)
hs.alert.show("Space not found: " .. spaceName)
end
end
-- Bind keys ctrl + shift + 1-6
for i = 1, 6 do
hs.hotkey.bind({"ctrl", "shift"}, tostring(i), function()
log.i("Hotkey pressed: ctrl + shift + " .. i)
moveFocusedWindowToSpace(i)
end)
end
the logs reads
2024-10-25 11:57:57: -- Lazy extension loading enabled
2024-10-25 11:57:57: -- Loading ~/.hammerspoon/init.lua
2024-10-25 11:57:57: -- Loading extension: logger
2024-10-25 11:57:57: -- Loading extension: hotkey
2024-10-25 11:57:57: 11:57:57 hotkey: Enabled hotkey ⌃⇧1
2024-10-25 11:57:57: hotkey: Enabled hotkey ⌃⇧2
2024-10-25 11:57:57: hotkey: Enabled hotkey ⌃⇧3
2024-10-25 11:57:57: hotkey: Enabled hotkey ⌃⇧4
2024-10-25 11:57:57: hotkey: Enabled hotkey ⌃⇧5
2024-10-25 11:57:57: hotkey: Enabled hotkey ⌃⇧6
2024-10-25 11:57:57: -- Done.
2024-10-25 11:58:07: 11:58:07 WindowMove: Hotkey pressed: ctrl + shift + 2
2024-10-25 11:58:07: WindowMove: Attempting to move window to Desktop 2
2024-10-25 11:58:07: -- Loading extension: spaces
2024-10-25 11:58:07: -- Loading extension: application
2024-10-25 11:58:08: 11:58:08 WindowMove: UUID: 7985EF1E-B2B7-C0CF-BC29-0CD90FBCB3D8
2024-10-25 11:58:08: WindowMove: Index: 1, Name: Desktop 1
2024-10-25 11:58:08: WindowMove: Index: 355, Name: Desktop 2
2024-10-25 11:58:08: WindowMove: Found spaceId for Desktop 2: 355
2024-10-25 11:58:08: -- Loading extension: window
2024-10-25 11:58:08: WindowMove: Moving window init.lua — .hammerspoon to spaceId 355
2024-10-25 11:58:09: 11:58:09 WindowMove: Hotkey pressed: ctrl + shift + 3
2024-10-25 11:58:09: WindowMove: Attempting to move window to Desktop 3
2024-10-25 11:58:09: WindowMove: UUID: 7985EF1E-B2B7-C0CF-BC29-0CD90FBCB3D8
2024-10-25 11:58:09: WindowMove: Index: 1, Name: Desktop 1
2024-10-25 11:58:09: WindowMove: Index: 355, Name: Desktop 2
2024-10-25 11:58:09: WindowMove: UUID: F84D7AD8-6D0C-F050-EE90-CFBE2074CBF0
2024-10-25 11:58:09: WindowMove: Index: 1, Name: Desktop 1
2024-10-25 11:58:09: WindowMove: Index: 355, Name: Desktop 2
2024-10-25 11:58:09: 11:58:09 ** Warning:WindowMove: Space not found: Desktop 3
2024-10-25 11:58:09: 11:58:09 ** Warning:WindowMove: Space not found: Desktop 3
2024-10-25 11:58:09: -- Loading extension: alert
2024-10-25 11:58:11: 11:58:11 WindowMove: Hotkey pressed: ctrl + shift + 1
2024-10-25 11:58:11: WindowMove: Attempting to move window to Desktop 1
2024-10-25 11:58:11: WindowMove: UUID: 7985EF1E-B2B7-C0CF-BC29-0CD90FBCB3D8
2024-10-25 11:58:11: WindowMove: Index: 1, Name: Desktop 1
2024-10-25 11:58:11: WindowMove: Found spaceId for Desktop 1: 1
2024-10-25 11:58:11: WindowMove: Moving window init.lua — .hammerspoon to spaceId 1
could not figure out what was wrong, it logs everything as expected. any comment is appreciated.
I was having the same issue. But the API started working again once I did the following
- Right click the application in the dock
- Click Options > (Assign To) ~~All spaces~~ All Desktops
It would be nice if there was a way to do this programmatically. I'm on Sequoia 15.0.1.
@niknbr I have only (Assing To) All Desktops, which does not help, any chance you know why there is such difference?
@krykra7 My bad. It is "All Desktops". If it helps here is the reference to the function I use it with
function moveWindowToCurrentScreen(appName)
local app = hs.application.get(appName)
local window = app:mainWindow()
-- Set window frame when moved to different monitor
local mainScreen = hs.screen.mainScreen()
local mainScreenFrame = mainScreen:frame()
window:setFrame(mainScreenFrame)
-- Move window
local currentSpace = hs.spaces.focusedSpace()
hs.spaces.moveWindowToSpace(window, currentSpace) -- Started working after setting it to "All Desktops"
window:focus()
end
@niknbr isn't the whole point of the "Assign to All desktops" command to have all windows of this app always visible in every space? And why someone would want to move them around if they are appearing on every desktop anyway?
This is frustrating. I've tried the following work-arounds without success:
-
Mouse click down on window title bar. Switch to new space. Wait until new space is active. Drag window to the center of the screen for the new space.
hs.spaces.windowsForSpace()andhs.spaces.windowSpaces()never report that the window is on the new space. As soon as the mouse is released, the window disappears back to the old space. -
Click down on window title bar. Open Mission Control. Get the pixel location of the new space desktop preview in the bar on the top of the screen. Move the window with
hs.window:move()over the new space desktop preview. Note: mouse drag events do not register while Mission Control is open. The window is positioned over the new space desktop preview but it is not "sucked down" into the new space.
Both these actions work when performed manually with the mouse and keyboard. They fail when automated with HammerSpoon.
My main purpose of using hammerspoon was to summon, hide and show terminal in any space and any screen which stopped working with broken hs.spaces.windowSpaces(). After many attempts with provided tips I finally had to switch to yabai + hammerspoon (with ipc module) for achieving my goal. If somebody is interested in such solution just let me know and I will provide my scripts.
@krykra7 I would like to know you achieved this.
@tomasz-grabowski-netbulls Sure, you would need yabai, ipc module enabled in hammerspoon, jq and software for handling shortcuts.
For shortcuts hammerspoon is fine but I found that hs.execute is really slow, maybe some improvements are possible using hs.task but In general I stick with karabiner-elements for handling shortcuts.
Your .hammerspoon/init.lua should include following two first lines (I provided shortcut handled just for reference):
require("hs.ipc")
hs.ipc.cliInstall("/opt/homebrew/") -- this is important for remotely calling hammerspoon
hs.hotkey.bind({ "ctrl" }, "F12", function()
-- execute script that handles terminal with yabai
local output, status, type = hs.execute("/script/location/dropdown.sh")
end)
-- This worked before macOS 15.0 Sequoia, just as reference
-- hs.hotkey.bind({ "ctrl" }, "F12", function()
-- local appName = "kitty"
-- local app = hs.application.get(appName)
-- local currentSpace = hs.spaces.focusedSpace()
--
-- if app then
-- hs.spaces.moveWindowToSpace(app:mainWindow(), currentSpace)
-- if not app:mainWindow() then
-- app:selectMenuItem({ appName, "New OS window" })
-- elseif app:isFrontmost() then
-- app:hide()
-- else
-- app:activate()
-- end
-- else
-- hs.application.launchOrFocus(appName)
-- end
-- end)
dropdown.sh Script that handles opening new instance if app is not running yet, bringing to current space, focusing if not focused and hiding if focused:
#!/usr/bin/env bash
yabai="/opt/homebrew/bin/yabai"
hs="/opt/homebrew/bin/hs"
app="kitty"
while getopts "a:" opt; do
case $opt in
a)
app="$OPTARG"
;;
*)
echo "Invalid option."
;;
esac
done
current_space=$($yabai -m query --spaces --space | jq '.index')
current_focused_window=$($yabai -m query --windows --window | jq '.id')
app_window=$($yabai -m query --windows | jq ".[] | select(.app == \"$app\") | .id")
app_space=$($yabai -m query --windows | jq ".[] | select(.app == \"$app\") | .space")
# Handle app is not running yet
if [ -z "$app_window" ]; then
open -a "$app"
while [ -z "$app_window"]; do
app_window=$(yabai -m query --windows | jq ".[] | select(.app == \"$app\") | .id")
done
yabai -m window --focus "$app_window"
exit 0
fi
if [ "$current_space" == "$app_space" ]; then
if [ "$current_focused_window" == "$app_window" ]; then
$hs -c "hs.application.get(\"$app\"):hide()"
else
$yabai -m window --focus "$app_window"
fi
else
$yabai -m window $app_window --space $current_space
$yabai -m window --focus "$app_window"
fi
I'm using hammerspoon only for hiding app here, because yabai only support minimizing which starts animation and it seems the easier way than using osascript or other tricks.
I figured out the issue with dragging windows to spaces in Mission Control. I didn't realize that Mission Control was a full screen application and that the windows were buttons with screen shots for images, not application windows.
Here's a replacement for hs.spaces.moveWindowToSpace() for MacOS 15: https://github.com/mogenson/Drag.spoon
Use it like:
Drag = loadSpoon("Drag")
-- figure out the space_id for the target space
-- > hs.spaces.allSpaces()
-- {
-- ["1E4625E7-5C5E-4DDC-B4C7-991CCCEF0732"] = { 1301 },
-- ["37D8832A-2D66-02CA-B9F7-8F30A301B230"] = { 528, 2, 1306 }
-- }
-- eg. 1306 is the third space on the second screen
Drag:focusedWindowToSpace(1306)
There's a few limitations listed in the README. The main one is that I use the window title to find the window button in Mission Control. If anyone knows how to set a window title to a unique string, or can think of another way to mark a window so it can be found in Mission Control, then this utility can be a lot more robust.
Also stuck with this issue, but because my needs are very minimal, I manually wrote two functions as a temporary workaround. I’m sharing them here in case they might inspire someone else.
move_window_to_next_desktop and move_window_to_previous_desktop (link).
The logic is below:
- Get the current active window and ensures it's frontmost
- Calculate the click position (5,12 pixels offset from window top-left) and store the center position
- Move the mouse to the click position
- Simulate a mouse press
- Trigger the desktop switch with Ctrl+Left or Ctrl+Right (These are my system shortcuts for switching desktop in current screen/monitor)
- Release the mouse
- Move the mouse back to the center of the window
Also stuck with this issue, but because my needs are very minimal, I manually wrote two functions as a temporary workaround. I’m sharing them here in case they might inspire someone else.
Thank you @xgungnir, it worked for me too on MacOS 15.2. Just had to adjust simulateKeyEvent to accept two modifiers instead of one.
@mogenson—thanks so much for this. It's the only solution that has worked for me using yabai post-Sequoia. Window title seems to be working okay; will let you know otherwise.
Having just updated to Sequoia, I'm seeing similar behavior to what others have described here. One thing that does work is moving a window to a space that is on a different screen that the space the window is currently in. As a result, the following seems to work, provided that you have multiple monitors:
local log = hs.logger.new('init', 'debug')
local function screenCount()
return tableSize(hs.screen.allScreens())
end
local function findDifferentScreen(currentScreen)
log.df("trying to find different screen than %s", currentScreen)
for _, screen in ipairs(hs.screen.allScreens()) do
if screen ~= currentScreen then
log.df("found different screen %s", screen)
return screen;
end
end
end
local function _moveWindowToSpaceOnOtherScreen(window, targetSpace, maximize)
log.df("moving %s to %d", hs.inspect(window), targetSpace)
hs.spaces.gotoSpace(targetSpace)
hs.spaces.moveWindowToSpace(window:id(), targetSpace)
hs.timer.doAfter(0.5, function()
window:moveToScreen(hs.spaces.spaceDisplay(targetSpace))
if (maximize) then
log.df("maximizing %s", window)
hs.timer.doAter(0.1, function() window:maximize(0) end)
end
end)
end
local function moveWindowToSpace(window, targetSpace, maximize)
local currentWindowSpace = hs.spaces.windowSpaces(window)[1]
if (currentWindowSpace == targetSpace) then
log.df("window %s already on space %d", hs.inspect(window), targetSpace)
else
local targetSpaceScreen = hs.spaces.spaceDisplay(targetSpace)
-- unable to move a window from one space to antoher on the same screen, so it the target space is on the same
-- screen as the window's current space, first move it to a space on another screen.
if (targetSpaceScreen == hs.spaces.spaceDisplay(currentWindowSpace)) then
if (screenCount() == 1) then
log.df("unable to move windows between spaces when there is just one screen 🙁")
else
local tempScreen = findDifferentScreen(targetSpaceScreen)
local tempSpace = hs.spaces.activeSpaceOnScreen(tempScreen) -- hs.spaces.allSpaces()[tempScreen:getUUID()][1]
_moveWindowToSpaceOnOtherScreen(window, tempSpace, false)
window:focus()
log.df("window focused in alternate space")
hs.timer.doAfter(0.3, function()
_moveWindowToSpaceOnOtherScreen(window, targetSpace, maximize)
end)
end
else
_moveWindowToSpaceOnOtherScreen(window, targetSpace, maximize)
end
end
end
Note: the above is an excerpt from my init.lua. I think I've copied over all the necessary helper functions, but let me know if something appears to be missing.
I'm using the function below to move program windows to different desktops. It's not the most elegant method, but I've confirmed it works for now. I'm using Alt + 1-5 as hotkeys for moving between desktops. If you're using Ctrl hotkeys, you can change "Alt" to "Ctrl" in the code below.
-- Function to move window to space using mouse drag simulation
local function moveWindowToSpaceByDrag(spaceNumber)
local win = hs.window.focusedWindow()
if not win then
hs.alert.show("No focused window")
return
end
-- Calculate window header position (near top-left)
local frame = win:frame()
local headerX = frame.x + 15
local headerY = frame.y + 15
-- Store current mouse position
local currentMouse = hs.mouse.getAbsolutePosition()
-- Move mouse to window header
hs.mouse.setAbsolutePosition({x = headerX, y = headerY})
hs.timer.usleep(10000) -- Wait 10ms
-- Mouse down (press and hold)
local mouseDown = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseDown, {x = headerX, y = headerY})
mouseDown:post()
hs.timer.usleep(10000) -- Wait 10ms
-- Press Alt + number key (while holding mouse)
hs.eventtap.keyStroke({"alt"}, tostring(spaceNumber), 0)
hs.timer.usleep(10000) -- Wait 10ms
-- Mouse up (release)
local mouseUp = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseUp, {x = headerX, y = headerY})
mouseUp:post()
hs.timer.usleep(10000) -- Wait 10ms
-- Restore original mouse position
hs.mouse.setAbsolutePosition(currentMouse)
hs.alert.show("Moved window to space " .. spaceNumber)
end
I'm using the function below to move program windows to different desktops. It's not the most elegant method, but I've confirmed it works for now. I'm using Alt + 1-5 as hotkeys for moving between desktops. If you're using Ctrl hotkeys, you can change "Alt" to "Ctrl" in the code below.
@elgar328 Does this work to move a window to a space on a different screen? I couldn't get the mouse hold + Switch To Desktop keyboard shortcut to work across screens. The window remains on the original screen.
https://github.com/user-attachments/assets/cd63aad5-7435-4b87-b96f-1a8f5940514a
I use a dedicated Window Control Mode to prevent hotkey conflicts with other programs. I enter this mode by pressing Ctrl+Shift+J, and I can exit it by pressing either Esc or Q. Within this mode, I navigate windows using the H, J, K, L keys for movement, and Ctrl along with H, J, K, L to resize them. Additionally, I can switch between virtual desktops using the number keys 1 through 5.
-- Window control mode
local STEP_SIZE = 40
-- Function to move window to space using mouse drag simulation
local function moveWindowToSpaceByDrag(spaceNumber)
local win = hs.window.focusedWindow()
if not win then
hs.alert.show("No focused window")
return
end
-- Calculate window header position (near top-left)
local frame = win:frame()
local headerX = frame.x + 15
local headerY = frame.y + 15
-- Store current mouse position
local currentMouse = hs.mouse.getAbsolutePosition()
-- Move mouse to window header
hs.mouse.setAbsolutePosition({x = headerX, y = headerY})
hs.timer.usleep(10000) -- Wait 10ms
-- Mouse down (press and hold)
local mouseDown = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseDown, {x = headerX, y = headerY})
mouseDown:post()
hs.timer.usleep(10000) -- Wait 10ms
-- Press Alt + number key (while holding mouse)
hs.eventtap.keyStroke({"alt"}, tostring(spaceNumber), 0)
hs.timer.usleep(10000) -- Wait 10ms
-- Mouse up (release)
local mouseUp = hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseUp, {x = headerX, y = headerY})
mouseUp:post()
hs.timer.usleep(10000) -- Wait 10ms
-- Restore original mouse position
hs.mouse.setAbsolutePosition(currentMouse)
hs.alert.show("Moved window to space " .. spaceNumber)
end
local function controlWindow(cmd)
local win = hs.window.focusedWindow()
local f = win:frame()
if cmd == "h+" then f.h = f.h + 2 * STEP_SIZE; f.y = f.y - STEP_SIZE
elseif cmd == "h-" then f.h = f.h - 2 * STEP_SIZE; f.y = f.y + STEP_SIZE
elseif cmd == "w+" then f.w = f.w + 2 * STEP_SIZE; f.x = f.x - STEP_SIZE
elseif cmd == "w-" then f.w = f.w - 2 * STEP_SIZE; f.x = f.x + STEP_SIZE
elseif cmd == "left" then f.x = f.x - STEP_SIZE
elseif cmd == "down" then f.y = f.y + STEP_SIZE
elseif cmd == "up" then f.y = f.y - STEP_SIZE
elseif cmd == "right" then f.x = f.x + STEP_SIZE
end
win:setFrame(f)
end
rMode = hs.hotkey.modal.new({"ctrl","shift"}, "j")
function rMode:entered() hs.alert'Window control mode' end
function rMode:exited() hs.alert'Normal mode' end
rMode:bind("", "escape", nil, function() rMode:exit() end)
rMode:bind("", "return", nil, function() rMode:exit() end)
rMode:bind("", "q", nil, function() rMode:exit() end)
-- Window size controls (Ctrl + H/J/K/L)
rMode:bind("ctrl", "h", function() controlWindow("w-") end , nil, function() controlWindow("w-") end )
rMode:bind("ctrl", "j", function() controlWindow("h+") end , nil, function() controlWindow("h+") end )
rMode:bind("ctrl", "k", function() controlWindow("h-") end , nil, function() controlWindow("h-") end )
rMode:bind("ctrl", "l", function() controlWindow("w+") end , nil, function() controlWindow("w+") end )
-- Window position controls (H/J/K/L)
rMode:bind("", "h", function() controlWindow("left") end , nil, function() controlWindow("left") end )
rMode:bind("", "j", function() controlWindow("down") end , nil, function() controlWindow("down") end )
rMode:bind("", "k", function() controlWindow("up") end , nil, function() controlWindow("up") end )
rMode:bind("", "l", function() controlWindow("right") end, nil, function() controlWindow("right") end )
-- Window space movement (1-5)
for i = 1, 5 do
rMode:bind("", tostring(i), function()
moveWindowToSpaceByDrag(i)
end)
end
Any update on this? Can't get hs.spaces.moveWindowToSpace(win, space) to work.
Just decided to move to Aerospace this week because of this issue. No regrets, working great.
Drag = loadSpoon("Drag") Drag:focusedWindowToSpace(1306)
This worked really well. Thank you, @mogenson.