<commit_before>/*******************************************************************************
 * 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 android.content.Context;
import android.view.MotionEvent;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.android.AndroidInput.TouchEvent;

/** Multitouch handler for devices running Android >= 2.0. If device is capable of (fake) multitouch this will report additional
 * pointers.
 * 
 * @author <EMAIL> */
public class AndroidMultiTouchHandler implements AndroidTouchHandler {
	public void onTouch (MotionEvent event, AndroidInput input) {
		final int action = event.getAction() & MotionEvent.ACTION_MASK;
		int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
		int pointerId = event.getPointerId(pointerIndex);

		int x = 0, y = 0;
		int realPointerIndex = 0;

		long timeStamp = System.nanoTime();
		synchronized (input) {
			switch (action) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				realPointerIndex = input.getFreePointerIndex(); // get a free pointer index as reported by Input.getX() etc.
				input.realId[realPointerIndex] = pointerId;
				x = (int)event.getX(pointerIndex);
				y = (int)event.getY(pointerIndex);
				postTouchEvent(input, TouchEvent.TOUCH_DOWN, x, y, realPointerIndex, timeStamp);
				input.touchX[realPointerIndex] = x;
				input.touchY[realPointerIndex] = y;
				input.deltaX[realPointerIndex] = 0;
				input.deltaY[realPointerIndex] = 0;
				input.touched[realPointerIndex] = true;
				break;

			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_OUTSIDE:
			case MotionEvent.ACTION_CANCEL:
				realPointerIndex = input.lookUpPointerIndex(pointerId);
				if (realPointerIndex == -1) break;
				input.realId[realPointerIndex] = -1;
				x = (int)event.getX(pointerIndex);
				y = (int)event.getY(pointerIndex);
				postTouchEvent(input, TouchEvent.TOUCH_UP, x, y, realPointerIndex, timeStamp);
				input.touchX[realPointerIndex] = x;
				input.touchY[realPointerIndex] = y;
				input.deltaX[realPointerIndex] = 0;
				input.deltaY[realPointerIndex] = 0;
				input.touched[realPointerIndex] = false;
				break;

			case MotionEvent.ACTION_MOVE:
				int pointerCount = event.getPointerCount();
				for (int i = 0; i < pointerCount; i++) {
					pointerIndex = i;
					pointerId = event.getPointerId(pointerIndex);
					x = (int)event.getX(pointerIndex);
					y = (int)event.getY(pointerIndex);
					realPointerIndex = input.lookUpPointerIndex(pointerId);
					if (realPointerIndex == -1) continue;
					postTouchEvent(input, TouchEvent.TOUCH_DRAGGED, x, y, realPointerIndex, timeStamp);
					input.deltaX[realPointerIndex] = x - input.touchX[realPointerIndex];
					input.deltaY[realPointerIndex] = y - input.touchY[realPointerIndex];
					input.touchX[realPointerIndex] = x;
					input.touchY[realPointerIndex] = y;
				}
				break;
			}
		}
		Gdx.app.getGraphics().requestRendering();
	}

	private void logAction (int action, int pointer) {
		String actionStr = "";
		if (action == MotionEvent.ACTION_DOWN)
			actionStr = "DOWN";
		else if (action == MotionEvent.ACTION_POINTER_DOWN)
			actionStr = "POINTER DOWN";
		else if (action == MotionEvent.ACTION_UP)
			actionStr = "UP";
		else if (action == MotionEvent.ACTION_POINTER_UP)
			actionStr = "POINTER UP";
		else if (action == MotionEvent.ACTION_OUTSIDE)
			actionStr = "OUTSIDE";
		else if (action == MotionEvent.ACTION_CANCEL)
			actionStr = "CANCEL";
		else if (action == MotionEvent.ACTION_MOVE)
			actionStr = "MOVE";
		else
			actionStr = "UNKNOWN (" + action + ")";
		Gdx.app.log("AndroidMultiTouchHandler", "action " + actionStr + ", Android pointer id: " + pointer);
	}

	private void postTouchEvent (AndroidInput input, int type, int x, int y, int pointer, long timeStamp) {
		TouchEvent event = input.usedTouchEvents.obtain();
		event.timeStamp = timeStamp;
		event.pointer = pointer;
		event.x = x;
		event.y = y;
		event.type = type;
		input.touchEvents.add(event);
	}

	public boolean supportsMultitouch (Context activity) {
		return activity.getPackageManager().hasSystemFeature("android.hardware.touchscreen.multitouch");
	}
}<commit_msg>Experimental: Attempted fix for rare ArrayIndexOutOfBoundsException<commit_after>/*******************************************************************************
 * 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 android.content.Context;
import android.view.MotionEvent;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.android.AndroidInput.TouchEvent;

/** Multitouch handler for devices running Android >= 2.0. If device is capable of (fake) multitouch this will report additional
 * pointers.
 * 
 * @author <EMAIL> */
