Position window at largest unused space

Before I attempt this from scratch I would like to know if it has been done already or if anyone has any good ideas. Is there a way of positioning a new window in the largest free space on the screen?

I would imagine it would involve:

  1. Get the dimensions of the screen
  2. Get the size and position of every open window
  3. Math
  4. Create new window in “ideal” location.

Nigel Garvey and DJ Bazzie Wazzie have made great contributions to solving this problem in this thread : http://macscripter.net/viewtopic.php?id=40137

I was thinking of something like this to get the bounds of every window:


set theBounds to {}

tell application "System Events" to set theApps to name of every application process whose visible = true
repeat with anApp in theApps
	tell application anApp
		try
			set appWindows to its every window
			repeat with aWindow in appWindows
				set end of theBounds to aWindow's bounds
			end repeat
		end try
	end tell
end repeat

Let’s first do it with a pen and paper, to understand.

  1. Draw some rectangles with different sizes on a piece of paper with some overlap to other rectangle(s) allowed.
  2. Now extend the lines of the rectangle to ends of the paper so you’re seeing a grid with all kind of different size cells.
  3. Now mark the cells that are overlapped/inside the initially drawn rectangles in step 1.
  4. At last try to find the biggest rectangle by using only non-marked (marked in step 3) rectangles.

When we do it by hand we find in a very few steps the largest rectangle because we don’t think/work in pixels but in rectangles right away. The same approach should be used here, now you don’t have grid of 1920 x 1200 but only a grid with a few to a hundred cells instead of millions.

The technique to find the biggest cell can be done with some minor modifications to Nigel’s brute force script. Note: You need to sum up the sizes of the cells in the grid because they are different. To save yourself some unnecessary calculation time you can remove the rectangles first that fits inside another rectangle (or couple of rectangles) as the first step.

Also another thing is that the menu bar is 22 pixels in height and the dock (when is set to permanently up) should be considered as used space as well.

Change the repeat with theWindow in every window of process “AppleScript Editor” into repeat with the window in every window of every process.

Here an better version:

set ymin to 22 --height of system menu, retina or not it is always 22 pixels
set xmin to 0 ----you could subtract height of dock from ymax if it is permanent visible

tell application "Finder"
	tell bounds of window of the desktop as list to set {xmax, ymax} to {item 3, item 4}
end tell

set windowRects to {} --the array where are used rectangles are in (windows)
set columnOffsets to {xmin, xmax} --already add the boundaries in it
set rowOffsets to {ymin, ymax} -- already add the boundaries in it

--fill the windowRects array with the rectangles of the windows. Also fill in the grid lines 
tell application "System Events"
	repeat with theWindow in (every window of process "AppleScript Editor" whose value of its attribute "AXMinimized" is false) --change this line to whatever group of UI elements you want
		set s to theWindow's size
		set l to theWindow's position
		
		tell (item 1 of l)
			if it is not in columnOffsets and it > xmin and it < xmax then set end of columnOffsets to it
		end tell
		tell (item 1 of l) + (item 1 of s)
			if it is not in columnOffsets and it > xmin and it < xmax then set end of columnOffsets to it
		end tell
		tell (item 2 of l)
			if it is not in rowOffsets and it > ymin and it < ymax then set end of rowOffsets to it
		end tell
		tell (item 2 of l) + (item 2 of s)
			if it is not in rowOffsets and it > ymin and it < ymax then set end of rowOffsets to it
		end tell
		
		set end of windowRects to my newRect(item 1 of l, item 2 of l, (item 1 of s) + (item 1 of l), (item 2 of s) + (item 2 of l))
	end repeat
end tell

--sort the grid lines from low to high. This needed to build up a grid where the index actually matches the rectangles
set rowOffsets to bubblesort(rowOffsets)
set columnOffsets to bubblesort(columnOffsets)

--now build the grid with the rectangles 
set b to item 1 of rowOffsets
set gridView to {}
repeat with h from 1 to (count rowOffsets) - 1
	set thisRow to {}
	set a to item 1 of columnOffsets
	set y to item (h + 1) of rowOffsets
	repeat with v from 1 to (count columnOffsets) - 1
		set x to item (v + 1) of columnOffsets
		set theRect to newRect(a, b, x, y)
		repeat with usedRect in windowRects
			--check if this rectangles is in a used spot or not. 
			if theRect's location's xpos ≥ usedRect's location's xpos then
				if theRect's location's ypos ≥ usedRect's location's ypos then
					if theRect's endpoint's xpos ≤ usedRect's endpoint's xpos then
						if theRect's endpoint's ypos ≤ usedRect's endpoint's ypos then
							set theRect's inUse to true
						end if
					end if
				end if
			end if
		end repeat
		set end of thisRow to theRect
		set a to x
	end repeat
	set b to y
	set end of gridView to thisRow
