package org.gnu.emacs;
-import android.view.inputmethod.BaseInputConnection;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+
+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;
+import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.SurroundingText;
+import android.view.inputmethod.TextAttribute;
import android.view.inputmethod.TextSnapshot;
-import android.view.KeyEvent;
-
-import android.os.Build;
-
import android.util.Log;
/* Android input methods, take number six. See textconv.c for more
details; this is more-or-less a thin wrapper around that file. */
-public final class EmacsInputConnection extends BaseInputConnection
+public final class EmacsInputConnection implements InputConnection
{
private static final String TAG = "EmacsInputConnection";
+
+ /* View associated with this input connection. */
private EmacsView view;
+
+ /* The handle ID associated with that view's window. */
private short windowHandle;
/* Whether or not to synchronize and call `updateIC' with the
extractAbsoluteOffsets = true;
};
+
public
EmacsInputConnection (EmacsView view)
{
- super (view, true);
-
this.view = view;
this.windowHandle = view.window.handle;
}
+\f
+ /* The functions below are called by input methods whenever they
+ need to perform an edit. */
+
@Override
public boolean
beginBatchEdit ()
return true;
}
- @Override
public boolean
commitCompletion (CompletionInfo info)
{
return true;
}
+ @Override
+ public boolean
+ commitCorrection (CorrectionInfo info)
+ {
+ /* The input method calls this function not to commit text, but to
+ indicate that a subsequent edit will consist of a correction.
+ Emacs has no use for this information.
+
+ Of course this completely contradicts the provided
+ documentation, but this is how Android actually behaves. */
+ return false;
+ }
+
@Override
public boolean
commitText (CharSequence text, int newCursorPosition)
return true;
}
+ @Override
+ public boolean
+ commitText (CharSequence text, int newCursorPosition,
+ TextAttribute textAttribute)
+ {
+ return commitText (text, newCursorPosition);
+ }
+
@Override
public boolean
deleteSurroundingText (int leftLength, int rightLength)
return true;
}
+ @Override
+ public boolean
+ deleteSurroundingTextInCodePoints (int leftLength, int rightLength)
+ {
+ /* Emacs returns characters which cannot be represented in a Java
+ `char' as NULL characters, so code points always reflect
+ characters themselves. */
+ return deleteSurroundingText (leftLength, rightLength);
+ }
+
@Override
public boolean
finishComposingText ()
return true;
}
+ @Override
+ public boolean
+ setComposingText (CharSequence text, int newCursorPosition,
+ TextAttribute textAttribute)
+ {
+ return setComposingText (text, newCursorPosition);
+ }
+
@Override
public boolean
setComposingRegion (int start, int end)
return true;
}
+ @Override
+ public boolean
+ setComposingRegion (int start, int end, TextAttribute textAttribute)
+ {
+ return setComposingRegion (start, end);
+ }
+
@Override
public boolean
performEditorAction (int editorAction)
}
@Override
+ /* ACTION_MULTIPLE is apparently obsolete. */
+ @SuppressWarnings ("deprecation")
public boolean
sendKeyEvent (KeyEvent key)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "sendKeyEvent: " + key);
- return super.sendKeyEvent (key);
- }
+ /* Use the standard API if possible. */
- @Override
- public boolean
- deleteSurroundingTextInCodePoints (int beforeLength, int afterLength)
- {
- /* Return if the input connection is out of date. */
- if (view.icSerial < view.icGeneration)
- return false;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ view.imManager.dispatchKeyEventFromInputMethod (view, key);
+ else
+ {
+ /* Fall back to dispatching the event manually if not. */
+
+ switch (key.getAction ())
+ {
+ case KeyEvent.ACTION_DOWN:
+ view.onKeyDown (key.getKeyCode (), key);
+ break;
+
+ case KeyEvent.ACTION_UP:
+ view.onKeyUp (key.getKeyCode (), key);
+ break;
+
+ case KeyEvent.ACTION_MULTIPLE:
+ view.onKeyMultiple (key.getKeyCode (),
+ key.getRepeatCount (),
+ key);
+ break;
+ }
+ }
- /* This can be implemented the same way as
- deleteSurroundingText. */
- return this.deleteSurroundingText (beforeLength, afterLength);
+ return true;
}
@Override
return true;
}
+ @Override
+ public boolean
+ requestCursorUpdates (int cursorUpdateMode, int filter)
+ {
+ if (filter != 0)
+ return false;
+
+ return requestCursorUpdates (cursorUpdateMode);
+ }
+
@Override
public SurroundingText
getSurroundingText (int beforeLength, int afterLength,
\f
/* Override functions which are not implemented. */
+ @Override
+ public Handler
+ getHandler ()
+ {
+ return null;
+ }
+
+ @Override
+ public void
+ closeConnection ()
+ {
+
+ }
+
+ @Override
+ public boolean
+ commitContent (InputContentInfo inputContentInfo, int flags,
+ Bundle opts)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean
+ setImeConsumesInput (boolean imeConsumesInput)
+ {
+ return false;
+ }
+
@Override
public TextSnapshot
takeSnapshot ()
{
- Log.d (TAG, "takeSnapshot");
return null;
}
+
+ @Override
+ public boolean
+ clearMetaKeyStates (int states)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean
+ reportFullscreenMode (boolean enabled)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean
+ performSpellCheck ()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean
+ performPrivateCommand (String action, Bundle data)
+ {
+ return false;
+ }
+
+ @Override
+ public int
+ getCursorCapsMode (int reqModes)
+ {
+ return 0;
+ }
}