This source file includes following definitions.
- beginBatchEdit
- endBatchEdit
- commitCompletion
- commitCorrection
- commitText
- commitText
- deleteSurroundingText
- deleteSurroundingTextInCodePoints
- finishComposingText
- getSelectedText
- getTextAfterCursor
- getTextBeforeCursor
- setComposingText
- setComposingText
- setComposingRegion
- setComposingRegion
- performEditorAction
- performContextMenuAction
- getExtractedText
- setSelection
- sendKeyEvent
- requestCursorUpdates
- requestCursorUpdates
- getSurroundingText
- takeSnapshot
- closeConnection
- reset
- getHandler
- commitContent
- setImeConsumesInput
- clearMetaKeyStates
- reportFullscreenMode
- performSpellCheck
- performPrivateCommand
- getCursorCapsMode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.gnu.emacs;
21
22 import android.os.Build;
23 import android.os.Bundle;
24 import android.os.Handler;
25
26 import android.view.KeyEvent;
27
28 import android.view.inputmethod.CompletionInfo;
29 import android.view.inputmethod.CorrectionInfo;
30 import android.view.inputmethod.ExtractedText;
31 import android.view.inputmethod.ExtractedTextRequest;
32 import android.view.inputmethod.InputConnection;
33 import android.view.inputmethod.InputContentInfo;
34 import android.view.inputmethod.SurroundingText;
35 import android.view.inputmethod.TextAttribute;
36 import android.view.inputmethod.TextSnapshot;
37
38 import android.util.Log;
39
40
41
42
43 public final class EmacsInputConnection implements InputConnection
44 {
45 private static final String TAG = "EmacsInputConnection";
46
47
48 private EmacsView view;
49
50
51 private short windowHandle;
52
53
54
55
56 private int batchEditCount;
57
58
59
60
61
62
63
64
65
66 private static boolean syncAfterCommit;
67
68
69
70
71
72
73
74
75
76
77 private static boolean extractAbsoluteOffsets;
78
79 static
80 {
81 if (Build.MANUFACTURER.equalsIgnoreCase ("Huawei")
82 || Build.MANUFACTURER.equalsIgnoreCase ("Honor"))
83 extractAbsoluteOffsets = syncAfterCommit = true;
84
85
86
87
88
89 if (Build.MANUFACTURER.equalsIgnoreCase ("Samsung")
90 || Build.MANUFACTURER.equalsIgnoreCase ("Vivo"))
91 extractAbsoluteOffsets = true;
92 };
93
94
95 public
96 EmacsInputConnection (EmacsView view)
97 {
98 this.view = view;
99 this.windowHandle = view.window.handle;
100 }
101
102
103
104
105
106 @Override
107 public boolean
108 beginBatchEdit ()
109 {
110
111 if (view.icSerial < view.icGeneration)
112 return false;
113
114 if (EmacsService.DEBUG_IC)
115 Log.d (TAG, "beginBatchEdit");
116
117 EmacsNative.beginBatchEdit (windowHandle);
118
119
120
121 batchEditCount++;
122 return true;
123 }
124
125 @Override
126 public boolean
127 endBatchEdit ()
128 {
129
130 if (view.icSerial < view.icGeneration)
131 return false;
132
133 if (EmacsService.DEBUG_IC)
134 Log.d (TAG, "endBatchEdit");
135
136 EmacsNative.endBatchEdit (windowHandle);
137
138
139
140
141 if (batchEditCount > 0)
142 batchEditCount -= 1;
143
144 return batchEditCount > 0;
145 }
146
147 public boolean
148 commitCompletion (CompletionInfo info)
149 {
150
151 if (view.icSerial < view.icGeneration)
152 return false;
153
154 if (EmacsService.DEBUG_IC)
155 Log.d (TAG, "commitCompletion: " + info);
156
157 EmacsNative.commitCompletion (windowHandle,
158 info.getText ().toString (),
159 info.getPosition ());
160 return true;
161 }
162
163 @Override
164 public boolean
165 commitCorrection (CorrectionInfo info)
166 {
167
168
169
170
171
172
173 return false;
174 }
175
176 @Override
177 public boolean
178 commitText (CharSequence text, int newCursorPosition)
179 {
180 int[] selection;
181
182
183 if (view.icSerial < view.icGeneration)
184 return false;
185
186 if (EmacsService.DEBUG_IC)
187 Log.d (TAG, "commitText: " + text + " " + newCursorPosition);
188
189 EmacsNative.commitText (windowHandle, text.toString (),
190 newCursorPosition);
191
192 if (syncAfterCommit)
193 {
194
195
196
197 selection = EmacsNative.getSelection (windowHandle);
198
199 if (EmacsService.DEBUG_IC && selection != null)
200 Log.d (TAG, "commitText: new selection is " + selection[0]
201 + ", by " + selection[1]);
202
203 if (selection != null)
204
205
206 view.imManager.updateSelection (view, selection[0],
207 selection[1], -1, -1);
208 }
209
210 return true;
211 }
212
213 @Override
214 public boolean
215 commitText (CharSequence text, int newCursorPosition,
216 TextAttribute textAttribute)
217 {
218 return commitText (text, newCursorPosition);
219 }
220
221 @Override
222 public boolean
223 deleteSurroundingText (int leftLength, int rightLength)
224 {
225
226 if (view.icSerial < view.icGeneration)
227 return false;
228
229 if (EmacsService.DEBUG_IC)
230 Log.d (TAG, ("deleteSurroundingText: "
231 + leftLength + " " + rightLength));
232
233 EmacsNative.deleteSurroundingText (windowHandle, leftLength,
234 rightLength);
235 return true;
236 }
237
238 @Override
239 public boolean
240 deleteSurroundingTextInCodePoints (int leftLength, int rightLength)
241 {
242
243
244
245 return deleteSurroundingText (leftLength, rightLength);
246 }
247
248 @Override
249 public boolean
250 finishComposingText ()
251 {
252
253 if (view.icSerial < view.icGeneration)
254 return false;
255
256 if (EmacsService.DEBUG_IC)
257 Log.d (TAG, "finishComposingText");
258
259 EmacsNative.finishComposingText (windowHandle);
260 return true;
261 }
262
263 @Override
264 public String
265 getSelectedText (int flags)
266 {
267
268 if (view.icSerial < view.icGeneration)
269 return null;
270
271 if (EmacsService.DEBUG_IC)
272 Log.d (TAG, "getSelectedText: " + flags);
273
274 return EmacsNative.getSelectedText (windowHandle, flags);
275 }
276
277 @Override
278 public String
279 getTextAfterCursor (int length, int flags)
280 {
281 String string;
282
283
284 if (view.icSerial < view.icGeneration)
285 return null;
286
287 if (EmacsService.DEBUG_IC)
288 Log.d (TAG, "getTextAfterCursor: " + length + " " + flags);
289
290 string = EmacsNative.getTextAfterCursor (windowHandle, length,
291 flags);
292
293 if (EmacsService.DEBUG_IC)
294 Log.d (TAG, " --> " + string);
295
296 return string;
297 }
298
299 @Override
300 public String
301 getTextBeforeCursor (int length, int flags)
302 {
303 String string;
304
305
306 if (view.icSerial < view.icGeneration)
307 return null;
308
309 if (EmacsService.DEBUG_IC)
310 Log.d (TAG, "getTextBeforeCursor: " + length + " " + flags);
311
312 string = EmacsNative.getTextBeforeCursor (windowHandle, length,
313 flags);
314
315 if (EmacsService.DEBUG_IC)
316 Log.d (TAG, " --> " + string);
317
318 return string;
319 }
320
321 @Override
322 public boolean
323 setComposingText (CharSequence text, int newCursorPosition)
324 {
325
326 if (view.icSerial < view.icGeneration)
327 return false;
328
329 if (EmacsService.DEBUG_IC)
330 Log.d (TAG, ("setComposingText: "
331 + text + " ## " + newCursorPosition));
332
333 EmacsNative.setComposingText (windowHandle, text.toString (),
334 newCursorPosition);
335 return true;
336 }
337
338 @Override
339 public boolean
340 setComposingText (CharSequence text, int newCursorPosition,
341 TextAttribute textAttribute)
342 {
343 return setComposingText (text, newCursorPosition);
344 }
345
346 @Override
347 public boolean
348 setComposingRegion (int start, int end)
349 {
350
351 if (view.icSerial < view.icGeneration)
352 return false;
353
354 if (EmacsService.DEBUG_IC)
355 Log.d (TAG, "setComposingRegion: " + start + " " + end);
356
357 EmacsNative.setComposingRegion (windowHandle, start, end);
358 return true;
359 }
360
361 @Override
362 public boolean
363 setComposingRegion (int start, int end, TextAttribute textAttribute)
364 {
365 return setComposingRegion (start, end);
366 }
367
368 @Override
369 public boolean
370 performEditorAction (int editorAction)
371 {
372
373 if (view.icSerial < view.icGeneration)
374 return false;
375
376 if (EmacsService.DEBUG_IC)
377 Log.d (TAG, "performEditorAction: " + editorAction);
378
379 EmacsNative.performEditorAction (windowHandle, editorAction);
380 return true;
381 }
382
383 @Override
384 public boolean
385 performContextMenuAction (int contextMenuAction)
386 {
387 int action;
388
389
390 if (view.icSerial < view.icGeneration)
391 return false;
392
393 if (EmacsService.DEBUG_IC)
394 Log.d (TAG, "performContextMenuAction: " + contextMenuAction);
395
396
397
398
399 switch (contextMenuAction)
400 {
401 case android.R.id.selectAll:
402 action = 0;
403 break;
404
405 case android.R.id.startSelectingText:
406 action = 1;
407 break;
408
409 case android.R.id.stopSelectingText:
410 action = 2;
411 break;
412
413 case android.R.id.cut:
414 action = 3;
415 break;
416
417 case android.R.id.copy:
418 action = 4;
419 break;
420
421 case android.R.id.paste:
422 action = 5;
423 break;
424
425 default:
426 return true;
427 }
428
429 EmacsNative.performContextMenuAction (windowHandle, action);
430 return true;
431 }
432
433 @Override
434 public ExtractedText
435 getExtractedText (ExtractedTextRequest request, int flags)
436 {
437 ExtractedText text;
438 int[] selection;
439
440
441 if (view.icSerial < view.icGeneration)
442 return null;
443
444 if (EmacsService.DEBUG_IC)
445 Log.d (TAG, "getExtractedText: " + request.hintMaxChars + ", "
446 + request.hintMaxLines + " " + flags);
447
448
449
450
451
452 if (extractAbsoluteOffsets
453 && request.hintMaxChars == 0
454 && request.hintMaxLines == 0
455 && flags == 0)
456 {
457
458 selection = EmacsNative.getSelection (windowHandle);
459 if (selection == null)
460 return null;
461
462
463 text = new ExtractedText ();
464 text.partialStartOffset = -1;
465 text.partialEndOffset = -1;
466 text.text = "";
467 text.selectionStart = selection[0];
468 text.selectionEnd = selection[1];
469 }
470 else
471 text = EmacsNative.getExtractedText (windowHandle, request,
472 flags);
473
474 if (text == null)
475 {
476 if (EmacsService.DEBUG_IC)
477 Log.d (TAG, "getExtractedText: text is NULL");
478
479 return null;
480 }
481
482 if (EmacsService.DEBUG_IC)
483 Log.d (TAG, "getExtractedText: " + text.text + " @"
484 + text.startOffset + ":" + text.selectionStart
485 + ", " + text.selectionEnd);
486
487 return text;
488 }
489
490 @Override
491 public boolean
492 setSelection (int start, int end)
493 {
494
495 if (view.icSerial < view.icGeneration)
496 return false;
497
498 if (EmacsService.DEBUG_IC)
499 Log.d (TAG, "setSelection: " + start + " " + end);
500
501 EmacsNative.setSelection (windowHandle, start, end);
502 return true;
503 }
504
505 @Override
506
507 @SuppressWarnings ("deprecation")
508 public boolean
509 sendKeyEvent (KeyEvent key)
510 {
511
512 if (view.icSerial < view.icGeneration)
513 return false;
514
515 if (EmacsService.DEBUG_IC)
516 Log.d (TAG, "sendKeyEvent: " + key);
517
518
519
520 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
521 view.imManager.dispatchKeyEventFromInputMethod (view, key);
522 else
523 {
524
525
526 switch (key.getAction ())
527 {
528 case KeyEvent.ACTION_DOWN:
529 view.onKeyDown (key.getKeyCode (), key);
530 break;
531
532 case KeyEvent.ACTION_UP:
533 view.onKeyUp (key.getKeyCode (), key);
534 break;
535
536 case KeyEvent.ACTION_MULTIPLE:
537 view.onKeyMultiple (key.getKeyCode (),
538 key.getRepeatCount (),
539 key);
540 break;
541 }
542 }
543
544 return true;
545 }
546
547 @Override
548 public boolean
549 requestCursorUpdates (int cursorUpdateMode)
550 {
551
552 if (view.icSerial < view.icGeneration)
553 return false;
554
555 if (EmacsService.DEBUG_IC)
556 Log.d (TAG, "requestCursorUpdates: " + cursorUpdateMode);
557
558 EmacsNative.requestCursorUpdates (windowHandle, cursorUpdateMode);
559 return true;
560 }
561
562 @Override
563 public boolean
564 requestCursorUpdates (int cursorUpdateMode, int filter)
565 {
566 if (filter != 0)
567 return false;
568
569 return requestCursorUpdates (cursorUpdateMode);
570 }
571
572 @Override
573 public SurroundingText
574 getSurroundingText (int beforeLength, int afterLength,
575 int flags)
576 {
577 SurroundingText text;
578
579
580 if (view.icSerial < view.icGeneration)
581 return null;
582
583 if (EmacsService.DEBUG_IC)
584 Log.d (TAG, ("getSurroundingText: " + beforeLength + ", "
585 + afterLength));
586
587 text = EmacsNative.getSurroundingText (windowHandle, beforeLength,
588 afterLength, flags);
589
590 if (EmacsService.DEBUG_IC && text != null)
591 Log.d (TAG, ("getSurroundingText: "
592 + text.getSelectionStart ()
593 + ","
594 + text.getSelectionEnd ()
595 + "+"
596 + text.getOffset ()
597 + ": "
598 + text.getText ()));
599
600 return text;
601 }
602
603 @Override
604 public TextSnapshot
605 takeSnapshot ()
606 {
607 TextSnapshot snapshot;
608
609
610 if (view.icSerial < view.icGeneration)
611 return null;
612
613 snapshot = EmacsNative.takeSnapshot (windowHandle);
614
615 if (EmacsService.DEBUG_IC)
616 Log.d (TAG, ("takeSnapshot: "
617 + snapshot.getSurroundingText ().getText ()
618 + " @ " + snapshot.getCompositionEnd ()
619 + ", " + snapshot.getCompositionStart ()));
620
621 return snapshot;
622 }
623
624 @Override
625 public void
626 closeConnection ()
627 {
628 batchEditCount = 0;
629 }
630
631
632
633 public void
634 reset ()
635 {
636 batchEditCount = 0;
637 }
638
639
640
641
642 @Override
643 public Handler
644 getHandler ()
645 {
646 return null;
647 }
648
649 @Override
650 public boolean
651 commitContent (InputContentInfo inputContentInfo, int flags,
652 Bundle opts)
653 {
654 return false;
655 }
656
657 @Override
658 public boolean
659 setImeConsumesInput (boolean imeConsumesInput)
660 {
661 return false;
662 }
663
664 @Override
665 public boolean
666 clearMetaKeyStates (int states)
667 {
668 return false;
669 }
670
671 @Override
672 public boolean
673 reportFullscreenMode (boolean enabled)
674 {
675 return false;
676 }
677
678 @Override
679 public boolean
680 performSpellCheck ()
681 {
682 return false;
683 }
684
685 @Override
686 public boolean
687 performPrivateCommand (String action, Bundle data)
688 {
689 return false;
690 }
691
692 @Override
693 public int
694 getCursorCapsMode (int reqModes)
695 {
696 return 0;
697 }
698 }