end repeat

--now we have a grid we can start looking for the biggest rectangle the brute force way
set bigRect to newRect(0, 0, 0, 0)
repeat with a from 1 to count gridView
	repeat with b from 1 to count item 1 of gridView
		set currentRect to newRect(0, 0, 0, 0)
		set maxWidth to (count item 1 of gridView) - b + 2
		set location of currentRect to location of item b of item a of gridView
		set endpoint of currentRect to endpoint of item b of item a of gridView
		repeat with x from a to count gridView
			repeat with y from b to count item 1 of gridView
				log bigRect
				if inUse of item y of item x of gridView or y = maxWidth then
					set maxWidth to y
					exit repeat
				end if
				set currentRect's endpoint to endpoint of item y of item x of gridView
				if getSizeFromRect(currentRect) > getSizeFromRect(bigRect) then copy currentRect to bigRect
			end repeat
		end repeat
	end repeat
end repeat

--just for the show create the a new window in the biggest largest available rectangle on you screen.
tell bigRect to set {a, b, x, y} to {it's location's xpos, it's location's ypos, it's endpoint's xpos, it's endpoint's ypos}
tell application "AppleScript Editor"
	set theDoc to make new document
	tell theDoc's window to set it's bounds to {a, b, x, y}
end tell

--return the biggest avilable rectangle.
return bigRect

on newPoint(x, y)
	return {xpos:x, ypos:y}
end newPoint

on newRect(x, y, h, w)
	return {location:newPoint(x, y), endpoint:newPoint(h, w), inUse:false}
end newRect

on getSizeFromRect(rect)
	tell rect
		return ((it's endpoint's xpos) - (it's location's xpos)) * ((it's endpoint's ypos) - (it's location's ypos))
	end tell
end getSizeFromRect

on bubblesort(theList)
	script o
		property lst : theList
	end script
	
	repeat with i from (count theList) to 2 by -1
		set a to beginning of o's lst
		repeat with j from 2 to i
			set b to item j of o's lst
			if (a > b) then
				set item (j - 1) of o's lst to b
				set item j of o's lst to a
			else
				set a to b
			end if
		end repeat
	end repeat
	return o's lst
end bubblesort

Thanks DJ.

tell application "System Events"
	set theApps to every window of every application process
end tell

→ System Events got an error: Access for assistive devices is disabled.

However, Access for assistive devices is NOT disabled

This works most of the time… although I can’t pinpoint what makes it fail…


set ymin to 22 --height of system menu, retina or not it is always 22 pixels
set xmin to 0 ----you could subtract height of dock from ymax if it is permanent visible

tell application "Finder"
	tell bounds of window of the desktop as list to set {xmax, ymax} to {item 3, item 4}
end tell

set windowRects to {} --the array where are used rectangles are in (windows)
set columnOffsets to {xmin, xmax} --already add the boundaries in it
set rowOffsets to {ymin, ymax} -- already add the boundaries in it

--adayzdone
set myWindows to {}
tell application "System Events"
	set theApps to every application process whose visible = true
	repeat with anApp in theApps
		set appWindows to every window of anApp
		repeat with aWindow in appWindows
			set end of myWindows to contents of aWindow
		end repeat
	end repeat
end tell

--fill the windowRects array with the rectangles of the windows. Also fill in the grid lines
tell application "System Events"
	repeat with theWindow in myWindows
		set s to theWindow's size
		set l to theWindow's position
		
		tell (item 1 of l)
			if it is not in columnOffsets and it > xmin and it < xmax then set end of columnOffsets to it
		end tell
		tell (item 1 of l) + (item 1 of s)
			if it is not in columnOffsets and it > xmin and it < xmax then set end of columnOffsets to it
		end tell
		tell (item 2 of l)
			if it is not in rowOffsets and it > ymin and it < ymax then set end of rowOffsets to it
		end tell
		tell (item 2 of l) + (item 2 of s)
			if it is not in rowOffsets and it > ymin and it < ymax then set end of rowOffsets to it
		end tell
		
		set end of windowRects to my newRect(item 1 of l, item 2 of l, (item 1 of s) + (item 1 of l), (item 2 of s) + (item 2 of l))
		
	end repeat
