Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hs.spaces.moveWindowToSpace does not work on macOS 15.0 Sequoia #3698

Open
RichDom2185 opened this issue Oct 6, 2024 · 18 comments
Open

hs.spaces.moveWindowToSpace does not work on macOS 15.0 Sequoia #3698

RichDom2185 opened this issue Oct 6, 2024 · 18 comments

Comments

@RichDom2185
Copy link

image

It simply returns true without actually moving the window.

@QuantumLibet
Copy link

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?

@benjaminv
Copy link

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

@RichDom2185
Copy link
Author

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

@krykra7
Copy link

krykra7 commented Oct 11, 2024

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

@marcelja
Copy link

They discussed here already. It seems like there's no good option to make it work
#3636

@RichDom2185
Copy link
Author

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 #3636 (comment) seems to have done the trick for me.

@krykra7
Copy link

krykra7 commented Oct 17, 2024

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.

@benjaminv
Copy link

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.

@niknbr
Copy link

niknbr commented Oct 28, 2024

I was having the same issue. But the API started working again once I did the following

  1. Right click the application in the dock
  2. 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.

@krykra7
Copy link

krykra7 commented Oct 28, 2024

@niknbr I have only (Assing To) All Desktops, which does not help, any chance you know why there is such difference?

@niknbr
Copy link

niknbr commented Oct 28, 2024

@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

@certainlyakey
Copy link

@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?

@mogenson
Copy link

This is frustrating. I've tried the following work-arounds without success:

  1. 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() and hs.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.

  2. 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.

@krykra7
Copy link

krykra7 commented Nov 28, 2024

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.

@tomasz-grabowski-netbulls
Copy link

tomasz-grabowski-netbulls commented Nov 28, 2024

@krykra7 I would like to know you achieved this.

@krykra7
Copy link

krykra7 commented Nov 28, 2024

@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.

@mogenson
Copy link

mogenson commented Nov 30, 2024

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.

@xgungnir
Copy link

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:

  1. Get the current active window and ensures it's frontmost
  2. Calculate the click position (5,12 pixels offset from window top-left) and store the center position
  3. Move the mouse to the click position
  4. Simulate a mouse press
  5. Trigger the desktop switch with Ctrl+Left or Ctrl+Right (These are my system shortcuts for switching desktop in current screen/monitor)
  6. Release the mouse
  7. Move the mouse back to the center of the window

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants