Print result from two functions to console - applescript

I've created a small script to get the current size and position of a window. Unfortunately, I only can get one result at a time and need to comment/uncomment the other one.
tell application "System Events" to tell process "Toggl Track"
# get position of window 1
get size of window 1
end tell
If I uncomment both, I will only get the size.
So, my I tried to write the results in a variable and then log these instead.
tell application "System Events" to tell process "Toggl Track"
set position to get position of window 1
set size to get size of window 1
log position & size
end tell
With this, I get no result at all.
What did I do wrong?

position and size are part of the terminology of System Events. You cannot use them as variable names. Rename the variables
tell application "System Events" to tell process "Toggl Track"
set windowPosition to position of window 1
set windowSize to size of window 1
log windowPosition & windowSize
end tell
Regarding the first script, get saves the result of the line in the AppleScript property result and overwrites previous values.

Related

Applescript get application from second desktop

I am trying to get the foreground application from my second monitor (In Mavericks, second desktop). Here's my code that only gets the foreground application:
tell application "System Events"
set frontApp to name of first application process whose frontmost is true
end tell
How can I change it so it gets the application from a specific desktop / screen?
I don't think you can do as you want. If you look at the properties of frontApp there is no property that would indicate which screen it is on. However, what you can do is check the location of the application's windows. If you get the properties of a window of a process then you will see that it has a "position" property. You could check those coordinates to determine which screen it is on.
For example, I have 2 screens. My laptop is setup to be the main screen. I know the screen resolution of the main screen is 1680x1050. Therefore, if I check a window and it has a position outside of those coordinates then I know it must be on the second monitor. Here's how I could do that.
NOTE: I can tell which applications have windows on the second monitor, but not which application on the second monitor is frontmost... like you asked. You'll have to figure something else out for that. I'm showing you this as an idea that maybe you can make workable for your situation.
Here I am only getting the first application with a window on the second monitor. This should show you the idea and you can adjust the code to do as you need.
set mainScreenResX to 1680
set mainScreenResY to 1050
tell application "System Events"
set firstFoundAppOnSecondScreen to missing value
set visibleApps to application processes whose visible is true
repeat with visibleApp in visibleApps
try
tell visibleApp
set {x, y} to position of window 1
if x > mainScreenResX or x < 0 or y > mainScreenResY or y < 0 then
set firstFoundAppOnSecondScreen to name
exit repeat
end if
end tell
end try
end repeat
return firstFoundAppOnSecondScreen
end tell

How to set a window's index to last (furthest back) in applescript

I've seen a lot of posts for how to send a window to the front in applescript, but I want to be able to send it to the back. How do I write an applescript that will do this?
Maybe you don't actually need to move any windows. Maybe you can just hide your application so your window isn't showing. Since you don't want your window on the top then it's probably OK to just hide your application. It continues running and does its thing but its window doesn't cover any other windows.
Just change "Safari" to the name of your application.
set myAppName to "Safari"
tell application myAppName to activate
tell application "System Events"
-- wait until your application comes forward and then hide it
repeat
set p to first process whose frontmost is true
if name of p is myAppName then
set visible of p to false -- hide your application
exit repeat
end if
delay 0.2
end repeat
end tell
EDIT: if hiding your app doesn't work then you could just keystroke command-tab which is the application switcher command. Basically your app will come to the front and then the keystroke will make the previously frontmost application come to the front. So your window won't go all the way back but it won't be in the front. Maybe that will work.
set myAppName to "Safari"
tell application myAppName to activate
tell application "System Events"
-- wait until your application comes forward
repeat
set p to first process whose frontmost is true
if name of p is myAppName then exit repeat
delay 0.2
end repeat
-- use the application switcher to bring the previously frontmost application forward
keystroke tab using command down
end tell
Something like set index to 999 doesn't seem to work, but set index to (count windows) does:
tell application "TextEdit"
set index of window 1 to (count windows)
end tell
You might also raise all other windows:
tell application "System Events" to tell process "TextEdit"
repeat with w in windows 2 thru -1
perform action "AXRaise" of w
end repeat
end tell
This will move the front finder window to the back...
tell application "Finder" to set index of front Finder window to (count Finder windows)
I have not used "openFrameWorks" so I am not sure of how it works…
But rather than reinvent the wheel with Applescript.
Can you not set the window level in "openFrameWorks"
In xcode/Objective - c I would use the NSWindow Window Levels constants.
To set a normal window:
[awindow setLevel: NSNormalWindowLevel];
But set a window below other normal windows:
[awindow setLevel: NSNormalWindowLevel - 1000];
This will insure the window is always below any normal applications windows. Even when I click on it or drag it. It stays behind other windows.

Embed external application inside a Cocoa SplitView

I would like to have an application under Mac OS X that enables me to have Sublime Text 2 and a terminal (for showing test result, run grunt tasks and so on) in the same fullscreen window. I couldn't find an application whith this behaviour and I think of reproducing it myself with cocoa split view.
I would like to know if it's possible and, if yes, how can I start implementing it
Thank you
You can't create a new application from 2 other applications. It won't work. However you can use applescript to make it easy for you to position these windows as you want.
As an example I'll use Safari and Terminal as my 2 applications. Open them and place them on the screen as you want them to appear. I opened each window large and positioned them side-by-side. Then I ran this applescript to get their window size and position properties...
tell application "System Events"
tell process "Safari"
set safariSize to size of window 1
set safariPosition to position of window 1
end tell
tell process "Terminal"
set terminalSize to size of window 1
set terminalPosition to position of window 1
end tell
end tell
return {safariSize, safariPosition, terminalSize, terminalPosition}
Then I copy/pasted the result from that script into the "theValues" variable in this script. Now whenever I want I can run this script to recreate those window positions.
set theValues to {{1001, 1025}, {0, 22}, {613, 1024}, {1003, 22}}
tell application "Safari" to activate
tell application "Terminal" to activate
tell application "System Events"
tell process "Safari"
set size of window 1 to item 1 of theValues
set position of window 1 to item 2 of theValues
end tell
tell process "Terminal"
set size of window 1 to item 3 of theValues
set position of window 1 to item 4 of theValues
end tell
end tell
I hope that helps. Good luck.

Using AXIdentifier in UI Scripting for Applescript

10.7.4 OSX Lion
Applescript
I am working with an application (built in house and has no Applescript dictionary) that has a static text element I want to copy to the clipboard and send to another app but I'm having a hard time getting it to work.
The script I was using for targeting the element looked like this:
Tell application "System Events" to set frontmost of process "*application*" to true
Tell application "System Events"
Tell process "*application*"
Tell static text 1 of tab view 1 scroll area 1 of splitter group 1 of splitter group 1 of splitter group 1 of window 1
keystroke "a" using command down
delay 0.1
keystroke "c" using command down
delay 0.1
end tell
end tell
end tell
end tell
What would happen was that the wrong text from the wrong element was copied to the clipboard every time I clicked in a different spot on the application (there are numerous text fields).
I noticed in UI Accessor/Accessibility Accessor that each UI element in the application has a unique AXIdentifier value when you mouse over them.
Is there anyway to accomplishing what I am trying to do, using AXIdentifier values to target that element and copy the text from it?
Thanks for all the help this is my first post and I hope it was worthy! ~TheLarkInn
You can do this by using AppleScript's filtering. For example, to get the From: pop-up menu in a message composition window in Apple Mail, there is no accessibility description you can match on, however there is a unique AXIdentifier which you can match as follows:
tell application "System Events"
tell application process "Mail"
tell window 1
get first pop up button whose value of attribute "AXIdentifier" is "popup_from"
end tell
end tell
end tell
This is more efficient than looping in AppleScript as it only involves sending one Apple Event to System Events.
I don't think there is a way to directly do what you're trying to do. It seems like you can only access attributes once you have a handle on an element via selector. Here is a very ugly solution that does what you're asking by iterating over all UI elements, but it is really slow with bigger UIs and probably not ideal for any production level code.
tell application "System Events"
tell process "Some Process"
set tElements to entire contents of window "Some Window"
repeat with tElement in tElements
if (exists attribute "AXIdentifier" of tElement) then
if value of attribute "AXIdentifier" of tElement = "Some AXIdentifier" then set tText to value of tElement
end if
end repeat
end tell
end tell
tText
I think using UIElementInspector or Accessibility Inspector from Xcode to build a selector string is the way to go!
Tell application "*application*" to activate
Tell application "System Events"
Tell application process "*application*"
set textStaticTextValue to value of static text 1 of tab view 1 scroll area 1 of splitter group 1 of splitter group 1 of splitter group 1 of window 1
end tell
end tell

Positioning a window with AppleScript using dual monitors

