how to activate window, not app?

I'm trying to write a very simple applescript to just create a new
Terminal window and set it to be frontmost (i.e. so it has focus)
without raising all the other Terminal I have open. The following
creates the new Terminal window but results in all the other Terminal
windows I have open behind my other windows being raised, which I'm
trying to avoid:

tell application "Terminal"
activate
do script ""
end tell


I stumbled on an old thread that seemed to be asking the same
question at http://groups.google.com/group/alt.comp.lang.applescript/browse_frm/thread/31a26 61b7ee29f06, but I don't see how the example given accomplishes this. Can anyone help?

Thanks!
Josh

[Note: Cross posted from http://groups.google.com/group/alt.comp.lang.applescript/browse_frm/thread/b1fee 62777be00e2, as I haven't had any responses on the newsgroup.]

MacBook5,1, Mac OS X (10.6.1)

Posted on Nov 2, 2009 1:37 PM

Reply
Question marked as Top-ranking reply

Posted on Nov 2, 2009 2:10 PM

--Does this help?


tell application "Terminal"
set visible of every window whose visible is true to false
do script ""
end tell


-- to recover the original visible window(s), add this (the 5 second delay gives you time to assess the first part of the script):


delay 5
tell application "Terminal"
set visible of every window whose visible is false to true
end tell


-- I think there can be a number of variations on this entire approach. I find that if I quit and then relaunch Terminal, the new Terminal window is not there (or not visible), but the original window(s) are once again visible.
20 replies
Question marked as Top-ranking reply

Nov 2, 2009 2:10 PM in response to jab630

--Does this help?


tell application "Terminal"
set visible of every window whose visible is true to false
do script ""
end tell


-- to recover the original visible window(s), add this (the 5 second delay gives you time to assess the first part of the script):


delay 5
tell application "Terminal"
set visible of every window whose visible is false to true
end tell


-- I think there can be a number of variations on this entire approach. I find that if I quit and then relaunch Terminal, the new Terminal window is not there (or not visible), but the original window(s) are once again visible.

Nov 3, 2009 4:18 AM in response to jab630

Suppose that only three windows are open on your computer: two Safari windows in the background, and one TextEdit window at front. Now, if you click on one of the Safari windows, that window will become the frontmost window, and Safari the frontmost application, while the other Safari window will stay behind the TextEdit window. It seems to me impossible to do the same thing with AppleScript alone, even with GUI scripting.

Morevover, it seems to me that such a situation, where the windows of different applications are “interlaced”, is somewhat inconsistent with the usual behavior of Mac OS X. Normally, as soon as an application is activated, all of its windows should be brought in front of the windows of all the other applications.

Nov 4, 2009 2:31 AM in response to jab630

_PLEASE NOTE_: A few hours ago I inadvertently posted this as a reply to Pierre L. (which is okay, as I'd like him to have a look at it as well). But, in the meantime, I've made a very small change to the Finisher_.app, and I've included that in this response -- it's probably totally unnecessary, but could conceivably improve the overall reliability of this approach. There is one other issue I'm a bit concerned about (although I haven't had any problems); but, if you should get an error message regarding the PID number ("doesn't exist"), let me know and I'll see what I can do about it.

No promises, and I've sort of lost track of your original goal, but you might try this double-pronged approach:

1) paste this script into your editor and save it as " Starter_" _as an application to the desktop_:
tell application "Terminal"
set visible of every window whose visible is true to false
do script ""
set WinID_ to item 1 of every window
end tell
tell application "Finisher_" to activate


2) Now paste the following script into a fresh editor window and save it as " Finisher_" _as an application to the desktop_:
set PIDlist_ to do shell script "ps -cx"
set PIDcnt_ to count paragraphs of PIDlist_
repeat with i_ from 1 to PIDcnt_
set TarPar_ to paragraph i_ of PIDlist_
if TarPar_ contains "Starter_.app" then
set Starter_PID to characters 1 through 5 of TarPar_ as string
exit repeat
end if
end repeat
tell application "Terminal" to activate
do shell script "kill " & Starter_PID


*From this point on, ignore the Finisher_.app on the desktop* (it probably can be saved elsewhere).

Now arrange the desktop as you wish, with Terminal windows you can afford to lose (but I don't expect you will). Then double-click "Starter_.app" and see what that buys you. Once again, the original Terminal windows should be retrievable by quitting and relaunching Terminal.

This works for me to bring up a new Terminal window (only) at the front of all windows of other applications, with Terminal in focus. And, once again, seems to me a lot of other things could be accomplished with this approach, but we'll see.

Nov 3, 2009 8:36 AM in response to Noaks

Is this consistent with what you are saying?


That's exactly what I was saying (or rather trying to say). On the other hand, taking your example, if you activate Script Editor not by clicking on ScriptEditor #1, but by pressing the TAB key four times (or seven times) while maintaining the ⌘ key down, both Script Editor #1 and Script Editor #2 come to the front, while all other windows retain their original relative positions. I was also trying to say that it seems impossible to me, using AppleScript (and even GUI scripting), to activate any application without automatically bringing all of its windows to the front.

Nov 4, 2009 7:14 AM in response to jab630

Hello

As far as I know, what you're asking for is hard to accomplish even in Objective-C because Apple is not documenting the Window Server's basic APIs which are essential to globally control the windows' order and such.

If the window in question belongs to your own application, -(void)orderFront: of NSWindow will do what you want.
But, if I'm not mistaken, you cannot do the same thing for a Terminal's window from outside the Terminal's address space.
cf.
http://lists.apple.com/archives/cocoa-dev/2002/May/msg00609.html
http://lists.apple.com/archives/cocoa-dev/2002/May/msg00717.html
etc.

Someone has reverse engineered some undocumented APIs of Core Graphics for controlling windows globally.
Just FYI.
cf.
http://www.cocoadev.com/index.pl?CoreGraphicsPrivate

Also there's rather new official Quartz Window Services Reference.
However, these functions seem to only get some information about windows.
cf.
http://developer.apple.com/mac/library/documentation/Carbon/Reference/CGWindow_R eference/index.html

After all, I don't think it's a simple task for user to manipulate the global z-order of windows programmatically.
(I'd guess the Witch - http://www.manytricks.com/witch/ - is using undocumented APIs, though of course I may be wrong.)

Cheers,
H

Message was edited by: Hiroto (fixed typo)

Nov 2, 2009 3:51 PM in response to jab630

--Odd, that's not the behavior I'm seeing. Is it possible you're combining the two parts of the script without removing the redundant tell & end tell commands? Try the script below exactly as shown -- to which I've added a command that hopefully will make the new Terminal window open at the front (but note my comment about the initial relative positions of the Terminal and script editor applications).

--If this works, I'd suggest you make a new post about the Safari issue.


tell application "Terminal"
set visible of every window whose visible is true to false
tell application "System Events" to keystroke tab using command down -- which will work if Terminal is the app immediately "behind" the script editor app you're using. (The script editor is always trying to hog center stage -- after all, it's the application you're last using.)

do script ""

delay 10 -- (or however much time you need)

set visible of every window whose visible is false to true

end tell

Nov 3, 2009 9:45 AM in response to Noaks

… activate a window without activating all the other windows…


Oops… That's not what I had in mind. Let's try again.

I think (but I'd like to be wrong) that it is impossible, using AppleScript alone, to activate a window without bringing all the other windows of the same application in front of the windows of all the other applications.

Nov 3, 2009 10:12 PM in response to Pierre L.

No promises, and I've sort of lost track of your original goal, but you might try this double-pronged approach:

1) paste this script into your editor and save it as " Starter_" as an application to the desktop:

tell application "Terminal"
set visible of every window whose visible is true to false
do script ""
set WinID_ to item 1 of every window
end tell
tell application "Finisher_" to activate


2) Now paste the following script into a fresh editor window and save it as " Finisher_" as an application to the desktop:

set PIDlist_ to do shell script "ps -cx"
set PIDcnt_ to count paragraphs of PIDlist_
repeat with i_ from 1 to PIDcnt_
set TarPar_ to paragraph i_ of PIDlist_
if TarPar_ contains "Starter_.app" then
set Starter_PID to characters 1 through 5 of TarPar_ as string
end if
end repeat
tell application "Terminal" to activate
do shell script "kill " & Starter_PID


*From this point on, ignore the Finisher_.app on the desktop* (it probably can be saved elsewhere).

Now arrange the desktop as you wish, with Terminal windows you can afford to lose (but I don't expect you will). Then double-click "Starter_.app" and see what that buys you. Once again, the original Terminal windows should be retrievable by quitting and relaunching Terminal.

This works for me to bring up a new Terminal window (only) at the front of all windows of other applications, with Terminal in focus. And, once again, seems to me a lot of other things could be accomplished with this approach, but we'll see.

Nov 2, 2009 3:06 PM in response to Noaks

Thanks for the reply. I tried this out but it doesn't seem to be what I'm looking for. Unfortunately it resulted in my losing my existing Terminal windows (even after the second half of the script executed), and quitting and relaunching Terminal did not restore them. Moreover, the new terminal window which was spawned did not actually get the focus; I still had to command-tab over to give Terminal focus, which is a show-stopper because it results in raising all (visible) Terminal windows rather than just the new one.

I know it's possible to raise and activate only a single window from an application which doesn't currently have the focus as this is exactly what http://www.manytricks.com/witch/ allows you to do. Hopefully someone knows a way to Applescript this.

I'd also like to be able to do the same for the following Applescript, which just opens a new Safari window:

tell application "Safari"
activate
make new document
end tell

Nov 2, 2009 4:07 PM in response to Noaks

Thanks again for the reply. Unfortunately, hardcoding in a single Command+Tab keystroke isn't going to work because Terminal won't always be the previous application. Sorry, I should have given more context: I've added this script to my QuickSilver catalog and added a custom trigger for it, so I can simply hit e.g. CommandControlN to pop up a new Terminal window from anywhere on my system. Any ideas on how Witch is selectively and exclusively raising and setting focus to a single window of another application?

Nov 3, 2009 6:36 AM in response to Pierre L.

I'm not certain you are correct on that. I think I presently have the following windows "interlaced" on the desktop, rearmost to frontmost:

12) Script Debugger #1
11) TextEdit #1
10) Safari #1
9) Mail
8) Script Editor #1
7) Script Debugger #2
6) Finder
5) Script Editor #2
4) TextEdit #2
3) Script Debugger #3
2) Firefox
1) Safari #2

Now, if I click on Script Editor #1 (originally #8 overall), it becomes frontmost while all other windows move back a step but retain their original relative positions. If I now click on the window originally #1 overall (this window, in fact), it regains its frontmost position but Script Editor #1 now assumes the #2 overall position -- but all other windows retain their original relative positions.

If I do the above routine starting with Safari #1, an identical scenario ensues.

Is this consistent with what you are saying?

(Excuse me, I need to find a concrete wall to bang my head against!)

Nov 3, 2009 8:00 AM in response to Pierre L.

Pierre L. wrote:
It seems to me impossible to do the same thing with AppleScript alone, even with GUI scripting.


If that's true, then I'm posting in the wrong place! Anyone have any other ideas? My solution doesn't have to be Applescript, I'll take anything that will work.

Morevover, it seems to me that such a situation, where the windows of different applications are “interlaced”, is somewhat inconsistent with the usual behavior of Mac OS X.


Disagree; this is merely one aspect of the usual behavior, and one we've all come to expect at that. If I'm working in window 1 of application 1 and I click on the titlebar of window x of application 2, I expect only window x to be raised, not all other windows of application 2. That would be totally disruptive.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

how to activate window, not app?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.