Update Android port

* java/org/gnu/emacs/EmacsInputConnection.java
(EmacsInputConnection, performContextMenuAction): New function.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative)
(performContextMenuAction): New function.
* src/android.c (android_get_gc_values): Implement more
efficiently.
* src/androidterm.c (android_handle_ime_event): Pass through
`update' argument to `finish_composing_text'.  Fix thinko.
* src/textconv.c (really_finish_composing_text)
(really_set_composing_text, really_set_composing_region)
(handle_pending_conversion_events_1, finish_composing_text): New
argument `update'.  Notify IME of conversion region changes if
set.
* src/textconv.h: Update structs and prototypes.
This commit is contained in:
Po Lu 2023-06-01 15:16:02 +08:00
parent 9a958c59a2
commit aed0a11147
6 changed files with 136 additions and 23 deletions

View file

@ -256,6 +256,52 @@ public final class EmacsInputConnection extends BaseInputConnection
return true;
}
@Override
public boolean
performContextMenuAction (int contextMenuAction)
{
int action;
if (EmacsService.DEBUG_IC)
Log.d (TAG, "performContextMenuAction: " + contextMenuAction);
/* Translate the action in Java code. That way, a great deal of
JNI boilerplate can be avoided. */
switch (contextMenuAction)
{
case android.R.id.selectAll:
action = 0;
break;
case android.R.id.startSelectingText:
action = 1;
break;
case android.R.id.stopSelectingText:
action = 2;
break;
case android.R.id.cut:
action = 3;
break;
case android.R.id.copy:
action = 4;
break;
case android.R.id.paste:
action = 5;
break;
default:
return true;
}
EmacsNative.performContextMenuAction (windowHandle, action);
return true;
}
@Override
public ExtractedText
getExtractedText (ExtractedTextRequest request, int flags)

View file

@ -208,6 +208,8 @@ public static native void setComposingRegion (short window, int start,
public static native void setSelection (short window, int start, int end);
public static native void performEditorAction (short window,
int editorAction);
public static native void performContextMenuAction (short window,
int contextMenuAction);
public static native ExtractedText getExtractedText (short window,
ExtractedTextRequest req,
int flags);

View file

@ -3863,22 +3863,13 @@ android_get_gc_values (struct android_gc *gc,
values->clip_y_origin = gc->clip_y_origin;
if (mask & ANDROID_GC_FILL_STYLE)
values->fill_style
= (*android_java_env)->GetIntField (android_java_env,
gcontext,
emacs_gc_fill_style);
values->fill_style = gc->fill_style;
if (mask & ANDROID_GC_TILE_STIP_X_ORIGIN)
values->ts_x_origin
= (*android_java_env)->GetIntField (android_java_env,
gcontext,
emacs_gc_ts_origin_x);
values->ts_x_origin = gc->ts_x_origin;
if (mask & ANDROID_GC_TILE_STIP_Y_ORIGIN)
values->ts_y_origin
= (*android_java_env)->GetIntField (android_java_env,
gcontext,
emacs_gc_ts_origin_y);
values->ts_y_origin = gc->ts_y_origin;
/* Fields involving handles are not used by Emacs, and thus not
implemented */

View file

@ -681,7 +681,6 @@ android_handle_ime_event (union android_event *event, struct frame *f)
switch (event->ime.operation)
{
case ANDROID_IME_COMMIT_TEXT:
case ANDROID_IME_FINISH_COMPOSING_TEXT:
case ANDROID_IME_SET_COMPOSING_TEXT:
text = android_decode_utf16 (event->ime.text,
event->ime.length);
@ -708,7 +707,8 @@ android_handle_ime_event (union android_event *event, struct frame *f)
break;
case ANDROID_IME_FINISH_COMPOSING_TEXT:
finish_composing_text (f, event->ime.counter);
finish_composing_text (f, event->ime.counter,
event->ime.length);
break;
case ANDROID_IME_SET_COMPOSING_TEXT:
@ -5161,7 +5161,71 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
/* Undocumented behavior: performEditorAction is apparently expected
to finish composing any text. */
NATIVE_NAME (finishComposingText) (env, object, window);
event.ime.type = ANDROID_INPUT_METHOD;
event.ime.serial = ++event_serial;
event.ime.window = window;
event.ime.operation = ANDROID_IME_FINISH_COMPOSING_TEXT;
event.ime.start = 0;
event.ime.end = 0;
/* This value of `length' means that the input method should receive
an update containing the new conversion region. */
event.ime.length = 1;
event.ime.position = 0;
event.ime.text = NULL;
event.ime.counter = ++edit_counter;
android_write_event (&event);
/* Finally, send the return key press. */
event.xkey.type = ANDROID_KEY_PRESS;
event.xkey.serial = ++event_serial;
event.xkey.window = window;
event.xkey.time = 0;
event.xkey.state = 0;
event.xkey.keycode = 66;
event.xkey.unicode_char = 0;
android_write_event (&event);
}
JNIEXPORT void JNICALL
NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object,
jshort window, int action)
{
JNI_STACK_ALIGNMENT_PROLOGUE;
union android_event event;
int key;
/* Note that ACTION is determined in EmacsInputConnection, and as
such they are not actual resource IDs. */
switch (action)
{
case 0: /* android.R.id.selectAll */
case 1: /* android.R.id.startSelectingText */
case 2: /* android.R.id.stopSelectingText */
/* These actions are not implemented. */
return;
case 3: /* android.R.id.cut */
key = 277;
break;
case 4: /* android.R.id.copy */
key = 278;
break;
case 5: /* android.R.id.paste */
key = 279;
break;
default:
emacs_abort ();
}
event.xkey.type = ANDROID_KEY_PRESS;
event.xkey.serial = ++event_serial;

View file

@ -676,10 +676,11 @@ really_commit_text (struct frame *f, EMACS_INT position,
}
/* Remove the composition region on the frame F, while leaving its
contents intact. */
contents intact. If UPDATE, also notify the input method of the
change. */
static void
really_finish_composing_text (struct frame *f)
really_finish_composing_text (struct frame *f, bool update)
{
if (!NILP (f->conversion.compose_region_start))
{
@ -687,6 +688,10 @@ really_finish_composing_text (struct frame *f)
Fset_marker (f->conversion.compose_region_end, Qnil, Qnil);
f->conversion.compose_region_start = Qnil;
f->conversion.compose_region_end = Qnil;
if (update && text_interface
&& text_interface->compose_region_changed)
(*text_interface->compose_region_changed) (f);
}
/* Delete the composition region overlay. */
@ -796,7 +801,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t position,
the documentation, but is ultimately what programs expect. */
if (!SCHARS (text))
really_finish_composing_text (f);
really_finish_composing_text (f, false);
/* If PT hasn't changed, the conversion region definitely has.
Otherwise, redisplay will update the input method instead. */
@ -838,7 +843,7 @@ really_set_composing_region (struct frame *f, ptrdiff_t start,
if (max (0, start) == max (0, end))
{
really_finish_composing_text (f);
really_finish_composing_text (f, false);
return;
}
@ -1167,7 +1172,7 @@ handle_pending_conversion_events_1 (struct frame *f,
break;
case TEXTCONV_FINISH_COMPOSING_TEXT:
really_finish_composing_text (f);
really_finish_composing_text (f, !NILP (data));
break;
case TEXTCONV_SET_COMPOSING_TEXT:
@ -1360,16 +1365,20 @@ commit_text (struct frame *f, Lisp_Object string,
/* Remove the composition region and its overlay from F's current
buffer. Leave the text being composed intact.
If UPDATE, call `compose_region_changed' after the region is
removed.
COUNTER means the same as in `start_batch_edit'. */
void
finish_composing_text (struct frame *f, unsigned long counter)
finish_composing_text (struct frame *f, unsigned long counter,
bool update)
{
struct text_conversion_action *action, **last;
action = xmalloc (sizeof *action);
action->operation = TEXTCONV_FINISH_COMPOSING_TEXT;
action->data = Qnil;
action->data = update ? Qt : Qnil;
action->next = NULL;
action->counter = counter;
for (last = &f->conversion.actions; *last; last = &(*last)->next)

View file

@ -128,7 +128,8 @@ extern void start_batch_edit (struct frame *, unsigned long);
extern void end_batch_edit (struct frame *, unsigned long);
extern void commit_text (struct frame *, Lisp_Object, ptrdiff_t,
unsigned long);
extern void finish_composing_text (struct frame *, unsigned long);
extern void finish_composing_text (struct frame *, unsigned long,
bool);
extern void set_composing_text (struct frame *, Lisp_Object,
ptrdiff_t, unsigned long);
extern void set_composing_region (struct frame *, ptrdiff_t, ptrdiff_t,