I have two monitors set up and I am trying to position the window of an application in the second monitor but nothing I do seems to work. For example I am using my laptop and the terminal window is maximized on the screen. Then I plug in an external monitor. I then want to run the applescript and have the terminal maximize on the larger second monitor.
Here is what I have right now:
set monitorTwoPos to {1050, -600}
set monitorTwoSze to {1200, 1920}
tell application "Microsoft Outlook"
set position of window 1 to monitorTwoPos
set size of window 1 to monitorTwoSze
end tell
Here is the error I get:
/Users/vcutten/AppleScripts/SpacesWork.scpt:1291:1332: execution error:
Microsoft Outlook got an error: Can’t make position of window 1 into type specifier. (-1700)
I'm pretty sure I'm just using set position and set size completely wrong :( When I used bounds it kind of works...
Bonus Question:
How can I loop through the open windows and get their size? Thanks!
What have you tried?
I think to solve this you need to calculate the screen size and coordinates of the second monitor. For example, your main monitor starts at position {0,0}. So the starting position of the second monitor has to be something different and you need to find that. Luckily I have written a tool that will give you both the starting coordinates and screen size of your monitors. Once you have the size and position then it's simple. System events can set the size and position of a window so you could do something like this...
set monitorSize to {800, 600}
set monitorPosition to {-800, 0}
tell application "System Events"
tell process "Terminal"
set frontWindow to first window
set position of frontWindow to monitorPosition
set size of frontWindow to monitorSize
end tell
end tell
So from the above script you just need the size and position variables. You can get my tool here called hmscreens which will give you those. You may need to do some adjusting of the coordinates depending on if the screen is measured from the lower left corner or upper left, but that's just simple math.
I hope that helps...
Use bounds instead of position, it works. You can get bounds of the window like this:
tell application "Microsoft Outlook"
get bounds of first window
end tell
Answer to the bonus question:
tell application "Microsoft Outlook"
repeat with nextWindow in (get every window)
get bounds of nextWindow
end repeat
end tell
If you open Replies tab at bottom part of Applescript editor, you will see all get results.
Hope it helps.
Here is a script that handles saving and restoring size and postion for multiple display configurations. It may have some issues with fullscreen apps but it seems to work ok.
-- allSettings is a list of records containing {width:? height:? apps:{{name:? pos:? size:?},...}
-- for each display setup store the apps and their associated position and size
property allSettings : {}
-- create a variable for the current settings
set currentSettings to {}
display dialog "Restore or save window settings?" buttons {"Restore", "Save"} default button "Restore"
set dialogResult to result
tell application "Finder"
-- use the desktop bounds to determine display config
set desktopBounds to bounds of window of desktop
set desktopWidth to item 3 of desktopBounds
set desktopHeight to item 4 of desktopBounds
set desktopResolution to desktopWidth & "x" & desktopHeight
-- find the saved settings for the display config
repeat with i from 1 to (count of allSettings)
if (w of item i of allSettings is desktopWidth) and (h of item i of allSettings is desktopHeight) then
set currentSettings to item i of allSettings
end if
end repeat
if (count of currentSettings) is 0 then
-- add the current display settings to the stored settings
set currentSettings to {w:desktopWidth, h:desktopHeight, apps:{}}
set end of allSettings to currentSettings
--say "creating new config for " & desktopResolution
else
--say "found config for " & desktopResolution
end if
end tell
tell application "System Events"
if (button returned of dialogResult is "Save") then
say "saving"
repeat with p in every process
if background only of p is false then
tell application "System Events" to tell application process (name of p as string)
set appName to name of p
if (count of windows) > 0 then
set appSize to size of window 1
set appPosition to position of window 1
else
set appSize to 0
set appPosition to 0
end if
set appSettings to {}
repeat with i from 1 to (count of apps of currentSettings)
if name of item i of apps of currentSettings is name of p then
set appSettings to item i of apps of currentSettings
end if
end repeat
if (count of appSettings) is 0 then
set appSettings to {name:appName, position:appPosition, size:appSize}
set end of apps of currentSettings to appSettings
else
set position of appSettings to appPosition
set size of appSettings to appSize
end if
end tell
end if
end repeat
end if
if (button returned of dialogResult is "Restore") then
if (count of apps of currentSettings) is 0 then
say "no window settings were found"
else
say "restoring"
repeat with i from 1 to (count of apps of currentSettings)
set appSettings to item i of apps of currentSettings
set appName to (name of appSettings as string)
try
tell application "System Events" to tell application process appName
if (count of windows) > 0 then
set position of window 1 to position of appSettings
set size of window 1 to size of appSettings
end if
end tell
end try
end repeat
end if
end if
end tell
https://gist.github.com/cmackay/5863257

Resources