public class AndroidMultiTouchHandler implements AndroidTouchHandler {
	public void onTouch (MotionEvent event, AndroidInput input) {
		final int action = event.getAction() & MotionEvent.ACTION_MASK;
		int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
		int pointerId = event.getPointerId(pointerIndex);

		int x = 0, y = 0;
		int realPointerIndex = 0;

		long timeStamp = System.nanoTime();
		synchronized (input) {
			switch (action) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				realPointerIndex = input.getFreePointerIndex(); // get a free pointer index as reported by Input.getX() etc.
				if (realPointerIndex > input.realId.length || realPointerIndex > input.touchX.length || realPointerIndex > input.touchY.length || realPointerIndex > input.deltaX.length || realPointerIndex > input.deltaY.length || realPointerIndex > input.touched.length) break;
				input.realId[realPointerIndex] = pointerId;
				x = (int)event.getX(pointerIndex);
				y = (int)event.getY(pointerIndex);
				postTouchEvent(input, TouchEvent.TOUCH_DOWN, x, y, realPointerIndex, timeStamp);
				input.touchX[realPointerIndex] = x;
				input.touchY[realPointerIndex] = y;
				input.deltaX[realPointerIndex] = 0;
				input.deltaY[realPointerIndex] = 0;
				input.touched[realPointerIndex] = true;
				break;

			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_OUTSIDE:
			case MotionEvent.ACTION_CANCEL:
				realPointerIndex = input.lookUpPointerIndex(pointerId);
				if (realPointerIndex == -1) break;
				if (realPointerIndex > input.realId.length || realPointerIndex > input.touchX.length || realPointerIndex > input.touchY.length || realPointerIndex > input.deltaX.length || realPointerIndex > input.deltaY.length || realPointerIndex > input.touched.length) break;
				input.realId[realPointerIndex] = -1;
				x = (int)event.getX(pointerIndex);
				y = (int)event.getY(pointerIndex);
				postTouchEvent(input, TouchEvent.TOUCH_UP, x, y, realPointerIndex, timeStamp);
				input.touchX[realPointerIndex] = x;
				input.touchY[realPointerIndex] = y;
				input.deltaX[realPointerIndex] = 0;
				input.deltaY[realPointerIndex] = 0;
				input.touched[realPointerIndex] = false;
				break;

			case MotionEvent.ACTION_MOVE:
				int pointerCount = event.getPointerCount();
				for (int i = 0; i < pointerCount; i++) {
					pointerIndex = i;
					pointerId = event.getPointerId(pointerIndex);
					x = (int)event.getX(pointerIndex);
					y = (int)event.getY(pointerIndex);
					realPointerIndex = input.lookUpPointerIndex(pointerId);
					if (realPointerIndex == -1) continue;
					if (realPointerIndex > input.touchX.length || realPointerIndex > input.touchY.length || realPointerIndex > input.deltaX.length || realPointerIndex > input.deltaY.length) break;
					postTouchEvent(input, TouchEvent.TOUCH_DRAGGED, x, y, realPointerIndex, timeStamp);
					input.deltaX[realPointerIndex] = x - input.touchX[realPointerIndex];
					input.deltaY[realPointerIndex] = y - input.touchY[realPointerIndex];
					input.touchX[realPointerIndex] = x;
					input.touchY[realPointerIndex] = y;
				}
				break;
			}
		}
		Gdx.app.getGraphics().requestRendering();
	}

	private void logAction (int action, int pointer) {
		String actionStr = "";
		if (action == MotionEvent.ACTION_DOWN)
			actionStr = "DOWN";
		else if (action == MotionEvent.ACTION_POINTER_DOWN)
			actionStr = "POINTER DOWN";
		else if (action == MotionEvent.ACTION_UP)
			actionStr = "UP";
		else if (action == MotionEvent.ACTION_POINTER_UP)
			actionStr = "POINTER UP";
		else if (action == MotionEvent.ACTION_OUTSIDE)
			actionStr = "OUTSIDE";
		else if (action == MotionEvent.ACTION_CANCEL)
			actionStr = "CANCEL";
		else if (action == MotionEvent.ACTION_MOVE)
			actionStr = "MOVE";
		else
			actionStr = "UNKNOWN (" + action + ")";
		Gdx.app.log("AndroidMultiTouchHandler", "action " + actionStr + ", Android pointer id: " + pointer);
	}

	private void postTouchEvent (AndroidInput input, int type, int x, int y, int pointer, long timeStamp) {
		TouchEvent event = input.usedTouchEvents.obtain();
		event.timeStamp = timeStamp;
		event.pointer = pointer;
		event.x = x;
		event.y = y;
		event.type = type;
		input.touchEvents.add(event);
	}

	public boolean supportsMultitouch (Context activity) {
		return activity.getPackageManager().hasSystemFeature("android.hardware.touchscreen.multitouch");
	}
}

{'fraction_non_alphanumeric': 0.13251127266034785, 'fraction_numerical': 0.0038649121192601455, 'mean_word_length': 3.928798185941043, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5222346', 'n_tokens_mistral': 3716, 'n_tokens_neox': 3204, 'n_words': 791}