I'd like to change the fullscreen (green) button to a maximize/restore button. A lot of people tried something similar but I could not find a suitable solution. My approach would be the following:
Get current window size (width and height)
Get screen size (on which the current window or mouse is)
Somehow get or calculate the dock and menubar height to take into account
Check if the window is maximized based on the above.
I think the only way to get the size of the current window is via AppleScript. Maybe it could set up a variable for window height and another one for width and JavaScript could read these variables and conditionally call Maximize or Restore builtin actions.
In theory this could work, but a little help would be appreciated in the implementation, since I'm not familiar with BTT scripting and AppleScript.
Or do you have a better idea for checking if a window is maximized or not?
I tried this script, but the variables are not visible in the Settings - BTT Scripting menu.
tell application "System Events" to tell (process 1 where frontmost is true)
set windowSize to the size of window 1
set windowPositon to the position of window 1
end tell
tell application "BetterTouchTool"
set_string_variable "windowSize" to windowSize
set_string_variable "windowPosition" to windowPosition
end tell
Here is an AppleScript to checking if a window is maximized or not and maximize/restore the frontmost window with the BTT Predefined Actions:
use framework "Foundation"
use framework "AppKit"
property ca : current application
set activeScreenVisibleFrame to ca's NSScreen's mainScreen()'s visibleFrame()
set activeScreenSize to {ca's NSWidth(activeScreenVisibleFrame) as integer, ca's NSHeight(activeScreenVisibleFrame) as integer}
tell application "System Events"
set currentAppName to name of first application process whose frontmost is true
tell application process currentAppName
set activeWindowSize to (size of window 1)
end tell
end tell
set isMaximized to ((item 1 of activeScreenSize) - (item 1 of activeWindowSize) ≤ 1 and (item 2 of activeScreenSize) - (item 2 of activeWindowSize) ≤ 1)
tell application "BetterTouchTool"
if isMaximized then
trigger_action "{\"BTTPredefinedActionType\":84}"
else
trigger_action "{\"BTTPredefinedActionType\":21}"
end if
end tell
However, sometimes the BTTPredefinedActionMaxWindow Action does not seem to set the height to the full value and BTTPredefinedActionRestoreOldWindowSize has no value.
It is therefore better to trigger "Option + Click" on the green button directly:
tell application "System Events"
perform action "AXZoomWindow" of (first button whose subrole is "AXFullScreenButton") of (first window whose subrole is "AXStandardWindow") of (first process whose frontmost is true)
end tell
Thank you very much, I don't think I would have been able to create this script myself.
But currently it does not take into account the dock. For the height <=1 should be <=dockHeight. I could hardcode the value, but I'm not sure if it will be the same for all external monitors.
But maybe we can assume that if the window width fills the screen and the height is only like 50px off, then the intention was that it's maximized.
FYI: AXZoomWindow does not maximize windows (usually it does, but every app can decide itself. Finder for example does not maximize). If you just want the AXZoomWindow function you can achieve that without Apple Script by changing the zoom button click to an option click:
Hmmm...
Maybe it does take the dock into account. I'm currently using uBar and it does not take that one into account. So I assumed that it would not work with the default dock either.
Maybe I'll make it a bit more general by detecting uBar and setting the tolerance based on that.
Modifying the green button to always be Zoom is not suitable for me, I'd like it to act as a Maximize/Minimize toggle button. Dirk's script works for that.
Thanks again for the help.
I just got to trying Dirk's script with external displays. It seems like the activeScreenVisibleFrame returns the internal display's frame regardless of where are the application window (and which menu bar is highlighted). But after a while it starts to work correctly. Maybe some internal apple script stuff takes some time to update or it's just not deterministic.
In my case, mainScreen always returns the screen with the foreground window that has the focus. Possibly the focus (active screen) is not yet set during the script execution (at the time of clicking the green button).
unfortunately that function has been buggy for years. It should return the screen with the focused window, but it often does not. That's why I have stopped using it long ago ;-(
I don't know the exact scenarios when it doesn't work, but there have been multiple.
I think it might be related to how keyboard focus does not always mean window focus, but I haven't bothered to look into the details.
I use the script below currently, it works (triggered by green button click). But even this is not consistent. Sometimes it refuses to do anything and only works after I resize the window. From that point it's consistent. I will continue to use it and experiment with it, but for maximising I mostly just use the default snapping to top behavior, it works every time.
use framework "Foundation"
use framework "AppKit"
property ca : current application
tell application "System Events"
set currentAppName to name of first application process whose frontmost is true
tell application process currentAppName
set activeWindowSize to (size of window 1)
end tell
end tell
set heightOffset to 100
tell application "BetterTouchTool"
set activeScreenWidth to get_number_variable "mouse_screen_width"
set activeScreenHeight to get_number_variable "mouse_screen_height"
set isMaximized to (activeScreenWidth - (item 1 of activeWindowSize) ≤ 1 and activeScreenHeight - (item 2 of activeWindowSize) ≤ heightOffset)
if isMaximized then
trigger_action "{\"BTTPredefinedActionType\":84}"
else
trigger_action "{\"BTTPredefinedActionType\":21}"
end if
end tell
In my opinion, this is not due to Maximized-detection. in this case, there is no value for the Restore function. You can test this by running the following script with a shortcut in this case:
tell application "BetterTouchTool"
trigger_action "{\"BTTPredefinedActionType\":84}"
end tell
Tip: In your script you do not need these lines (no ASObjC used):
use framework "Foundation"
use framework "AppKit"
property ca : current application
PS:
get_number_variable "mouse_screen_width" or get_number_variable "mouse_screen_height"
returns "missing value" for me
(BTT-Version 3.954)