blob: 696fd44eb9c0c4b46ee921a7ca62bd1f6882ad91 [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.mozc.android.inputmethod.japanese;
import android.annotation.TargetApi;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
/**
* The proxy of the {@code InputConnection} with tracking the composing text.
*
* There is no interface to extract the current composing text from {@code InputConnection}.
* So, instead, we track all the message to {@code InputConnection} and keep the current composing
* text as fall back. Note that the kept composing text might be different from the composing text
* in the application because it can overwrite any events from IME freely in theory.
* However, we can do nothing in such cases unfortunately, so just give them up.
*
*/
public class ComposingTextTrackingInputConnection implements InputConnection {
private final InputConnection baseConnection;
private String composingText = "";
public ComposingTextTrackingInputConnection(InputConnection baseConnection) {
if (baseConnection == null) {
throw new NullPointerException();
}
this.baseConnection = baseConnection;
}
public String getComposingText() {
return composingText;
}
@Override
public boolean beginBatchEdit() {
return baseConnection.beginBatchEdit();
}
@Override
public boolean clearMetaKeyStates(int states) {
return baseConnection.clearMetaKeyStates(states);
}
@Override
public boolean commitCompletion(CompletionInfo text) {
return baseConnection.commitCompletion(text);
}
@TargetApi(11)
@Override
public boolean commitCorrection(CorrectionInfo correctionInfo) {
return baseConnection.commitCorrection(correctionInfo);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
return baseConnection.commitText(text, newCursorPosition);
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
return baseConnection.deleteSurroundingText(beforeLength, afterLength);
}
@Override
public boolean endBatchEdit() {
return baseConnection.endBatchEdit();
}
@Override
public boolean finishComposingText() {
composingText = "";
return baseConnection.finishComposingText();
}
@Override
public int getCursorCapsMode(int reqModes) {
return baseConnection.getCursorCapsMode(reqModes);
}
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
return baseConnection.getExtractedText(request, flags);
}
@Override
public CharSequence getSelectedText(int flags) {
return baseConnection.getSelectedText(flags);
}
@Override
public CharSequence getTextAfterCursor(int n, int flags) {
return baseConnection.getTextAfterCursor(n, flags);
}
@Override
public CharSequence getTextBeforeCursor(int n, int flags) {
return baseConnection.getTextBeforeCursor(n, flags);
}
@Override
public boolean performContextMenuAction(int id) {
return baseConnection.performContextMenuAction(id);
}
@Override
public boolean performEditorAction(int editorAction) {
return baseConnection.performEditorAction(editorAction);
}
@Override
public boolean performPrivateCommand(String action, Bundle data) {
return baseConnection.performPrivateCommand(action, data);
}
@Override
public boolean reportFullscreenMode(boolean enabled) {
return baseConnection.reportFullscreenMode(enabled);
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
return baseConnection.sendKeyEvent(event);
}
@TargetApi(9)
@Override
public boolean setComposingRegion(int start, int end) {
// Note: This method is introduced since API level 9. Mozc supports API level 7,
// so we don't need to track the composing text by the invocation of this method.
return baseConnection.setComposingRegion(start, end);
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
composingText = text == null ? "" : text.toString();
return baseConnection.setComposingText(text, newCursorPosition);
}
@Override
public boolean setSelection(int start, int end) {
return baseConnection.setSelection(start, end);
}
/**
* Returns the instance of ComposingTextTrackingInputConnection based on the given baseConnection.
* This method will return:
* - {@code null}, if the given connection is {@code null}.
* - the given connection instance as is, if it is the instance of
* ComposingTextTrackingInputConnection.
* - the new instance of ComposingTextTrackingInputConnection wrapping baseConnection, otherwise.
*/
public static ComposingTextTrackingInputConnection newInstance(InputConnection baseConnection) {
if (baseConnection == null) {
return null;
}
if (baseConnection instanceof ComposingTextTrackingInputConnection) {
// The InputConnection is already wrapped by ComposingTextTrackingInputConnection,
// so we don't need to re-wrap it.
return ComposingTextTrackingInputConnection.class.cast(baseConnection);
}
return new ComposingTextTrackingInputConnection(baseConnection);
}
@Override
public boolean requestCursorUpdates(int cursorUpdateMode) {
return baseConnection.requestCursorUpdates(cursorUpdateMode);
}
}