[CB06] Fix a design error.
The event interpreter should intervene later, after decoding. Decoding should happen first, and then the Event should be passed to the InputLogic. For the time being, we will leave the (unused) EventInterpreter class and its friends, because we'll use them again later. Bug: 13406701 Change-Id: I7582d486724311e39e6692e606cca50c78800643
This commit is contained in:
parent
f4f4ae8fee
commit
5eac728b4a
6 changed files with 35 additions and 146 deletions
|
@ -168,4 +168,8 @@ public class Event {
|
||||||
public boolean isCommittable() {
|
public boolean isCommittable() {
|
||||||
return EVENT_INPUT_KEYPRESS == mType || EVENT_MODE_KEY == mType || EVENT_TOGGLE == mType;
|
return EVENT_INPUT_KEYPRESS == mType || EVENT_MODE_KEY == mType || EVENT_TOGGLE == mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHandled() {
|
||||||
|
return EVENT_NOT_HANDLED != mType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
|
|
||||||
package com.android.inputmethod.event;
|
package com.android.inputmethod.event;
|
||||||
|
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.Constants;
|
|
||||||
import com.android.inputmethod.latin.LatinIME;
|
|
||||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -37,25 +32,9 @@ public class EventInterpreter {
|
||||||
// TODO: Implement an object pool for events, as we'll create a lot of them
|
// TODO: Implement an object pool for events, as we'll create a lot of them
|
||||||
// TODO: Create a combiner
|
// TODO: Create a combiner
|
||||||
// TODO: Create an object type to represent input material + visual feedback + decoding state
|
// TODO: Create an object type to represent input material + visual feedback + decoding state
|
||||||
// TODO: Create an interface to call back to Latin IME through the above object
|
|
||||||
|
|
||||||
final EventDecoderSpec mDecoderSpec;
|
private final EventDecoderSpec mDecoderSpec;
|
||||||
final SparseArray<HardwareEventDecoder> mHardwareEventDecoders;
|
private final ArrayList<Combiner> mCombiners;
|
||||||
final SoftwareEventDecoder mSoftwareEventDecoder;
|
|
||||||
final LatinIME mLatinIme;
|
|
||||||
final ArrayList<Combiner> mCombiners;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a default interpreter.
|
|
||||||
*
|
|
||||||
* This creates a default interpreter that does nothing. A default interpreter should normally
|
|
||||||
* only be used for fallback purposes, when we really don't know what we want to do with input.
|
|
||||||
*
|
|
||||||
* @param latinIme a reference to the ime.
|
|
||||||
*/
|
|
||||||
public EventInterpreter(final LatinIME latinIme) {
|
|
||||||
this(null, latinIme);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an event interpreter according to a specification.
|
* Create an event interpreter according to a specification.
|
||||||
|
@ -70,64 +49,10 @@ public class EventInterpreter {
|
||||||
* interpreter that does no specific combining, and assumes the most common cases.
|
* interpreter that does no specific combining, and assumes the most common cases.
|
||||||
*
|
*
|
||||||
* @param specification the specification for event interpretation. null for default.
|
* @param specification the specification for event interpretation. null for default.
|
||||||
* @param latinIme a reference to the ime.
|
|
||||||
*/
|
*/
|
||||||
public EventInterpreter(final EventDecoderSpec specification, final LatinIME latinIme) {
|
public EventInterpreter(final EventDecoderSpec specification) {
|
||||||
mDecoderSpec = null != specification ? specification : new EventDecoderSpec();
|
mDecoderSpec = null != specification ? specification : new EventDecoderSpec();
|
||||||
// For both, we expect to have only one decoder in almost all cases, hence the default
|
|
||||||
// capacity of 1.
|
|
||||||
mHardwareEventDecoders = new SparseArray<HardwareEventDecoder>(1);
|
|
||||||
mSoftwareEventDecoder = new SoftwareKeyboardEventDecoder();
|
|
||||||
mCombiners = CollectionUtils.newArrayList();
|
mCombiners = CollectionUtils.newArrayList();
|
||||||
mCombiners.add(new DeadKeyCombiner());
|
mCombiners.add(new DeadKeyCombiner());
|
||||||
mLatinIme = latinIme;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to decode a hardware key event into a generic event, and execute any
|
|
||||||
// necessary action.
|
|
||||||
public boolean onHardwareKeyEvent(final KeyEvent hardwareKeyEvent) {
|
|
||||||
final Event decodedEvent = getHardwareKeyEventDecoder(hardwareKeyEvent.getDeviceId())
|
|
||||||
.decodeHardwareKey(hardwareKeyEvent);
|
|
||||||
return onEvent(decodedEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onSoftwareEvent() {
|
|
||||||
final Event decodedEvent = getSoftwareEventDecoder().decodeSoftwareEvent();
|
|
||||||
return onEvent(decodedEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private HardwareEventDecoder getHardwareKeyEventDecoder(final int deviceId) {
|
|
||||||
final HardwareEventDecoder decoder = mHardwareEventDecoders.get(deviceId);
|
|
||||||
if (null != decoder) return decoder;
|
|
||||||
// TODO: create the decoder according to the specification
|
|
||||||
final HardwareEventDecoder newDecoder = new HardwareKeyboardEventDecoder(deviceId);
|
|
||||||
mHardwareEventDecoders.put(deviceId, newDecoder);
|
|
||||||
return newDecoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SoftwareEventDecoder getSoftwareEventDecoder() {
|
|
||||||
// Within the context of Latin IME, since we never present several software interfaces
|
|
||||||
// at the time, we should never need multiple software event decoders at a time.
|
|
||||||
return mSoftwareEventDecoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean onEvent(final Event event) {
|
|
||||||
Event currentlyProcessingEvent = event;
|
|
||||||
boolean processed = false;
|
|
||||||
for (int i = 0; i < mCombiners.size(); ++i) {
|
|
||||||
currentlyProcessingEvent = mCombiners.get(i).combine(event);
|
|
||||||
}
|
|
||||||
while (null != currentlyProcessingEvent) {
|
|
||||||
if (currentlyProcessingEvent.isCommittable()) {
|
|
||||||
mLatinIme.onCodeInput(currentlyProcessingEvent.mCodePoint,
|
|
||||||
Constants.EXTERNAL_KEYBOARD_COORDINATE,
|
|
||||||
Constants.EXTERNAL_KEYBOARD_COORDINATE);
|
|
||||||
processed = true;
|
|
||||||
} else if (event.isDead()) {
|
|
||||||
processed = true;
|
|
||||||
}
|
|
||||||
currentlyProcessingEvent = currentlyProcessingEvent.mNextEvent;
|
|
||||||
}
|
|
||||||
return processed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 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 com.android.inputmethod.event;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An event decoder for events out of a software keyboard.
|
|
||||||
*
|
|
||||||
* This defines the interface for an event decoder that supports events out of a software keyboard.
|
|
||||||
* This differs significantly from hardware keyboard event decoders in several respects. First,
|
|
||||||
* a software keyboard does not have a scancode/layout system; the keypresses that insert
|
|
||||||
* characters output unicode characters directly.
|
|
||||||
*/
|
|
||||||
public interface SoftwareEventDecoder extends EventDecoder {
|
|
||||||
public Event decodeSoftwareEvent();
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 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 com.android.inputmethod.event;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A decoder for events from software keyboard, like the ones displayed by Latin IME.
|
|
||||||
*/
|
|
||||||
public class SoftwareKeyboardEventDecoder implements SoftwareEventDecoder {
|
|
||||||
@Override
|
|
||||||
public Event decodeSoftwareEvent() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -45,6 +45,7 @@ import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.PrintWriterPrinter;
|
import android.util.PrintWriterPrinter;
|
||||||
import android.util.Printer;
|
import android.util.Printer;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
@ -60,6 +61,8 @@ import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||||
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||||
import com.android.inputmethod.event.Event;
|
import com.android.inputmethod.event.Event;
|
||||||
|
import com.android.inputmethod.event.HardwareEventDecoder;
|
||||||
|
import com.android.inputmethod.event.HardwareKeyboardEventDecoder;
|
||||||
import com.android.inputmethod.event.InputTransaction;
|
import com.android.inputmethod.event.InputTransaction;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.keyboard.KeyboardActionListener;
|
import com.android.inputmethod.keyboard.KeyboardActionListener;
|
||||||
|
@ -120,6 +123,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private final Settings mSettings;
|
private final Settings mSettings;
|
||||||
private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
|
private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
|
||||||
this /* SuggestionStripViewAccessor */);
|
this /* SuggestionStripViewAccessor */);
|
||||||
|
// We expect to have only one decoder in almost all cases, hence the default capacity of 1.
|
||||||
|
// If it turns out we need several, it will get grown seamlessly.
|
||||||
|
final SparseArray<HardwareEventDecoder> mHardwareEventDecoders
|
||||||
|
= new SparseArray<HardwareEventDecoder>(1);
|
||||||
|
|
||||||
private View mExtractArea;
|
private View mExtractArea;
|
||||||
private View mKeyPreviewBackingView;
|
private View mKeyPreviewBackingView;
|
||||||
|
@ -1588,19 +1595,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HardwareEventDecoder getHardwareKeyEventDecoder(final int deviceId) {
|
||||||
|
final HardwareEventDecoder decoder = mHardwareEventDecoders.get(deviceId);
|
||||||
|
if (null != decoder) return decoder;
|
||||||
|
// TODO: create the decoder according to the specification
|
||||||
|
final HardwareEventDecoder newDecoder = new HardwareKeyboardEventDecoder(deviceId);
|
||||||
|
mHardwareEventDecoders.put(deviceId, newDecoder);
|
||||||
|
return newDecoder;
|
||||||
|
}
|
||||||
|
|
||||||
// Hooks for hardware keyboard
|
// Hooks for hardware keyboard
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
|
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
|
||||||
if (!ProductionFlag.IS_HARDWARE_KEYBOARD_SUPPORTED) return super.onKeyDown(keyCode, event);
|
if (!ProductionFlag.IS_HARDWARE_KEYBOARD_SUPPORTED) {
|
||||||
// onHardwareKeyEvent, like onKeyDown returns true if it handled the event, false if
|
return super.onKeyDown(keyCode, keyEvent);
|
||||||
// it doesn't know what to do with it and leave it to the application. For example,
|
}
|
||||||
// hardware key events for adjusting the screen's brightness are passed as is.
|
final Event event = getHardwareKeyEventDecoder(
|
||||||
if (mInputLogic.mEventInterpreter.onHardwareKeyEvent(event)) {
|
keyEvent.getDeviceId()).decodeHardwareKey(keyEvent);
|
||||||
final long keyIdentifier = event.getDeviceId() << 32 + event.getKeyCode();
|
// If the event is not handled by LatinIME, we just pass it to the parent implementation.
|
||||||
mInputLogic.mCurrentlyPressedHardwareKeys.add(keyIdentifier);
|
// If it's handled, we return true because we did handle it.
|
||||||
|
if (event.isHandled()) {
|
||||||
|
mInputLogic.onCodeInput(mSettings.getCurrent(), event,
|
||||||
|
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onKeyDown(keyCode, event);
|
return super.onKeyDown(keyCode, keyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -80,8 +80,6 @@ public final class InputLogic {
|
||||||
public SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
|
public SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
|
||||||
// TODO: mSuggest should be touched by a single thread.
|
// TODO: mSuggest should be touched by a single thread.
|
||||||
public volatile Suggest mSuggest;
|
public volatile Suggest mSuggest;
|
||||||
// The event interpreter should never be null.
|
|
||||||
public final EventInterpreter mEventInterpreter;
|
|
||||||
|
|
||||||
public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
||||||
public final WordComposer mWordComposer;
|
public final WordComposer mWordComposer;
|
||||||
|
@ -104,7 +102,6 @@ public final class InputLogic {
|
||||||
mLatinIME = latinIME;
|
mLatinIME = latinIME;
|
||||||
mSuggestionStripViewAccessor = suggestionStripViewAccessor;
|
mSuggestionStripViewAccessor = suggestionStripViewAccessor;
|
||||||
mWordComposer = new WordComposer();
|
mWordComposer = new WordComposer();
|
||||||
mEventInterpreter = new EventInterpreter(latinIME);
|
|
||||||
mConnection = new RichInputConnection(latinIME);
|
mConnection = new RichInputConnection(latinIME);
|
||||||
mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
|
mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue