Global key listener

349 views
Skip to first unread message

dflorey

unread,
Jul 24, 2007, 4:51:43 AM7/24/07
to Google Web Toolkit
Hi all,
what is the best way to implement a reliable "global" key listener? I
want to implement a key binding for my app that works regardless which
widget is focussed. Any tips?
Thanks in advance,
Daniel

Reinier Zwitserloot

unread,
Jul 24, 2007, 12:16:59 PM7/24/07
to Google Web Toolkit
It's not exactly intended use, I think, but you could use the event
preview system (DOM.set/addEventPreview if memory serves).

Note that key listeners in general are an inconsolable inter-browser
mess. I'm not sure what you're trying to do, but I can virtually
guarantee that it won't work very well.

keyCode numbers differ between both Browsers and keyboard layouts. As
there's no practical way to test the keyboard layout of a user, you're
stuck. Also, keyhandlers act differently on different browsers (e.g.
most control keys don't trigger a keyPressed on IE, but they do on all
other browsers).

Currently, GWT does NOT try and normalize these differences. In fact,
it's impossible to fully normalize this, but there is an issue about
at least making a keyboard listener that normalizes as much as is
possible.

There's LOTS of info on keyboard handling in general (not specifically
for binding globally) archived for the RFE issue, here:

http://code.google.com/p/google-web-toolkit/issues/detail?id=1061&can=4

If you want to keep tabs on this, star the issue and make sure the
tracker knows your email address, then you'll receive emails anytime
someone updates that issue.

Fred Sauer

unread,
Jul 30, 2007, 5:25:32 PM7/30/07
to Google-We...@googlegroups.com
Daniel,

I filed this issue which hopefully will address your question long term:
  http://code.google.com/p/google-web-toolkit/issues/detail?id=1442

In the short term I recommend using JSNI to hook $doc.onkeydown/up/press with your own handler.

Below it a bit of code to get you started, which handles global key events. It still needs to some work though, like making sure the cleanup code is complete, and that it actual works as expected in all the GWT supported browsers (I only tested a few). Also, the keyboard handling could certainly be improved as the issue that Reinier mentioned is addressed.

package example.client;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window ;
import com.google.gwt.user.client.WindowCloseListener;

/**
 * Use at your own risk. But, have fun.
 */
public final class Keyboard {
  private static final class WindowCloseListenerImpl implements WindowCloseListener {
    public native void onWindowClosed()
    /*-{
      $doc.onkeydown = null;
      $doc.onkeypress = null;
      $doc.onkeyup = null;
    }-*/;

    public String onWindowClosing() {
      return null;
    }

    private native void init()
    /*-{
      $doc.onkeydown = function(evt) {
        @example.client.Keyboard::onKeyDown(Lcom/google/gwt/user/client/Event;)(evt || $wnd.event);
      }
      $doc.onkeypress = function(evt) {
        @example.client.Keyboard::onKeyPress(Lcom/google/gwt/user/client/Event;)(evt || $wnd.event);
      }
      $doc.onkeyup = function(evt) {
        @example.client.Keyboard::onKeyUp(Lcom/google/gwt/user/client/Event;)(evt || $wnd.event);
      }
    }-*/;
  }

  static {
    WindowCloseListenerImpl closeListener = new WindowCloseListenerImpl();
    Window.addWindowCloseListener(closeListener);
    closeListener.init();
  }

  /**
   * Can be called from your code to force installation of
   * the event handling hooks.
   */
  public static void forceStaticInit() {
  };

  private static void onKeyDown(Event event) {
    char keyCode = (char) DOM.eventGetKeyCode(event);
    // ....your code here....
  }

  private static void onKeyPress(Event event) {
    char keyCode = (char) DOM.eventGetKeyCode(event);
    // ....your code here....
  }

  private static void onKeyUp(Event event) {
    char keyCode = (char) DOM.eventGetKeyCode(event);
    // ....your code here....
  }

  /**
   * Prevent instantiation.
   */
  private Keyboard() {
  }
}


Hope that helps,
Fred
--
Fred Sauer
fr...@allen-sauer.com
Reply all
Reply to author
Forward
0 new messages