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:
parent
9a958c59a2
commit
aed0a11147
6 changed files with 136 additions and 23 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue