@Override
 public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) {
   final Key[] keys = getKeys();
   final int touchX = getTouchX(x);
   final int touchY = getTouchY(y);
   int closestKeyIndex = AnyKeyboardViewBase.NOT_A_KEY;
   int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
   final int keyCount = keys.length;
   for (int i = 0; i < keyCount; i++) {
     final Key key = keys[i];
     int dist = key.squaredDistanceFrom(touchX, touchY);
     if (dist < closestKeyDist) {
       closestKeyIndex = i;
       closestKeyDist = dist;
     }
   }
   if (allKeys != null && closestKeyIndex != AnyKeyboardViewBase.NOT_A_KEY) {
     final Key key = keys[closestKeyIndex];
     allKeys[0] = key.getCodeAtIndex(0, isKeyShifted(key));
   }
   return closestKeyIndex;
 }
  @Override
  public void setKeyboard(AnyKeyboard newKeyboard, float verticalCorrection) {
    mExtensionKey = null;
    mExtensionVisible = false;

    mUtilityKey = null;
    super.setKeyboard(newKeyboard, verticalCorrection);
    if (newKeyboard != null
        && newKeyboard instanceof GenericKeyboard
        && ((GenericKeyboard) newKeyboard).disableKeyPreviews()) {
      // Phone keyboard never shows popup preview (except language
      // switch).
      setPreviewEnabled(false);
    } else {
      setPreviewEnabled(AnyApplication.getConfig().getShowKeyPreview());
    }
    // TODO: For now! should be a calculated value
    // lots of key : true
    // some keys: false
    setProximityCorrectionEnabled(true);
    // One-seventh of the keyboard width seems like a reasonable threshold
    // mJumpThresholdSquare = newKeyboard.getMinWidth() / 7;
    // mJumpThresholdSquare *= mJumpThresholdSquare;
    // Assuming there are 4 rows, this is the coordinate of the last row
    // mLastRowY = (newKeyboard.getHeight() * 3) / 4;
    // setKeyboardLocal(newKeyboard);

    // looking for the space-bar, so I'll be able to detect swipes starting
    // at it
    mSpaceBarKey = null;
    if (newKeyboard != null) {
      for (Key aKey : newKeyboard.getKeys()) {
        if (aKey.getPrimaryCode() == KeyCodes.SPACE) {
          mSpaceBarKey = aKey;
          break;
        }
      }
    }
  }
 public void openUtilityKeyboard() {
   dismissAllKeyPreviews();
   if (mUtilityKey == null) {
     mUtilityKey = new AnyKey(new Row(getKeyboard()), getThemedKeyboardDimens());
     mUtilityKey.edgeFlags = Keyboard.EDGE_BOTTOM;
     mUtilityKey.height = 0;
     mUtilityKey.width = 0;
     mUtilityKey.popupResId = R.xml.ext_kbd_utility_utility;
     mUtilityKey.externalResourcePopupLayout = false;
     mUtilityKey.x = getWidth() / 2;
     mUtilityKey.y = getHeight() - getThemedKeyboardDimens().getSmallKeyHeight();
   }
   super.onLongPress(mDefaultAddOn, mUtilityKey, true, false);
   mMiniKeyboard.setPreviewEnabled(true);
 }
  @Override
  public boolean onTouchEvent(@NonNull MotionEvent me) {
    if (getKeyboard()
        == null) // I mean, if there isn't any keyboard I'm handling, what's the point?
    return false;

    if (areTouchesDisabled()) return super.onTouchEvent(me);

    if (me.getAction() == MotionEvent.ACTION_DOWN) {
      mFirstTouchPoint.x = (int) me.getX();
      mFirstTouchPoint.y = (int) me.getY();
      mIsFirstDownEventInsideSpaceBar =
          mSpaceBarKey != null && mSpaceBarKey.isInside(mFirstTouchPoint.x, mFirstTouchPoint.y);
    } else if (mIsFirstDownEventInsideSpaceBar) {
      if (me.getAction() == MotionEvent.ACTION_MOVE) {
        setGesturePreviewText(mSwitcher, me);
        return true;
      } else if (me.getAction() == MotionEvent.ACTION_UP) {
        final int slide = getSlideDistance(me);
        final int distance = slide & 0x00FF; // removing direction
        if (distance > SLIDE_RATIO_FOR_GESTURE) {
          // cancelling the touch (since we handle this)
          disableTouchesTillFingersAreUp();
          // handling the gesture
          switch (slide & 0xFF00) {
            case DIRECTION_DOWN:
              mKeyboardActionListener.onSwipeDown(true);
              break;
            case DIRECTION_UP:
              mKeyboardActionListener.onSwipeUp(true);
              break;
            case DIRECTION_LEFT:
              mKeyboardActionListener.onSwipeLeft(true, isAtTwoFingersState());
              break;
            case DIRECTION_RIGHT:
              mKeyboardActionListener.onSwipeRight(true, isAtTwoFingersState());
              break;
          }
        }
        super.onTouchEvent(me);
        return true; // handled
      }
    }
    // If the motion event is above the keyboard and it's a MOVE event
    // coming even before the first MOVE event into the extension area
    if (!mIsFirstDownEventInsideSpaceBar
        && me.getY() < mExtensionKeyboardYActivationPoint
        && !mMiniKeyboardPopup.isShowing()
        && !mExtensionVisible
        && me.getAction() == MotionEvent.ACTION_MOVE) {
      if (mExtensionKeyboardAreaEntranceTime <= 0)
        mExtensionKeyboardAreaEntranceTime = System.currentTimeMillis();

      if (System.currentTimeMillis() - mExtensionKeyboardAreaEntranceTime
          > DELAY_BEFORE_POPPING_UP_EXTENSION_KBD) {
        KeyboardExtension extKbd = ((ExternalAnyKeyboard) getKeyboard()).getExtensionLayout();
        if (extKbd == null || extKbd.getKeyboardResId() == -1) {
          return super.onTouchEvent(me);
        } else {
          // telling the main keyboard that the last touch was
          // canceled
          MotionEvent cancel =
              MotionEvent.obtain(
                  me.getDownTime(),
                  me.getEventTime(),
                  MotionEvent.ACTION_CANCEL,
                  me.getX(),
                  me.getY(),
                  0);
          super.onTouchEvent(cancel);
          cancel.recycle();

          mExtensionVisible = true;
          dismissAllKeyPreviews();
          if (mExtensionKey == null) {
            mExtensionKey = new AnyKey(new Row(getKeyboard()), getThemedKeyboardDimens());
            mExtensionKey.edgeFlags = 0;
            mExtensionKey.height = 1;
            mExtensionKey.width = 1;
            mExtensionKey.popupResId = extKbd.getKeyboardResId();
            mExtensionKey.externalResourcePopupLayout = mExtensionKey.popupResId != 0;
            mExtensionKey.x = getWidth() / 2;
            mExtensionKey.y = mExtensionKeyboardPopupOffset;
          }
          // so the popup will be right above your finger.
          mExtensionKey.x = (int) me.getX();

          onLongPress(
              extKbd,
              mExtensionKey,
              AnyApplication.getConfig().isStickyExtensionKeyboard(),
              !AnyApplication.getConfig().isStickyExtensionKeyboard());
          // it is an extension..
          mMiniKeyboard.setPreviewEnabled(true);
          return true;
        }
      } else {
        return super.onTouchEvent(me);
      }
    } else if (mExtensionVisible && me.getY() > mExtensionKeyboardYDismissPoint) {
      // closing the popup
      dismissPopupKeyboard();
      return true;
    } else {
      return super.onTouchEvent(me);
    }
  }