Tuesday, October 21, 2014

#1 2005-12-28 09:19:18 am

Adam Bell
Administrator
From: Nova Scotia, Canada
Registered: 2005-10-04
Posts: 4635

Exploring Dual Screens

In an effort to locate things on my dual-screen setup without shoving them up against the menu bar or under the dock on my primary screen, I put this together. It returns nearly everything you might want to know about dual screens - errors if you have only one [This was fixed to allow a primary screen on either port of a dual-screen card and the menu bar to be on either screen - thanks to Rick Smykla for pointing out the flaws and testing].

Applescript:

to GetScreenParameters()
   tell (do shell script " defaults read /Library/Preferences/com.apple.windowserver | grep -w -m 2 Unit") to if word 3 = word 6 then return display dialog "There is only one screen attached to this computer!" buttons {"Oops"} default button 1 giving up after 5 with icon 2
   tell (do shell script "echo `defaults read /Library/Preferences/com.apple.windowserver | grep -wA 1 -m 2 OriginX``defaults read /Library/Preferences/com.apple.windowserver | grep -w -m 2 Height``defaults read /Library/Preferences/com.apple.windowserver | grep -w -m 2 Width``defaults read /Library/Preferences/com.apple.windowserver | grep DisplayLayoutToRight``defaults read com.apple.dock | grep orientation``defaults read com.apple.dock | grep tilesize`") to set details to {word 3, word 6, word 9, word 12, word 15, word 18, word 21, word 24, word 27, word 30, word 33}
   
   --> Origin1 x, y; Origin2 x, y; Height 1, 2; Width 1, 2; DisplayLayout 1 = Right; DockPosition 0 = Left; DockSize; Extent x, y. The screen with origin 0, 0 has the menu bar, or if Display2toRight = 1, then the menu bar is on the left.
   
   repeat with anItem in details -- not really necessary, but I wanted numbers.
       try
           set contents of anItem to contents of anItem as number
       end try
   end repeat
   
   tell application "Finder" to tell (bounds of desktop's window) as list to set details to details & {(item 3) - (item 1), (item 4) - (item 2)}
   tell details to return {OriginPrimaryX:item 1, OriginPrimaryY:item 2, Origin2X:item 3, Origin2Y:item 4, HeightPrimary:item 5, Height2:item 6, WidthPrimary:item 7, Width2:item 8, Display2toRight:item 9, DockPosition:item 10, DockSize:item 11, WidthDesk:item 12, HeightDesk:item 13}
end GetScreenParameters

GetScreenParameters()
--> {OriginPrimaryX:0, OriginPrimaryY:0, Origin2X:1152, Origin2Y:156, HeightPrimary:870, Height2:768, WidthPrimary:1152, Width2:1024, Display2toRight:1, DockPosition:"left", DockSize:36, WidthDesk:2176, HeightDesk:924}


iMac & MBP both running OS X 10.9.1

Filed under: Finder

Offline

 

#2 2006-05-12 11:18:25 pm

beowulf
Member
From: San Jose, CA
Registered: 2006-05-12
Posts: 2

Re: Exploring Dual Screens

Very cool function. Do you know of any way to set the desktop picture of the secondary display?

Thanks.


Dave
____________________________
"Imagination is more important than knowledge." -- Albert Einstein

Offline

 

#3 2007-03-26 01:30:17 pm

kevincody1964
Member
Registered: 2003-11-14
Posts: 8

Re: Exploring Dual Screens

can you get the desktop to be the itunes screensaver?

Just asking.

Kc

Offline

 

#4 2007-04-14 12:11:49 pm

regulus6633
Member
From: Taulov, Denmark
Registered: 2006-11-01
Posts: 1695
Website

Re: Exploring Dual Screens

Hi Adam, I just posted a similar script to code exchange and then I came across your script. I sure wish I would have found your script before I went through the trouble of creating mine from scratch. We took very similar approaches. You can see mine here: http://bbs.applescript.net/viewtopic.ph … 207#p79207

Anyway, as I was looking at my script and comparing it to yours I found an error in your script. I only noticed it because when testing my script I stumbled across a tricky part. I found that when getting the values from the plist file by using "word 3" (for example) that a negative sign is dropped (if there are any negative signs). So if you have your second display situated above or to the left of your main display, then either the OriginX or OriginY values for the second display will have a negative value. I had to format the origin values specially (not using "words" to coerce to a list) to retain the negative value. Your script displays those values as positive numbers.

I just thought you'd like to know.

Offline

 

#5 2007-04-25 12:55:43 pm

Adam Bell
Administrator
From: Nova Scotia, Canada
Registered: 2005-10-04
Posts: 4635

Re: Exploring Dual Screens

Hi, Reg;

Just back from 2 weeks away. Thanks for the heads up, but one of the returned values is "Display2toRight" where 1 is true and 0 is false. Did that not work for you?


iMac & MBP both running OS X 10.9.1

Offline

 

#6 2011-01-27 11:45:30 am

yiam-jin-qui
Member
Registered: 2010-10-10
Posts: 34

Re: Exploring Dual Screens

Using System Events can give quite a simple and legible reading of the sizes/positions of the two screens.

Here is an example which resizes and repositions the selected window, making it occupy the rightmost one third of whichever of two screens it happens to be on.

(Can also be called, with proportional parameters [OriginX OriginY Width Depth] as an osascript shell command. Repeated calls with the same parameters will cycle through complementary screen-tiling transforms of the primary rectangle. This makes it possible to quickly tile the screen with a smaller number of assigned key-strokes [a smaller set of arguments for osascript calls])

Applescript:

property pVer : "1.9"
property pTitle : "Place and size window by % of screen" & tab & pVer

-- SET SIZE AND POSITION OF SELECTED WINDOW (ANY APPLICATION)
-- (WORKS WITH SINGLE OR DUAL DISPLAY SYSTEMS)

-- NAME
--    PlaceWin
--
-- SYNOPSIS
-- OS X terminal command line, in a shell script
-- (Assigned to a key by something like Keyboard Maestro or FastScripts)

-- Toggle window between full screen and last remembered size
-- and position:
-- osascript ~/Library/Scripts/PlaceWin.scpt --zoom

-- Cycle between left, middle and right-hand vertical third
-- of the screen:
-- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 .333 1

-- Cycle between 4 vertical quarters of the screen:
-- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 .25 1

-- Toggle between left half and right half of the screen:
-- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 .5 1

-- Toggle between top and bottom half of screen:
-- osascript ~/Library/Scripts/PlaceWin.scpt 0 1 1 .5

-- Toggle between left 2/3 and right 1/3 of the screen:
-- osascript ~/Library/Scripts/PlaceWin.scpt 0 0 .667 1

-- Cycle between top and bottom half of right-hand 1/3 of the
-- screen, and top and bottom half of left-hand 2/3 of the screen:
-- osascript ~/Library/Scripts/PlaceWin.scpt .666 0 .333 .5

-- Clear window placing history, or save recent history to an
-- executable shell script for restoring work-spaces:
-- osascript ~/Library/Scripts/PlaceWin.scpt --history
--
-- Example of a shell script generated by the history switch
-- Places Textedit in the top right-hand corner of the
-- screen (1/3 of screen width, half of screen depth),
-- and Dictionary in the lower right-hand corner of the
-- screen (1/3 of screen width, half of screen depth):

-- open -a '/Applications/TextEdit.app'
-- osascript ~/Library/Scripts/PlaceWin.scpt 0.666 0.0 0.333 0.5 --screen=1 --tile=1
-- open -a '/Applications/Dictionary.app'
-- osascript ~/Library/Scripts/PlaceWin.scpt 0.666 0.0 0.333 0.5 --screen=1 --tile=2



-- Ver 1.4 Accepts tile argument in form of bare integer or as --Tile=N.
--            (Providing a Tile argument suppresses cycles through complementary tiles, and gives an index to a particular tile)
-- Ver 1.6 In the absence of an argument, saves a restorable history to a clickable .command file on the Desktop
-- Ver 1.7 The dialog for naming the saved history shell script (restore work-space commands) offers to clear the history
-- Ver 1.71 Correctly sizes OmniFocus windows
-- Ver 1.72 Fixes a bug arising when history is empty and a history list is requested
-- Ver 1.8 Remembers the preZoom state of different zoomed applications
-- Ver 1.9 half-half splits toggle horizontally or vertically, rather than cycling between all four possibilities


-- DEFAULT: A full-height window, rightmost third of the screen:
-- NB (Not all windows can be arbitrarily resized)

-- UNITS - proportion of whichever screen is displaying the selected window
-- POSITION - (origin: top left)
property pPosnAcross : 0
property pPosnDown : 0

-- SIZE
property pSizeAcross : 2 / 3
property pSizeDown : 1

property pblnMenuWindow : false
property pMenuHeight : 22

property plngMSOfficeOffset : 22

property pstrWinPrefsPath : "/Library/Preferences/com.apple.windowserver.plist"
property pTimeout : 10 -- Maximum number of seconds to wait for a loading app to present a window

property plstDisplays : {}
property piBox : 0
property piTile : missing value -- cycle to next complementary tile? or choose specific tile ?
property piScreen : missing value -- screen on which selected windows top left corner falls ? or specific screen ?
property pblnRepeat : false

property plstHistory : {} -- {App, Screen, PosX, PosY, SizeX, SizeY}
property plstPreZoom : {}
property plngMaxHistory : 10
property pstrWorkSpaceFolder : "~/Desktop/"

property pstrSave : "Save"
property pstrClear : "Clear history"

on run argv
   -- PROCESS ANY ARGUMENTS PASSED BY AN OSASCRIPT SHELL COMMAND
   -- set argv to {"0", "0", ".666", "1"}
   --set argv to {"zoom"}
   
   try
       set blnZoom to false
       if class of argv is list then
           set lngArgs to length of argv
           if lngArgs < 4 then
               -- return history in form of alternating open and placewin shell lines
               if lngArgs > 0 then
                   set strFlag to first item of argv
                   if strFlag contains "history" then
                       set strHistory to HistoryCmds()
                       if strHistory is "" then
                           tell application id "com.apple.systemevents"
                               activate
                               display dialog "No window positioning history found." buttons {"OK"} default button 1 with title pTitle
                           end tell
                       else
                           MakeCommand(strHistory)
                           return
                       end if
                   else if strFlag contains "zoom" then
                       set blnZoom to true
                   end if
               end if
           else
               -- FIRST FOUR ARGUMENTS REQUIRED: OriginX, OriginY, Width, Height
               set lstPosnSize to items 1 thru 4 of argv
               repeat with i from 1 to 4
                   set item i of lstPosnSize to (item i of lstPosnSize) as real
               end repeat
               
               -- RECORD WHETHER THESE ARGUMENTS MATCH THOSE OF THE PREVIOUS CALL
               --        (WE MAY NEED TO CYCLE TO THE NEXT COMPLEMENTARY TRANSFORM)
               set pblnRepeat to ((lstPosnSize) = {pPosnAcross, pPosnDown, pSizeAcross, pSizeDown})
               
               -- AND UPDATE THE PERSISTENT PARAMETERS IF THEY HAVE CHANGED
               if not pblnRepeat then set {pPosnAcross, pPosnDown, pSizeAcross, pSizeDown} to lstPosnSize
               
               -- HANDLE THE OPTIONAL ADDITIONAL ARGUMENTS: --TILE=N --SCREEN=M
               -- (TILE: AN INDEX TO A SPECIFIC COMPLEMENTARY TRANSFORM (LEFT/RIGHT OR TOP/DOWN) OF THE BASE RECTANGLE)
               --    USEFUL IF THE OSASCRIPT CALL FOLLOWS AN OPEN -A CALL
               -- WHICH AIMS TO OPEN A NAMED APP TO A SPECIFIC WINDOW SIZE/POSN
               -- SCREEN: PLACE THE WINDOW ON A SPECIFIC DISPLAY USING ITS INDEX IN THE PLIST
               -- (IN THE ABSENCE OF THIS FLAG, THE WINDOWS IS REPOSITIONED AND RESIZED ON THE SCREEN WHICH CONTAINS ITS
               -- UPPER LEFT CORNER
               set {piTile, piScreen} to {missing value, missing value}
               if length of argv > 4 then
                   set lstFlags to items 5 thru end of argv
                   repeat with oFlag in lstFlags
                       if oFlag contains "=" then
                           set my text item delimiters to "="
                           set lstParts to text items of oFlag
                           set strFlag to first item of lstParts
                           if strFlag contains "screen" then
                               try
                                   set piScreen to (item 2 of lstParts as integer)
                               on error strMsg
                                   return strMsg
                               end try
                           else if strFlag contains "tile" then
                               try
                                   set piTile to (item 2 of lstParts as integer)
                               on error strMsg
                                   return strMsg
                               end try
                           else
                               return "Unknown argument: " & oFlag
                           end if
                           
                           set my text item delimiters to space
                       else -- if this additional argument is a bare integer, interpret it as --Tile=N
                           try
                               set piTile to (oFlag as integer)
                           on error strMsg
                               return strMsg
                           end try
                       end if
                   end repeat
               end if
               
               -- IF THIS IS NOT A REPEATED CALL WITH THE SAME ARGUMENTS,
               -- (AND NO TRANSFORM HAS BEEN SPECIFIED),
               -- THEN DEFAULT TO THE BASE RECTANGLE (TRANSFORM 1)
               if (not pblnRepeat) and (piTile is missing value) then set piTile to 1
           end if
           -- NOW REPOSITION AND RESIZE THE FRONT WINDOW,
           -- USING THE GIVEN PROPORTIONS OF THE CURRENT SCREEN SIZE
           ReSizePosn(blnZoom)
           
       else -- Class of argv not list - not launched at command line. Try to generate a restore workspace command
           set strHistory to HistoryCmds()
           if strHistory is "" then
               ReSizePosn(false)
           else
               MakeCommand(strHistory)
           end if
       end if
   on error strError
       return strError
   end try
end run

on MakeCommand(strHistory)
   tell application id "com.apple.systemevents"
       activate
       try
           set varResponse to (display dialog strHistory & return & "Enter name for this workspace:" default answer ¬
               "" buttons {"Esc", pstrClear, pstrSave} cancel button 1 default button 3 with title pTitle)
       on error
           return
       end try
       set strBtn to button returned of varResponse
       if strBtn = pstrSave then
           set strSpaceName to text returned of varResponse
           set my text item delimiters to space
           set lstParts to text items of strSpaceName
           set my text item delimiters to "_"
           set strSpaceName to lstParts as text
           set my text item delimiters to space
           set strFile to pstrWorkSpaceFolder & strSpaceName & ".command"
           set strCmd to "echo " & quoted form of strHistory & " > " & strFile
           do shell script strCmd
           do shell script "chmod +x " & strFile
           --    set strScript to "do shell script \"" & strHistory & "\""
           --    set strCmd to "echo " & quoted form of strScript & " | osacompile -o ~/DeskTop/sample.scpt"
           --    do shell script strCmd
           set plstHistory to {}
           display dialog "Set of window positions saved in:" & return & return & strFile & ¬
               return & return & "Dbl-Click the command file to restore the workspace." buttons {"OK"} default button 1 with title pTitle
       else if strBtn = pstrClear then
           set plstHistory to {}
       else
           display dialog "Unknown button: " & strBtn with title pTitle
       end if
   end tell
end MakeCommand


-- GET THE CURRENT SCREEN SIZE,
-- AND MOVE AND RESIZE THE FRONT WINDOW USING PROPORTIONAL DIMENSIONS
on ReSizePosn(blnZoom)
   -- GET THE PROPERTIES OF THE REMEMBERED DISPLAYS
   tell application id "com.apple.systemevents"
       tell contents of property list file pstrWinPrefsPath
           set plstDisplays to (first item of ((value of (property list item "DisplaySets")) as list))
       end tell
       
       -- GET THE FRONT WINDOW AND ITS POSITION
       set oWin to missing value
       tell (first application process where frontmost = true)
           repeat with i from 1 to pTimeout * 2
               if (count of windows) > 0 then exit repeat
               do shell script "sleep 0.5"
           end repeat
           set strAppFile to application file
           set strAppFile to (POSIX path of strAppFile)
           set oWin to front window
       end tell
       if oWin is missing value then return
       
       set {lngWinX, lngWinY} to position of oWin
       
       
       
       -- FIND THE DISPLAY CONTAINING THE TOP LEFT CORNER OF THIS WINDOW
       set blnFound to false
       repeat with iDisplay from 1 to length of plstDisplays
           set {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown} to {OriginX, OriginY, Width, Height} of (item iDisplay of plstDisplays)
           if ((lngWinX ≥ lngScreenX) and (lngWinX < (lngScreenX + lngScreenAcross)) and ¬
               ((lngWinY ≥ lngScreenY) and (lngWinY < (lngScreenY + lngScreenDown)))) then
               set pblnMenuWindow to {lngScreenX, lngScreenY} = {0, 0}
               set blnFound to true
               exit repeat
           end if
       end repeat
       if not blnFound then return
       
       if blnZoom then
           set {lngWinWidth, lngWinHeight} to size of oWin
           set lngMargin to pMenuHeight * 2
           if lngWinX > lngScreenX or lngWinY > (lngScreenY + lngMargin) or lngWinWidth < lngScreenAcross or lngWinHeight < (lngScreenDown - lngMargin) then
               set lngAdjustedY to lngWinY
               set lngAdjustedHeight to lngWinHeight
               if pblnMenuWindow then set lngAdjustedY to lngAdjustedY - pMenuHeight
               if strAppFile contains "Microsoft Word" then
                   set lngAdjustedY to lngAdjustedY - plngMSOfficeOffset
                   set lngAdjustedHeight to lngAdjustedHeight + plngMSOfficeOffset
               end if
               
               my StoreZoom({strAppFile, lngWinX, lngAdjustedY, lngWinWidth, lngAdjustedHeight})
               -- set plstPreZoom to {lngWinX, lngAdjustedY, lngWinWidth, lngAdjustedHeight}
               
               set {lngWinX, lngWinY, lngWinWidth, lngWinHeight} to {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown}
           else
               set lstOldZoom to my GetZoom(strAppFile)
               if lstOldZoom = {} then
                   set {lngWinX, lngWinY, lngWinWidth, lngWinHeight} to {lngScreenX + (lngScreenAcross / 4), lngScreenY + (lngScreenDown / 4), lngScreenAcross / 2, lngScreenDown / 2}
               else
                   set {lngWinX, lngWinY, lngWinWidth, lngWinHeight} to (items 2 thru end of lstOldZoom)
               end if
           end if
       else
           set lstBoxes to my GetTransforms({pPosnAcross, pPosnDown, pSizeAcross, pSizeDown}, {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown})
           if piTile is missing value then
               set piBox to piBox + 1
               if piBox > length of lstBoxes then set piBox to 1
           else
               try
                   set piBox to (piTile as integer) -- specified as an argument on the command line
               on error
                   set piBox to 1
               end try
           end if
           set {lngWinX, lngWinY, lngWinWidth, lngWinHeight} to item piBox of lstBoxes
       end if
       
       if pblnMenuWindow then set lngWinY to lngWinY + pMenuHeight
       tell oWin
           if strAppFile contains "Microsoft Word" then
               tell application id "com.Microsoft.Word"
                   version
                   tell front window of active document
                       set position to {lngWinX, lngWinY + plngMSOfficeOffset}
                       set width to lngWinWidth
                       set height to lngWinHeight
                   end tell
               end tell
           else if strAppFile contains "OmniFocus" then
               tell application id "com.omnigroup.omnifocus"
                   tell front document window of front document
                       if lngWinWidth = lngScreenAcross / 2 then
                           set bounds to {lngWinX, lngWinY, lngWinX + lngWinWidth, lngWinY + lngWinHeight * 0.95}
                       end if
                       set bounds to {lngWinX, lngWinY, lngWinX + lngWinWidth, lngWinY + lngWinHeight}
                   end tell
               end tell
           else if strAppFile contains "Accordance" then
               set {lngAccX, lngAccY} to {lngWinX, lngWinY}
               if lngAccX ≤ 23 then set lngAccX to 30
               if lngAccY < 23 then set lngAccY to 95
               set {position, size} to {{lngAccX, lngAccY}, {lngWinWidth, lngWinHeight}}
           else
               set {position, size} to {{lngWinX, lngWinY}, {lngWinWidth, lngWinHeight}}
           end if
       end tell
   end tell
   
   set lstEvent to {strAppFile, iDisplay, pPosnAcross, pPosnDown, pSizeAcross, pSizeDown, piBox}
   if length of plstHistory > 0 then
       set strLastApp to first item of item -1 of plstHistory
       if (strAppFile = strLastApp) then
           set item -1 of plstHistory to lstEvent
       else
           set end of plstHistory to lstEvent
           if length of plstHistory > plngMaxHistory then set plstHistory to (items 2 thru end of plstHistory)
       end if
   else
       set plstHistory to {lstEvent}
   end if
   
   return
end ReSizePosn

on HistoryCmds()
   set str to ""
   
   set text item delimiters to (POSIX path of (path to home folder))
   set strScriptPath to "~/" & last text item of (POSIX path of (path to me))
   
   set text item delimiters to space
   if length of plstHistory > 0 then
       repeat with i from 1 to length of plstHistory
           set {strAppFile, iDisplay, pPosnAcross, pPosnDown, pSizeAcross, pSizeDown, piBox} to (item i of plstHistory)
           set str to ((str & "open -a " & (quoted form of strAppFile) & "
"
& "osascript " & strScriptPath & space & ({pPosnAcross, pPosnDown, pSizeAcross, pSizeDown} as text) & ¬
               " --tile=" & piBox as string) & " --screen=" & iDisplay as string) & "
"

       end repeat
   end if
   
   if str ≠ "" then tell application id "com.apple.finder" to set the clipboard to str
   set plstHistory to {}
   return str
end HistoryCmds


-- FOR RECTANGLES WHICH INCLUDE ONE OR TWO CORNERS OF THE SCREEN,
-- OR TOUCH OPPOSITE EDGES OF THE SCREEN, AND HAVE A HEIGHT OR WIDTH
-- WHICH IS A SIMPLE FRACTION OF THE CORRESPONDING SCREEN DIMENSION
-- GENERATE THE SCREEN-TILING SET OF COMPLEMENTARY RECTANGLES.

-- (REPEATED CALLS OF THE SCRIPT WITH THE SAME PARAMETERS CYCLE THROUGH THESE COMPLEMENTARY TRANSFORMS,
-- ALLOWING SIMPLE TILING OF THE SCREEN WITH A SMALL NUMBER OF ASSIGNED KEYSTROKES)
on GetTransforms({pPosnAcross, pPosnDown, pSizeAcross, pSizeDown}, {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown})
   if pblnMenuWindow then
       set lngScreenDown to lngScreenDown - pMenuHeight
       --set lngScreenY to lngScreenY + pMenuHeight
   end if
   set {lngX, lngY, lngWidth, lngHeight} to {(pPosnAcross * lngScreenAcross) + lngScreenX, (pPosnDown * lngScreenDown) + lngScreenY, pSizeAcross * lngScreenAcross, pSizeDown * lngScreenDown}
   set {pSizeAcross, pSizeDown} to {pSizeAcross as real, pSizeDown as real}
   
   set {lngDeltaX, lngDeltaY} to {0, 0}
   if lngX = 0 then set lngDeltaX to lngWidth
   if lngY = 0 then set lngDeltaY to lngHeight
   
   if (pSizeAcross = 1.0) or (pSizeDown = 1.0) then -- Single split left/right or up/down
       if pSizeAcross = 1.0 then
           -- UP DOWN
           if pSizeDown = 0.5 then -- (horizontal splits)
               {{0, 0, lngWidth, lngHeight}, {0, lngHeight, lngWidth, lngScreenDown - lngHeight}}
           else if pSizeDown ≥ (1 / 6) and IsSimpleFraction(pSizeDown) then
               set lst to {}
               set lngDeltaY to 0
               repeat with i from 1 to (1 / pSizeDown) as integer
                   set end of lst to {lngX, lngDeltaY, lngWidth, lngHeight}
                   set lngDeltaY to lngDeltaY + lngHeight
               end repeat
               lst
           else
               {{lngX, lngY, lngWidth, lngHeight}, {lngX, lngDeltaY, lngWidth, lngScreenDown - lngHeight}}
           end if
       else
           -- LEFT RIGHT
           if pSizeAcross = 0.5 then -- vertical splits
               {{lngX, lngY, lngWidth, lngHeight}, {lngDeltaX, lngY, lngScreenAcross - lngWidth, lngHeight}}
           else if pSizeAcross ≥ (1 / 6) and IsSimpleFraction(pSizeAcross) then
               set lst to {}
               set lngDeltaX to 0
               repeat with i from 1 to (1 / pSizeAcross) as integer
                   set end of lst to {lngDeltaX, lngY, lngWidth, lngHeight}
                   set lngDeltaX to lngDeltaX + lngWidth
               end repeat
               lst
           else
               {{lngX, lngY, lngWidth, lngHeight}, {lngDeltaX, lngY, lngScreenAcross - lngWidth, lngHeight}}
           end if
       end if
   else -- does this have at least one corner ? (at {0,0} or (height+y)=1) or ((width+x)=1)
       if ({lngX, lngY} = {0, 0}) or AlmostOne(pSizeDown + pPosnDown) or AlmostOne(pSizeAcross + pPosnAcross) then
           
           {{lngX, lngY, lngWidth, lngHeight}, ¬
               {lngX, lngDeltaY, lngWidth, lngScreenDown - lngHeight}, ¬
               {lngDeltaX, lngDeltaY, lngScreenAcross - lngWidth, lngScreenDown - lngHeight}, ¬
               {lngDeltaX, lngY, lngScreenAcross - lngWidth, lngHeight}}
       else
           {{lngX, lngY, lngWidth, lngHeight}}
       end if
   end if
end GetTransforms

on AlmostOne(rNumber)
   (1 - rNumber) < 0.01
end AlmostOne

on IsSimpleFraction(nNumber)
   if nNumber > 0.5 then
       return false
   else
       set N to 1 / nNumber
       Abs((N as real) - (N as integer)) < 0.01
   end if
end IsSimpleFraction

on Abs(N)
   if N < 0 then
       -N
   else
       N
   end if
end Abs

on StoreZoom({strAppFile, lngWinX, lngAdjustedY, lngWinWidth, lngAdjustedHeight})
   set lngZoom to length of plstPreZoom
   if lngZoom > 0 then
       repeat with i from 1 to lngZoom
           if first item of (item i of plstPreZoom) = strAppFile then
               set item i of plstPreZoom to {strAppFile, lngWinX, lngAdjustedY, lngWinWidth, lngAdjustedHeight}
               return
           end if
       end repeat
       set end of plstPreZoom to {strAppFile, lngWinX, lngAdjustedY, lngWinWidth, lngAdjustedHeight}
   else
       set end of plstPreZoom to {strAppFile, lngWinX, lngAdjustedY, lngWinWidth, lngAdjustedHeight}
   end if
end StoreZoom

on GetZoom(strAppFile)
   set lngZoom to length of plstPreZoom
   if lngZoom > 0 then
       repeat with lstZoom in plstPreZoom
           if first item of lstZoom = strAppFile then return lstZoom
       end repeat
       {}
   else
       {}
   end if
end GetZoom

Last edited by yiam-jin-qui (2011-02-20 07:43:41 am)


天地不仁, 仁者人也

Houthakker / RobTrew

Offline

 

#7 2011-01-29 12:04:56 am

yiam-jin-qui
Member
Registered: 2010-10-10
Posts: 34

Re: Exploring Dual Screens

... and a briefer summary of the basic method:

Applescript:

property pVer : "0.1"
property pTitle : "Get Origin, Size of current screen Ver " & pVer

property pstrWinPrefsPath : "/Library/Preferences/com.apple.windowserver.plist"

-- READ THE DETAILS OF THE REMEMBERED DISPLAYS
tell application id "com.apple.systemevents"
   tell contents of property list file pstrWinPrefsPath
       set lstDisplays to (first item of ((value of (property list item "DisplaySets")) as list))
   end tell
   
   -- GET THE SELECTED WINDOW AND ITS POSITION
   set {lngWinX, lngWinY} to position of (front window of (first application process where frontmost = true))
   
   -- FIND THE DIMENSIONS OF THE SCREEN CONTAINING THE TOP LEFT CORNER OF THE SELECTED WINDOW
   repeat with recDisplay in lstDisplays
       set {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown} to {OriginX, OriginY, Width, Height} of recDisplay
       if ((lngWinX ≥ lngScreenX) and (lngWinX < (lngScreenX + lngScreenAcross)) and ¬
           ((lngWinY ≥ lngScreenY) and (lngWinY < (lngScreenY + lngScreenDown)))) then
           exit repeat
       end if
   end repeat
end tell

-- REPORT ORIGIN AND SIZE OF THIS SCREEN
set text item delimiters to return
display dialog {lngScreenX, lngScreenY, lngScreenAcross, lngScreenDown} as string buttons {"OK"} with title pTitle
set text item delimiters to space

Last edited by yiam-jin-qui (2011-01-29 07:10:55 am)


天地不仁, 仁者人也

Houthakker / RobTrew

Offline

 

#8 2011-01-29 08:28:19 am

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 3549

Re: Exploring Dual Screens

Hi, yiam-jin-qui.

Thanks for that. I think you mean "" or {""} in the last line rather than 'space'.


NG

Offline

 

#9 2011-01-29 03:36:14 pm

yiam-jin-qui
Member
Registered: 2010-10-10
Posts: 34

Re: Exploring Dual Screens

A personal house style, I guess cool

Not sure why, but I prefer to default to something like a word-level segmentation).

( And, of course, text 2 thru 3 of "hello" is still "el" )

Last edited by yiam-jin-qui (2011-01-29 03:38:35 pm)


天地不仁, 仁者人也

Houthakker / RobTrew

Offline

 

#10 2011-01-30 12:42:47 am

regulus6633
Member
From: Taulov, Denmark
Registered: 2006-11-01
Posts: 1695
Website

Re: Exploring Dual Screens

I just wanted to point out my experience. I have found that the plist file (/Library/Preferences/com.apple.windowserver.plist) is not always accurate. If you're screen configuration is stable then it seems to work well but if you add or remove a screen periodically, or change it's position, then the actual configuration can be different than the configuration you find in the plist. As such I wrote a command line tool which will always give accurate information. It uses NSScreen and other cocoa classes to get the information from the window server (rather than its plist) at the time of the query. If you're interested you can find it here.

Offline

 

#11 2011-01-30 04:23:37 am

yiam-jin-qui
Member
Registered: 2010-10-10
Posts: 34

Re: Exploring Dual Screens

Your hmscreens tool looks good, and I have certainly noticed that run-time display-switching and menu swapping can occasionally leave a disjunction between hardware and plist.

Empirically, explicitly setting a value in System Preferences > Displays > Resolutions seems to force a write to the plist. The problem seems to come when a non-manual change in resolution occurs, for example after a lower resolution mirrored device is disconnected.

It certainly helps to be able to write:

Applescript:

set {{OriginX, OriginY}, {Width, Height}} to (run script text 18 thru end of (paragraph 3 of (do shell script "/usr/local/bin/hmscreens -info")))

Last edited by yiam-jin-qui (2011-02-01 04:39:03 pm)


天地不仁, 仁者人也

Houthakker / RobTrew

Offline

 

#12 2011-02-24 11:10:50 pm

relishgargler
Member
From: Eagan, MN
Registered: 2010-07-21
Posts: 78
Website

Re: Exploring Dual Screens

Adam, your code works fine on my machine at home (Mac Pro running 10.6), but when I tried it at work (PMG5 running 10.4) earlier today it would error out at the line

Applescript:

to set details to {word 3, word 6, word 9, word 12, word 15, word 18, word 21, word 24, word 27, word 30, word 33}

I can't remember exactly what it said, but I seem to remember it didn't like "word 3"

Offline

 

#13 2011-02-26 05:51:20 am

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 3549

Re: Exploring Dual Screens

And, Adam, my single-screen MacBook Pro with OS 10.6 doesn't like the first line. ("\"                Unit = 0;
                Unit = 0;\" doesn’t understand the display dialog message.") It needs a 'tell me' or something neater:

Applescript:

tell (do shell script " defaults read /Library/Preferences/com.apple.windowserver | grep -w -m 2 Unit") to if word 3 = word 6 then tell me to return (display dialog "There is only one screen attached to this computer!" buttons {"Oops"} default button 1 giving up after 5 with icon 2)


NG

Offline

 

#14 2011-03-01 03:41:12 am

yiam-jin-qui
Member
Registered: 2010-10-10
Posts: 34

Re: Exploring Dual Screens

I think things get easier if one simply writes:

Applescript:

property pstrWinPrefsPath : "/Library/Preferences/com.apple.windowserver.plist"

tell application id "com.apple.systemevents"
   tell contents of property list file pstrWinPrefsPath
       set lstDisplays to (first item of ((value of (property list item "DisplaySets")) as list))
   end tell
end tell


天地不仁, 仁者人也

Houthakker / RobTrew

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.084 seconds, 8 queries executed ]

RSS (new topics) RSS (active topics)