aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorPo Lu2023-06-14 15:37:47 +0800
committerPo Lu2023-06-14 15:37:47 +0800
commit90ae3cc387530229e5aca32c00d35495ab680e21 (patch)
treef35e1da961f97a04a9b35ff6e62536587a6164b6 /java
parent87b8f8769e6cd4563f82747c279c858617ce1b2b (diff)
downloademacs-90ae3cc387530229e5aca32c00d35495ab680e21.tar.gz
emacs-90ae3cc387530229e5aca32c00d35495ab680e21.zip
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.
Diffstat (limited to 'java')
-rw-r--r--java/org/gnu/emacs/EmacsInputConnection.java189
1 files changed, 167 insertions, 22 deletions
diff --git a/java/org/gnu/emacs/EmacsInputConnection.java b/java/org/gnu/emacs/EmacsInputConnection.java
index 73c93c67ac7..1bcc9a62a81 100644
--- a/java/org/gnu/emacs/EmacsInputConnection.java
+++ b/java/org/gnu/emacs/EmacsInputConnection.java
@@ -19,26 +19,35 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20package org.gnu.emacs; 20package org.gnu.emacs;
21 21
22import android.view.inputmethod.BaseInputConnection; 22import android.os.Build;
23import android.os.Bundle;
24import android.os.Handler;
25
26import android.view.KeyEvent;
27
23import android.view.inputmethod.CompletionInfo; 28import android.view.inputmethod.CompletionInfo;
29import android.view.inputmethod.CorrectionInfo;
24import android.view.inputmethod.ExtractedText; 30import android.view.inputmethod.ExtractedText;
25import android.view.inputmethod.ExtractedTextRequest; 31import android.view.inputmethod.ExtractedTextRequest;
32import android.view.inputmethod.InputConnection;
33import android.view.inputmethod.InputContentInfo;
26import android.view.inputmethod.SurroundingText; 34import android.view.inputmethod.SurroundingText;
35import android.view.inputmethod.TextAttribute;
27import android.view.inputmethod.TextSnapshot; 36import android.view.inputmethod.TextSnapshot;
28 37
29import android.view.KeyEvent;
30
31import android.os.Build;
32
33import android.util.Log; 38import android.util.Log;
34 39
35/* Android input methods, take number six. See textconv.c for more 40/* Android input methods, take number six. See textconv.c for more
36 details; this is more-or-less a thin wrapper around that file. */ 41 details; this is more-or-less a thin wrapper around that file. */
37 42
38public final class EmacsInputConnection extends BaseInputConnection 43public final class EmacsInputConnection implements InputConnection
39{ 44{
40 private static final String TAG = "EmacsInputConnection"; 45 private static final String TAG = "EmacsInputConnection";
46
47 /* View associated with this input connection. */
41 private EmacsView view; 48 private EmacsView view;
49
50 /* The handle ID associated with that view's window. */
42 private short windowHandle; 51 private short windowHandle;
43 52
44 /* Whether or not to synchronize and call `updateIC' with the 53 /* Whether or not to synchronize and call `updateIC' with the
@@ -77,15 +86,18 @@ public final class EmacsInputConnection extends BaseInputConnection
77 extractAbsoluteOffsets = true; 86 extractAbsoluteOffsets = true;
78 }; 87 };
79 88
89
80 public 90 public
81 EmacsInputConnection (EmacsView view) 91 EmacsInputConnection (EmacsView view)
82 { 92 {
83 super (view, true);
84
85 this.view = view; 93 this.view = view;
86 this.windowHandle = view.window.handle; 94 this.windowHandle = view.window.handle;
87 } 95 }
88 96
97
98 /* The functions below are called by input methods whenever they
99 need to perform an edit. */
100
89 @Override 101 @Override
90 public boolean 102 public boolean
91 beginBatchEdit () 103 beginBatchEdit ()
@@ -116,7 +128,6 @@ public final class EmacsInputConnection extends BaseInputConnection
116 return true; 128 return true;
117 } 129 }
118 130
119 @Override
120 public boolean 131 public boolean
121 commitCompletion (CompletionInfo info) 132 commitCompletion (CompletionInfo info)
122 { 133 {
@@ -135,6 +146,19 @@ public final class EmacsInputConnection extends BaseInputConnection
135 146
136 @Override 147 @Override
137 public boolean 148 public boolean
149 commitCorrection (CorrectionInfo info)
150 {
151 /* The input method calls this function not to commit text, but to
152 indicate that a subsequent edit will consist of a correction.
153 Emacs has no use for this information.
154
155 Of course this completely contradicts the provided
156 documentation, but this is how Android actually behaves. */
157 return false;
158 }
159
160 @Override
161 public boolean
138 commitText (CharSequence text, int newCursorPosition) 162 commitText (CharSequence text, int newCursorPosition)
139 { 163 {
140 int[] selection; 164 int[] selection;
@@ -172,6 +196,14 @@ public final class EmacsInputConnection extends BaseInputConnection
172 196
173 @Override 197 @Override
174 public boolean 198 public boolean
199 commitText (CharSequence text, int newCursorPosition,
200 TextAttribute textAttribute)
201 {
202 return commitText (text, newCursorPosition);
203 }
204
205 @Override
206 public boolean
175 deleteSurroundingText (int leftLength, int rightLength) 207 deleteSurroundingText (int leftLength, int rightLength)
176 { 208 {
177 /* Return if the input connection is out of date. */ 209 /* Return if the input connection is out of date. */
@@ -189,6 +221,16 @@ public final class EmacsInputConnection extends BaseInputConnection
189 221
190 @Override 222 @Override
191 public boolean 223 public boolean
224 deleteSurroundingTextInCodePoints (int leftLength, int rightLength)
225 {
226 /* Emacs returns characters which cannot be represented in a Java
227 `char' as NULL characters, so code points always reflect
228 characters themselves. */
229 return deleteSurroundingText (leftLength, rightLength);
230 }
231
232 @Override
233 public boolean
192 finishComposingText () 234 finishComposingText ()
193 { 235 {
194 /* Return if the input connection is out of date. */ 236 /* Return if the input connection is out of date. */
@@ -279,6 +321,14 @@ public final class EmacsInputConnection extends BaseInputConnection
279 321
280 @Override 322 @Override
281 public boolean 323 public boolean
324 setComposingText (CharSequence text, int newCursorPosition,
325 TextAttribute textAttribute)
326 {
327 return setComposingText (text, newCursorPosition);
328 }
329
330 @Override
331 public boolean
282 setComposingRegion (int start, int end) 332 setComposingRegion (int start, int end)
283 { 333 {
284 /* Return if the input connection is out of date. */ 334 /* Return if the input connection is out of date. */
@@ -294,6 +344,13 @@ public final class EmacsInputConnection extends BaseInputConnection
294 344
295 @Override 345 @Override
296 public boolean 346 public boolean
347 setComposingRegion (int start, int end, TextAttribute textAttribute)
348 {
349 return setComposingRegion (start, end);
350 }
351
352 @Override
353 public boolean
297 performEditorAction (int editorAction) 354 performEditorAction (int editorAction)
298 { 355 {
299 /* Return if the input connection is out of date. */ 356 /* Return if the input connection is out of date. */
@@ -430,6 +487,8 @@ public final class EmacsInputConnection extends BaseInputConnection
430 } 487 }
431 488
432 @Override 489 @Override
490 /* ACTION_MULTIPLE is apparently obsolete. */
491 @SuppressWarnings ("deprecation")
433 public boolean 492 public boolean
434 sendKeyEvent (KeyEvent key) 493 sendKeyEvent (KeyEvent key)
435 { 494 {
@@ -440,20 +499,33 @@ public final class EmacsInputConnection extends BaseInputConnection
440 if (EmacsService.DEBUG_IC) 499 if (EmacsService.DEBUG_IC)
441 Log.d (TAG, "sendKeyEvent: " + key); 500 Log.d (TAG, "sendKeyEvent: " + key);
442 501
443 return super.sendKeyEvent (key); 502 /* Use the standard API if possible. */
444 }
445 503
446 @Override 504 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
447 public boolean 505 view.imManager.dispatchKeyEventFromInputMethod (view, key);
448 deleteSurroundingTextInCodePoints (int beforeLength, int afterLength) 506 else
449 { 507 {
450 /* Return if the input connection is out of date. */ 508 /* Fall back to dispatching the event manually if not. */
451 if (view.icSerial < view.icGeneration) 509
452 return false; 510 switch (key.getAction ())
511 {
512 case KeyEvent.ACTION_DOWN:
513 view.onKeyDown (key.getKeyCode (), key);
514 break;
515
516 case KeyEvent.ACTION_UP:
517 view.onKeyUp (key.getKeyCode (), key);
518 break;
519
520 case KeyEvent.ACTION_MULTIPLE:
521 view.onKeyMultiple (key.getKeyCode (),
522 key.getRepeatCount (),
523 key);
524 break;
525 }
526 }
453 527
454 /* This can be implemented the same way as 528 return true;
455 deleteSurroundingText. */
456 return this.deleteSurroundingText (beforeLength, afterLength);
457 } 529 }
458 530
459 @Override 531 @Override
@@ -472,6 +544,16 @@ public final class EmacsInputConnection extends BaseInputConnection
472 } 544 }
473 545
474 @Override 546 @Override
547 public boolean
548 requestCursorUpdates (int cursorUpdateMode, int filter)
549 {
550 if (filter != 0)
551 return false;
552
553 return requestCursorUpdates (cursorUpdateMode);
554 }
555
556 @Override
475 public SurroundingText 557 public SurroundingText
476 getSurroundingText (int beforeLength, int afterLength, 558 getSurroundingText (int beforeLength, int afterLength,
477 int flags) 559 int flags)
@@ -506,10 +588,73 @@ public final class EmacsInputConnection extends BaseInputConnection
506 /* Override functions which are not implemented. */ 588 /* Override functions which are not implemented. */
507 589
508 @Override 590 @Override
591 public Handler
592 getHandler ()
593 {
594 return null;
595 }
596
597 @Override
598 public void
599 closeConnection ()
600 {
601
602 }
603
604 @Override
605 public boolean
606 commitContent (InputContentInfo inputContentInfo, int flags,
607 Bundle opts)
608 {
609 return false;
610 }
611
612 @Override
613 public boolean
614 setImeConsumesInput (boolean imeConsumesInput)
615 {
616 return false;
617 }
618
619 @Override
509 public TextSnapshot 620 public TextSnapshot
510 takeSnapshot () 621 takeSnapshot ()
511 { 622 {
512 Log.d (TAG, "takeSnapshot");
513 return null; 623 return null;
514 } 624 }
625
626 @Override
627 public boolean
628 clearMetaKeyStates (int states)
629 {
630 return false;
631 }
632
633 @Override
634 public boolean
635 reportFullscreenMode (boolean enabled)
636 {
637 return false;
638 }
639
640 @Override
641 public boolean
642 performSpellCheck ()
643 {
644 return false;
645 }
646
647 @Override
648 public boolean
649 performPrivateCommand (String action, Bundle data)
650 {
651 return false;
652 }
653
654 @Override
655 public int
656 getCursorCapsMode (int reqModes)
657 {
658 return 0;
659 }
515} 660}