Monday, August 26, 2019

#1 2018-07-06 08:33:51 am

daBee
Member
Registered: 2010-02-09
Posts: 105

Window Dimensions

Hi folks.

Just wondering what is the most convenient/best way to get window dimensions to put into my scripts.  I often work with browser windows that I want to put on a specific monitor (I have 4 on my Mac Pro), with dimensions and location.  Here's an example:

Applescript:

tell application "Google Chrome"
   activate
   set myw1 to (make new window)
   set the URL of tab 1 of myw1 to "http://hq.local"
   set bounds of myw1 to {1, 1, 1140, 1600}
end tell

It's a bit of a task getting those dimensions (I don't always use {1,1} as a TL corner), then setting the proper width, etc., without trial and error. 

Is there a better way?  I'm sure someone has a tip.  Fully appreciated. 

Cheers


Filed under: window, dimensions

Offline

 

#2 2018-07-08 04:45:59 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4950

Re: Window Dimensions

If you're looking for the usable bounds of all your screens and are running Yosemite or later, the current wisdom would be to use something like this. It returns a list of records, each record containing an ID number and the usable bounds for a screen ("usable" meaning not impinging on the menu bar or Dock). I only have one screen per computer myself, so apologies if I've failed to allow for anything.

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

-- Get the usable bounds of all attached screens, avoiding the menu bar and Dock.
on getUsableScreenBounds()
   set |⌘| to current application
   
   set theResult to {}
   set theScreens to |⌘|'s class "NSScreen"'s screens()
   repeat with thisScreen in theScreens
       set screenID to ((thisScreen's deviceDescription())'s valueForKey:("NSScreenNumber")) as integer
       set wholeFrame to thisScreen's frame()
       set visibleFrame to thisScreen's visibleFrame()
       
       -- In High Sierra, the frame rects are returned as lists instead of records, but the functions below work with either.
       set x1 to (|⌘|'s NSMinX(visibleFrame)) as integer
       -- The y origin in NSScreen is at the bottom of the screen. It needs to be converted to an origin at the top for AS.
       set y1 to ((|⌘|'s NSMaxY(wholeFrame)) - (|⌘|'s NSMaxY(visibleFrame))) as integer
       set x2 to (|⌘|'s NSMaxX(visibleFrame)) as integer
       set y2 to (y1 + (|⌘|'s NSHeight(visibleFrame))) as integer
       set end of theResult to {screenID:screenID, usableBounds:{x1, y1, x2, y2}}
   end repeat
   
   return theResult
end getUsableScreenBounds

getUsableScreenBounds()
--> {{screenID:69981780, usableBounds:{0, 23, 2560, 1440}}}


NG

Offline

 

#3 2018-07-14 03:09:53 am

daBee
Member
Registered: 2010-02-09
Posts: 105

Re: Window Dimensions

Thanks for the post. 

Ya I was thinking something more pragmatic, like a third party app of some sort. 

Now I'm just trying to copy the "measure first Chrome window's bounds" to the clipboard.

Offline

 

#4 2018-08-07 03:19:15 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 411

Re: Window Dimensions

I'm confused about what exactly you're looking for, and I'm not clear if Nigel's answer helped. It sounded to me more like you were trying to get the current bounds of the Chrome Window?

Applescript:


tell application "System Events"
   tell application process "Google Chrome"
       set frontmost to true
       set currentWindow to window 1
       set windowPositon to the position of currentWindow
       set windowSize to the size of currentWindow
   end tell
end tell


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#5 2018-08-14 01:06:53 pm

seanmurp
Member
Registered: 2018-08-14
Posts: 4

Re: Window Dimensions

Here is a little script you could use for getting the bounds of all Chrome windows.  Set the windows up on screen as you want them positioned and it will output a dialog with the name of the window and its bound values.  You could then copy those out to your script.

Applescript:

set dimensionsList to {}
tell application "Google Chrome"
   set windowList to every window
   repeat with win in windowList
       tell application "System Events"
           tell application process "Google Chrome"
               set frontmost to true
               set tabName to name of win
               set windowPosition to the bounds of win
               set lastBound to item 4 of windowPosition as text
               set boundList to ""
               repeat with a in windowPosition
                   set thisBound to a as text
                   if thisBound is not equal to lastBound then
                       set boundList to boundList & thisBound & ", " as text
                   else
                       set boundList to boundList & thisBound as text
                   end if
               end repeat
               set end of dimensionsList to {tabName, boundList}
           end tell
       end tell
   end repeat
   
   set dialogText to ""
   repeat with b in dimensionsList
       set windowName to item 1 of b as text
       set windowBounds to item 2 of b as text
       set dialogText to dialogText & "Window Name: " & windowName & return & "Window Bounds: " & windowBounds & return & return
   end repeat
   
   display dialog dialogText buttons {"Cancel", "OK"} default button "OK"
end tell

If you don't need it in dialog format and just want to read the values returned then you can eliminate the portion from "set dialogText to""" down.

Offline

 

#6 2019-01-22 04:55:35 pm

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Nigel;

Could you provide a short code snippet to illustrate how you intended your posted getUsableScreenBounds() routine to be used? I have two screens and would like to be able to resize application windows that I've opened on either monitor.

Offline

 

#7 2019-01-23 04:17:13 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4950

Re: Window Dimensions

Hi GG.

I've only ever had one screen attached to any of my computers, so I wrote the handler in the hope that it would be useful to those with more than one!

It returns a list of records, each record corresponding to a screen and having screenID and usableBounds properties. With my one screen, there's only one record and I don't need to know the screen's ID. I can simply get its usable bounds like this:

Applescript:

set screensInfo to getUsableScreenBounds()
set usableBounds to usableBounds of item 1 of screensInfo
--> {0, 23, 2560, 1440} for my screen.

With more than one screen, you'd need to know or be able to find out the ID(s) of the screen(s) of interest and loop through the list to find the relevant record(s). Obviously the exact form of the search and what it returned would depend on how many screens' bounds you needed to know, but for a particular screen:

Applescript:

set myScreenID to 69981780 -- Or whatever. You'd need to know this or find it out.
set screensInfo to getUsableScreenBounds()

repeat with thisScreen in screensInfo
   if (thisScreen's screenID is myScreenID) then
       set usableBounds to thisScreen's usableBounds
       exit repeat
   end if
end repeat
usableBounds
--> {0, 23, 2560, 1440} for my screen.

It's possible, with a different handler, to get the information specifically for the "main" screen, which is described in the Xcode documentation as "the screen object containing the window with the keyboard focus."

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

on getMainScreenUsableBounds()
   set |⌘| to current application
   
   set mainScreen to |⌘|'s class "NSScreen"'s mainScreen()
   
   set wholeFrame to mainScreen's frame()
   set visibleFrame to mainScreen's visibleFrame()
   
   -- In High Sierra, the frame rects are returned as lists instead of records, but the functions below work with either.
   set x1 to (|⌘|'s NSMinX(visibleFrame)) as integer
   -- The y origin in NSScreen is at the bottom of the screen. It needs to be converted to an origin at the top for AS.
   set y1 to ((|⌘|'s NSMaxY(wholeFrame)) - (|⌘|'s NSMaxY(visibleFrame))) as integer
   set x2 to (|⌘|'s NSMaxX(visibleFrame)) as integer
   set y2 to (y1 + (|⌘|'s NSHeight(visibleFrame))) as integer
   
   return {x1, y1, x2, y2}
end getMainScreenUsableBounds

getMainScreenUsableBounds()
--> {0, 23, 2560, 1440}


NG

Offline

 

#8 2019-01-23 02:38:37 pm

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Thank you both. The project is now starting to come together.

Offline

 

#9 2019-01-23 05:04:03 pm

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Nigel;

The routine for getting the usable bounds of the primary monitor is working for a multi-monitor configuration may not be working.

I'm getting the following returned:   {-254, 23, 833.0, 540.0}

My primary desktop is my MacBook Pro (Retina) and my secondary screen is a 27 inch Dell monitor. I don't have the screens mirrored, which may be an issue. (I'm also running Mojave).

I think the routine may be seeing the bounds differently in a multi-monitor setup. The following article seems to shed some light on this:

https://daringfireball.net/2006/12/disp … e_lazy_way

Last edited by GG (2019-01-23 05:17:57 pm)

Offline

 

#10 2019-01-23 06:45:31 pm

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Did a bit of reading on the subject of the monitor bounds, then checked it out.

The getMainScreenUsableBounds() routine (as written) will give you the bounds for the screen that has keyboard focus.

When I run it from my built-in retina screen, I get {0, 23, 720.0, 430.0} and get {-254, 23, 833.0, 540.0} from my external (27" Dell) screen. I get a negative for the first item of the secondary monitor, because my screen is in extended vertically, rather than being in mirrored mode. It seems as if the system looks at my two monitors as one big rectangular workspace with a "dead zone" on either side of the smaller (lower) monitor. (By the way; this would explain why the cursor can get hung up in the dead zones. It's a heck of a thing to get it freed up.)

Sounds like there may be a bit more programming needed to use getMainScreenUsableBounds() and have it work as expected.

I think that the equations (that flip the coordinates) need to be adjusted, if there are two monitors detected in "extended workspace" mode. The adjustments would also need to take into account how the monitors are arranged. The end result would be that the whole workspace would look like one big screen and have one set of coordinates. If the monitors are mirrored, I believe the primary (built-in) monitor takes precedence and it just looks like a one monitor system.

A last important thing to keep in mind... While the system might look at the two monitors as one big workspace, it will only display things properly if the whole window is on one monitor or the other.

Offline

 

#11 2019-01-24 04:18:37 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4950

Re: Window Dimensions

GG wrote:

I'm getting the following returned:   {-254, 23, 833.0, 540.0}


There's something strange going on there. My handlers explicitly coerce all the numbers to integer, so there shouldn't be any reals in the list. Have you altered any of the code?

Apart from that, as I've said above, I only have one monitor attached to my computer and can't really help with any vagaries in multiple-screen situations.


NG

Offline

 

#12 2019-01-24 07:43:10 am

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Sorry about that Nigel. The last two items are the subroutine results divided by 2, so they may have come out as non-integer.

I think I can figure this out myself, providing I know on which which physical monitor the numbers are based i.e. the monitor ID.

Your original script returned the values for all screens. If I were to use that, I could get the usable bounds for the primary monitor. Then I'll just open the windows on the primary screen, no matter how many monitors there are. Probably the safest solution.

Offline

 

#13 2019-01-31 08:04:36 am

looking_glass
Member
Registered: 2009-01-08
Posts: 31

Re: Window Dimensions

@GG
Seems we been working on parallel projects. Maybe you find some inspiration (copypasta encouraged!) here: https://gitlab.com/therwe/corral-windows.

Offline

 

#14 2019-01-31 05:31:48 pm

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Hi looking_glass;

Thank you.

I had a quick peek at your code. While I'm not trying to do the  widows staking on the primary screen in a generic way, I am trying to do it for the windows of a particular app. Will have a good look at the code. I think I can use it for what I have in mind.

Regards;
Gary

Offline

 

#15 2019-02-02 05:11:54 am

looking_glass
Member
Registered: 2009-01-08
Posts: 31

Re: Window Dimensions

GG wrote:

I am trying to do it for the windows of a particular app.


You can filter the app in the following line:

Applescript:

set visibProcs to a reference to (processes whose visible = true and name ≠ "Finder")

Just change '≠ "Finder"' to '= "MyApp"'.
And you can throw out all code that treats Finder windows.

Offline

 

#16 2019-02-02 09:27:55 am

GG
Member
Registered: 2019-01-14
Posts: 98

Re: Window Dimensions

Thank you.

Offline

 

#17 2019-02-02 10:29:56 am

looking_glass
Member
Registered: 2009-01-08
Posts: 31

Re: Window Dimensions

My pleasure!

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)