AppleScript: Trying to bring one Safari window to the front without bringing all Safari windows to the front

Posted by Pierre Igot in: Macintosh
July 13th, 2004 • 11:35 pm

I have a fairly simple problem. I use Safari to view a variety of web pages that I read right away or that I leave open in Safari in order to read them later.

And I also use Safari to access a terminology database called TERMIUM that I need for my translation work.

When I am working, I need to be able to switch quickly from Microsoft Word to the Safari window containing TERMIUM and back — and also to keep all my currently open Word document windows visible, even when they are in the background.

And I want to be able to do this with the keyboard.

In order to switch between Word and Safari, I can use Mac OS X’s Application Switcher (command-Tab) or I can assign specific keyboard shortcuts to Word and Safari using DragThing and then use these shortcuts instead.

The problem is that, in both cases, using the keyboard to switch between applications causes all application windows to come to the front. This is not a problem when I switch to Word, because I want to see all the Word windows I have open. But it is a problem in Safari, because, when I am working, I only want to see the TERMIUM window. I don’t want to see all the other web pages that I have open in several other windows in Safari, because they are most often unrelated to what I am working on.

Is there a simple way to bring only a specific application window to the front using the keyboard? Not that I can tell… The only way to switch from Word to Safari and only bring the TERMIUM window to the front is either to click on the TERMIUM window itself with the mouse pointer or to select the TERMIUM window in Safari’s Dock menu (but only if Safari is not hidden; if Safari is hidden, selecting a window in Safari’s Dock menu will bring all Safari windows to the front).

Since I knew a little about AppleScript and in particular about GUI Scripting, I figured I could try to create an AppleScript script that would mimic the mouse click on the TERMIUM window and bring that window only to the foreground.

Well, it turns out that it is not as straightforward as I thought. With the help of Sven-S. Porst, I was able to determine the object hierarchy of the TERMIUM window in Safari that I wanted to bring to the foreground.

I was also able to use a command to bring the TERMIUM window to the fore inside the Safari window hierarchy, and to obtain the bounds of that particular window:

tell application "System Events"
	if window "TERMIUM Plus®" of application process "Safari" exists then
		set (index of window ¬
			"TERMIUM Plus®" of application process "Safari") to 1
		set myBounds to bounds of window ¬
			"TERMIUM Plus®" of application process "Safari"
		click at myBounds
	end if
end tell

But I was simply unable to mimic the actual click on the window to bring it to the foreground. There is a click command in System Events’ AppleScript dictionary, but I was unable to get it to do what I wanted. Presumably it is because System Events interprets the click as coming from within the Safari application itself, in which case it will obviously not cause my system to switch to Safari in the first place, which is exactly what I want.

Yet strangely, as Sven and I noted, when using the UI Element Inspector to lock on the Safari window in question, the UI Element Inspector palette offers an option to perform an action on the window called “AXRaise“, and performing that action does cause Mac OS X to switch to Safari and to bring only the TERMIUM window to the foreground, which is exactly what I want to do.

However, if I try to tell the window to perform the action in the script, using this line:

perform (action "AXRaise")

nothing happens.

So I am effectively stumped.

Since I can’t really spend hours trying to solve this mystery, I ended up creating a different script that “hides” all my other Safari windows behind the TERMIUM window:

tell application "Safari"
	get name of window "TERMIUM Plus®"
	if (window "TERMIUM Plus®") exists then
		set myBounds to bounds of window "TERMIUM Plus®"
		set index of window "TERMIUM Plus®" to 1
		set myCount to count of windows
		repeat with i from 2 to myCount
			set bounds of window i to ¬
				{(item 1 of myBounds) + 5 * i, ¬
					(item 2 of myBounds) + 5 * i, ¬
					(item 3 of myBounds) + 5 * i, ¬
					(item 4 of myBounds) + 5 * i}
		end repeat
	end if
end tell

After I have used that script, I can now use the Application Switcher to switch between Word and Safari. It will still bring all Safari windows to the front, but since all other Safari windows are hidden behind my TERMIUM window, it doesn’t really matter.

I am still disappointed that I have been unable to script this properly the way I wanted to. The whole premise of GUI Scripting is that you should be able to mimic UI actions with AppleScript scripts. But it seems to work best within the context of a single application (whether the application is scriptable or not). When you try to use it for switching between applications, it becomes a problem.

The key thing to understand here is that what I am trying to do involves scripting Mac OS X itself, not one specific Mac OS X application. In previous generations of AppleScript, this was a bit tricky because some system-wide actions were actually done through the Finder, even though they had nothing to do with the Finder. Now in Panther we have this “System Events” application which actually pilots those system-wide aspects of the computing environment. However, as my experience here demonstrates, even a seemingly simple thing such as a click on a background window to bring it to the front is not so easy to achieve by scripting System Events. Maybe I am missing something obvious here. Or maybe it simply isn’t part of what you can do with System Events, which would be a shame.

In any case, I am leaving things as they are now, and I’ll use my “Hide Windows Behind TERMIUM” script whenever I need to focus on work and on TERMIUM and other windows open in Safari might get in the way.

(I could also use a different browser, such as Camino, to access TERMIUM, but unfortunately TERMIUM doesn’t support these other browsers properly. In fact, it doesn’t even support Safari 100%. There are still visual glitches here and there, but fortunately they don’t prevent the database from being usable. I have reported the glitches to TERMIUM, but they have yet to do anything about them.)

PS: Thanks to Sven-S. Porst for his help.

7 Responses to “AppleScript: Trying to bring one Safari window to the front without bringing all Safari windows to the front”

  1. Pierre Igot says:

    Will: Thanks. Your script does the same as mine when it comes to changing the order of windows within Safari, but it does nothing when it comes to bringing Safari to the foreground :).

    I’ll have a look at the virtual desktop software, but I am a bit wary of adding yet another layer of third-party software customization.

  2. Will says:

    This was the best I could do, after misreading what you wanted :)

    tell application “Safari”
    –return properties of window “Google”
    set the visible of window “Google” to false
    set the visible of window “Google” to true
    end tell

    Thought it might be interesting nonetheless.

    Alternatively, I’d recommend virtual desktops. As a recent convert to them, this is one of the cases that they fix ideally.

    I use Desktop Manager, which is free:

  3. Grant Thompson says:

    Why don’t you just use tabs in Safari, instead of opening all those windows?

  4. Pierre Igot says:

    I use both tabs and windows, depending on how I organize my reading. Tabs are fine up to a point. You don’t want 15 tabs in the same window. And sometimes you want to be able to see pages side by side.

  5. mikeh says:

    I found this while googling for a solution to another issue. While reading your entry, it occurred to me that one could go up a level from gui scripting (as far as clicking is concerned) and invoke mousekeys from an applescript. Just for kicks, turn on mousekeys (in accessibility preferences) and then run this in the script editor:

    tell application “System Events”
    say “one”
    delay 1
    say “two”
    delay 1
    say “three”
    delay 1
    key code 87
    end tell

    I’m not exactly sure how this is useful, but thought I might as well pitch it in.

  6. Pierre Igot says:

    Wow, this Witch application actually does work :). Thanks for the link!

  7. mikeh says:

    oh, you should also definitely check out this new window switching app:

Leave a Reply

Comments are closed.