end tell

--sort the grid lines from low to high. This needed to build up a grid where the index actually matches the rectangles
set rowOffsets to bubblesort(rowOffsets)
set columnOffsets to bubblesort(columnOffsets)

--now build the grid with the rectangles
set b to item 1 of rowOffsets
set gridView to {}
repeat with h from 1 to (count rowOffsets) - 1
	set thisRow to {}
	set a to item 1 of columnOffsets
	set y to item (h + 1) of rowOffsets
	repeat with v from 1 to (count columnOffsets) - 1
		set x to item (v + 1) of columnOffsets
		set theRect to newRect(a, b, x, y)
		repeat with usedRect in windowRects
			--check if this rectangles is in a used spot or not.
			if theRect's location's xpos ≥ usedRect's location's xpos then
				if theRect's location's ypos ≥ usedRect's location's ypos then
					if theRect's endpoint's xpos ≤ usedRect's endpoint's xpos then
						if theRect's endpoint's ypos ≤ usedRect's endpoint's ypos then
							set theRect's inUse to true
						end if
					end if
				end if
			end if
		end repeat
		set end of thisRow to theRect
		set a to x
	end repeat
	set b to y
	set end of gridView to thisRow
end repeat

--now we have a grid we can start looking for the biggest rectangle the brute force way
set bigRect to newRect(0, 0, 0, 0)
repeat with a from 1 to count gridView
	repeat with b from 1 to count item 1 of gridView
		set currentRect to newRect(0, 0, 0, 0)
		set maxWidth to (count item 1 of gridView) - b + 2
		set location of currentRect to location of item b of item a of gridView
		set endpoint of currentRect to endpoint of item b of item a of gridView
		repeat with x from a to count gridView
			repeat with y from b to count item 1 of gridView
				log bigRect
				if inUse of item y of item x of gridView or y = maxWidth then
					set maxWidth to y
					exit repeat
				end if
				set currentRect's endpoint to endpoint of item y of item x of gridView
				if getSizeFromRect(currentRect) > getSizeFromRect(bigRect) then set bigRect to currentRect
			end repeat
		end repeat
	end repeat
end repeat

--just for the show create the a new window in the biggest largest available rectangle on you screen.
tell bigRect to set {a, b, x, y} to {it's location's xpos, it's location's ypos, it's endpoint's xpos, it's endpoint's ypos}
tell application "AppleScript Editor"
	set theDoc to make new document
	tell theDoc's window to set it's bounds to {a, b, x, y}
end tell

--return the biggest avilable rectangle.
return bigRect

on newPoint(x, y)
	return {xpos:x, ypos:y}
end newPoint

on newRect(x, y, h, w)
	return {location:newPoint(x, y), endpoint:newPoint(h, w), inUse:false}
end newRect

on getSizeFromRect(rect)
	tell rect
		return ((it's endpoint's xpos) - (it's location's xpos)) * ((it's endpoint's ypos) - (it's location's ypos))
	end tell
end getSizeFromRect

on bubblesort(theList)
	script o
		property lst : theList
	end script
	
	repeat with i from (count theList) to 2 by -1
		set a to beginning of o's lst
		repeat with j from 2 to i
			set b to item j of o's lst
			if (a > b) then
				set item (j - 1) of o's lst to b
				set item j of o's lst to a
			else
				set a to b
			end if
		end repeat
	end repeat
	return o's lst
end bubblesort

This does not completely fill the empty space:

Weird, that code runs perfectly fine on my machine (behind an SL at the moment). Too bad because the code is easy adjustable and works smooth (fast) so I don’t know how to help you further from this point because the error doesn’t seems to be syntax related.

edit
: code above working now. It should copy the record to bigrect instead of setting it.

I think I found the problem. The script was still treating minimized windows as if they were visible and excluding the space they “should have” used. Thanks for the time guys!

FWIW, here’s a different approach. It involves subtracting each window from a list of available rectangles, returning the remaining free rectangles.

I’ve used ASObjC Runner for the screen to take into account the Dock and menu bar. I’ve also set minimum values for a space to be considered viable.

