mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-29 08:31:35 -08:00
Improve IM synchronization on Android
* java/org/gnu/emacs/EmacsInputConnection.java (EmacsInputConnection): Reimplement as an InputConnection, not BaseInputConnection. * src/androidterm.c (performEditorAction): Sync prior to sending keyboard events.
This commit is contained in:
parent
87b8f8769e
commit
90ae3cc387
2 changed files with 176 additions and 24 deletions
|
|
@ -19,26 +19,35 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
import android.view.inputmethod.TextSnapshot;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import android.os.Build;
|
||||
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.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
|
||||
|
|
@ -77,15 +86,18 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
extractAbsoluteOffsets = true;
|
||||
};
|
||||
|
||||
|
||||
public
|
||||
EmacsInputConnection (EmacsView view)
|
||||
{
|
||||
super (view, true);
|
||||
|
||||
this.view = view;
|
||||
this.windowHandle = view.window.handle;
|
||||
}
|
||||
|
||||
|
||||
/* The functions below are called by input methods whenever they
|
||||
need to perform an edit. */
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
beginBatchEdit ()
|
||||
|
|
@ -116,7 +128,6 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
commitCompletion (CompletionInfo info)
|
||||
{
|
||||
|
|
@ -133,6 +144,19 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
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)
|
||||
|
|
@ -170,6 +194,14 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
commitText (CharSequence text, int newCursorPosition,
|
||||
TextAttribute textAttribute)
|
||||
{
|
||||
return commitText (text, newCursorPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
deleteSurroundingText (int leftLength, int rightLength)
|
||||
|
|
@ -187,6 +219,16 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
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 ()
|
||||
|
|
@ -277,6 +319,14 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
setComposingText (CharSequence text, int newCursorPosition,
|
||||
TextAttribute textAttribute)
|
||||
{
|
||||
return setComposingText (text, newCursorPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
setComposingRegion (int start, int end)
|
||||
|
|
@ -292,6 +342,13 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
setComposingRegion (int start, int end, TextAttribute textAttribute)
|
||||
{
|
||||
return setComposingRegion (start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
performEditorAction (int editorAction)
|
||||
|
|
@ -430,6 +487,8 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
}
|
||||
|
||||
@Override
|
||||
/* ACTION_MULTIPLE is apparently obsolete. */
|
||||
@SuppressWarnings ("deprecation")
|
||||
public boolean
|
||||
sendKeyEvent (KeyEvent key)
|
||||
{
|
||||
|
|
@ -440,20 +499,33 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
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. */
|
||||
|
||||
/* This can be implemented the same way as
|
||||
deleteSurroundingText. */
|
||||
return this.deleteSurroundingText (beforeLength, afterLength);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -471,6 +543,16 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
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,
|
||||
|
|
@ -505,11 +587,74 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue