Package org.mt4j.input.inputSources

Source Code of org.mt4j.input.inputSources.Win7NativeTouchSource

/***********************************************************************
* mt4j Copyright (c) 2008 - 2010 Christopher Ruff, Fraunhofer-Gesellschaft All rights reserved.
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.input.inputSources;

import java.util.HashMap;

import javax.swing.SwingUtilities;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.mt4j.MTApplication;
import org.mt4j.input.inputData.ActiveCursorPool;
import org.mt4j.input.inputData.InputCursor;
import org.mt4j.input.inputData.MTFingerInputEvt;
import org.mt4j.input.inputData.MTWin7TouchInputEvt;
import org.mt4j.util.MT4jSettings;

/**
* Input source for native Windows 7 WM_TOUCH messages for single/multi-touch.
* <br>Be careful to instantiate this class only ONCE!
*
* @author C.Ruff
*
*/
public class Win7NativeTouchSource extends AbstractInputSource {
  /** The Constant logger. */
  private static final Logger logger = Logger.getLogger(Win7NativeTouchSource.class.getName());
  static{
//    logger.setLevel(Level.ERROR);
//    logger.setLevel(Level.DEBUG);
    logger.setLevel(Level.INFO);
    SimpleLayout l = new SimpleLayout();
    ConsoleAppender ca = new ConsoleAppender(l);
    logger.addAppender(ca);
  }
 
  static boolean loaded = false;
 
  private MTApplication app;

  private int sunAwtCanvasHandle;

  private int awtFrameHandle;
 
  private Native_WM_TOUCH_Event wmTouchEvent;

  private boolean initialized;
 
  private boolean success;
 
  private HashMap<Integer, Long> touchToCursorID;
 
  private static final String dllName32 = "Win7Touch";
 
  private static final String dllName64 = "Win7Touch64";
 
  private static final String canvasClassName = "SunAwtCanvas";
 
 
  // NATIVE METHODS //
  private native int findWindow(String tmpTitle, String subWindowTitle);
 
  private native boolean init(long HWND);
 
  private native boolean getSystemMetrics();
 
  private native boolean quit();
 
  private native boolean pollEvent(Native_WM_TOUCH_Event myEvent);
  // NATIVE METHODS //
 
 
  //TODO remove points[] array? -> if digitizer has more than 255 touchpoints we could get out of bounds in points[]
  //TODO did we "delete [] ti;" in wndProc?
  //TODO- check dpi, if higher than 96 - if the screen is set to High DPI (more than 96 DPI),
  // you may also need to divide the values by 96 and multiply by the current DPI. (or already handled by ScreenToClient()?)
  //TODO try again getWindow() in windows -> no success in all thread (we probably need to do it in the awt-windows thread?)
 
  //TODO make singleton to avoid multiple instances
 
  /**
   * Instantiates a new win7 native touch source.
   *
   * @param mtApp the mt app
   */
  public Win7NativeTouchSource(MTApplication mtApp) {
    super(mtApp);
    this.app = mtApp;
    this.success = false;
   
    String platform = System.getProperty("os.name").toLowerCase();
    logger.debug("Platform: \"" + platform + "\"");
   
//    /*
    if (!platform.contains("windows 7")) {
      logger.error("Win7NativeTouchSource input source can only be used on platforms running windows 7!");
      return;
    }
   
    if (!loaded){
      loaded = true;
      String dllName = (MT4jSettings.getInstance().getArchitecture() == MT4jSettings.ARCHITECTURE_32_BIT)? dllName32 : dllName64;
      System.loadLibrary(dllName);
//      System.load(System.getProperty("user.dir") + File.separator + dllName + ".dll");
    }else{
      logger.error("Win7NativeTouchSource may only be instantiated once.");
      return;
    }
   
    boolean touchAvailable = this.getSystemMetrics();
    if (!touchAvailable){
      logger.error("Windows 7 Touch Input currently not available!");
      return;
    }else{
      logger.info("Windows 7 Touch Input available.");
    }
//    */
   
    wmTouchEvent = new Native_WM_TOUCH_Event();
    wmTouchEvent.id = -1;
    wmTouchEvent.type = -1;
    wmTouchEvent.x = -1;
    wmTouchEvent.y = -1;
   
    initialized = false;
   
    touchToCursorID = new HashMap<Integer, Long>();
   
    this.getNativeWindowHandles();
    success = true;
  }

 
//  private boolean addedArtificalTouchDown = false; //FIXME REMOVE
 
  public boolean isSuccessfullySetup() {
    return success;
  }