set xMin to 200 -- ignore if width is below this
set yMin to 200 -- ignore if height is below this

-- get screen size (ignore secondary screens)
tell application id "au.com.myriad-com.ASObjC-Runner" -- ASObjC Runner.app
	set {theWidth, theHeight} to usable dimensions of screen 1
	set {x1, y1} to usable offset of screen 1
end tell
set usableBounds to {x1, y1, x1 + theWidth, y1 + theHeight}
set availableRects to {usableBounds}

set existingWindows to {}
tell application "System Events"
	repeat with theWindow in every window of process "AppleScript Editor" --change this line to whatever group of UI elements you want
		set {theWidth, theHeight} to theWindow's size
		set {x1, y1} to theWindow's position
		set end of existingWindows to {x1, y1, x1 + theWidth, y1 + theHeight}
	end repeat
end tell

repeat with i from 1 to count of existingWindows
	set newList to {}
	repeat with j from 1 to count of availableRects
		set m to item j of availableRects
		set n to item i of existingWindows
		set newList to newList & subtractArea_from_(n, m)
	end repeat
	copy checkSize(xMin, yMin, newList) to availableRects -- remove any that are too small
end repeat

set theBounds to findBiggest(availableRects)
if theBounds = missing value then
	display dialog "Not enough room left."
else
	tell application "AppleScript Editor"
		set theDoc to make new document
		tell theDoc's window to set it's bounds to theBounds
	end tell
end if

on subtractArea_from_({xMinus1, yMinus1, xMinus2, yMinus2}, {x1, y1, x2, y2})
	if xMinus1 > x2 or xMinus2 < x1 or yMinus1 > y2 or yMinus2 < y1 then
		-- rects don't intersect, so return full area in list
		return {{x1, y1, x2, y2}}
	end if
	set theResult to {}
	if xMinus1 > x1 and xMinus1 < x2 then
		set end of theResult to {x1, y1, xMinus1, y2}
	end if
	if xMinus2 < x2 and xMinus2 > x1 then
		set end of theResult to {xMinus2, y1, x2, y2}
	end if
	if yMinus1 > y1 and yMinus1 < y2 then
		set end of theResult to {x1, y1, x2, yMinus1}
	end if
	if yMinus2 < y2 and yMinus2 > y1 then
		set end of theResult to {x1, yMinus2, x2, y2}
	end if
	return theResult
end subtractArea_from_

on checkSize(xMin, yMin, newList) -- remove any rects that are too small
	set newerList to {}
	repeat with i from 1 to count of newList
		set oneValue to item i of newList
		if (item 3 of oneValue) - (item 1 of oneValue) > xMin and (item 4 of oneValue) - (item 2 of oneValue) > yMin then
			set end of newerList to oneValue
		end if
	end repeat
	return newerList
end checkSize

on findBiggest(newList)
	local oneValue, theArea, maxArea, maxValue
	set maxArea to 0
	set maxValue to missing value
	repeat with i from 1 to count of newList
		set oneValue to item i of newList
		set theArea to ((item 3 of oneValue) - (item 1 of oneValue)) * ((item 4 of oneValue) - (item 2 of oneValue))
		if theArea > maxArea then
			set maxArea to theArea
			set maxValue to oneValue
		end if
	end repeat
	return maxValue
end findBiggest

The problem you mention in your screenshot was because bigrect was a reference to currentrect. currentrect is a variable that keeps expanding it’s range until it fails and will be compared with bigrect (self). I haven’t noticed this because when there is a window in the upper left corner of your screen there is no problem. So to avoid this I’ve replaced the setter for bigrect with a copy command so it’s no longer a reference but an object on it’s own, which I thought it was from the beginning.

I’ve changed the code above so it will ignore miniaturized windows (like i said you can easily change the repeat in system events).

These two versions should take into account windows from all applications and not consider those that are minimized. Thank you Nigel Garvey, DJ Bazzie Wazzie, and Shane Stanley for a great resource!

DJ Bazzie Wazzie’s modified script:

set ymin to 22 --height of system menu, retina or not it is always 22 pixels
set xmin to 0 ----you could subtract height of dock from ymax if it is permanent visible

tell application "Finder"
	tell bounds of window of the desktop as list to set {xmax, ymax} to {item 3, item 4}
end tell

