1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.keyboard; 18 19 /** 20 * This class handles key detection. 21 */ 22 public class KeyDetector { 23 private final int mKeyHysteresisDistanceSquared; 24 private final int mKeyHysteresisDistanceForSlidingModifierSquared; 25 26 private Keyboard mKeyboard; 27 private int mCorrectionX; 28 private int mCorrectionY; 29 KeyDetector()30 public KeyDetector() { 31 this(0.0f /* keyHysteresisDistance */, 0.0f /* keyHysteresisDistanceForSlidingModifier */); 32 } 33 34 /** 35 * Key detection object constructor with key hysteresis distances. 36 * 37 * @param keyHysteresisDistance if the pointer movement distance is smaller than this, the 38 * movement will not be handled as meaningful movement. The unit is pixel. 39 * @param keyHysteresisDistanceForSlidingModifier the same parameter for sliding input that 40 * starts from a modifier key such as shift and symbols key. 41 */ KeyDetector(final float keyHysteresisDistance, final float keyHysteresisDistanceForSlidingModifier)42 public KeyDetector(final float keyHysteresisDistance, 43 final float keyHysteresisDistanceForSlidingModifier) { 44 mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance); 45 mKeyHysteresisDistanceForSlidingModifierSquared = (int)( 46 keyHysteresisDistanceForSlidingModifier * keyHysteresisDistanceForSlidingModifier); 47 } 48 setKeyboard(final Keyboard keyboard, final float correctionX, final float correctionY)49 public void setKeyboard(final Keyboard keyboard, final float correctionX, 50 final float correctionY) { 51 if (keyboard == null) { 52 throw new NullPointerException(); 53 } 54 mCorrectionX = (int)correctionX; 55 mCorrectionY = (int)correctionY; 56 mKeyboard = keyboard; 57 } 58 getKeyHysteresisDistanceSquared(final boolean isSlidingFromModifier)59 public int getKeyHysteresisDistanceSquared(final boolean isSlidingFromModifier) { 60 return isSlidingFromModifier 61 ? mKeyHysteresisDistanceForSlidingModifierSquared : mKeyHysteresisDistanceSquared; 62 } 63 getTouchX(final int x)64 public int getTouchX(final int x) { 65 return x + mCorrectionX; 66 } 67 68 // TODO: Remove vertical correction. getTouchY(final int y)69 public int getTouchY(final int y) { 70 return y + mCorrectionY; 71 } 72 getKeyboard()73 public Keyboard getKeyboard() { 74 return mKeyboard; 75 } 76 alwaysAllowsKeySelectionByDraggingFinger()77 public boolean alwaysAllowsKeySelectionByDraggingFinger() { 78 return false; 79 } 80 81 /** 82 * Detect the key whose hitbox the touch point is in. 83 * 84 * @param x The x-coordinate of a touch point 85 * @param y The y-coordinate of a touch point 86 * @return the key that the touch point hits. 87 */ detectHitKey(final int x, final int y)88 public Key detectHitKey(final int x, final int y) { 89 if (mKeyboard == null) { 90 return null; 91 } 92 final int touchX = getTouchX(x); 93 final int touchY = getTouchY(y); 94 95 int minDistance = Integer.MAX_VALUE; 96 Key primaryKey = null; 97 for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) { 98 // An edge key always has its enlarged hitbox to respond to an event that occurred in 99 // the empty area around the key. (@see Key#markAsLeftEdge(KeyboardParams)} etc.) 100 if (!key.isOnKey(touchX, touchY)) { 101 continue; 102 } 103 final int distance = key.squaredDistanceToEdge(touchX, touchY); 104 if (distance > minDistance) { 105 continue; 106 } 107 // To take care of hitbox overlaps, we compare key's code here too. 108 if (primaryKey == null || distance < minDistance 109 || key.getCode() > primaryKey.getCode()) { 110 minDistance = distance; 111 primaryKey = key; 112 } 113 } 114 return primaryKey; 115 } 116 } 117