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

com.badlogic.gdx.backends.android.AndroidInput Maven / Gradle / Ivy

There is a newer version: 1.13.1
Show newest version
/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * 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 com.badlogic.gdx.backends.android;

import java.util.ArrayList;
import java.util.Arrays;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Handler;
import android.os.Vibrator;
import android.service.wallpaper.WallpaperService.Engine;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics.DisplayMode;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Input.TextInputListener;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.backends.android.AndroidLiveWallpaperService.AndroidWallpaperEngine;
import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.Pool;

/** An implementation of the {@link Input} interface for Android.
 * 
 * @author mzechner */
/** @author jshapcot */
public class AndroidInput implements Input, OnKeyListener, OnTouchListener {
	static class KeyEvent {
		static final int KEY_DOWN = 0;
		static final int KEY_UP = 1;
		static final int KEY_TYPED = 2;

		long timeStamp;
		int type;
		int keyCode;
		char keyChar;
	}

	static class TouchEvent {
		static final int TOUCH_DOWN = 0;
		static final int TOUCH_UP = 1;
		static final int TOUCH_DRAGGED = 2;
		static final int TOUCH_SCROLLED = 3;
		static final int TOUCH_MOVED = 4;

		long timeStamp;
		int type;
		int x;
		int y;
		int scrollAmount;
		int button;
		int pointer;
	}

	Pool usedKeyEvents = new Pool(16, 1000) {
		protected KeyEvent newObject () {
			return new KeyEvent();
		}
	};

	Pool usedTouchEvents = new Pool(16, 1000) {
		protected TouchEvent newObject () {
			return new TouchEvent();
		}
	};

	public static final int NUM_TOUCHES = 20;
	public static final int SUPPORTED_KEYS = 260;
	
	ArrayList keyListeners = new ArrayList();
	ArrayList keyEvents = new ArrayList();
	ArrayList touchEvents = new ArrayList();
	int[] touchX = new int[NUM_TOUCHES];
	int[] touchY = new int[NUM_TOUCHES];
	int[] deltaX = new int[NUM_TOUCHES];
	int[] deltaY = new int[NUM_TOUCHES];
	boolean[] touched = new boolean[NUM_TOUCHES];
	int[] button = new int[NUM_TOUCHES];
	int[] realId = new int[NUM_TOUCHES];
	final boolean hasMultitouch;
	private int keyCount = 0;
	private boolean[] keys = new boolean[SUPPORTED_KEYS];
	private boolean keyJustPressed = false;
	private boolean[] justPressedKeys = new boolean[SUPPORTED_KEYS];
	private SensorManager manager;
	public boolean accelerometerAvailable = false;
	private final float[] accelerometerValues = new float[3];
	public boolean gyroscopeAvailable = false;
	private final float[] gyroscopeValues = new float[3];
	private String text = null;
	private TextInputListener textListener = null;
	private Handler handle;
	final Application app;
	final Context context;
	private final AndroidTouchHandler touchHandler;
	private int sleepTime = 0;
	private boolean catchBack = false;
	private boolean catchMenu = false;
	protected final Vibrator vibrator;
	private boolean compassAvailable = false;
	boolean keyboardAvailable;
	private final float[] magneticFieldValues = new float[3];
	private float azimuth = 0;
	private float pitch = 0;
	private float roll = 0;
	private float inclination = 0;
	private boolean justTouched = false;
	private InputProcessor processor;
	private final AndroidApplicationConfiguration config;
	private final Orientation nativeOrientation;
	private long currentEventTimeStamp = System.nanoTime();
	private final AndroidOnscreenKeyboard onscreenKeyboard;

	private SensorEventListener accelerometerListener;
	private SensorEventListener gyroscopeListener;
	private SensorEventListener compassListener;

	public AndroidInput (Application activity, Context context, Object view, AndroidApplicationConfiguration config) {
		// we hook into View, for LWPs we call onTouch below directly from
		// within the AndroidLivewallpaperEngine#onTouchEvent() method.
		if (view instanceof View) {
			View v = (View)view;
			v.setOnKeyListener(this);
			v.setOnTouchListener(this);
			v.setFocusable(true);
			v.setFocusableInTouchMode(true);
			v.requestFocus();
		}
		this.config = config;
		this.onscreenKeyboard = new AndroidOnscreenKeyboard(context, new Handler(), this);

		for (int i = 0; i < realId.length; i++)
			realId[i] = -1;
		handle = new Handler();
		this.app = activity;
		this.context = context;
		this.sleepTime = config.touchSleepTime;
		touchHandler = new AndroidMultiTouchHandler();
		hasMultitouch = touchHandler.supportsMultitouch(context);

		vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);

