From e9a0e66716dab4dd3184d009d8920de1961efdfa Mon Sep 17 00:00:00 2001 From: Amin Bandali Date: Mon, 16 Dec 2024 21:45:41 -0500 Subject: Rename to Kelar Keyboard (org.kelar.inputmethod.latin) --- .../src/org/kelar/inputmethod/latin/InputView.java | 252 +++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 java/src/org/kelar/inputmethod/latin/InputView.java (limited to 'java/src/org/kelar/inputmethod/latin/InputView.java') diff --git a/java/src/org/kelar/inputmethod/latin/InputView.java b/java/src/org/kelar/inputmethod/latin/InputView.java new file mode 100644 index 000000000..9aab0e7c7 --- /dev/null +++ b/java/src/org/kelar/inputmethod/latin/InputView.java @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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 org.kelar.inputmethod.latin; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; + +import org.kelar.inputmethod.accessibility.AccessibilityUtils; +import org.kelar.inputmethod.keyboard.MainKeyboardView; +import org.kelar.inputmethod.latin.suggestions.MoreSuggestionsView; +import org.kelar.inputmethod.latin.suggestions.SuggestionStripView; + +public final class InputView extends FrameLayout { + private final Rect mInputViewRect = new Rect(); + private MainKeyboardView mMainKeyboardView; + private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder; + private MoreSuggestionsViewCanceler mMoreSuggestionsViewCanceler; + private MotionEventForwarder mActiveForwarder; + + public InputView(final Context context, final AttributeSet attrs) { + super(context, attrs, 0); + } + + @Override + protected void onFinishInflate() { + final SuggestionStripView suggestionStripView = + (SuggestionStripView)findViewById(R.id.suggestion_strip_view); + mMainKeyboardView = (MainKeyboardView)findViewById(R.id.keyboard_view); + mKeyboardTopPaddingForwarder = new KeyboardTopPaddingForwarder( + mMainKeyboardView, suggestionStripView); + mMoreSuggestionsViewCanceler = new MoreSuggestionsViewCanceler( + mMainKeyboardView, suggestionStripView); + } + + public void setKeyboardTopPadding(final int keyboardTopPadding) { + mKeyboardTopPaddingForwarder.setKeyboardTopPadding(keyboardTopPadding); + } + + @Override + protected boolean dispatchHoverEvent(final MotionEvent event) { + if (AccessibilityUtils.getInstance().isTouchExplorationEnabled() + && mMainKeyboardView.isShowingMoreKeysPanel()) { + // With accessibility mode on, discard hover events while a more keys keyboard is shown. + // The {@link MoreKeysKeyboard} receives hover events directly from the platform. + return true; + } + return super.dispatchHoverEvent(event); + } + + @Override + public boolean onInterceptTouchEvent(final MotionEvent me) { + final Rect rect = mInputViewRect; + getGlobalVisibleRect(rect); + final int index = me.getActionIndex(); + final int x = (int)me.getX(index) + rect.left; + final int y = (int)me.getY(index) + rect.top; + + // The touch events that hit the top padding of keyboard should be forwarded to + // {@link SuggestionStripView}. + if (mKeyboardTopPaddingForwarder.onInterceptTouchEvent(x, y, me)) { + mActiveForwarder = mKeyboardTopPaddingForwarder; + return true; + } + + // To cancel {@link MoreSuggestionsView}, we should intercept a touch event to + // {@link MainKeyboardView} and dismiss the {@link MoreSuggestionsView}. + if (mMoreSuggestionsViewCanceler.onInterceptTouchEvent(x, y, me)) { + mActiveForwarder = mMoreSuggestionsViewCanceler; + return true; + } + + mActiveForwarder = null; + return false; + } + + @Override + public boolean onTouchEvent(final MotionEvent me) { + if (mActiveForwarder == null) { + return super.onTouchEvent(me); + } + + final Rect rect = mInputViewRect; + getGlobalVisibleRect(rect); + final int index = me.getActionIndex(); + final int x = (int)me.getX(index) + rect.left; + final int y = (int)me.getY(index) + rect.top; + return mActiveForwarder.onTouchEvent(x, y, me); + } + + /** + * This class forwards series of {@link MotionEvent}s from SenderView to + * ReceiverView. + * + * @param a {@link View} that may send a {@link MotionEvent} to . + * @param a {@link View} that receives forwarded {@link MotionEvent} from + * . + */ + private static abstract class + MotionEventForwarder { + protected final SenderView mSenderView; + protected final ReceiverView mReceiverView; + + protected final Rect mEventSendingRect = new Rect(); + protected final Rect mEventReceivingRect = new Rect(); + + public MotionEventForwarder(final SenderView senderView, final ReceiverView receiverView) { + mSenderView = senderView; + mReceiverView = receiverView; + } + + // Return true if a touch event of global coordinate x, y needs to be forwarded. + protected abstract boolean needsToForward(final int x, final int y); + + // Translate global x-coordinate to ReceiverView local coordinate. + protected int translateX(final int x) { + return x - mEventReceivingRect.left; + } + + // Translate global y-coordinate to ReceiverView local coordinate. + protected int translateY(final int y) { + return y - mEventReceivingRect.top; + } + + /** + * Callback when a {@link MotionEvent} is forwarded. + * @param me the motion event to be forwarded. + */ + protected void onForwardingEvent(final MotionEvent me) {} + + // Returns true if a {@link MotionEvent} is needed to be forwarded to + // ReceiverView. Otherwise returns false. + public boolean onInterceptTouchEvent(final int x, final int y, final MotionEvent me) { + // Forwards a {link MotionEvent} only if both SenderView and + // ReceiverView are visible. + if (mSenderView.getVisibility() != View.VISIBLE || + mReceiverView.getVisibility() != View.VISIBLE) { + return false; + } + mSenderView.getGlobalVisibleRect(mEventSendingRect); + if (!mEventSendingRect.contains(x, y)) { + return false; + } + + if (me.getActionMasked() == MotionEvent.ACTION_DOWN) { + // If the down event happens in the forwarding area, successive + // {@link MotionEvent}s should be forwarded to ReceiverView. + if (needsToForward(x, y)) { + return true; + } + } + + return false; + } + + // Returns true if a {@link MotionEvent} is forwarded to ReceiverView. + // Otherwise returns false. + public boolean onTouchEvent(final int x, final int y, final MotionEvent me) { + mReceiverView.getGlobalVisibleRect(mEventReceivingRect); + // Translate global coordinates to ReceiverView local coordinates. + me.setLocation(translateX(x), translateY(y)); + mReceiverView.dispatchTouchEvent(me); + onForwardingEvent(me); + return true; + } + } + + /** + * This class forwards {@link MotionEvent}s happened in the top padding of + * {@link MainKeyboardView} to {@link SuggestionStripView}. + */ + private static class KeyboardTopPaddingForwarder + extends MotionEventForwarder { + private int mKeyboardTopPadding; + + public KeyboardTopPaddingForwarder(final MainKeyboardView mainKeyboardView, + final SuggestionStripView suggestionStripView) { + super(mainKeyboardView, suggestionStripView); + } + + public void setKeyboardTopPadding(final int keyboardTopPadding) { + mKeyboardTopPadding = keyboardTopPadding; + } + + private boolean isInKeyboardTopPadding(final int y) { + return y < mEventSendingRect.top + mKeyboardTopPadding; + } + + @Override + protected boolean needsToForward(final int x, final int y) { + // Forwarding an event only when {@link MainKeyboardView} is visible. + // Because the visibility of {@link MainKeyboardView} is controlled by its parent + // view in {@link KeyboardSwitcher#setMainKeyboardFrame()}, we should check the + // visibility of the parent view. + final View mainKeyboardFrame = (View)mSenderView.getParent(); + return mainKeyboardFrame.getVisibility() == View.VISIBLE && isInKeyboardTopPadding(y); + } + + @Override + protected int translateY(final int y) { + final int translatedY = super.translateY(y); + if (isInKeyboardTopPadding(y)) { + // The forwarded event should have coordinates that are inside of the target. + return Math.min(translatedY, mEventReceivingRect.height() - 1); + } + return translatedY; + } + } + + /** + * This class forwards {@link MotionEvent}s happened in the {@link MainKeyboardView} to + * {@link SuggestionStripView} when the {@link MoreSuggestionsView} is showing. + * {@link SuggestionStripView} dismisses {@link MoreSuggestionsView} when it receives any event + * outside of it. + */ + private static class MoreSuggestionsViewCanceler + extends MotionEventForwarder { + public MoreSuggestionsViewCanceler(final MainKeyboardView mainKeyboardView, + final SuggestionStripView suggestionStripView) { + super(mainKeyboardView, suggestionStripView); + } + + @Override + protected boolean needsToForward(final int x, final int y) { + return mReceiverView.isShowingMoreSuggestionPanel() && mEventSendingRect.contains(x, y); + } + + @Override + protected void onForwardingEvent(final MotionEvent me) { + if (me.getActionMasked() == MotionEvent.ACTION_DOWN) { + mReceiverView.dismissMoreSuggestionsPanel(); + } + } + } +} -- cgit v1.2.3-83-g751a