1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-28 16:21:07 -08:00

Update Android port

* configure.ac (HAVE_TEXT_CONVERSION): Define on Android.
* doc/emacs/input.texi (On-Screen Keyboards): Document ``text
conversion'' slightly.
* doc/lispref/commands.texi (Misc Events): Document new
`text-conversion' event.
* java/org/gnu/emacs/EmacsContextMenu.java (display): Use
`syncRunnable'.
* java/org/gnu/emacs/EmacsDialog.java (display): Likewise.
* java/org/gnu/emacs/EmacsEditable.java: Delete file.
* java/org/gnu/emacs/EmacsInputConnection.java
(EmacsInputConnection): Reimplement from scratch.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Add new
functions.
* java/org/gnu/emacs/EmacsService.java (EmacsService, getEmacsView)
(getLocationOnScreen, sync, getClipboardManager, restartEmacs):
Use syncRunnable.
(syncRunnable): New function.
(updateIC, resetIC): New functions.

* java/org/gnu/emacs/EmacsView.java (EmacsView): New field
`inputConnection' and `icMode'.
(onCreateInputConnection): Update accordingly.
(setICMode, getICMode): New functions.

* lisp/bindings.el (global-map): Ignore text conversion events.
* src/alloc.c (mark_frame): Mark text conversion data.
* src/android.c (struct android_emacs_service): New fields
`update_ic' and `reset_ic'.
(event_serial): Export.
(android_query_sem): New function.
(android_init_events): Initialize new semaphore.
(android_write_event): Export.
(android_select): Check for UI thread code.
(setEmacsParams, android_init_emacs_service): Initialize new
methods.
(android_check_query, android_begin_query, android_end_query)
(android_run_in_emacs_thread):
(android_update_ic, android_reset_ic): New functions for
managing synchronous queries from one thread to another.

* src/android.h: Export new functions.
* src/androidgui.h (enum android_event_type): Add input method
events.
(enum android_ime_operation, struct android_ime_event)
(union android_event, enum android_ic_mode): New structs and
enums.

* src/androidterm.c (android_window_to_frame): Allow DPYINFO to
be NULL.
(android_decode_utf16, android_handle_ime_event)
(handle_one_android_event, android_sync_edit)
(android_copy_java_string, beginBatchEdit, endBatchEdit)
(commitCompletion, deleteSurroundingText, finishComposingText)
(getSelectedtext, getTextAfterCursor, getTextBeforeCursor)
(setComposingText, setComposingRegion, setSelection, getSelection)
(performEditorAction, getExtractedText): New functions.
(struct android_conversion_query_context):
(android_perform_conversion_query):
(android_text_to_string):
(struct android_get_selection_context):
(android_get_selection):
(struct android_get_extracted_text_context):
(android_get_extracted_text):
(struct android_extracted_text_request_class):
(struct android_extracted_text_class):
(android_update_selection):
(android_reset_conversion):
(android_set_point):
(android_compose_region_changed):
(android_notify_conversion):
(text_conversion_interface): New functions and structures.
(android_term_init): Initialize text conversion.

* src/coding.c (syms_of_coding): Define Qutf_16le on Android.
* src/frame.c (make_frame): Clear conversion data.
(delete_frame): Reset conversion state.

* src/frame.h (enum text_conversion_operation)
(struct text_conversion_action, struct text_conversion_state)
(GCALIGNED_STRUCT): Update structures.
* src/keyboard.c (read_char, readable_events, kbd_buffer_get_event)
(syms_of_keyboard): Handle text conversion events.
* src/lisp.h:
* src/process.c: Fix includes.

* src/textconv.c (enum textconv_batch_edit_flags, textconv_query)
(reset_frame_state, detect_conversion_events)
(restore_selected_window, really_commit_text)
(really_finish_composing_text, really_set_composing_text)
(really_set_composing_region, really_delete_surrounding_text)
(really_set_point, complete_edit)
(handle_pending_conversion_events_1)
(handle_pending_conversion_events, start_batch_edit)
(end_batch_edit, commit_text, finish_composing_text)
(set_composing_text, set_composing_region, textconv_set_point)
(delete_surrounding_text, get_extracted_text)
(report_selected_window_change, report_point_change)
(register_texconv_interface): New functions.

* src/textconv.h (struct textconv_interface)
(TEXTCONV_SKIP_CONVERSION_REGION): Update prototype.
* src/xdisp.c (mark_window_display_accurate_1):
* src/xfns.c (xic_string_conversion_callback):
* src/xterm.c (init_xterm): Adjust accordingly.
This commit is contained in:
Po Lu 2023-02-15 12:23:03 +08:00
parent 5a7855e84a
commit a158c1d5b9
27 changed files with 2806 additions and 525 deletions

View file

@ -25,6 +25,7 @@ import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.SurroundingText;
import android.view.inputmethod.TextSnapshot;
import android.view.KeyEvent;
import android.text.Editable;
@ -38,35 +39,115 @@ import android.util.Log;
public class EmacsInputConnection extends BaseInputConnection
{
private static final String TAG = "EmacsInputConnection";
public EmacsView view;
private EmacsEditable editable;
/* The length of the last string to be committed. */
private int lastCommitLength;
int currentLargeOffset;
private EmacsView view;
private short windowHandle;
public
EmacsInputConnection (EmacsView view)
{
super (view, false);
super (view, true);
this.view = view;
this.editable = new EmacsEditable (this);
this.windowHandle = view.window.handle;
}
@Override
public Editable
getEditable ()
public boolean
beginBatchEdit ()
{
return editable;
Log.d (TAG, "beginBatchEdit");
EmacsNative.beginBatchEdit (windowHandle);
return true;
}
@Override
public boolean
endBatchEdit ()
{
Log.d (TAG, "endBatchEdit");
EmacsNative.endBatchEdit (windowHandle);
return true;
}
@Override
public boolean
commitCompletion (CompletionInfo info)
{
Log.d (TAG, "commitCompletion: " + info);
EmacsNative.commitCompletion (windowHandle,
info.getText ().toString (),
info.getPosition ());
return true;
}
@Override
public boolean
commitText (CharSequence text, int newCursorPosition)
{
Log.d (TAG, "commitText: " + text + " " + newCursorPosition);
EmacsNative.commitText (windowHandle, text.toString (),
newCursorPosition);
return true;
}
@Override
public boolean
deleteSurroundingText (int leftLength, int rightLength)
{
Log.d (TAG, ("deleteSurroundingText: "
+ leftLength + " " + rightLength));
EmacsNative.deleteSurroundingText (windowHandle, leftLength,
rightLength);
return true;
}
@Override
public boolean
finishComposingText ()
{
Log.d (TAG, "finishComposingText");
EmacsNative.finishComposingText (windowHandle);
return true;
}
@Override
public String
getSelectedText (int flags)
{
Log.d (TAG, "getSelectedText: " + flags);
return EmacsNative.getSelectedText (windowHandle, flags);
}
@Override
public String
getTextAfterCursor (int length, int flags)
{
Log.d (TAG, "getTextAfterCursor: " + length + " " + flags);
return EmacsNative.getTextAfterCursor (windowHandle, length,
flags);
}
@Override
public String
getTextBeforeCursor (int length, int flags)
{
Log.d (TAG, "getTextBeforeCursor: " + length + " " + flags);
return EmacsNative.getTextBeforeCursor (windowHandle, length,
flags);
}
@Override
public boolean
setComposingText (CharSequence text, int newCursorPosition)
{
editable.compositionStart ();
super.setComposingText (text, newCursorPosition);
Log.d (TAG, "setComposingText: " + newCursorPosition);
EmacsNative.setComposingText (windowHandle, text.toString (),
newCursorPosition);
return true;
}
@ -74,102 +155,40 @@ public class EmacsInputConnection extends BaseInputConnection
public boolean
setComposingRegion (int start, int end)
{
int i;
if (lastCommitLength != 0)
{
Log.d (TAG, "Restarting composition for: " + lastCommitLength);
for (i = 0; i < lastCommitLength; ++i)
sendKeyEvent (new KeyEvent (KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_DEL));
lastCommitLength = 0;
}
editable.compositionStart ();
super.setComposingRegion (start, end);
return true;
}
@Override
public boolean
finishComposingText ()
{
editable.compositionEnd ();
return super.finishComposingText ();
}
@Override
public boolean
beginBatchEdit ()
{
editable.beginBatchEdit ();
return super.beginBatchEdit ();
}
@Override
public boolean
endBatchEdit ()
{
editable.endBatchEdit ();
return super.endBatchEdit ();
}
@Override
public boolean
commitText (CharSequence text, int newCursorPosition)
{
editable.compositionEnd ();
super.commitText (text, newCursorPosition);
/* An observation is that input methods rarely recompose trailing
spaces. Avoid re-setting the commit length in that case. */
if (text.toString ().equals (" "))
lastCommitLength += 1;
else
/* At this point, the editable is now empty.
The input method may try to cancel the edit upon a subsequent
backspace by calling setComposingRegion with a region that is
the length of TEXT.
Record this length in order to be able to send backspace
events to ``delete'' the text in that case. */
lastCommitLength = text.length ();
Log.d (TAG, "commitText: \"" + text + "\"");
Log.d (TAG, "setComposingRegion: " + start + " " + end);
EmacsNative.setComposingRegion (windowHandle, start, end);
return true;
}
/* Return a large offset, cycling through 100000, 30000, 0.
The offset is typically used to force the input method to update
its notion of ``surrounding text'', bypassing any caching that
it might have in progress.
There must be another way to do this, but I can't find it. */
public int
largeSelectionOffset ()
@Override
public boolean
performEditorAction (int editorAction)
{
switch (currentLargeOffset)
{
case 0:
currentLargeOffset = 100000;
return 100000;
Log.d (TAG, "performEditorAction: " + editorAction);
case 100000:
currentLargeOffset = 30000;
return 30000;
EmacsNative.performEditorAction (windowHandle, editorAction);
return true;
}
case 30000:
currentLargeOffset = 0;
return 0;
}
@Override
public ExtractedText
getExtractedText (ExtractedTextRequest request, int flags)
{
Log.d (TAG, "getExtractedText: " + request + " " + flags);
currentLargeOffset = 0;
return -1;
return EmacsNative.getExtractedText (windowHandle, request,
flags);
}
/* Override functions which are not implemented. */
@Override
public TextSnapshot
takeSnapshot ()
{
Log.d (TAG, "takeSnapshot");
return null;
}
}