  @Override
  public void pre(){ //we dont have to call registerPre() again (already in superclass and called there)
    if (initialized){ //Only poll events if native c++ core was initialized successfully
      while (pollEvent(wmTouchEvent)) {
        /*
         //FIXME TEST, make a artifical TOUCH_DOWN event REMOVE LATER!
        if (!addedArtificalTouchDown){
          addedArtificalTouchDown = true;
          wmTouchEvent.type = Native_WM_TOUCH_Event.TOUCH_DOWN;
        }
         */
       
        switch (wmTouchEvent.type) {
        case Native_WM_TOUCH_Event.TOUCH_DOWN:{
//          logger.debug("TOUCH_DOWN ==> ID:" + wmTouchEvent.id + " x:" +  wmTouchEvent.x + " y:" +  wmTouchEvent.y);
         
          InputCursor c = new InputCursor();
          long cursorID = c.getId();
          MTWin7TouchInputEvt touchEvt = new MTWin7TouchInputEvt(this, wmTouchEvent.x, wmTouchEvent.y, wmTouchEvent.contactSizeX, wmTouchEvent.contactSizeY, MTFingerInputEvt.INPUT_DETECTED, c);
          int touchID = wmTouchEvent.id;
          ActiveCursorPool.getInstance().putActiveCursor(cursorID, c);
          touchToCursorID.put(touchID, cursorID);
          this.enqueueInputEvent(touchEvt);
         
          break;
        }case Native_WM_TOUCH_Event.TOUCH_MOVE:{
//          logger.debug("TOUCH_MOVE ==> ID:" + wmTouchEvent.id + " x:" +  wmTouchEvent.x + " y:" +  wmTouchEvent.y);
//          System.out.println("Contact area X:" + wmTouchEvent.contactSizeX + " Y:" + wmTouchEvent.contactSizeY);
         
          Long cursorID = touchToCursorID.get(wmTouchEvent.id);
          if (cursorID != null){
            InputCursor c = ActiveCursorPool.getInstance().getActiveCursorByID(cursorID);
            if (c != null){
              MTWin7TouchInputEvt te = new MTWin7TouchInputEvt(this, wmTouchEvent.x, wmTouchEvent.y, wmTouchEvent.contactSizeX, wmTouchEvent.contactSizeY, MTFingerInputEvt.INPUT_UPDATED, c);
              this.enqueueInputEvent(te)
            }
          }
         
          break;
        }case Native_WM_TOUCH_Event.TOUCH_UP:{
//          logger.debug("TOUCH_UP ==> ID:" + wmTouchEvent.id + " x:" +  wmTouchEvent.x + " y:" +  wmTouchEvent.y);

          Long cursorID = touchToCursorID.get(wmTouchEvent.id);
          if (cursorID != null){
            InputCursor c = ActiveCursorPool.getInstance().getActiveCursorByID(cursorID);
            if (c != null){
              MTWin7TouchInputEvt te = new MTWin7TouchInputEvt(this, wmTouchEvent.x, wmTouchEvent.y, wmTouchEvent.contactSizeX, wmTouchEvent.contactSizeY, MTFingerInputEvt.INPUT_ENDED, c);
              this.enqueueInputEvent(te);
            }
            ActiveCursorPool.getInstance().removeCursor(cursorID);
            touchToCursorID.remove(wmTouchEvent.id);
          }
         
          break;
        }default:
          break;
        }
      }
    }

    super.pre();
  }
 
 
 
  private void getNativeWindowHandles(){
    if (app.frame == null){
      logger.error("applet.frame == null! -> cant set up windows 7 input!");
      return;
    }
   
    //TODO kind of hacky way of getting the HWND..but there seems to be no real alternative(?)
    final String oldTitle = app.frame.getTitle();
    final String tmpTitle = "Initializing Native Windows 7 Touch Input " + Math.random();
    app.frame.setTitle(tmpTitle);
    logger.debug("Temp title: " + tmpTitle);
   
    //FIXME TEST REMOVE
    //Window window = SwingUtilities.getWindowAncestor(app);
//    AWTUtilities.setWindowOpacity(window, 0.5f); //works!
       
    //Invokelater because of some crash issue
    //-> maybe we need to wait a frame until windows is informed of the window name change
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        int awtCanvasHandle = 0;
        try {
//          //TODO also search for window class?
          awtCanvasHandle = (int)findWindow(tmpTitle, canvasClassName);
          setSunAwtCanvasHandle(awtCanvasHandle);
        } catch (Exception e) {
          System.err.println(e.getMessage());
        }
        app.frame.setTitle(oldTitle); //Reset title text
      }
    });
  }

 
  private void setTopWindowHandle(int HWND){
    if (HWND > 0){
      this.awtFrameHandle = HWND;
      logger.debug("-> Found AWT HWND: " + this.awtFrameHandle);
    }else{
      logger.error("-> Couldnt retrieve the top window handle!");
    }
  }
 
 
  private void setSunAwtCanvasHandle(int HWND){
    if (HWND > 0){
      this.sunAwtCanvasHandle = HWND;
      logger.debug("-> Found SunAwtCanvas HWND: " + this.sunAwtCanvasHandle);
      //Initialize c++ core (subclass etc)
      this.init(this.sunAwtCanvasHandle);
      this.initialized = true;
    }else{
      logger.error("-> Couldnt retrieve the SunAwtCanvas handle!");
    }
  }
 
  private class Native_WM_TOUCH_Event{
    //can be real enums in Java 5.0.
      /** The Constant TOUCH_DOWN. */
      public static final int TOUCH_DOWN = 0;
     
      /** The Constant TOUCH_MOVE. */
      public static final int TOUCH_MOVE = 1;
     
      /** The Constant TOUCH_UP. */
      public static final int TOUCH_UP = 2;
     
      /** The type. */
      public int type;
     
      /** The id. */
      public int id;
     
      /** The x value. */
      public int x;
     
      /** The y value. */
      public int y;
     
      /** The contact size area X dimension */
      public int contactSizeX;
     
      /** The contact size area Y dimension */
      public int contactSizeY;
  }

}
TOP

Related Classes of org.mt4j.input.inputSources.Win7NativeTouchSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.