Open Madd0g opened 4 years ago
This might not be exclusive to Electron apps. I have a similar problem with Firefox Developer Edition when using it with or without an external display.
The example above is me trying to move FF from external to MBP's screen:
You're right, it happens with other apps as well. It's happening with iTerm for me.
The animation is one weird symptom and another is that my logic for moving the app between screens doesn't work properly, like it loses the screen, or the window/screen relationship.
Are you using a spoon or the API itself? I am using WindowGrid spoon which does depend on http://www.hammerspoon.org/docs/hs.grid.html
Sometimes this kind of thing can be caused by apps having a different name in their Info.plist from the name of their .app bundle. If that’s the case here, maybe we can figure out where we’re using the wrong one, and try to fix it.
I'm using both hs.grid
and simpler window methods like win:maximize()
and both have the same problem
@cmsj do you need anything from me? Console log or any other info? I am not familiar with macOS internals & Lua but would love to help. :)
Are there any errors in the Hammerspoon Console when the movements fail to trigger?
I get no errors.
In addition to simple win:maximize()
having this problem, I have a big pile of custom code for moving windows between screens, so within a screen there's one problem (unwanted animation, need to call the function multiple times to get the desired result), but my own code is also failing to move the window to the next screen (maybe failing to detect which screen it's on, or maybe the total number of screens).
I'll dig more over the weekend, I'm sure I can figure out exactly where my code is failing, maybe that will provide some additional hint.
Also, yesterday, vscode was having this problem, today it doesn't have the problem, but now firefox does. I don't think it's related to specific apps.
im hittingthis at the moment.
with vscode focusedWindow() is nil but also happens when doing hs.application.frontmostApplication():focusedWindow()
or :allWindows()
to hammerspoon its like vscode has no windows at all.
I also found that ecamm live's customziation docks are not detectable/filterable by hammerspoon. which is shame as their auto layout is bad and i would love to fix it.
I'm having a similar issue with slack. Hammerspoon does not detect any slack windows:
> hs.application.find("Slack"):mainWindow()
nil
This seems to have happened recently.
I've been seeing this issue as well when using hs.grid
.
My Emacs would sometimes require three calls, which in no particular order would resize height, resize width, and set origin.
Another datapoint that bolsters the theory that the issue is with untitled windows: After changing my Emacs window title to begin with Emacs |
, it works on the first try every time.
Hopefully not just pouring confusion on the fire, but I just had this happen to me with Slack, and found that restarting Slack fixed the issue. (For now...)
i am having a similar issue with VScode that Hammerspoon does not detect any VSCode windows. After I changed my VSCode window title to start with VSCode -
, it works without a problem. So it probably has something to do with untitled windows.
My Emacs would sometimes require three calls, which in no particular order would resize height, resize width, and set origin.
I'm actually amazed by this bug, some things work but require multiple "tries" and others simply don't work.
I have my own screen-moving logic and I also tried using the WinWin spoon, both using moveToScreen()
, funnily mine never works with these windows (window:moveToScreen(previousScreen)
just doesn't do anything) but WinWin stutters (making few wrong resizes in-place) but sometimes eventually does jump to the next screen.
just weird, man.
EDIT: one thing I noticed today is that the behavior is better when passing some more arguments to moveToScreen
-- works better!
window:moveToScreen(previousScreen, true, false)
For me the win:maximize()
function requires 3 tries for apps like Firefox Nightly or VSCode to lead to a maximized window (note: I have set hs.window.animationDuration = 0
).
When looking at the code of the maximize
function one can see that it only calls _setFrame
with the appropriate frame for the screen: https://github.com/Hammerspoon/hammerspoon/blob/53257ea54f376455c710e22af82834aba0621110/extensions/window/init.lua#L594
The _setFrame
function performs 3 calls: setSize
followed by setTopLeft
and again setSize
: https://github.com/Hammerspoon/hammerspoon/blob/53257ea54f376455c710e22af82834aba0621110/extensions/window/init.lua#L313
It seems that the _setFrame
function aborts execution after setSize
and/or setTopLeft
?!
This seems like a macOS or Chrome problem, because even macOS's built-in context menu for moving a window to other screen is broken.
So if we still want this functions, this app https://github.com/rxhanson/Rectangle can do this at this moment.
Sorry ,Rectangle does not work too.
So if we still want this functions, this app https://github.com/rxhanson/Rectangle can do this at this moment.
Sorry ,Rectangle does not work too.
oh I got U, they are both work when I restart vscode. It's weird !
I got the same issue, but solely with Finder. Even with the example taken from the "Getting Started" page.
Before migrating my window management to Hammerspoon, I used pure AppleScript for Window Management, and here, there are two methods for resizing windows, one of which caused the same issue while the other worked fine. Maybe this helps with fixing this issue?
# using bounds, everything works fine
# however, setting window bounds is only available for apps with proper AppleScript support
use framework "AppKit"
set allFrames to (current application's NSScreen's screens()'s valueForKey:"frame") as list
set max_x to item 1 of item 2 of item 1 of allFrames
set max_y to item 2 of item 2 of item 1 of allFrames
set x to 0.2 * max_x
set y to 0.1 * max_y
set w to 0.6 * max_x
set h to 0.8 * max_y
tell application "Finder" to set bounds of window 1 to {x, y, x + w, y + h}
# using size and position works for apps without regular AppleScript support
# but causes issues with some apps that do have regular AppleScript support
use framework "AppKit"
set allFrames to (current application's NSScreen's screens()'s valueForKey:"frame") as list
set max_x to item 1 of item 2 of item 1 of allFrames
set max_y to item 2 of item 2 of item 1 of allFrames
set x to 0.2 * max_x
set y to 0.1 * max_y
set w to 0.6 * max_x
set h to 0.8 * max_y
tell application "System Events"
tell process "Finder"
tell window 1
set position to {x, y}
set size to {w, h}
end tell
end tell
end tell
Okay, I looked into it and I am quite positive that the issue is caused by the difference between the position-size-method and the bounds-method I posted above.
After a bunch of testing, the issue 100% only occurs for apps with explicit AppleScript support. You can check whether an app has explicit AppleScript support by launching the Script Editor, and then selecting "open dictionary" in the file menu. You can also check it programmatically by looking whether a .sdef
file exists somewhere in the app bundle (the .app
).
1) If the app has explicit AppleScript support, the bounds-method and the position-size-method both work to resize a window. However, the position-size-method will lead to the glitching bug, where you sometimes need multiple attempts. The bounds-method works without any issue.
2) If the app does not have explicit AppleScript support, it can only be indirectly scripted via AppleScript by targeting process windows via tell application "System Events" ...
. Resizing windows only works via the position-size-method for these apps, but it works issue-free.
Consequently, you should use the bounds-method for AppleScript-capable apps, and the position-size-method for the others. From what I can tell, Hammerspoon seems to use purely the position-size-approach for all apps, resulting in the bug. Using the bounds-approach for the apps in question should also fix the problem for Hammerspoon. Unfortunately, I have zero knowledge of C and Objective-C, but maybe someone who does can fix this?
edit: there seems to be one exception for me: Sublime Text does not have explicit AppleScript support (i.e. the bounds-method does not work), but still has the issue when using the the position-size approach 😵💫
In the meantime, you can effectively use hs.applescript
to create a workaround that fixes the window movement issue. Add this function to your init.lua and use resizingWorkaround
instead of win:moveToUnit
for moving windows. I have tested this and the issue with the windows not moving properly 100% stops for me with this workaround. (Sorry if the code isn't really clean, I only learned lua 2 days ago when I started using Hammerspoon.)
function resizingWorkaround(win, pos)
local winApp = win:application():name()
-- add Applescript-capable apps you are using to the if-condition below
if (winApp == "Finder" or winApp == "Brave Browser" or winApp == "BusyCal" or winApp == "Safari") then
hs.applescript([[
use framework "AppKit"
set allFrames to (current application's NSScreen's screens()'s valueForKey:"frame") as list
set max_x to item 1 of item 2 of item 1 of allFrames
set max_y to item 2 of item 2 of item 1 of allFrames
]] ..
"set x to " .. pos.x .. " * max_x\n" ..
"set y to " .. pos.y .. " * max_y\n" ..
"set w to " .. pos.w .. " * max_x\n" ..
"set h to " .. pos.h .. " * max_y\n" ..
'tell application "' .. winApp .. '" to set bounds of front window to {x, y, x + w, y + h}'
)
else
win:moveToUnit(pos)
end
end
I got the same behavior with Chrome for a while (multisteps necessary to move and place windows, and animation is happening even if my animation duration setting is set to 0). My other electron based apps (slack, vscode) were always working fine.
The culprit on my end was the Gramarly Desktop app, which adds a little overlay on top of some apps. Just dropping this here in case this helps someone with a similar issue.
Well after 2 years of no problems I'm back with Slack giving nil
for every variation of focusedWindow
I've tried. Restarting Slack doesn't work either. Is there no way to get a hs.window
for Slack now?
Looks like this is probably an issue with the AXEnhancedUserInterface
attribute. Full explanation and workaround posted here: https://github.com/Hammerspoon/hammerspoon/issues/3224#issuecomment-1294359070
I was so annoyed that positioning windows is not working, that for some features, I developed a timer based loop hack that keeps issuing the command until the window seems to be in the right spot.
I'm almost sad to see it go, I kinda like to see the window twitching 4-5 times until it settles down in the desired position :)
https://user-images.githubusercontent.com/1171003/198724824-c8076d10-d62c-4074-810f-762a9d5bc57d.mp4
I am still experiencing this issue for specific applications, notably Firefox (Librewolf). Closed my issue to instead track this one, but more details can be found there:
https://github.com/Hammerspoon/hammerspoon/issues/3624
Quite hacky, but this is the workaround for moving windows with retries that I came up with; feedback is always welcome!
-- Convert relative `unitrect` to `rect` (couldn't get hs.window:fromUnitRect to work)
local function _unit_rect_to_rect(unit_rect)
local screen_frame = hs.screen.mainScreen():frame()
return hs.geometry.rect(
screen_frame.x + (unit_rect.x * screen_frame.w),
screen_frame.y + (unit_rect.y * screen_frame.h),
unit_rect.w * screen_frame.w,
unit_rect.h * screen_frame.h
)
end
-- Temporary workaround: move windows until we confirm that they are at the frame that
-- we expect. Have a retry of 3 to prevent any unwanted infinite loops.
local function _move_to_unit_with_retries(geometry, window)
window:moveToUnit(geometry)
local retries = 3
hs.timer.doUntil(function()
return retries == 0 or window:frame():equals(_unit_rect_to_rect(geometry):floor())
end, function()
window:moveToUnit(geometry)
retries = retries - 1
end, 0.25)
end
EDIT EDIT: it happened again after a restart, so I'm not sure what triggered it. Restarting Firefox got it back to normal. OK, it happens pretty much every time I open my computer until I restart Firefox.
EDIT: nvm, a restart fixed it - I guess something happens with Firefox that makes it persist how it was created. I'll update this if I ever see anything awry again. So it's all good! 0 bugs!
Hah - yes, I can confirm I have the same issue as @cmpadden - it works for everything except Firefox (I'm using canon Firefox). I'm writing my own config directly using hs.grid
, and have the same resizing issue described above - at times, it takes multiple tries to get it to comply. So far I haven't seen any other problematic applications. The animation duration is also not respected, just for Firefox.
This is me hitting the same shortcut twice to invoke hs.grid.set(win, cell, screen)
with the exact same params, but it takes only the second time:
2024-09-10 20:10:50: cell used to resize
2024-09-10 20:10:50: hs.geometry.rect(3.0,0.0,3,6.0)
2024-09-10 20:10:50: after resize
2024-09-10 20:10:50: hs.geometry.rect(0.0,0.0,3.0,6.0)
2024-09-10 20:10:52: cell used to resize
2024-09-10 20:10:52: hs.geometry.rect(3.0,0.0,3,6.0)
2024-09-10 20:10:52: after resize
2024-09-10 20:10:52: hs.geometry.rect(3.0,0.0,3.0,6.0)
As has been mentioned above, this happens even for simple functions like maximizeWindow
Spectacle/Rectangle, which I used till now, doesn't have this issue. Looking through their code to see what's different between them and hs.grid
.
Looks like this is probably an issue with the
AXEnhancedUserInterface
attribute. Full explanation and workaround posted here: #3224 (comment)
Completely missed this. This was the issue. Can this be closed as a duplicate? Looks like everyone here actually has the same root cause.
@cmpadden @purajit The Firefox/Librewolf-specific problems are probably a result of Firefox setting AXEnhancedUserInterface
on itself. See https://github.com/Hammerspoon/hammerspoon/issues/3224#issuecomment-2155567686 for more details.
@cmpadden @purajit The Firefox/Librewolf-specific problems are probably a result of Firefox setting
AXEnhancedUserInterface
on itself. See https://github.com/Hammerspoon/hammerspoon/issues/3224#issuecomment-2155567686 for more details.
Oh, sorry, yeah, that's what I meant - I found that comment and it was exactly the issue. I think this issue #2316 should be closed as a duplicate of that. I completely missed your comment on this thread initially, and found #3224 after furiously debugging and looking things up!
All the electron applications I use (actually slack and vscode, but not spotify) have the same problem moving/resizing within a screen and between screens.
I have to press the shortcut key multiple times and every time it does part of the movement (resize only, then on next press it'll put the window in the right place). Also, only those apps are animating the resize, even though I have
hs.window.animationDuration = 0
.All the shortcuts work in Finder/Spotify, but as soon as I switch to vscode, it starts animating and not fully working.
I thought it was just
hs.grid
based code, but seems like it happens withwin:maximize()
andwin:moveToScreen()
.Thanks