Is there a reliable way to detect the application window losing focus (minimizing, etc.)?

458 views
Skip to first unread message

Dawson

unread,
Jul 18, 2008, 3:36:27 PM7/18/08
to Google Web Toolkit
Simply put we are developing a testing application that needs to know
if the person taking the test leaves the test window at any time so
that the test event can be brought to the proctor's attention. I have
created something similar to what I found in some previous postings
but it does not seem reliable and has some odd behavior.

In the GWT Shell I always see:

WindowEventManager.notifyOnFocus...
WindowEventManager.notifyOnBlur...

When the then window loses focus and regains its. This seems
backwards. To gain focus and then loses it makes no sense. When I
compile and use Firefox I receive multiples of the events so the
counter goes up by 2 each time a focus change happens and sometime
just when the TextBox loses focus. IE and Safari (all tested on
Windows XP) seem to behave much better.

Am I missing something? I really need to find a solution here as we
need to support all the primary browsers. Any and all help is much
appreciated.

Thanks, Dawson


FocusTest.java
----------------------
package org.nwea.gwt.test.focus.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class FocusTest implements EntryPoint, WindowEventListener {

private int lostCount = 0;
private HTML countLabel = null;
private SimplePanel main = new SimplePanel();
private TextBox edit = new TextBox();
private WindowEventListener windowListener = null;

/**
* This is the entry point method.
*/
public void onModuleLoad() {
main.setStylePrimaryName("n0-Body");
main.setSize("100%", "100%");
VerticalPanel panel = new VerticalPanel();
panel.setSpacing(4);
panel.add(new HTML("Switch to a different program to blur this
page."));
panel.add(new HTML("You can also just click the location bar."));
panel.add(new HTML("Click this page again to focus it."));
panel.add(new HTML("When blurred, this page will have a black
background with white text."));
countLabel = new HTML("This page has lost focus " + lostCount + "
times.");
panel.add(countLabel);
panel.add(edit);
main.add(panel);
RootPanel.get().add(main);

windowListener = this;

DeferredCommand.addCommand( new Command() {

public void execute() {
edit.setFocus(true);
WindowEventManager.addListener(windowListener);
}

});
}

public void onWindowBlurred() {
lostCount++;
countLabel.setHTML("This page has lost focus " + lostCount + "
times.");
}

public void onWindowFocused() {
}

}


WindowEventManager.java
---------------------------------------
package org.nwea.gwt.test.focus.client;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;

public class WindowEventManager {

private static final WindowEventManager instance = new
WindowEventManager();

private static List<WindowEventListener> listeners = new
ArrayList<WindowEventListener>();

private WindowEventManager() {
WindowEventManager.initialize();
}

private native static void initialize() /*-{

$wnd.onblur = function()
{ @org.nwea.gwt.test.focus.client.WindowEventManager::notifyOnBlur()
(); }

$wnd.onfocus = function()
{ @org.nwea.gwt.test.focus.client.WindowEventManager::notifyOnFocus()
(); }

}-*/;

public static WindowEventManager getInstance() {
return WindowEventManager.instance;
}

static void notifyOnFocus() {
GWT.log("WindowEventManager.notifyOnFocus...", null);
for (WindowEventListener listener : listeners) {
listener.onWindowFocused();
}
}

static void notifyOnBlur() {
GWT.log("WindowEventManager.notifyOnBlur...", null);
for (WindowEventListener listener : listeners) {
listener.onWindowBlurred();
}
}

public static void addListener(WindowEventListener listener) {
GWT.log("add listener = " + listener, null);
listeners.add(listener);
}

public static void removeListener(WindowEventListener listener) {
listeners.remove(listener);
}

}



WindowEventListener.java
--------------------------------------
package org.nwea.gwt.test.focus.client;

public interface WindowEventListener {

public void onWindowFocused();

public void onWindowBlurred();

}




Fred Sauer

unread,
Jul 20, 2008, 10:13:22 AM7/20/08
to Google-We...@googlegroups.com
Dawson,

The interpretation is that only one element can be focused at a time. Right after the window gains focus, it is lost again to an element on your page. If you can track focus on elements on your page, then you can distinguish real window blurs from blurs lost to element focus.

I wrote a game, Hornet Blast, which I wanted to pause when the window blurred, and resume when it gained focus. I offer it up because you can test the automatic gaming pausing functionality in your target browsers and confirm that the principals work. Start the game, then give another window focus to pause the game. Simply ALT-TAB (or your platform equivalent) back to the game window to have the game resume. Here's the URL.

  http://allen-sauer.com/com.allen_sauer.gwt.game.hornetblast.HornetBlast/HornetBlast.html

Fred Sauer
fr...@allen-sauer.com

sloughran

unread,
Jul 21, 2008, 9:48:15 AM7/21/08
to Google Web Toolkit
I have a question regarding your game. Do you just use Timers to
update the positions of all the "enemies" and the Ammunition on a
giant Absolute Panel? I have made animations like this and wasn't sure
if that was the best way to do, but it's the only way I know how to.

On Jul 20, 10:13 am, "Fred Sauer" <f...@allen-sauer.com> wrote:
> Dawson,
>
> The interpretation is that only one element can be focused at a time. Right
> after the window gains focus, it is lost again to an element on your page.
> If you can track focus on elements on your page, then you can distinguish
> real window blurs from blurs lost to element focus.
>
> I wrote a game, Hornet Blast, which I wanted to pause when the window
> blurred, and resume when it gained focus. I offer it up because you can test
> the automatic gaming pausing functionality in your target browsers and
> confirm that the principals work. Start the game, then give another window
> focus to pause the game. Simply ALT-TAB (or your platform equivalent) back
> to the game window to have the game resume. Here's the URL.
>
> http://allen-sauer.com/com.allen_sauer.gwt.game.hornetblast.HornetBla...
>
> Fred Sauer
> f...@allen-sauer.com

Dawson

unread,
Jul 21, 2008, 2:56:16 PM7/21/08
to Google Web Toolkit
So did you use the same technique I did to detect the Window.onBlur()
event? If not how did you do it? I did try the game in several of
the browser and the pause effect functioned as expected. Thank you
for at least illustrating that it could be done reliably. Now I just
need to find out how if it differs from what I'm already trying.

Thanks, Dawson

On Jul 20, 7:13 am, "Fred Sauer" <f...@allen-sauer.com> wrote:
> Dawson,
>
> The interpretation is that only one element can be focused at a time. Right
> after the window gains focus, it is lost again to an element on your page.
> If you can track focus on elements on your page, then you can distinguish
> real window blurs from blurs lost to element focus.
>
> I wrote a game, Hornet Blast, which I wanted to pause when the window
> blurred, and resume when it gained focus. I offer it up because you can test
> the automatic gaming pausing functionality in your target browsers and
> confirm that the principals work. Start the game, then give another window
> focus to pause the game. Simply ALT-TAB (or your platform equivalent) back
> to the game window to have the game resume. Here's the URL.
>
> http://allen-sauer.com/com.allen_sauer.gwt.game.hornetblast.HornetBla...
>
> Fred Sauer
> f...@allen-sauer.com
>

Fred Sauer

unread,
Jul 22, 2008, 12:50:35 AM7/22/08
to Google-We...@googlegroups.com
There is a recurring timer which executes one event loop to update all the sprite positions, which are indeed on one or two big absolute panels.

Fred Sauer
fr...@allen-sauer.com

Fred Sauer

unread,
Jul 22, 2008, 12:54:42 AM7/22/08
to Google-We...@googlegroups.com
Since the game was a very specific use case (I didn't have lots of text widgets to deal with for example), I was able to implement a single in browser widget (focus panel if memory serves) which always gets focus when the window object blurs as a result of focus flowing to a child. Having said that, IE6 was a *pain* since it handles transparency differently. I reverted to some conditional CSS to finally workaround the last of those issues.

You may be able to do the same without requiring a focus listener on every single widget on your page. Then again, there seem to be issues with focus/blur events not bubbling, or not being event previewable or both.

In any case, I wanted to do exactly what you said: show you what could be accomplished, so you'd know if you were on an impossible or feasible mission.

HTH
Fred Sauer
fr...@allen-sauer.com
Reply all
Reply to author
Forward
0 new messages