Get active window size and screen size

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

Hi Dirk,

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.

In my case it works with and without dock and also on external dsplays:


(I had maximized it by double-clicking on the title bar. The BTT function does not always zoom it to the maximum).

But the second script is better, because it uses the system internal AXZoomWindow function.

NSScreen's mainScreen()'s visibleFrame()

Takes into account the dock. (see the first image):

image

But with this line you should get the height of the dock:

set dockHeight to item 2 of item 1 of activeScreenVisibleFrame as integer
--> 49

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:

1 Like

Good idea :+1:

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.

mainScreen doesn't return the active screen unfortunately.

BTT has some variables that you could use via the get_number_variable function (but these return the full frame, not excluding the dock):

image

In my case, mainScreen always returns the screen with the foreground window that has the focus. :thinking: Possibly the focus (active screen) is not yet set during the script execution (at the time of clicking the green button).

See: Apple Developer Documentation

But the restore function sometimes moves the window to the previous screen. (MacBook Pro + 2 Thunderbolt Display)

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.

You are right. Switching the screen also seems to happen with some delay, so you can't rely on it. At least not if you react to a mouse click event.

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)