Home | History | Annotate | Download | only in keyboard
      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 
     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      */
     42     public KeyDetector(final float keyHysteresisDistance,
     43             final float keyHysteresisDistanceForSlidingModifier) {
     44         mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
     45         mKeyHysteresisDistanceForSlidingModifierSquared = (int)(
     46                 keyHysteresisDistanceForSlidingModifier * keyHysteresisDistanceForSlidingModifier);
     47     }
     48 
     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 
     59     public int getKeyHysteresisDistanceSquared(final boolean isSlidingFromModifier) {
     60         return isSlidingFromModifier
     61                 ? mKeyHysteresisDistanceForSlidingModifierSquared : mKeyHysteresisDistanceSquared;
     62     }
     63 
     64     public int getTouchX(final int x) {
     65         return x + mCorrectionX;
     66     }
     67 
     68     // TODO: Remove vertical correction.
     69     public int getTouchY(final int y) {
     70         return y + mCorrectionY;
     71     }
     72 
     73     public Keyboard getKeyboard() {
     74         return mKeyboard;
     75     }
     76 
     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      */
     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