set windowRects to {} --the array where are used rectangles are in (windows)
set columnOffsets to {xmin, xmax} --already add the boundaries in it
set rowOffsets to {ymin, ymax} -- already add the boundaries in it

-- adayzdone
set myWindows to {}
tell application "System Events"
	set theWindows to (every window of (every process whose visible is true) whose value of its attribute "AXMinimized" is false)
	repeat with aWindow in theWindows
		if contents of aWindow ≠ {} then set myWindows to myWindows & contents of aWindow
	end repeat
end tell

--fill the windowRects array with the rectangles of the windows. Also fill in the grid lines
tell application "System Events"
	repeat with theWindow in myWindows
		set s to theWindow's size
		set l to theWindow's position
		
		tell (item 1 of l)
			if it is not in columnOffsets and it > xmin and it < xmax then set end of columnOffsets to it
		end tell
		tell (item 1 of l) + (item 1 of s)
			if it is not in columnOffsets and it > xmin and it < xmax then set end of columnOffsets to it
		end tell
		tell (item 2 of l)
			if it is not in rowOffsets and it > ymin and it < ymax then set end of rowOffsets to it
		end tell
		tell (item 2 of l) + (item 2 of s)
			if it is not in rowOffsets and it > ymin and it < ymax then set end of rowOffsets to it
		end tell
		
		set end of windowRects to my newRect(item 1 of l, item 2 of l, (item 1 of s) + (item 1 of l), (item 2 of s) + (item 2 of l))
	end repeat
end tell

--sort the grid lines from low to high. This needed to build up a grid where the index actually matches the rectangles
set rowOffsets to bubblesort(rowOffsets)
set columnOffsets to bubblesort(columnOffsets)

--now build the grid with the rectangles
set b to item 1 of rowOffsets
set gridView to {}
repeat with h from 1 to (count rowOffsets) - 1
	set thisRow to {}
	set a to item 1 of columnOffsets
	set y to item (h + 1) of rowOffsets
	repeat with v from 1 to (count columnOffsets) - 1
		set x to item (v + 1) of columnOffsets
		set theRect to newRect(a, b, x, y)
		repeat with usedRect in windowRects
			--check if this rectangles is in a used spot or not.
			if theRect's location's xpos ≥ usedRect's location's xpos then
				if theRect's location's ypos ≥ usedRect's location's ypos then
					if theRect's endpoint's xpos ≤ usedRect's endpoint's xpos then
						if theRect's endpoint's ypos ≤ usedRect's endpoint's ypos then
							set theRect's inUse to true
						end if
					end if
				end if
			end if
		end repeat
		set end of thisRow to theRect
		set a to x
	end repeat
	set b to y
	set end of gridView to thisRow
end repeat

--now we have a grid we can start looking for the biggest rectangle the brute force way
set bigRect to newRect(0, 0, 0, 0)
repeat with a from 1 to count gridView
	repeat with b from 1 to count item 1 of gridView
		set currentRect to newRect(0, 0, 0, 0)
		set maxWidth to (count item 1 of gridView) - b + 2
		set location of currentRect to location of item b of item a of gridView
		set endpoint of currentRect to endpoint of item b of item a of gridView
		repeat with x from a to count gridView
			repeat with y from b to count item 1 of gridView
				log bigRect
				if inUse of item y of item x of gridView or y = maxWidth then
					set maxWidth to y
					exit repeat
				end if
				set currentRect's endpoint to endpoint of item y of item x of gridView
				if getSizeFromRect(currentRect) > getSizeFromRect(bigRect) then copy currentRect to bigRect
			end repeat
		end repeat
	end repeat
end repeat

--just for the show create the a new window in the biggest largest available rectangle on you screen.
tell bigRect to set {a, b, x, y} to {it's location's xpos, it's location's ypos, it's endpoint's xpos, it's endpoint's ypos}
tell application "AppleScript Editor"
	set theDoc to make new document
	tell theDoc's window to set it's bounds to {a, b, x, y}
end tell

--return the biggest avilable rectangle.
return bigRect

on newPoint(x, y)
	return {xpos:x, ypos:y}
end newPoint

on newRect(x, y, h, w)
	return {location:newPoint(x, y), endpoint:newPoint(h, w), inUse:false}
end newRect

on getSizeFromRect(rect)
	tell rect
		return ((it's endpoint's xpos) - (it's location's xpos)) * ((it's endpoint's ypos) - (it's location's ypos))
	end tell
end getSizeFromRect

on bubblesort(theList)
	script o
		property lst : theList
	end script
	
	repeat with i from (count theList) to 2 by -1
		set a to beginning of o's lst
		repeat with j from 2 to i
			set b to item j of o's lst
			if (a > b) then
				set item (j - 1) of o's lst to b
				set item j of o's lst to a
			else
				set a to b
			end if
		end repeat
	end repeat
	return o's lst
end bubblesort

Shane Stanley’s modified script:

set xMin to 200 -- ignore if width is below this
set yMin to 200 -- ignore if height is below this

-- get screen size (ignore secondary screens)
tell application id "au.com.myriad-com.ASObjC-Runner" -- ASObjC Runner.app
	set {theWidth, theHeight} to usable dimensions of screen 1
	set {x1, y1} to usable offset of screen 1
end tell
set usableBounds to {x1, y1, x1 + theWidth, y1 + theHeight}
set availableRects to {usableBounds}

-- adayzdone
set myWindows to {}
tell application "System Events"
	set theWindows to (every window of (every process whose visible is true) whose value of its attribute "AXMinimized" is false)
	repeat with aWindow in theWindows
		if contents of aWindow ≠ {} then set myWindows to myWindows & contents of aWindow
	end repeat
end tell

set existingWindows to {}
tell application "System Events"
	repeat with theWindow in myWindows
		set {theWidth, theHeight} to theWindow's size
		set {x1, y1} to theWindow's position
		set end of existingWindows to {x1, y1, x1 + theWidth, y1 + theHeight}
	end repeat
end tell

repeat with i from 1 to count of existingWindows
	set newList to {}
	repeat with j from 1 to count of availableRects
		set m to item j of availableRects
		set n to item i of existingWindows
		set newList to newList & subtractArea_from_(n, m)
	end repeat
	copy checkSize(xMin, yMin, newList) to availableRects -- remove any that are too small
end repeat

set theBounds to findBiggest(availableRects)
if theBounds = missing value then
	display dialog "Not enough room left."
else
	tell application "AppleScript Editor"
		set theDoc to make new document
		tell theDoc's window to set it's bounds to theBounds
	end tell
end if

on subtractArea_from_({xMinus1, yMinus1, xMinus2, yMinus2}, {x1, y1, x2, y2})
	if xMinus1 > x2 or xMinus2 < x1 or yMinus1 > y2 or yMinus2 < y1 then
		-- rects don't intersect, so return full area in list
		return {{x1, y1, x2, y2}}
	end if
	set theResult to {}
	if xMinus1 > x1 and xMinus1 < x2 then
		set end of theResult to {x1, y1, xMinus1, y2}
	end if
	if xMinus2 < x2 and xMinus2 > x1 then
		set end of theResult to {xMinus2, y1, x2, y2}
	end if
	if yMinus1 > y1 and yMinus1 < y2 then
		set end of theResult to {x1, y1, x2, yMinus1}
	end if
	if yMinus2 < y2 and yMinus2 > y1 then
		set end of theResult to {x1, yMinus2, x2, y2}
	end if
	return theResult
end subtractArea_from_

on checkSize(xMin, yMin, newList) -- remove any rects that are too small
	set newerList to {}
	repeat with i from 1 to count of newList
		set oneValue to item i of newList
		if (item 3 of oneValue) - (item 1 of oneValue) > xMin and (item 4 of oneValue) - (item 2 of oneValue) > yMin then
			set end of newerList to oneValue
		end if
	end repeat
	return newerList
end checkSize

on findBiggest(newList)
	local oneValue, theArea, maxArea, maxValue
	set maxArea to 0
	set maxValue to missing value
	repeat with i from 1 to count of newList
		set oneValue to item i of newList
		set theArea to ((item 3 of oneValue) - (item 1 of oneValue)) * ((item 4 of oneValue) - (item 2 of oneValue))
		if theArea > maxArea then
			set maxArea to theArea
			set maxValue to oneValue
		end if
	end repeat
	return maxValue
end findBiggest

A great extension of this thread would be how to deal with instances when the empty space is too small to be considered viable. Shane uses 200x200.

What is the best way of resizing and positioning all non-minimized windows that keeps each as close to its original size and position, yet makes room for a new window of at least the minimum size ? Nigel, please let me know if this would be best in its own thread.

Well I think you can take a look here.