Subversion Repositories AndroidProjects

Rev

Rev 564 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.Bauzoid.platform.windows;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.lwjgl.opengl.Display;

import com.badlogic.gdx.Gdx;
import com.gebauz.Bauzoid.app.Game;
import com.gebauz.Bauzoid.input.Input;

/** Handle Windows 7 multitouch input (if any).
 * On Windows, GDX only supports index 0 for touch/mouse input.
 * Therefore, this class overrides the default Bauzoid input behaviour and reads WM_TOUCH messages from a DLL.
 *
 *
 * @author chris
 *
 */

public class Win7TouchInput extends Input
{
        public static class WindowsTouchInfo
        {
                public static final int TOUCHEVENTF_MOVE                = 0x0001;       // Movement has occurred. Cannot be combined with TOUCHEVENTF_DOWN.
                public static final int TOUCHEVENTF_DOWN                = 0x0002;       // The corresponding touch point was established through a new contact. Cannot be combined with TOUCHEVENTF_MOVE or TOUCHEVENTF_UP.
                public static final int TOUCHEVENTF_UP                  = 0x0004;       // A touch point was removed.
                public static final int TOUCHEVENTF_INRANGE             = 0x0008;       // A touch point is in range. This flag is used to enable touch hover support on compatible hardware. Applications that do not want support for hover can ignore this flag.
                public static final int TOUCHEVENTF_PRIMARY             = 0x0010;       // Indicates that this TOUCHINPUT structure corresponds to a primary contact point. See the following text for more information on primary touch points.
                public static final int TOUCHEVENTF_NOCOALESCE  = 0x0020;       // When received using GetTouchInputInfo, this input was not coalesced.
                public static final int TOUCHEVENTF_PAL                 = 0x0080;       // The touch event came from the user's palm.
               
                public int x = 0;
                public int y = 0;
                public int id = 0;
                public int actionFlags = 0;
        }
       
        //======= native functions begin =======
        public native void initTouch(long hwnd);
       
        //======= native functions end =========
       
       
        private int[] mIds = new int[20];
        private int[] mTouchX = new int[20];
        private int[] mTouchY = new int[20];
        private boolean[] mIsTouched = new boolean[20];
       
        public Win7TouchInput(Game game)
        {
                super(game);
               
                for (int i = 0; i < mIds.length; i++)
                        mIds[i] = -1;
                for (int i = 0; i < mTouchX.length; i++)
                        mTouchX[i] = 0;
                for (int i = 0; i < mTouchY.length; i++)
                        mTouchY[i] = 0;
                for (int i = 0; i < mIsTouched.length; i++)
                        mIsTouched[i] = false;
        }
       
        @Override
        public void init()
        {
                System.out.println("OS: " + System.getProperty("os.name"));
                System.out.println("JVM Bit size: " + System.getProperty("os.arch"));          
                System.loadLibrary("win7touch32");
               
                // call native function to hook message processing to window via subclasssing
                try
                {
                        long hwnd = -1;
                        Object displayImpl = null;
                         
                        Method[] displayMethods = Display.class.getDeclaredMethods();
                        for (Method m : displayMethods)
                        {
                                if (m.getName().equals("getImplementation"))
                                {
                                        m.setAccessible(true);
                                        displayImpl = m.invoke(null, (Object[])null);
                                        break;
                                }
                        }
                       
                        Field[] windowsDisplayFields = displayImpl.getClass().getDeclaredFields();
                        for (Field f : windowsDisplayFields)
                        {
                                if (f.getName().equals("hwnd"))
                                {
                                        f.setAccessible(true);
                                        hwnd = (Long) f.get(displayImpl);
                                        continue;
                                }
                        }

                        System.out.println("Address of hWnd: " + hwnd);
                        initTouch(hwnd);
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
               
                super.init();

        }
       
        @Override
        public int getX(int index)
        {
                /*int i = getActiveIndex(index);
                if (i == -1)
                        return 0;
                return mTouchX[i];*/

                if (index > 0)
                {
                        int i = getActiveIndex(index-1);
                        if (i == -1)
                                return 0;
                        else
                                return mTouchX[i];
                }
                else
                        return Gdx.input.getX(index);
        }
       
        @Override
        public int getY(int index)
        {
                /*int i = getActiveIndex(index);
                if (i == -1)
                        return 0;
                return mTouchY[i];*/

                if (index > 0)
                {
                        int i = getActiveIndex(index-1);
                        if (i == -1)
                                return 0;
                        else
                                return mTouchY[i];
                }
                else
                        return Gdx.input.getY(index);
        }
       
        @Override
        public boolean isTouched(int index)
        {
                /*int i = getActiveIndex(index);
                if (i == -1)
                        return false;
                return mIsTouched[i];*/

                if (index > 0)
                {
                        int i = getActiveIndex(index-1);
                        if (i == -1)
                                return false;
                        else
                                return mIsTouched[i];
                }
                else
                        return Gdx.input.isTouched(index);
        }
       
        /** Called from the DLL when a new WM_TOUCH has been received. */
        public void onTouch(WindowsTouchInfo info)
        {
                if (checkFlag(info.actionFlags, WindowsTouchInfo.TOUCHEVENTF_DOWN))
                {
                        //System.out.println("[Jav] ACTION_DOWN id: " + info.id + " (" + info.x + ", " + info.y + ")");
                       
                        int index = findIndex(info.id);
                        if (index == -1)
                                index = nextFreeIndex();
                       
                        mIds[index] = info.id;
                        mTouchX[index] = info.x;
                        mTouchY[index] = info.y;
                        mIsTouched[index] = true;
                }
                else if (checkFlag(info.actionFlags, WindowsTouchInfo.TOUCHEVENTF_MOVE))
                {
                        //System.out.println("[Jav] ACTION_MOVE id: " + info.id + " (" + info.x + ", " + info.y + ")");
                       
                        int index = findIndex(info.id);
                        if (index == -1) // should not happen actually
                                //index = nextFreeIndex();
                                return;
                        mIds[index] = info.id;
                        mTouchX[index] = info.x;
                        mTouchY[index] = info.y;
                        mIsTouched[index] = true;
                }
                else if (checkFlag(info.actionFlags, WindowsTouchInfo.TOUCHEVENTF_UP))
                {
                        //System.out.println("[Jav] ACTION_UP id: " + info.id + " (" + info.x + ", " + info.y + ")");
                       
                        int index = findIndex(info.id);
                        if (index == -1) // should not happen actually
                                //index = nextFreeIndex();
                                return;
                        mIds[index] = -1;
                        mTouchX[index] = info.x;
                        mTouchY[index] = info.y;
                        mIsTouched[index] = false;
                }
               
                String test = "";
                for (int i = 0; i < 10; i++)
                {
                        test = test + "|" + mIds[i];
                        if (mIsTouched[i])
                                test = test + "[T]";
                }
                System.out.println(test);
                // check actionFlags
                // if the action is DOWN, add the ID (over overwrite if it exists)
                // if the action is MOVE, update the x/y values
                // if the action is UP, remove the ID from the list.
        }
       
        public boolean checkFlag(int flags, int flag)
        {
                return ((flags & flag) == flag);
        }
       
        public int findIndex(int id)
        {
                for (int i = 0; i < mIds.length; i++)          
                {
                        if (mIds[i] == id)
                                return i;
                }
                return -1;
        }
       
        public int nextFreeIndex()
        {
                for (int i = 0; i < mIds.length; i++)
                {
                        if (mIds[i] == -1)
                                return i;
                }
               
                // expand array if not enough
                int[] tmp = new int[mIds.length + 1];
                System.arraycopy(mIds, 0, tmp, 0, mIds.length);
                mIds = tmp;
                return (mIds.length-1);
        }
       
        public int getActiveIndex(int index)
        {
                int n = 0;
                for (int i = 0; i < mIds.length; i++)
                {              
                        if (mIds[i] != -1)
                        {
                                if (n == index)
                                        return i;
                               
                                n++;
                        }
                }
               
                return -1;
        }
       
}