views:

56

answers:

1

I have a Swing application which consists of a single JFrame set to Always On Top.

When running under Windows, I use the following code to open the the native default email client and browser respectively:

Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + Utils.formatMailtoUrl(to, subject, body));
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);

Because the JFrame is set to Always On Top while the typical default browser or email client(IE and Outlook for our customer) does not open as Always On Top, the former obstructs the later.

Our current "solution" is to minimize the JFrame at the same time the native windows are opened. But this turns out to be a 508 compliance issue, and we are being asked to:

  1. Not minimize the JFrame.
  2. Return focus to the JFrame after either the browser or email client are closed

The strategy I have in mind is to "turn off" the Always On Top state of the JFrame and have some kind of callback or event listener which will notify the JFrame that email or browser windows have been closed and then switch the JFrame back to the Always On Top state and set focus.

Because this is a Java app, I am worried this is next to impossible because we are talking about native interop. Is my strategy doable, is there a better doable strategy, and, most importantly, how can it be done?!

Thanks in advance!

[Edit]

I am having some success with the following:

  1. When the action for opening the browser (for example) is fired, turn off the JFrame Always On Top setting.
  2. Have a on window focus action which turns on the JFrame Always On Top setting.
  3. If the user does not navigate to any other windows besides the browser, then when the browser closes the JFrame will automatically regain focus and thus be set back to Always On Top

There are two drawbacks I see with this approach. The first is that the user might manually go back to the JFrame window before closing the browser window causing the JFrame to regain focus and get stuck in Always On Top mode. But this might be acceptable. The second issue is that the JAWS version 9 screen reader goes crazy and re-reads the last focused component at least 3 times once the JFrame regains focus.

+1  A: 

I am not sure if there is a native way to do this, but you can run tasklist.exe or a vb script, capture the results and from there determine if Outlook or IExplore is running. This would require that you run a check at some reasonable interval instead of waiting on an event.

Process p = Runtime.getRuntime().exec("tasklist.exe /FO CSV /FI eq outlook.exe");
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
    look for a line containing outlook.exe
}
input.close();

You will have to check for outlook.exe and iexplorer.exe separately since I don't think you can filter tasklist on this OR that.

I'm sure that this can be generalized to look for whatever is opened by your original call.

Edit: Now that I have written all this, it occurs to me that your original call returns a process and that can be used. So something to try, start a new thread, open the default email program or browser in that thread, remove the "always on top" condition and call waitfor on the process that is returned. After that call, set the "always on top" condition. That thread will wait for the process to end without locking up your gui or other program functions.

phill
@phill, you've given me hope! I will get back to you when I am able to play around with this idea.
Stephen Swensen
If you use the second method, and expect more then one to be open at a time, make sure you use a semaphore to ensure the "always on top" property is not set prematurely. As it is now, the first one to close will set the property were you want the last one to close to do it instead.
phill
Nice tip, thanks. Right now, it looks like I might not be able to use the second method. First, the Process being returned is for rundll32 not the application rundll32 in turn launches. It's possible we'd be able to launch the IE and Outlook processes directly from their locations on the file system, but even then there is a fatal issue: multiple IE browser instances share a single Process so waitFor doesn't return until all of them are closed.
Stephen Swensen