		int rotation = getRotation();
		DisplayMode mode = app.getGraphics().getDisplayMode();
		if (((rotation == 0 || rotation == 180) && (mode.width >= mode.height))
			|| ((rotation == 90 || rotation == 270) && (mode.width <= mode.height))) {
			nativeOrientation = Orientation.Landscape;
		} else {
			nativeOrientation = Orientation.Portrait;
		}
	}

	@Override
	public float getAccelerometerX () {
		return accelerometerValues[0];
	}

	@Override
	public float getAccelerometerY () {
		return accelerometerValues[1];
	}

	@Override
	public float getAccelerometerZ () {
		return accelerometerValues[2];
	}
	
	@Override
	public float getGyroscopeX () {
		return gyroscopeValues[0];
	}

	@Override
	public float getGyroscopeY () {
		return gyroscopeValues[1];
	}

	@Override
	public float getGyroscopeZ () {
		return gyroscopeValues[2];
	}

	@Override
	public void getTextInput (final TextInputListener listener, final String title, final String text, final String hint) {
		handle.post(new Runnable() {
			public void run () {
				AlertDialog.Builder alert = new AlertDialog.Builder(context);
				alert.setTitle(title);
				final EditText input = new EditText(context);
				input.setHint(hint);
				input.setText(text);				
				input.setSingleLine();
				alert.setView(input);
				alert.setPositiveButton(context.getString(android.R.string.ok), new DialogInterface.OnClickListener() {
					public void onClick (DialogInterface dialog, int whichButton) {
						Gdx.app.postRunnable(new Runnable() {
							@Override
							public void run () {
								listener.input(input.getText().toString());
							}
						});
					}
				});
				alert.setNegativeButton(context.getString(android.R.string.cancel), new DialogInterface.OnClickListener() {
					public void onClick (DialogInterface dialog, int whichButton) {
						Gdx.app.postRunnable(new Runnable() {
							@Override
							public void run () {
								listener.canceled();
							}
						});
					}
				});
				alert.setOnCancelListener(new OnCancelListener() {
					@Override
					public void onCancel (DialogInterface arg0) {
						Gdx.app.postRunnable(new Runnable() {
							@Override
							public void run () {
								listener.canceled();
							}
						});
					}
				});
				alert.show();
			}
		});
	}

	@Override
	public int getX () {
		synchronized (this) {
			return touchX[0];
		}
	}

	@Override
	public int getY () {
		synchronized (this) {
			return touchY[0];
		}
	}

	@Override
	public int getX (int pointer) {
		synchronized (this) {
			return touchX[pointer];
		}
	}

	@Override
	public int getY (int pointer) {
		synchronized (this) {
			return touchY[pointer];
		}
	}

	public boolean isTouched (int pointer) {
		synchronized (this) {
			return touched[pointer];
		}
	}

	@Override
	public synchronized boolean isKeyPressed (int key) {
		if (key == Input.Keys.ANY_KEY) {
			return keyCount > 0;
		}
		if (key < 0 || key >= SUPPORTED_KEYS) {
			return false;
		}
		return keys[key];
	}

	@Override
	public synchronized boolean isKeyJustPressed (int key) {
		if (key == Input.Keys.ANY_KEY) {
			return keyJustPressed;
		}
		if (key < 0 || key >= SUPPORTED_KEYS) {
			return false;
		}
		return justPressedKeys[key];
	}

	@Override
	public boolean isTouched () {
		synchronized (this) {
			if (hasMultitouch) {
				for (int pointer = 0; pointer < NUM_TOUCHES; pointer++) {
					if (touched[pointer]) {
						return true;
					}
				}
			}
			return touched[0];
		}
	}

	public void setInputProcessor (InputProcessor processor) {
		synchronized (this) {
			this.processor = processor;
		}
	}

	void processEvents () {
		synchronized (this) {
			justTouched = false;
			if (keyJustPressed) {
				keyJustPressed = false;
				for (int i = 0; i < justPressedKeys.length; i++) {
					justPressedKeys[i] = false;
				}
			}

			if (processor != null) {
				final InputProcessor processor = this.processor;

				int len = keyEvents.size();
				for (int i = 0; i < len; i++) {
					KeyEvent e = keyEvents.get(i);
					currentEventTimeStamp = e.timeStamp;
					switch (e.type) {
					case KeyEvent.KEY_DOWN:
						processor.keyDown(e.keyCode);
						keyJustPressed = true;
						justPressedKeys[e.keyCode] = true;
						break;
					case KeyEvent.KEY_UP:
						processor.keyUp(e.keyCode);
						break;
					case KeyEvent.KEY_TYPED:
						processor.keyTyped(e.keyChar);
					}
					usedKeyEvents.free(e);
				}

				len = touchEvents.size();
				for (int i = 0; i < len; i++) {
					TouchEvent e = touchEvents.get(i);
					currentEventTimeStamp = e.timeStamp;
					switch (e.type) {
					case TouchEvent.TOUCH_DOWN:
						processor.touchDown(e.x, e.y, e.pointer, e.button);
						justTouched = true;
						break;
					case TouchEvent.TOUCH_UP:
						processor.touchUp(e.x, e.y, e.pointer, e.button);
						break;
					case TouchEvent.TOUCH_DRAGGED:
						processor.touchDragged(e.x, e.y, e.pointer);
						break;
					case TouchEvent.TOUCH_MOVED:
						processor.mouseMoved(e.x, e.y);
						break;
					case TouchEvent.TOUCH_SCROLLED:
						processor.scrolled(e.scrollAmount);
					}
					usedTouchEvents.free(e);
				}
			} else {
				int len = touchEvents.size();
				for (int i = 0; i < len; i++) {
					TouchEvent e = touchEvents.get(i);
					if (e.type == TouchEvent.TOUCH_DOWN) justTouched = true;
					usedTouchEvents.free(e);
				}

				len = keyEvents.size();
				for (int i = 0; i < len; i++) {
					usedKeyEvents.free(keyEvents.get(i));
				}
			}

			if (touchEvents.size() == 0) {
				for (int i = 0; i < deltaX.length; i++) {
					deltaX[0] = 0;
					deltaY[0] = 0;
				}
			}

			keyEvents.clear();
			touchEvents.clear();
		}
	}

	boolean requestFocus = true;

	@Override
	public boolean onTouch (View view, MotionEvent event) {
		if (requestFocus && view != null) {
			view.setFocusableInTouchMode(true);
			view.requestFocus();
			requestFocus = false;
		}

		// synchronized in handler.postTouchEvent()
		touchHandler.onTouch(event, this);

		if (sleepTime != 0) {
			try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
			}
		}
		return true;
	}

	/** Called in {@link AndroidLiveWallpaperService} on tap
	 * @param x
	 * @param y */
	public void onTap (int x, int y) {
		postTap(x, y);
	}

	/** Called in {@link AndroidLiveWallpaperService} on drop
	 * @param x
	 * @param y */
	public void onDrop (int x, int y) {
		postTap(x, y);
	}

	protected void postTap (int x, int y) {
		synchronized (this) {
			TouchEvent event = usedTouchEvents.obtain();
			event.timeStamp = System.nanoTime();
			event.pointer = 0;
			event.x = x;
			event.y = y;
			event.type = TouchEvent.TOUCH_DOWN;
			touchEvents.add(event);

			event = usedTouchEvents.obtain();
			event.timeStamp = System.nanoTime();
			event.pointer = 0;
			event.x = x;
			event.y = y;
			event.type = TouchEvent.TOUCH_UP;
			touchEvents.add(event);
		}
		Gdx.app.getGraphics().requestRendering();
	}

	@Override
	public boolean onKey (View v, int keyCode, android.view.KeyEvent e) {
		for (int i = 0, n = keyListeners.size(); i < n; i++)
			if (keyListeners.get(i).onKey(v, keyCode, e)) return true;

		synchronized (this) {
			KeyEvent event = null;

			if (e.getKeyCode() == android.view.KeyEvent.KEYCODE_UNKNOWN && e.getAction() == android.view.KeyEvent.ACTION_MULTIPLE) {
				String chars = e.getCharacters();
				for (int i = 0; i < chars.length(); i++) {
					event = usedKeyEvents.obtain();
					event.timeStamp = System.nanoTime();
					event.keyCode = 0;
					event.keyChar = chars.charAt(i);
					event.type = KeyEvent.KEY_TYPED;
					keyEvents.add(event);
				}
				return false;
			}

			char character = (char)e.getUnicodeChar();
			// Android doesn't report a unicode char for back space. hrm...
			if (keyCode == 67) character = '\b';
			if (e.getKeyCode() < 0 || e.getKeyCode() >= SUPPORTED_KEYS) {
				return false;
			}
			
			switch (e.getAction()) {
			case android.view.KeyEvent.ACTION_DOWN:
				event = usedKeyEvents.obtain();
				event.timeStamp = System.nanoTime();
				event.keyChar = 0;
				event.keyCode = e.getKeyCode();
				event.type = KeyEvent.KEY_DOWN;

				// Xperia hack for circle key. gah...
				if (keyCode == android.view.KeyEvent.KEYCODE_BACK && e.isAltPressed()) {
					keyCode = Keys.BUTTON_CIRCLE;
					event.keyCode = keyCode;
				}

				keyEvents.add(event);
				if (!keys[event.keyCode]) {
					keyCount++;
					keys[event.keyCode] = true;
				}
				break;
			case android.view.KeyEvent.ACTION_UP:
				long timeStamp = System.nanoTime();
				event = usedKeyEvents.obtain();
				event.timeStamp = timeStamp;
				event.keyChar = 0;
				event.keyCode = e.getKeyCode();
				event.type = KeyEvent.KEY_UP;
				// Xperia hack for circle key. gah...
				if (keyCode == android.view.KeyEvent.KEYCODE_BACK && e.isAltPressed()) {
					keyCode = Keys.BUTTON_CIRCLE;
					event.keyCode = keyCode;
				}
				keyEvents.add(event);

				event = usedKeyEvents.obtain();
				event.timeStamp = timeStamp;
				event.keyChar = character;
				event.keyCode = 0;
				event.type = KeyEvent.KEY_TYPED;
				keyEvents.add(event);

				if (keyCode == Keys.BUTTON_CIRCLE) {
					if (keys[Keys.BUTTON_CIRCLE]) {
						keyCount--;
						keys[Keys.BUTTON_CIRCLE] = false;
					}
				} else {
					if (keys[e.getKeyCode()]) {
						keyCount--;
						keys[e.getKeyCode()] = false;
					}
				}
			}
			app.getGraphics().requestRendering();
		}

		// circle button on Xperia Play shouldn't need catchBack == true
		if (keyCode == Keys.BUTTON_CIRCLE) return true;
		if (catchBack && keyCode == android.view.KeyEvent.KEYCODE_BACK) return true;
		if (catchMenu && keyCode == android.view.KeyEvent.KEYCODE_MENU) return true;
		return false;
	}

	@Override
	public void setOnscreenKeyboardVisible (final boolean visible) {
		handle.post(new Runnable() {
			public void run () {
				InputMethodManager manager = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
				if (visible) {
					View view = ((AndroidGraphics)app.getGraphics()).getView();
					view.setFocusable(true);
					view.setFocusableInTouchMode(true);
					manager.showSoftInput(((AndroidGraphics)app.getGraphics()).getView(), 0);
				} else {
					manager.hideSoftInputFromWindow(((AndroidGraphics)app.getGraphics()).getView().getWindowToken(), 0);
				}
			}
		});
	}

	@Override
	public void setCatchBackKey (boolean catchBack) {
		this.catchBack = catchBack;
	}

	@Override
	public boolean isCatchBackKey() {
		return catchBack;
	}

	@Override
	public void setCatchMenuKey (boolean catchMenu) {
		this.catchMenu = catchMenu;
	}
	
	@Override
	public boolean isCatchMenuKey () {
		return catchMenu;
	}

	@Override
	public void vibrate (int milliseconds) {
		vibrator.vibrate(milliseconds);
	}

	@Override
	public void vibrate (long[] pattern, int repeat) {
		vibrator.vibrate(pattern, repeat);
	}

	@Override
	public void cancelVibrate () {
		vibrator.cancel();
	}

	@Override
	public boolean justTouched () {
		return justTouched;
	}

	@Override
	public boolean isButtonPressed (int button) {
		synchronized (this) {
			if (hasMultitouch) {
				for (int pointer = 0; pointer < NUM_TOUCHES; pointer++) {
					if (touched[pointer] && (this.button[pointer] == button)) {
						return true;
					}
				}
			}
			return (touched[0] && (this.button[0] == button));
		}
	}

	final float[] R = new float[9];
	final float[] orientation = new float[3];

	private void updateOrientation () {
		if (SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticFieldValues)) {
			SensorManager.getOrientation(R, orientation);
			azimuth = (float)Math.toDegrees(orientation[0]);
			pitch = (float)Math.toDegrees(orientation[1]);
			roll = (float)Math.toDegrees(orientation[2]);
		}
	}

	/** Returns the rotation matrix describing the devices rotation as per SensorManager#getRotationMatrix(float[], float[], float[], float[]). Does not manipulate the matrix if the platform
	 * does not have an accelerometer.
	 * @param matrix */
	public void getRotationMatrix (float[] matrix) {
		SensorManager.getRotationMatrix(matrix, null, accelerometerValues, magneticFieldValues);
	}

	@Override
	public float getAzimuth () {
		if (!compassAvailable) return 0;

		updateOrientation();
		return azimuth;
	}

	@Override
	public float getPitch () {
		if (!compassAvailable) return 0;

		updateOrientation();
		return pitch;
	}

	@Override
	public float getRoll () {
		if (!compassAvailable) return 0;

		updateOrientation();
		return roll;
	}

	void registerSensorListeners () {
		if (config.useAccelerometer) {
			manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
			if (manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() == 0) {
				accelerometerAvailable = false;
			} else {
				Sensor accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
				accelerometerListener = new SensorListener(this.nativeOrientation, this.accelerometerValues, this.magneticFieldValues, this.gyroscopeValues);
				accelerometerAvailable = manager.registerListener(accelerometerListener, accelerometer,
					SensorManager.SENSOR_DELAY_GAME);
			}
		} else
			accelerometerAvailable = false;
		
		if (config.useGyroscope) {
			manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
			if (manager.getSensorList(Sensor.TYPE_GYROSCOPE).size() == 0) {
				gyroscopeAvailable = false;
			} else {
				Sensor gyroscope = manager.getSensorList(Sensor.TYPE_GYROSCOPE).get(0);
				gyroscopeListener = new SensorListener(this.nativeOrientation, this.gyroscopeValues, this.magneticFieldValues, this.gyroscopeValues);
				gyroscopeAvailable = manager.registerListener(gyroscopeListener, gyroscope,
					SensorManager.SENSOR_DELAY_GAME);
			}
		} else
			gyroscopeAvailable = false;
		
		if (config.useCompass) {
			if (manager == null) manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
			Sensor sensor = manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
			if (sensor != null) {
				compassAvailable = accelerometerAvailable;
				if (compassAvailable) {
					compassListener = new SensorListener(this.nativeOrientation, this.accelerometerValues, this.magneticFieldValues, this.gyroscopeValues);
					compassAvailable = manager.registerListener(compassListener, sensor, SensorManager.SENSOR_DELAY_GAME);
				}
			} else {
				compassAvailable = false;
			}
		} else
			compassAvailable = false;
		Gdx.app.log("AndroidInput", "sensor listener setup");
	}

	void unregisterSensorListeners () {
		if (manager != null) {
			if (accelerometerListener != null) {
				manager.unregisterListener(accelerometerListener);
				accelerometerListener = null;
			}
			if (gyroscopeListener != null) {
				manager.unregisterListener(gyroscopeListener);
				gyroscopeListener = null;
			}
			if (compassListener != null) {
				manager.unregisterListener(compassListener);
				compassListener = null;
			}
			manager = null;
		}
		Gdx.app.log("AndroidInput", "sensor listener tear down");
	}

	@Override
	public InputProcessor getInputProcessor () {
		return this.processor;
	}

	@Override
	public boolean isPeripheralAvailable (Peripheral peripheral) {
		if (peripheral == Peripheral.Accelerometer) return accelerometerAvailable;
		if (peripheral == Peripheral.Gyroscope) return gyroscopeAvailable;
		if (peripheral == Peripheral.Compass) return compassAvailable;
		if (peripheral == Peripheral.HardwareKeyboard) return keyboardAvailable;
		if (peripheral == Peripheral.OnscreenKeyboard) return true;
		if (peripheral == Peripheral.Vibrator)
			return (Build.VERSION.SDK_INT >= 11 && vibrator != null) ? vibrator.hasVibrator() : vibrator != null;
		if (peripheral == Peripheral.MultitouchScreen) return hasMultitouch;
		return false;
	}

	public int getFreePointerIndex () {
		int len = realId.length;
		for (int i = 0; i < len; i++) {
			if (realId[i] == -1) return i;
		}

		realId = resize(realId);
		touchX = resize(touchX);
		touchY = resize(touchY);
		deltaX = resize(deltaX);
		deltaY = resize(deltaY);
		touched = resize(touched);
		button = resize(button);

		return len;
	}

	private int[] resize (int[] orig) {
		int[] tmp = new int[orig.length + 2];
		System.arraycopy(orig, 0, tmp, 0, orig.length);
		return tmp;
	}

	private boolean[] resize (boolean[] orig) {
		boolean[] tmp = new boolean[orig.length + 2];
		System.arraycopy(orig, 0, tmp, 0, orig.length);
		return tmp;
	}

	public int lookUpPointerIndex (int pointerId) {
		int len = realId.length;
		for (int i = 0; i < len; i++) {
			if (realId[i] == pointerId) return i;
		}

		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < len; i++) {
			buf.append(i + ":" + realId[i] + " ");
		}
		Gdx.app.log("AndroidInput", "Pointer ID lookup failed: " + pointerId + ", " + buf.toString());
		return -1;
	}

	@Override
	public int getRotation () {
		int orientation = 0;

		if (context instanceof Activity) {
			orientation = ((Activity)context).getWindowManager().getDefaultDisplay().getRotation();
		} else {
			orientation = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
		}

		switch (orientation) {
		case Surface.ROTATION_0:
			return 0;
		case Surface.ROTATION_90:
			return 90;
		case Surface.ROTATION_180:
			return 180;
		case Surface.ROTATION_270:
			return 270;
		default:
			return 0;
		}
	}

	@Override
	public Orientation getNativeOrientation () {
		return nativeOrientation;
	}

	@Override
	public void setCursorCatched (boolean catched) {
	}

	@Override
	public boolean isCursorCatched () {
		return false;
	}

	@Override
	public int getDeltaX () {
		return deltaX[0];
	}

	@Override
	public int getDeltaX (int pointer) {
		return deltaX[pointer];
	}

	@Override
	public int getDeltaY () {
		return deltaY[0];
	}

	@Override
	public int getDeltaY (int pointer) {
		return deltaY[pointer];
	}

	@Override
	public void setCursorPosition (int x, int y) {
	}

	@Override
	public long getCurrentEventTime () {
		return currentEventTimeStamp;
	}

	public void addKeyListener (OnKeyListener listener) {
		keyListeners.add(listener);
	}

	public void onPause () {
		unregisterSensorListeners();

		// erase pointer ids. this sucks donkeyballs...
		Arrays.fill(realId, -1);

		// erase touched state. this also sucks donkeyballs...
		Arrays.fill(touched, false);
	}

	public void onResume () {
		registerSensorListeners();
	}

	/** Our implementation of SensorEventListener. Because Android doesn't like it when we register more than one Sensor to a single
	 * SensorEventListener, we add one of these for each Sensor. Could use an anonymous class, but I don't see any harm in
	 * explicitly defining it here. Correct me if I am wrong. */
	private class SensorListener implements SensorEventListener {
		final float[] accelerometerValues;
		final float[] magneticFieldValues;
		final Orientation nativeOrientation;
		final float[] gyroscopeValues;

		SensorListener (Orientation nativeOrientation, float[] accelerometerValues, float[] magneticFieldValues, float[] gyroscopeValues) {
			this.accelerometerValues = accelerometerValues;
			this.magneticFieldValues = magneticFieldValues;
			this.nativeOrientation = nativeOrientation;
			this.gyroscopeValues = gyroscopeValues;
		}

		@Override
		public void onAccuracyChanged (Sensor arg0, int arg1) {

		}

		@Override
		public void onSensorChanged (SensorEvent event) {
			if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
				if (nativeOrientation == Orientation.Portrait) {
					System.arraycopy(event.values, 0, accelerometerValues, 0, accelerometerValues.length);
				} else {
					accelerometerValues[0] = event.values[1];
					accelerometerValues[1] = -event.values[0];
					accelerometerValues[2] = event.values[2];
				}
			}
			if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
				System.arraycopy(event.values, 0, magneticFieldValues, 0, magneticFieldValues.length);
			}
			if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
				if (nativeOrientation == Orientation.Portrait) {
					System.arraycopy(event.values, 0, gyroscopeValues, 0, gyroscopeValues.length);
				} else {
					gyroscopeValues[0] = event.values[1];
					gyroscopeValues[1] = -event.values[0];
					gyroscopeValues[2] = event.values[2];
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy