Hi,
Just figured out that I can drag the visualizer to the second display with Mission Control. Does anyone know how to do this programatically? Maybe there’s a cocoa method?
Thanks,
kel
Hi,
Just figured out that I can drag the visualizer to the second display with Mission Control. Does anyone know how to do this programatically? Maybe there’s a cocoa method?
Thanks,
kel
Just thought of something that might work. Turn on Accessibilities’ drag lock. Then, somehow move the cursor to the second display. Yeah, I think it probably needs Accessibility. Hmmm, maybe.
Edited: somehow, it needs to get rid of the menu bar shadow in the visualizer, if possible.
Edited: I wonder if it’s possible to turn the menu bar background to black?
Edited: or transparent.
Later,
kel
Hello kel.
Maybe you can use this, combo of a library for figuring out the screens, (it stores a script later on in the caches directory, containing your current setup) It tests against this setup for each run, so that you have always the current configuration available, -it will rewrite the cache when said monitor configuration change, also with regard to resolution.
The second part is a teleport script, which moves a window from 1 screen to the other, placing it in the same position.
I hope you can use those bits, to move the iTunes window where you like to have it. Feel free to modify the scripts to suit your own needs.
# Most of the code Copyright McUsr (c) 2012 All rights reserverved.
# Version 17, there is a bug here, regarding minimized windows.
script Screens2
property parent : AppleScript
property _physScreens : (path to library folder from user domain as text) & "caches:" & "net.mcusr.screens"
property numberOfScreens : missing value -- 1 for 1, 2 for 2
property physScreens : missing value
-- basis function
to calcY for aScreen by aWinHeight given fromCenter:fromCenter, fromBottom:fromBottom -- for aWinPos
if fromBottom then
-- PROBLEM:
return ((_y of aScreen) + (_height of aScreen) - aWinHeight)
-- return ((_height of aScreen) - aWinHeight)
else if fromCenter then
return ((((_y of aScreen) + ((_y of aScreen) + (_height of aScreen))) / 2) - aWinHeight / 2)
end if
end calcY
to calcX for aScreen by aWinWidth given fromCenter:fromCenter, fromRight:fromRight
if fromRight then
return (((_x of aScreen) + (_width of aScreen)) - aWinWidth)
else if fromCenter then
return ((((_x of aScreen) + ((_x of aScreen) + (_width of aScreen))) / 2) - (aWinWidth / 2))
end if
end calcX
to findAllWins for theScr from anApp
-- bruken av denne rutinen:
-- vi skal finne all vinduer på skjermen, slik at vi kan flytte alle sammen til venstre eller
-- høyre for den saks skyld.
-- kontekst er at vi har kalt opp rutinen etter at vi har "funnet" det første vinduet
-- og skjermen.
-- tileggs problemer : filtrere utvinduer som ikke er på denne skjermen!
-- utvidelser:
-- Kunne ekskludere, includere, og bare levere minimerte vinduer!
-- nå ville det ha vært ok, å ha screen nummer her, når vi skal kikke etter vindu
-- om vinduet er til venstre eller noe?
global wc, psts, i, theId
set psts to {}
script o
property m : missing value
end script
-- Find the frontmost
set o's m to getVisibleWins for anApp
if o's m = null then return null
set wc to count o's m
if wc = 0 then return null
-- hit, nå har det seg så at vi skal filtrere
-- dette skal gå så fort som mulig, tror ikke filter er bra her, siden har to lister!
set foundIt to false
set i to 2
repeat while i ≤ wc -- the first is the one we already got!
set thisScr to findScreen for item 2 of item i of o's m with topleftcorner
if nr of theScr = nr of thisScr then
else
set item i of o's m to missing value
end if
set i to i + 1
end repeat
set o's m to o's m's lists
if o's m = {} then return null
set o's m to reverse of o's m
-- correct z-ordering for processing
return o's m
end findAllWins
to getVisibleWins for anApp
local wnList, wn2list, wc, wc2
set {failure, wc2} to {false, 0}
set {wnList, wn2list} to {{}, {}}
try
tell application "System Events" to tell application process anApp to set wn2list to (get {name, position} of its every window)
if wn2list is {} then
return null
else
set wc2 to count item 1 of wn2list
try
using terms from application "TextEdit"
tell application anApp
set wnList to get {name, id} of (every window whose miniaturized is false and visible is true)
end tell
end using terms from
on error e number n
try
using terms from application "Script Debugger 4.5"
tell application anApp
set wnList to get {name, id} of (every window whose minimized is false and visible is true)
end tell
end using terms from
on error e number n
try
using terms from application "Finder"
tell application anApp
set wnList to get {name, id} of (every window whose collapsed is false and visible is true)
end tell
end using terms from
-- we patch here for any Spotlight windows
if anApp is "Finder" then -- Smile also uses collapsed!
set i to 1
local wnname
repeat wc2 times
if item i of item 1 of wnList is "" then
tell application "Finder" to set wnname to displayed name of target of Finder window index i
set item i of item 1 of wnList to wnname
set item i of item 1 of wn2list to wnname
end if
set i to i + 1
end repeat
end if
on error e number n
set failure to true
end try
end try
end try
end if
end try
set AppleScript's text item delimiters to "" -- convenience during debugging
if failure then -- we have dealt with an we have to get the rest of the data, so we can do something meaningful
try
tell application "System Events"
tell application process anApp to set wnList to (get {name, position} of its every window whose visible = true)
end tell
on error
try
tell application "System Events"
tell application process anApp to set wnList to (get {name, position} of its every window)
end tell
end try
end try
set wc to count item 1 of wnList
if wc = 0 then return null
set wnList to transposeList(wc, item 1 of wnList, item 2 of wnList)
return wnList
else if wc2 = 0 then
return null -- should have found 1 window before calling this one
end if
script o
property sewl : wn2list
property tsewl : missing value
property apwl : wnList
property tapwl : missing value
property winIdList : {}
end script
set wc to count item 1 of wnList
(* So what we want is a list with just visible, and not minimized windows
so, we'll make a list for every window that is visible and not minimized.
Facts:
The windows are layerd, the first window we get is the first window we get returned.
the windows that will appear after the windows returned after system events by the application, is the windows not being in the current space.
Conclusion:
we have to filter and build the list we want based on those facts:
*)
set o's tsewl to transposeList(wc2, item 1 of o's sewl, item 2 of o's sewl)
set o's tapwl to transposeList(wc, item 1 of o's apwl, item 2 of o's apwl)
set i to 1
repeat wc2 times
set res to my getSingelton(o's tapwl, item 1 of item i of o's tsewl)
if res = null then
else
set end of o's winIdList to {res, contents of item 2 of item i of o's tsewl}
set o's tapwl to rmSublistByItem2(res, o's tapwl)
end if
set i to i + 1
end repeat
return o's winIdList
end getVisibleWins
to findScreen for winParams given topleftcorner:topleftcorner
-- best to use just number outside?
-- assumes that the window is capable of giving bounds object!
if topleftcorner then
if ((((item 1 of winParams) ≥ _x of physScreens's screen1) and (item 1 of winParams) < ((_x of physScreens's screen1) + (_width of physScreens's screen1))) and (((item 2 of winParams) ≥ _y of physScreens's screen1) and (item 2 of winParams) < ((_y of physScreens's screen1) + (_height of physScreens's screen1)))) then
return physScreens's screen1
else if ((item 1 of winParams) < _x of physScreens's screen1) and (item 2 of winParams) < ((_y of physScreens's screen1) + (_height of physScreens's screen1)) then
return physScreens's screen1
else if Screens2's numberOfScreens = 2 then
if ((item 1 of winParams) ≥ _x of physScreens's screen2) then
if (item 1 of winParams) < ((_x of physScreens's screen2) + (_width of physScreens's screen2)) then
if (((item 2 of winParams) ≥ _y of physScreens's screen2) and (item 2 of winParams) < ((_y of physScreens's screen2) + (_height of physScreens's screen2))) then
return physScreens's screen2
else if ((item 1 of winParams) < (_x of physScreens's screen2)) then
if ((_width of physScreens's screen2) + (_width of physScreens's screen1)) > (_width of physScreens's viritualScreen) then
return physScreens's screen2
end if
end if
end if
else if ((item 1 of winParams) < (_x of physScreens's screen2)) then
if ((_width of physScreens's screen2) + (_width of physScreens's screen1)) > (_width of physScreens's viritualScreen) then
return physScreens's screen2
else if ((_height of physScreens's screen2) + (_height of physScreens's screen1) + 22) = (_height of physScreens's viritualScreen) then
return physScreens's screen2
else if ((_height of physScreens's screen2) + (_height of physScreens's screen1) + 22) > (_height of physScreens's viritualScreen) then
if ((_y of physScreens's screen2) < (item 2 of winParams)) and ((item 2 of winParams) < 0) then
return physScreens's screen2
end if
end if
end if
end if
else -- decide by proportions
-- if the window is more than half way into the second screen choose second screen for centering.
if (item 1 of winParams) + (item 3 of winParams) / 2 > _width of physScreens's screen1 then
if Screens2's numberOfScreens = 2 then
return physScreens's screen2
else
return physScreens's screen1
end if
else
return physScreens's screen1
end if
end if
end findScreen
to findNextWin for theScr from anApp against tPosition
-- nå ville det ha vært ok, å ha screen nummer her, når vi skal kikke etter vindu
-- om vinduet er til venstre eller noe?
local wc, psts, nams, i, theId
set psts to {}
set nams to {}
script o
property m : missing value
property n : missing value
end script
-- Find the frontmost
tell application "System Events" to set wc to (count every window of application process anApp)
if wc = 1 then return null -- it is the window we got!
-- sjekk om det er noen flere vinduer på denne skjermen, og få de opp og frem!
tell application "System Events" to tell application process anApp to set {psts, nams} to (get {position, name} of its every window)
set o's m to psts
set o's n to nams
set foundIt to false
set i to 2
repeat while i ≤ wc -- the first is the one we already got!
set thisScr to findScreen for item i of o's m with topleftcorner
if nr of theScr = nr of thisScr then
set foundIt to true
exit repeat -- found a nother window!
else
set i to i + 1
end if
end repeat
if not foundIt then return null -- out of luck!
-- we want the id of the window, so we can activate it.
-- tell application anApp to set theId to id of window (item i of o's n)
return {item i of o's m, item i of o's n}
end findNextWin
-- initialize
on checkState() -- Fetches ScreenData<
local vScreen
try
-- stage 1: we get the desktop bounds for convenience up front!
tell application "Finder"
local newdtBounds
set newdtBounds to (get bounds of window of its desktop)
set vScreen to my mkScreen({originX:item 1 of newdtBounds, originY:item 2 of newdtBounds, theHeight:((item 4 of newdtBounds) - (item 2 of newdtBounds)), theWidth:((item 3 of newdtBounds) - (item 1 of newdtBounds))})
end tell
-- stage 2: do we have anything at all?
set my physScreens to load script alias _physScreens
-- stage 3: when stage 1 went ok. compares old new finder bounds
if not screensAlike(vScreen, physScreens's viritualScreen) then error number 3001
on error
local pScreen1, pScreen2
set details to getScreens()
set pScreen1 to mkScreen({originX:item 1 of details, originY:item 2 of details, theHeight:item 5 of details, theWidth:item 7 of details})
set isMain of pScreen1 to true -- the screen with the menu!
set pScreen2 to mkScreen({originX:item 3 of details, originY:item 4 of details, theHeight:item 6 of details, theWidth:item 8 of details})
set my physScreens to mkPhysScreens()
set defacto1 of physScreens to screensAlike(vScreen, pScreen1)
-- store script physScreens in _physScreens replacing yes
-- we have the current physical screen configuration. Some facts before we get the actual screen sizes!
-- - and the layout we are going to make it into the logical screens.
-- fact a: if bounds of the desktop mactches crt1, then there is one screen, if not we have two!
-- whether we have two screens and have replicated the other, there will be one!
-- fact b: the monitor with a menu on will be returned as screen 1 from window server,
-- regardless if it is the internal display or not!
-- fact c: we can drag the external monitor to the left of the current, and have a menubar on it, and everything will
-- be just good from the finder, with regards to coordinates.
-- fact e:
-- there are 11 different ways to organize one or two screens, even before considering
-- different resolutions.
-- fact f: the coordinates of the screen having the menubar, ALLWAYS start at 0,22!
-- Conventions:
-- the logical first screen, is the one to the left! or the one on top --> in that order!
if defacto1 of physScreens = true then
-- for consistency!
copy pScreen1 to screen1 of physScreens
set nr of (screen1 of physScreens) to 1
copy pScreen2 to screen2 of physScreens
set nr of (screen2 of physScreens) to 2
set _y of (screen1 of physScreens) to 22 -- menubar
set _height of (screen1 of physScreens) to (get _height of (screen1 of physScreens)) - 22
else if _x of vScreen < 0 then
copy pScreen2 to (screen1 of physScreens)
set nr of (screen1 of physScreens) to 1
-- logicalScreen1 is now the one without menu
copy pScreen1 to (screen2 of physScreens)
set nr of (screen2 of physScreens) to 2
-- we swap the screens, so that we number them from left to right and top to bottom, should the one with the menu be under and not to the left of the one without menu!
-- horizontal adjustments _x
set _x of (screen1 of physScreens) to _x of vScreen
if _y of vScreen < 0 then set _y of (screen1 of physScreens) to _y of vScreen
set _y of (screen2 of physScreens) to 22 -- menubar
set _height of (screen2 of physScreens) to (get _height of (screen2 of physScreens)) - 22
else if _y of vScreen < 0 and _width of vScreen = _width of pScreen1 then
copy pScreen2 to (screen1 of physScreens)
set nr of (screen1 of physScreens) to 1
-- logicalScreen1 is now the one without menu
copy pScreen1 to (screen2 of physScreens)
set nr of (screen2 of physScreens) to 2
-- we swap the screens, so that we number them from left to right and top to bottom, should the one with the menu be under and not to the left of the one without menu!
-- the physical screen with a menu is placed below,
-- vertical adjustments _y
set _y of (screen1 of physScreens) to _y of vScreen
set _y of (screen2 of physScreens) to 22 -- menubar
set _height of (screen2 of physScreens) to (get _height of (screen2 of physScreens)) - 22
else
copy pScreen1 to (screen1 of physScreens)
set nr of (screen1 of physScreens) to 1
copy pScreen2 to (screen2 of physScreens)
set nr of (screen2 of physScreens) to 2
set _y of (screen1 of physScreens) to 22 -- menubar
set _height of (screen1 of physScreens) to (get _height of (screen1 of physScreens)) - 22
if _y of vScreen < 0 then
set _y of (screen2 of physScreens) to (_y of vScreen)
-- dette må bli riktig!
else
set _y of (screen2 of physScreens) to (_height of vScreen) - (((screen1 of physScreens)'s _height) + 22)
end if
set _x of (screen2 of physScreens) to (_width of vScreen) - ((screen1 of physScreens)'s _width)
end if
set viritualScreen of physScreens to vScreen
-- set defacto1 of physScreens to practicallyOneScreen
-- set screen1 of physScreens to logicalScreen1
-- set screen2 of physScreens to logicalScreen2
store script physScreens in _physScreens replacing yes
-- you now can use the physical coordinates to calculate logical width and usable coordinates.
-- there are caveats with negative coordinates, that must be adressed!
end try
-- soft settings... Calculating the Dock! those can be changed on the fly! easier than the monitors!
-- fact a: if monitors are organized vertically, or diagonally, (without a common glitch) then the dock will be stuck
-- on the monitor with the menubar.
-- fact b: if monitors are aligned horizontally the dock setting left, and right
-- will put the dock on the left side of the monitor to the left, and to the right
-- of the monitor to the right respectively, but the bottom setting will always be put
-- on the monitor with the menubar!
-- fact c: if the dock is hidden at the moment (autohide), then we don't have to do anything!
-- This code only works from Leopard onwards!
local theAutoHide, theOrientation
tell application "System Events"
tell dock preferences
local thePosition
set theAutoHide to autohide
if theAutoHide is false then
set thePosition to (get screen edge)
if thePosition = left then
set theOrientation to 1
else if thePosition is bottom then
set theOrientation to 2
else
set theOrientation to 3
end if
end if
end tell
end tell
-- we elevate stuff into us, the "run-time object"
if defacto1 of physScreens is true then
if theAutoHide = false then
if my GUIScripting_status() = false then error number -128
adjustForDock({orient:theOrientation, overlap:false, screen1:screen1 of my physScreens, screen2:null})
end if
set numberOfScreens to 1
else
-- more than one screen!
-- idea: record windows so that you record a setup of applications!
if theAutoHide = false then
if my GUIScripting_status() = false then error number -128
-- we first find out how little we can get away with!
local totHeight
set totHeight to (_height of screen1 of physScreens) + (_height of screen2 of physScreens) + 22
# How do I at this state reckognize which monitor is which???
if _height of vScreen < totHeight then
-- We do have overlapping monitors and the dock will use both!
adjustForDock({orient:theOrientation, overlap:true, screen1:(screen1 of my physScreens), screen2:(screen2 of my physScreens)})
-- Screen1 is the one to the left, if not,then the one on top ( aligned)
else -- the dock will be placed on the monitor with the menu!
if isMain of screen1 of my physScreens then
adjustForDock({orient:theOrientation, overlap:false, screen1:(screen1 of my physScreens), screen2:null})
else
adjustForDock({orient:theOrientation, overlap:false, screen1:(screen2 of my physScreens), screen2:null})
end if
end if
end if
set numberOfScreens to 2
end if
end checkState
-- PRIVATE ROUTINES.
on mkPhysScreens()
script __physScreens
property parent : AppleScript
property screen1 : missing value
property screen2 : missing value
property viritualScreen : missing value
property defacto1 : missing value -- if just one screen!
end script
end mkPhysScreens
script screenObj
property parent : AppleScript
property isMain : missing value
property nr : missing value
property _x : missing value
property _y : missing value
property _height : missing value
property _width : missing value
-- Screendata
to screenX1()
return my _x
end screenX1
to screenY1()
return my _y
end screenY1
to bottomEdge()
return ((my _y) + (my _height))
end bottomEdge
to rightEdge()
return ((my _x) + (my _width))
end rightEdge
to screenY2()
return ((my _y) + (my _height))
end screenY2
to screenHeight()
return my _height
end screenHeight
to screenWidth()
return my _width
end screenWidth
to screenOldCoords() -- X1,y1,x2,y2
return {my _x, my_y, ((my _x) + (my _width)), ((my _y) + (my _height))}
end screenOldCoords
to screenCocoaCoords() -- x1,y1,width,height
return {my _x, my_y, my _width, my _height}
end screenCocoaCoords
-- Frame data:
to getCenter()
set ctr_X to (my _x) + ((my _width) / 2) as integer
set ctr_Y to (my _y) + (my _height) / 2 as integer
return {ctr_X, ctr_Y}
end getCenter
to getX2()
return ((my _x) + (my _width))
end getX2
on getLeftHalf() -- {startX,startY,width,height}
local theC, botE
set theC to (my _x) + ((my _width) / 2) as integer
set botE to ((my _y) + (my _height))
return {my _x, my _y, theC, botE}
end getLeftHalf
to getRightHalf() -- {startX,startY,width,height}
local theC, botE, righte
set theC to (my _x) + ((my _width) / 2) as integer
set botE to ((my _y) + (my _height))
set righte to ((my _x) + (my _width))
return {theC + 1, my _y, righte, botE}
end getRightHalf
end script
on mkScreen(r)
-- { originX:theX,originY:theY: theHeight:_height, theWidth:_width }
script aScreen
property parent : screenObj of Screens2
property isMain : false
property nr : 0 as number
property _x : originX of r as number
property _y : originY of r as number
property _height : theHeight of r as number
property _width : theWidth of r as number
end script
end mkScreen
to getScreens()
-- NG http://macscripter.net/viewtopic.php?id=17701
set f to (path to preferences from local domain as Unicode text) & "com.apple.windowserver.plist"
tell application "System Events"
set {{|OriginX|:x1, |OriginY|:y1, |Width|:w1, |Height|:h1}, {|OriginX|:x2, |OriginY|:y2, |Width|:w2, |Height|:h2}} to value of property list items of property list item 1 of property list item "DisplaySets" of property list file f
end tell
return {x1, x2, y1, y2, h1, h2, w1, w2}
end getScreens
to adjustForDock(r)
-- {orient:theOrientation, overlap:true,screen1:screen1 of my physScreens,sceen2:screen2 of my physScreens }
-- adjust the size of screen real estate for the dock, that is there when this handler is called!
local dockWidth, dockStartY
-- orient: 1 : left, 2 : bottom, 3 : right
if orient of r = 1 or orient of r = 3 then
tell application "System Events"
tell process "Dock"
set dockWidth to (((item 1 of (get value of attribute 9 of its list 1)) * 84) / 87) as integer
end tell
end tell
if orient of r = 1 then
set _x of (screen1 of r) to (get (_x of (screen1 of r)) + dockWidth)
set _width of (screen1 of r) to (get (_width of (screen1 of r)) - dockWidth)
else
if overlap of r is true then
set _width of (screen2 of r) to (get (_width of (screen2 of r)) - dockWidth)
else
set _width of (screen1 of r) to (get (_width of (screen1 of r)) - dockWidth)
end if
end if
else -- orientation = 2
tell application "System Events"
tell process "Dock"
set dockStartY to item 2 of value of (get properties of attribute 8 of its list 1)
end tell
end tell
if overlap of r is true then
if isMain of screen1 of r then
set _height of (screen1 of r) to dockStartY - 22
else
set _height of (screen2 of r) to dockStartY - 22
end if
else
set _height of (screen1 of r) to dockStartY - 22
end if
end if
end adjustForDock
on screensAlike(screen1, screen2)
if _x of screen1 = _x of screen2 then
if _y of screen1 = _y of screen2 then
if _height of screen1 = _height of screen2 then
if _width of screen1 = _width of screen2 then
return true
else
return false
end if
else
return false
end if
else
return false
end if
else
return false
end if
end screensAlike
on GUIScripting_status()
-- http://web.archive.org/web/20081223062546/http://www.apple.com/applescript/uiscripting/index.html
-- check to see if assistive devices is enabled
tell application "System Events"
set UI_enabled to UI elements enabled
end tell
if UI_enabled is false then
tell application "System Preferences"
activate
set current pane to pane id "com.apple.preference.universalaccess"
display dialog "This script utilizes the built-in Graphic User Interface Scripting architecture of Mac OS x which is currently disabled." & return & return & "You can activate GUI Scripting by selecting the checkbox \"Enable access for assistive devices\" in the Universal Access preference pane." with icon 1 buttons {"Cancel"} default button 1
end tell
end if
return UI_enabled
end GUIScripting_status
to getFrontmostWindow()
local wc, frontApp, prev_active, p1, p2, s1, s2
set prev_active to ""
-- Find the frontmost
tell application "System Events"
set frontApp to name of first application process whose frontmost is true and visible is true
set wc to (count every window of application process frontApp)
if wc = 0 then
set prev_active to name of application process frontApp
set visible of application process frontApp to false
repeat with i from 1 to (count (every application process whose visible is true))
set frontApp to item i of (get name of every application process whose frontmost is true and visible is true)
set wc to (count every window of application process frontApp)
if wc > 0 then exit repeat
end repeat
end if
tell application process frontApp
tell window 1
set {{p1, p2}, {s1, s2}, tApp} to {position, size, contents of frontApp}
end tell
end tell
end tell
return {{p1, p2}, {s1, s2}, frontApp, prev_active}
end getFrontmostWindow
to transposeList(ctr, list1, list2)
-- tested 05/09/12
script o
property newL : {}
property m : list1
property n : list2
end script
local i
set i to 1
repeat ctr times
set end of o's newL to {contents of item i of o's m, contents of item i of o's n}
set i to i + 1
end repeat
return o's newL
end transposeList
on rmSublistByItem2(what, L)
-- tested 05/09/12
local ct, i
set ct to count L
set i to 1
repeat ct times
if (item 2 of item i of L as text) is what then
if i = 1 then
return rest of L
else if i = ct then
return items 1 thru -2 of L
else
return items 1 thru (i - 1) of L & items (i + 1) thru -1 of L
end if
end if
set i to i + 1
end repeat
return
end rmSublistByItem2
to getSingelton(the_list, item_a)
-- tested 05/09/12
local p, q, tids
-- Nigel Garvey
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, return}
set the_list_as_string to the_list as text
set AppleScript's text item delimiters to item_a
try
if text item 1 of the_list_as_string = "" then
set q to paragraph 2 of text item 2 of the_list_as_string
else
set p to (count paragraphs of text item 1 of the_list_as_string) mod 2
set q to paragraph (p * 4 - 2) of text item (p + 1) of the_list_as_string
end if
set AppleScript's text item delimiters to tids
on error
set AppleScript's text item delimiters to tids
return null
end try
if q is item 1 of last item of the_list then
if item_a is item 2 of last item of the_list then
return q
else
return null
end if
else
return q
end if
end getSingelton
to logit(log_string, log_file)
do shell script ¬
"echo `date '+%Y-%m-%d %T: '`\"" & log_string & ¬
"\" >> $HOME/Library/Logs/" & log_file & ".log"
end logit
end script
You’ll have to load the screens script into the teleport script, since I use the load mechanism of Script Debugger.
-- Teleport positions a screen at the other screen
# Copyright McUsr (c) 2012 All rights reserverved.
property toplevel : me
# write load statement here.
script telePort
property parent : AppleScript
on run
local tPosition, tSize, tApp, pApp, theScr, otherScr, lbound
toplevel's Screens2's checkState()
if toplevel's Screens2's numberOfScreens = 1 then return 0
set {tPosition, tSize, tApp, pApp} to toplevel's Screens2's getFrontmostWindow() -- get postion and extent of window
set theScr to findScreen of (toplevel's Screens2) for tPosition with topleftcorner
# Find the other window
if nr of theScr = 1 then
set otherScr to getsecondscreen() of (toplevel's Screens2)
else
set otherScr to toplevel's Screens2's getfirstscreen()
end if
# Must adjust for menubar and Dock
# I need to know if the dock is not there (0), to the left(1), bottom(2) or right(3)
# AND I need to now the *space* it takes. Because it needs to be added before
# We calculate the proportions: They are now intialized to zero, there are still
# some logic to be dealt with
local _Xfactor1, _Xfactor2, _Yfactor1, _Yfactor2
set {_Yfactor1, _Yfactor2} to {0, 0}
if isMain of theScr = true then #menu ok!
if _dockPos of theScr = 2 then
set _Yfactor1 to (_dockSpace of theScr) + 22
else
set _Yfactor1 to 22
end if
set _Yscale to calcprops((_height of theScr) + _Yfactor1, _height of otherScr)
if _dockPos of theScr = 1 or _dockPos of theScr = 3 then
set _Xfactor1 to _dockSpace of theScr
else
set _Xfactor1 to 0
end if
if _dockPos of otherScr = 3 then
set _Xfactor2 to _dockSpace of otherScr
else
set _Xfactor2 to 0
end if
set _Xscale to calcprops((_width of theScr) + _Xfactor1, (_width of otherScr) + _Xfactor2)
else
if _dockPos of otherScr = 2 then
set _Yfactor2 to (_dockSpace of otherScr) + 22
else
set _Yfactor2 to 22
end if
set _Yscale to calcprops((_height of theScr), (_height of otherScr) + _Yfactor2)
if _dockPos of otherScr = 1 or _dockPos of otherScr = 3 then
set _Xfactor2 to _dockSpace of otherScr
else
set _Xfactor2 to 0
end if
if _dockPos of theScr = 3 then
set _Xfactor1 to _dockSpace of theScr
else
set _Xfactor1 to 0
end if
set _Xscale to calcprops((_width of theScr) + _Xfactor1, (_width of otherScr) + _Xfactor2)
end if
# Distance calculations: We are always moving from theScreen to theOther
# To get the true distance do we need to consider the Dock? for the width?
if _dockPos of theScr = 1 then
set _Xdist to ((_x of theScr) - _Xfactor1) - (_x of otherScr)
else if _dockPos of otherScr = 1 then
set _Xdist to (_x of theScr) - ((_x of otherScr) - _Xfactor2)
else
set _Xdist to (_x of theScr) - (_x of otherScr)
end if
# The dock at the bottom can't really inflict on the y positons, but the menu can!
if isMain of theScr = true then
set _Ydist to ((_y of theScr) - 22) - (_y of otherScr)
else
set _Ydist to (_y of theScr) - ((_y of otherScr) - 22)
end if
# Every factor calculated, it is time to do the actual translation
local newX, newY, newWidth, newHeight
set newX to (((item 1 of tPosition) - _Xfactor1 + _Xfactor2) * _Xscale) - _Xdist
set newY to (((item 2 of tPosition) - _Yfactor1 + _Yfactor2) * _Yscale) - _Ydist
set newWidth to ((item 1 of tSize) + _Xfactor1 - _Xfactor2) * _Xscale
set newHeight to ((item 2 of tSize) + _Yfactor1 - _Yfactor2) * _Yscale
tell application id "com.apple.systemevents"
tell application process (item 2 of tApp)
set position of window 1 to {newX, newY}
set size of window 1 to {newWidth, newHeight}
end tell
end tell
postProcessAllWindows of (toplevel's theWin) for item 2 of tApp without all
-- if (item 1 of pApp) ≠"" then
-- tell application id (item 1 of pApp) to activate
-- else
-- tell application id (item 1 of tApp) to activate
-- end if
end run
to calcprops(sc1, sc2)
return (sc1 / sc2)
end calcprops
end script
tell telePort to run
Edit
Added copyright statements.
Hi McUsr,
At a quick glance, it looks like there might be some things there.
What I was thinking was that iTunes would play and the visualizer would start. Then the visualizer would shift to the second display. The way it works is that the computer opens a new space for the full screen visualizer in the second display. It does that automatically, so that’s not needed in the script.
It’s too bad that Mission Control is not scriptable!
In my research on the internet, I haven’t seen anybody who knows how to place the visualizer in the second display. To me that is strange after all these years. I was thinking that maybe Mission Control is new and Apple is working on it.
We’ll get this, because many people want it which is very logical.
Thanks and have a good day,
kel
Hello.
Maybe it can help if you move a regular itunes window to the second display first, and then start the visualizer?
I really don’t use iTunes that much, so I can’t help you there.
Hi McUsr,
I did that before and it doesn’t work. When you run iTunes from the second display, the visualizer opens in the first display! Strange how different iTunes is. Well actually, several apps behave in the same manner I think.
Later,
kel
ps. Ive been trying to help someone else on the Apple site, so posts might be a little delayed.
Does anyone know how to make the menu bar invisible?
Hello Kel.
Maybe you can fix your original problem with changing main display to the external monitor in System Preferences. What I mean is that you drag over the menu bar over to the other display, in the screens preferences. Maybe that will work. Good luck.
Hi McUsr,
Good idea about changing the Display arrangement with the menu bar. I’ll try that later and see what happens.
Thanks a lot,
kel
Think I might have something with the menu bar. Need to experiment with:
Edited: it almost worked. I dragged the Xcode app to the second display and ran it. Only that space didn’t have the menu bar and not the visualizer. Back to the drawing board. I think it has to be done in iTunes.
Success!!!
Here’s what you do. After dragging the visualizer to the second display with Mission Control, go to System Preferences. In the Accessibility pane select Display. Then, check Invert colors. Then, uncheck it. All spaces return to default, but the visualizer menu bar disappears I think (or remains black). Quite sure the procedure went like that.
gl,
kel
Finally figured out the easier way. Didn’t know how to make the visualizer not come out of full screen. It needed to be done in the visualizer. This makes it easier. Now just need to move the window. Getting there.
Hi McUsr,
I decided to go with the quick and dirty ui element scripting Dock along with scripting iTunes for now. The big algorithm had too many pieces. I have most of them, but haven’t put them all together and don’t know what kind of speed I’ll get. Will look into that later.
Will post the quick and dirty and local (according to my setup on the computer) in a little while. Maybe someone can use it as an algorithm for their own setup.
Thanks for the script. I’ve read your posts before and looked at the script about moving the window. That’s what I’m doing with Dock ui element scripting.
Edited: and one thing. I don’t have Script Debugger, so couldn’t run it, but the part about the windows looks interesting.
Edited: thought of a new library script to add to Script Libraries, ScreenLib. That might come in handy later.
Thanks a lot,
kel
Hello Kel.
Add a property named Screens2 right below the toplevel property in the teleport script.
This property should load the screens2. script object.
Then everything should work as expected.
I will convert it into a script library, when I change it for some reason.
Hi McUsr,
Will try the property. Thanks.
Here’s the roughly working quicky in my setup :
-- macro
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "Desktop on Display 2"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
-- if full screen is true,
-- then that means that the visualizer might have opened in display 1
-- then, need to put the visualizer back in the window
-- then, re-full screen
tell application "iTunes"
launch
activate
set visuals enabled to true
if full screen then
say "full screen off" -- this delay maybe needed here
set full screen to false
end if
say "full screen on" -- this delay needed here
set full screen to true
end tell
delay 2 -- this delay maybe needed here
-- macro
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "Desktop on Display 1"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
tell application "iTunes"
play
end tell
-- Remember to return focus to iTunes (if you prefer).
-- Activate doesn't work because the focus is already on iTunes in the visualizer.
-- Maybe you can use this as a feature?
-- Remember to reset menu to what it was before.
Needs a lot of tweaking.
Have a good day,
kel
Have a good day you too kel, and good luck!
Thanks McUsr.
Think I have a new idea. I’m wondering if visible is set and unset then the focus will change to the browser. Hope I can sleep. Nice puzzle.
Later,
kel
Think I have the solution. Need to keystroke out of the visualizer’s space!
Edited: no can’t do that. Then, the visualizer won’t show! How to shift out of display 2? That’s the question.
Edited: by Jove, think I’ve got it. Use the same method!
Edited: figured how to move the focus with keystrokes!!!
Hi McUsr,
We’ve got it now!!! To open iTunes in space 6 on the second display from the first display:
tell application "System Events"
launch
key code 22 using control down -- Space 6
key code 26 using control down -- Space 7
key code 22 using control down -- Space 6
end tell
tell application "iTunes"
launch
activate
end tell
Keystrokes don’t work, but key codes do. Also, if on the second display, space 6 is already the selected space, then nothing will happen with just:
key code 22 using control down -- Space 6
So we need to key code to space 7 and then back to space 6.
This makes everything very easy!!!
The only hard part is that I want to move the browser back to the first display. That’s all that is left to do.
Have a good day,
Edited: it didn’t work. The browser still opens in where it was closed.
Back to the drawing board.
Have a good day anyway.
kel
Hi,
What I wanted to do was Open iTunes browser in Display 1 - Space 5 and the visualizer in Display 2
Here’s the working script if anyone wants to play around with it. I’m running it in AppleScript Editor in Space 4.
-- iTunes' browser opens in the display where it was closed.
-- Set iTunes to open in display 2.
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
-- might need delay here
tell menu "Options"
tell menu item "Desktop on Display 2"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
-- First move to space 5 where we want iTunes to open.
tell application "System Events"
key code 23 using control down
end tell
-- Open iTunes and enable the visualizer.
-- If the visualizer opens in full screen, it might have opened in display 1.
-- So, take it out of full screen and into the browser.
-- Now go back into full screen and the visualizer should open in display 2.
-- Focus is now on the visualizer.
tell application "iTunes"
launch
activate
set visuals enabled to true
delay 2 -- this delay needed
set full screen to false
delay 2 -- this delay needed
set full screen to true
end tell
delay 2 -- this delay needed
-- Move the browser back to display 1.
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "Desktop on Display 1"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
-- The focus is on display 2, last space (no index).
-- Set the focus on display 1, space 5 or 4.
tell application "System Events"
key code 23 using control down -- Space 5
key code 21 using control down -- Space 4
delay 2
key code 23 using control down -- Space 5
end tell
-- Reset where iTunes should open to None.
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "None"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
Try decreasing the delays if possible.
Edited: btw, Dock is set to always be open. I think that’s all.
Edited: one more thing if someone wants to make it international, then please do and post it. I don’t know how to get the indices for the menu items. Thanks.
gl,
kel
Added one more delay and decreased the others:
property delay1 : 1.5
property delay2 : 0.5
-- iTunes' browser opens in the display where it was closed.
-- Set iTunes to open in display 2.
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "Desktop on Display 2"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
-- First move to space 5 where we want iTunes to open.
tell application "System Events"
key code 23 using control down
end tell
-- Open iTunes and enable the visualizer.
-- If the visualizer opens in full screen, it might have opened in display 1.
-- So, take it out of full screen and into the browser.
-- Now go back into full screen and the visualizer should open in display 2.
-- Focus is now on the visualizer.
tell application "iTunes"
launch
activate
set visuals enabled to true
delay delay1 -- this delay needed
set full screen to false
delay delay1 -- this delay needed
set full screen to true
end tell
delay delay1 -- this delay needed
-- Move the browser back to display 1.
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "Desktop on Display 1"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
-- The focus is on display 2, last space (no index).
-- Set the focus on display 1, space 5.
tell application "System Events"
key code 23 using control down -- Space 5
key code 21 using control down -- Space 4
delay delay1
key code 23 using control down -- Space 5
end tell
-- Reset where iTunes should open to None.
tell application "System Events"
tell process "Dock"
tell list 1
tell UI element "iTunes"
perform action "AXShowMenu"
tell menu 1
tell menu item "Options"
click
tell menu "Options"
tell menu item "None"
click
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
delay delay2
tell application "iTunes"
activate
play
end tell
It should work ok for the time being. Might try speeding it up somehow.
Good Luck.