All Downloads are FREE. Search and download functionalities are using the official Maven repository.

playn.html.HtmlInput Maven / Gradle / Ivy

There is a newer version: 2.0.8
Show newest version
/**
 * Copyright 2011 The PlayN Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package playn.html;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;

import pythagoras.f.Point;
import react.RFuture;

import playn.core.*;

public class HtmlInput extends Input {

  private final HtmlPlatform plat;
  private final Element rootElement;

  private final Point lastMousePt = new Point();
  // true when we are in a drag sequence (after mouse down but before mouse up)
  private boolean inDragSequence = false;
  private boolean isRequestingMouseLock;

  // true when we are in a touch sequence (after touch start but before touch end)
  private boolean inTouchSequence = false;

  public HtmlInput (HtmlPlatform hplat, Element root) {
    super(hplat);
    this.plat = hplat;
    this.rootElement = root;

    // wire up keyboard handlers
    capturePageEvent("keydown", new EventHandler() {
      @Override public void handleEvent(NativeEvent nevent) {
        Key key = keyForCode(nevent.getKeyCode());
        dispatch(new Keyboard.KeyEvent(0, plat.time(), key, true), nevent);
      }
    });
    capturePageEvent("keypress", new EventHandler() {
      @Override public void handleEvent(NativeEvent nevent) {
        dispatch(new Keyboard.TypedEvent(0, plat.time(), (char)nevent.getCharCode()), nevent);
      }
    });
    capturePageEvent("keyup", new EventHandler() {
      @Override public void handleEvent(NativeEvent nevent) {
        Key key = keyForCode(nevent.getKeyCode());
        dispatch(new Keyboard.KeyEvent(0, plat.time(), key, false), nevent);
      }
    });

    // wire up mouse handlers
    abstract class XYEventHandler implements EventHandler {
      public void handleEvent(NativeEvent ev) {
        Point xy = plat.graphics().transformMouse(
          getRelativeX(ev, rootElement), getRelativeY(ev, rootElement));
        handleEvent(ev, xy.x, xy.y);
      }
      public abstract void handleEvent(NativeEvent ev, float x, float y);
    }

    abstract class MoveEventHandler extends XYEventHandler {
      private float lastX = -1, lastY = -1;

      @Override public void handleEvent(NativeEvent ev, float x, float y) {
        if (lastX == -1) {
          lastX = x;
          lastY = y;
        }
        if (inDragSequence == wantDragSequence()) {
          float dx;
          float dy;
          if (isMouseLocked()) {
            dx = getMovementX(ev);
            dy = getMovementY(ev);
          } else {
            dx = x - lastX;
            dy = y - lastY;
          }
          dispatch(new Mouse.MotionEvent(0, plat.time(), x, y, dx, dy), ev);
        }
        lastX = x;
        lastY = y;
        lastMousePt.set(x, y);
      }

      protected abstract boolean wantDragSequence();
    }

    // needed so the right mouse button becomes available
    addEventListener(Document.get(), "contextmenu", new EventHandler() {
      @Override public void handleEvent(NativeEvent evt) {
        evt.preventDefault();
        evt.stopPropagation();
      }
    }, false);

    // capture mouse down on the root element, only.
    captureEvent(rootElement, "mousedown", new XYEventHandler() {
      @Override public void handleEvent(NativeEvent ev, float x, float y) {
        inDragSequence = true;
        Mouse.ButtonEvent.Id btn = getMouseButton(ev);
        if (btn != null) dispatch(new Mouse.ButtonEvent(0, plat.time(), x, y, btn, true), ev);
      }
    });

    // capture mouse up anywhere on the page as long as we are in a drag sequence
    capturePageEvent("mouseup", new XYEventHandler() {
      @Override public void handleEvent(NativeEvent ev, float x, float y) {
        if (inDragSequence) {
          inDragSequence = false;
          Mouse.ButtonEvent.Id btn = getMouseButton(ev);
          if (btn != null) dispatch(new Mouse.ButtonEvent(0, plat.time(), x, y, btn, false), ev);
        }
        handleRequestsInUserEventContext();
      }
    });

    // capture mouse move anywhere on the page that fires only if we are in a drag sequence
    capturePageEvent("mousemove", new MoveEventHandler() {
      @Override protected boolean wantDragSequence() { return true; }
    });

    // capture mouse move on the root element that fires only if we are not in a drag sequence
    // (the page-level event listener will handle the firing when we are in a drag sequence)
    captureEvent(rootElement, "mousemove", new MoveEventHandler() {
      @Override protected boolean wantDragSequence() { return false; }
    });

    captureEvent(rootElement, getMouseWheelEvent(), new EventHandler() {
      @Override public void handleEvent(NativeEvent ev) {
        float vel = getMouseWheelVelocity(ev);
        dispatch(new Mouse.WheelEvent(0, plat.time(), lastMousePt.x, lastMousePt.y, vel), ev);
      }
    });

    // capture touch start on the root element, only.
    captureEvent(rootElement, "touchstart", new EventHandler() {
      @Override public void handleEvent(NativeEvent nevent) {
        inTouchSequence = true;
        dispatch(toTouchEvents(Touch.Event.Kind.START, nevent), nevent);
      }
    });

    // capture touch move anywhere on the page as long as we are in a touch sequence
    capturePageEvent("touchmove", new EventHandler() {
      @Override public void handleEvent(NativeEvent nevent) {
        if (inTouchSequence) dispatch(toTouchEvents(Touch.Event.Kind.MOVE, nevent), nevent);
      }
    });

    // capture touch end anywhere on the page as long as we are in a touch sequence
    capturePageEvent("touchend", new EventHandler() {
      @Override public void handleEvent(NativeEvent nevent) {
        if (inTouchSequence) {
          dispatch(toTouchEvents(Touch.Event.Kind.END, nevent), nevent);
          // if there are no remaining active touches, note that this touch sequence has ended
          if (nevent.getTouches().length() == 0) inTouchSequence = false;
        }
      }
    });
  }

  @Override public boolean hasHardwareKeyboard() {
    return true; // TODO: check whether we're on a mobile device or not
  }

  @Override public native boolean hasTouch() /*-{
    return ('ontouchstart' in $doc.documentElement) ||
      ($wnd.navigator.userAgent.match(/ipad|iphone|android/i) != null);
  }-*/;

  @Override public native boolean hasMouse() /*-{
    return ('onmousedown' in $doc.documentElement) &&
      ($wnd.navigator.userAgent.match(/ipad|iphone|android/i) == null);
  }-*/;

  @Override public native boolean hasMouseLock() /*-{
    return !!($doc.body.requestPointerLock || $doc.body.webkitRequestPointerLock ||
              $doc.body.mozRequestPointerLock);
  }-*/;

  @Override public RFuture getText(Keyboard.TextType textType, String label,
                                           String initVal) {
    String result = Window.prompt(label, initVal);
    emitFakeMouseUp();
    return RFuture.success(result);
  }

  @Override public RFuture sysDialog(String title, String message,
                                              String ok, String cancel) {
    boolean result;
    if (cancel != null) result = Window.confirm(message);
    else {
      Window.alert(message);
      result = true;
    }
    emitFakeMouseUp();
    return RFuture.success(result);
  }

  // HACK HACK HACK HACK!
  // Chrome and Firefox on Mac OS (at least) fail to deliver the MOUSE UP event that should be
  // delivered after a system dialog completes, assuming the dialog was triggered on MOUSE DOWN; so
  // we emit a fake mouse up event here just to avoid causing the Pointer system to fail to
  // terminate the current pointer interaction if it happens to have triggered a system dialog; if
  // the dialog was not shown on mouse down, a spurious mouse up is not likely to do much damage; a
  // better devil for sure than failing to deliver a needed mouse up
  private void emitFakeMouseUp () {
    mouseEvents.emit(new Mouse.ButtonEvent(0, plat.time(), 0, 0, Mouse.ButtonEvent.Id.LEFT, false));
  }

  @Override public native boolean isMouseLocked() /*-{
    return !!($doc.pointerLockElement || $doc.webkitPointerLockElement ||
              $doc.mozPointerLockElement);
  }-*/;

  @Override public void setMouseLocked(boolean locked) {
    if (locked) {
      if (hasMouseLock()) {
        isRequestingMouseLock = true;
        plat.log().debug("Requesting mouse lock (supported)");
      } else {
        plat.log().debug("Requesting mouse lock -- but unsupported");
      }
    } else {
      plat.log().debug("Requesting mouse unlock");
      if (hasMouseLock()) {
        isRequestingMouseLock = false;
        unlockImpl();
      }
    }
  }

  static class EventCloseHandler implements HandlerRegistration {
    private final JavaScriptObject target;
    private final String name;
    private final boolean capture;
    private JavaScriptObject listener;

    EventCloseHandler (JavaScriptObject target, String name,
                       EventHandler eventHandler, boolean capture) {
      this.target = target;
      this.name = name;
      this.capture = capture;
      addEventListener(this, target, name, eventHandler, capture);
    }

    void setListener (JavaScriptObject listener) {
      this.listener = listener;
    }

    @Override public void removeHandler () {
      removeEventListener(target, name, listener, capture);
    }

    private native void addEventListener (EventCloseHandler closeHandler,
                                          JavaScriptObject target, String name,
                                          EventHandler handler, boolean capture) /*-{
      var listener = function(e) {
        [email protected]::handleEvent(Lcom/google/gwt/dom/client/NativeEvent;)(e);
      };
      target.addEventListener(name, listener, capture);
      [email protected]::setListener(Lcom/google/gwt/core/client/JavaScriptObject;)(listener);
    }-*/;

    private native void removeEventListener (JavaScriptObject target, String name,
                                             JavaScriptObject listener, boolean capture)/*-{
      target.removeEventListener(name, listener, capture);
    }-*/;
  }

  static HandlerRegistration addEventListener (JavaScriptObject target, String name,
                                               EventHandler handler, boolean capture) {
    return new EventCloseHandler(target, name, handler, capture);
  };

  /** Capture events that occur anywhere on the page. Event values will be relative to the page
    * (not the rootElement) {@see #getRelativeX(NativeEvent, Element)} and
    * {@see #getRelativeY(NativeEvent, Element)}. */
  static HandlerRegistration capturePageEvent (String name, EventHandler handler) {
    return addEventListener(Document.get(), name, handler, true);
  }

  static HandlerRegistration captureEvent (Element target, String name, EventHandler handler) {
    return addEventListener(target, name, handler, true);
  }

  /**
   * Gets the event's x-position relative to a given element.
   *
   * @param e native event
   * @param target the element whose coordinate system is to be used
   * @return the relative x-position
   */
  static float getRelativeX (NativeEvent e, Element target) {
    return (e.getClientX() - target.getAbsoluteLeft() + target.getScrollLeft() +
            target.getOwnerDocument().getScrollLeft()) / HtmlGraphics.experimentalScale;
  }

  /**
   * Gets the event's y-position relative to a given element.
   *
   * @param e native event
   * @param target the element whose coordinate system is to be used
   * @return the relative y-position
   */
  static float getRelativeY (NativeEvent e, Element target) {
    return (e.getClientY() - target.getAbsoluteTop() + target.getScrollTop() +
            target.getOwnerDocument().getScrollTop()) / HtmlGraphics.experimentalScale;
  }

  void handleRequestsInUserEventContext () {
    // hack to allow requesting mouse lock from non-mouse/key handler event
    if (isRequestingMouseLock && !isMouseLocked()) {
      requestMouseLockImpl(rootElement);
    }
  }

  private int mods (NativeEvent event) {
    return modifierFlags(event.getAltKey(), event.getCtrlKey(), event.getMetaKey(),
                         event.getShiftKey());
  }

  private void dispatch (Keyboard.Event event, NativeEvent nevent) {
    try {
      event.setFlag(mods(nevent));
      plat.dispatchEvent(keyboardEvents, event);
    } finally {
      if (event.isSet(Event.F_PREVENT_DEFAULT)) nevent.preventDefault();
    }
  }

  private void dispatch (Mouse.Event event, NativeEvent nevent) {
    try {
      event.setFlag(mods(nevent));
      plat.dispatchEvent(mouseEvents, event);
    } finally {
      if (event.isSet(Event.F_PREVENT_DEFAULT)) nevent.preventDefault();
    }
  }

  private void dispatch (Touch.Event[] events, NativeEvent nevent) {
    try {
      plat.dispatchEvent(touchEvents, events);
    } finally {
      // TODO: is there a better alternative to being so extravagant? I don't want to go back to
      // having all touch events share a mutable Flags instance
      for (Touch.Event event : events) {
        if (event.isSet(Event.F_PREVENT_DEFAULT)) nevent.preventDefault();
      }
    }
  }

  private native int getMovementX (NativeEvent nevent) /*-{
    return nevent.webkitMovementX;
  }-*/;

  private native int getMovementY (NativeEvent nevent) /*-{
      return nevent.webkitMovementY;
  }-*/;

  native void requestMouseLockImpl (Element element) /*-{
     element.requestPointerLock = (element.requestPointerLock || element.webkitRequestPointerLock ||
                                   element.mozRequestPointerLock);
    if (element.requestPointerLock) element.requestPointerLock();
  }-*/;

  /**
   * Return the mouse wheel velocity for the event
   */
  private static native float getMouseWheelVelocity (NativeEvent evt) /*-{
    var delta = 0.0;
    var agentInfo = @playn.html.HtmlPlatform::agentInfo;

    if (agentInfo.isFirefox) {
      if (agentInfo.isMacOS) {
        delta = 1.0 * evt.detail;
      } else {
        delta = 1.0 * evt.detail/3;
      }
    } else if (agentInfo.isOpera) {
      if (agentInfo.isLinux) {
        delta = -1.0 * evt.wheelDelta/80;
      } else {
        // on mac
        delta = -1.0 * evt.wheelDelta/40;
      }
    } else if (agentInfo.isChrome || agentInfo.isSafari || agentInfo.isIE) {
      delta = -1.0 * evt.wheelDelta/120;
      // handle touchpad for chrome
      if (Math.abs(delta) < 1) {
        if (agentInfo.isWindows) {
          delta = -1.0 * evt.wheelDelta;
        } else if (agentInfo.isMacOS) {
          delta = -1.0 * evt.wheelDelta/3;
        }
      }
    }
    return delta;
  }-*/;

  /**
   * Return the appropriate mouse wheel event name for the current browser
   *
   * @return return the mouse wheel event name for the current browser
   */
  protected static native String getMouseWheelEvent () /*-{
    if (navigator.userAgent.toLowerCase().indexOf('firefox') != -1) {
      return "DOMMouseScroll";
    } else {
      return "mousewheel";
    }
  }-*/;

  protected static Mouse.ButtonEvent.Id getMouseButton (NativeEvent evt) {
    switch (evt.getButton()) {
    case (NativeEvent.BUTTON_LEFT):   return Mouse.ButtonEvent.Id.LEFT;
    case (NativeEvent.BUTTON_MIDDLE): return Mouse.ButtonEvent.Id.MIDDLE;
    case (NativeEvent.BUTTON_RIGHT):  return Mouse.ButtonEvent.Id.RIGHT;
    default:                          return null;
    }
  }

  private native void unlockImpl () /*-{
    $doc.exitPointerLock = $doc.exitPointerLock || $doc.webkitExitPointerLock || $doc.mozExitPointerLock;
    $doc.exitPointerLock && $doc.exitPointerLock();
  }-*/;

  private Touch.Event[] toTouchEvents (Touch.Event.Kind kind, NativeEvent nevent) {
    // Convert the JsArray to an array of Touch.Events
    JsArray nativeTouches = nevent.getChangedTouches();
    int nativeTouchesLen = nativeTouches.length();
    Touch.Event[] touches = new Touch.Event[nativeTouchesLen];
    double time = plat.time();
    for (int t = 0; t < nativeTouchesLen; t++) {
      com.google.gwt.dom.client.Touch touch = nativeTouches.get(t);
      float x = touch.getRelativeX(rootElement);
      float y = touch.getRelativeY(rootElement);
      Point xy = plat.graphics().transformMouse(x, y);
      int id = getTouchIdentifier(nevent, t);
      touches[t] = new Touch.Event(0, time, xy.x, xy.y, kind, id);
    }
    return touches;
  }

  /** Returns the unique identifier of a touch, or 0. */
  private static native int getTouchIdentifier (NativeEvent evt, int index) /*-{
    return evt.changedTouches[index].identifier || 0;
  }-*/;

  private static Key keyForCode (int keyCode) {
    switch (keyCode) {
    case KeyCodes.KEY_ALT: return Key.ALT;
    case KeyCodes.KEY_BACKSPACE: return Key.BACKSPACE;
    case KeyCodes.KEY_CTRL: return Key.CONTROL;
    case KeyCodes.KEY_DELETE: return Key.DELETE;
    case KeyCodes.KEY_DOWN: return Key.DOWN;
    case KeyCodes.KEY_END: return Key.END;
    case KeyCodes.KEY_ENTER: return Key.ENTER;
    case KeyCodes.KEY_ESCAPE: return Key.ESCAPE;
    case KeyCodes.KEY_HOME: return Key.HOME;
    case KeyCodes.KEY_LEFT: return Key.LEFT;
    case KeyCodes.KEY_PAGEDOWN: return Key.PAGE_DOWN;
    case KeyCodes.KEY_PAGEUP: return Key.PAGE_UP;
    case KeyCodes.KEY_RIGHT: return Key.RIGHT;
    case KeyCodes.KEY_SHIFT: return Key.SHIFT;
    case KeyCodes.KEY_TAB: return Key.TAB;
    case KeyCodes.KEY_UP: return Key.UP;

    case KEY_PAUSE: return Key.PAUSE;
    case KEY_CAPS_LOCK: return Key.CAPS_LOCK;
    case KEY_SPACE: return Key.SPACE;
    case KEY_INSERT: return Key.INSERT;
    case KEY_0: return Key.K0;
    case KEY_1: return Key.K1;
    case KEY_2: return Key.K2;
    case KEY_3: return Key.K3;
    case KEY_4: return Key.K4;
    case KEY_5: return Key.K5;
    case KEY_6: return Key.K6;
    case KEY_7: return Key.K7;
    case KEY_8: return Key.K8;
    case KEY_9: return Key.K9;
    case KEY_A: return Key.A;
    case KEY_B: return Key.B;
    case KEY_C: return Key.C;
    case KEY_D: return Key.D;
    case KEY_E: return Key.E;
    case KEY_F: return Key.F;
    case KEY_G: return Key.G;
    case KEY_H: return Key.H;
    case KEY_I: return Key.I;
    case KEY_J: return Key.J;
    case KEY_K: return Key.K;
    case KEY_L: return Key.L;
    case KEY_M: return Key.M;
    case KEY_N: return Key.N;
    case KEY_O: return Key.O;
    case KEY_P: return Key.P;
    case KEY_Q: return Key.Q;
    case KEY_R: return Key.R;
    case KEY_S: return Key.S;
    case KEY_T: return Key.T;
    case KEY_U: return Key.U;
    case KEY_V: return Key.V;
    case KEY_W: return Key.W;
    case KEY_X: return Key.X;
    case KEY_Y: return Key.Y;
    case KEY_Z: return Key.Z;
    case KEY_LEFT_WINDOW_KEY: return Key.WINDOWS;
    case KEY_RIGHT_WINDOW_KEY: return Key.WINDOWS;
    // case KEY_SELECT_KEY: return Key.SELECT_KEY;
    case KEY_NUMPAD0: return Key.NP0;
    case KEY_NUMPAD1: return Key.NP1;
    case KEY_NUMPAD2: return Key.NP2;
    case KEY_NUMPAD3: return Key.NP3;
    case KEY_NUMPAD4: return Key.NP4;
    case KEY_NUMPAD5: return Key.NP5;
    case KEY_NUMPAD6: return Key.NP6;
    case KEY_NUMPAD7: return Key.NP7;
    case KEY_NUMPAD8: return Key.NP8;
    case KEY_NUMPAD9: return Key.NP9;
    case KEY_MULTIPLY: return Key.NP_MULTIPLY;
    case KEY_ADD: return Key.NP_ADD;
    case KEY_SUBTRACT: return Key.NP_SUBTRACT;
    case KEY_DECIMAL_POINT_KEY: return Key.NP_DECIMAL;
    case KEY_DIVIDE: return Key.NP_DIVIDE;
    case KEY_F1: return Key.F1;
    case KEY_F2: return Key.F2;
    case KEY_F3: return Key.F3;
    case KEY_F4: return Key.F4;
    case KEY_F5: return Key.F5;
    case KEY_F6: return Key.F6;
    case KEY_F7: return Key.F7;
    case KEY_F8: return Key.F8;
    case KEY_F9: return Key.F9;
    case KEY_F10: return Key.F10;
    case KEY_F11: return Key.F11;
    case KEY_F12: return Key.F12;
    case KEY_NUM_LOCK: return Key.NP_NUM_LOCK;
    case KEY_SCROLL_LOCK: return Key.SCROLL_LOCK;
    case KEY_SEMICOLON: return Key.SEMICOLON;
    case KEY_EQUALS: return Key.EQUALS;
    case KEY_COMMA: return Key.COMMA;
    case KEY_DASH: return Key.MINUS;
    case KEY_PERIOD: return Key.PERIOD;
    case KEY_FORWARD_SLASH: return Key.SLASH;
    case KEY_GRAVE_ACCENT: return Key.BACKQUOTE;
    case KEY_OPEN_BRACKET: return Key.LEFT_BRACKET;
    case KEY_BACKSLASH: return Key.BACKSLASH;
    case KEY_CLOSE_BRACKET: return Key.RIGHT_BRACKET;
    case KEY_SINGLE_QUOTE: return Key.QUOTE;
    default: return Key.UNKNOWN;
    }
  }

  // these are absent from KeyCodes; we know not why...
  private static final int KEY_PAUSE = 19;
  private static final int KEY_CAPS_LOCK = 20;
  private static final int KEY_SPACE = 32;
  private static final int KEY_INSERT = 45;
  private static final int KEY_0 = 48;
  private static final int KEY_1 = 49;
  private static final int KEY_2 = 50;
  private static final int KEY_3 = 51;
  private static final int KEY_4 = 52;
  private static final int KEY_5 = 53;
  private static final int KEY_6 = 54;
  private static final int KEY_7 = 55;
  private static final int KEY_8 = 56;
  private static final int KEY_9 = 57;
  private static final int KEY_A = 65;
  private static final int KEY_B = 66;
  private static final int KEY_C = 67;
  private static final int KEY_D = 68;
  private static final int KEY_E = 69;
  private static final int KEY_F = 70;
  private static final int KEY_G = 71;
  private static final int KEY_H = 72;
  private static final int KEY_I = 73;
  private static final int KEY_J = 74;
  private static final int KEY_K = 75;
  private static final int KEY_L = 76;
  private static final int KEY_M = 77;
  private static final int KEY_N = 78;
  private static final int KEY_O = 79;
  private static final int KEY_P = 80;
  private static final int KEY_Q = 81;
  private static final int KEY_R = 82;
  private static final int KEY_S = 83;
  private static final int KEY_T = 84;
  private static final int KEY_U = 85;
  private static final int KEY_V = 86;
  private static final int KEY_W = 87;
  private static final int KEY_X = 88;
  private static final int KEY_Y = 89;
  private static final int KEY_Z = 90;
  private static final int KEY_LEFT_WINDOW_KEY = 91;
  private static final int KEY_RIGHT_WINDOW_KEY = 92;
  // private static final int KEY_SELECT_KEY = 93;
  private static final int KEY_NUMPAD0 = 96;
  private static final int KEY_NUMPAD1 = 97;
  private static final int KEY_NUMPAD2 = 98;
  private static final int KEY_NUMPAD3 = 99;
  private static final int KEY_NUMPAD4 = 100;
  private static final int KEY_NUMPAD5 = 101;
  private static final int KEY_NUMPAD6 = 102;
  private static final int KEY_NUMPAD7 = 103;
  private static final int KEY_NUMPAD8 = 104;
  private static final int KEY_NUMPAD9 = 105;
  private static final int KEY_MULTIPLY = 106;
  private static final int KEY_ADD = 107;
  private static final int KEY_SUBTRACT = 109;
  private static final int KEY_DECIMAL_POINT_KEY = 110;
  private static final int KEY_DIVIDE = 111;
  private static final int KEY_F1 = 112;
  private static final int KEY_F2 = 113;
  private static final int KEY_F3 = 114;
  private static final int KEY_F4 = 115;
  private static final int KEY_F5 = 116;
  private static final int KEY_F6 = 117;
  private static final int KEY_F7 = 118;
  private static final int KEY_F8 = 119;
  private static final int KEY_F9 = 120;
  private static final int KEY_F10 = 121;
  private static final int KEY_F11 = 122;
  private static final int KEY_F12 = 123;
  private static final int KEY_NUM_LOCK = 144;
  private static final int KEY_SCROLL_LOCK = 145;
  private static final int KEY_SEMICOLON = 186;
  private static final int KEY_EQUALS = 187;
  private static final int KEY_COMMA = 188;
  private static final int KEY_DASH = 189;
  private static final int KEY_PERIOD = 190;
  private static final int KEY_FORWARD_SLASH = 191;
  private static final int KEY_GRAVE_ACCENT = 192;
  private static final int KEY_OPEN_BRACKET = 219;
  private static final int KEY_BACKSLASH = 220;
  private static final int KEY_CLOSE_BRACKET = 221;
  private static final int KEY_SINGLE_QUOTE = 222;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy