Update Android port
* java/org/gnu/emacs/EmacsInputConnection.java (EmacsInputConnection): Apply workarounds on Vivo devices as well. * src/android.c (sendKeyPress, sendKeyRelease): Clear counter. * src/androidgui.h (struct android_key_event): New field `counter'. * src/androidterm.c (handle_one_android_event): Generate barriers as appropriate. (JNICALL): Set `counter'. * src/frame.h (enum text_conversion_operation): * src/textconv.c (detect_conversion_events) (really_set_composing_text, handle_pending_conversion_events_1) (handle_pending_conversion_events, textconv_barrier): * src/textconv.h: Implement text conversion barriers and fix various typos.
This commit is contained in:
parent
c3c2289b29
commit
189a91bfb6
7 changed files with 79 additions and 12 deletions
|
@ -66,11 +66,12 @@ public final class EmacsInputConnection extends BaseInputConnection
|
|||
|| Build.MANUFACTURER.equalsIgnoreCase ("Honor"))
|
||||
extractAbsoluteOffsets = syncAfterCommit = true;
|
||||
|
||||
/* The Samsung keyboard takes `selectionStart' at face value if
|
||||
some text is returned, and also searches for words solely
|
||||
within that text. However, when no text is returned, it falls
|
||||
back to getTextAfterCursor and getTextBeforeCursor. */
|
||||
if (Build.MANUFACTURER.equalsIgnoreCase ("Samsung"))
|
||||
/* The Samsung and Vivo keyboards take `selectionStart' at face
|
||||
value if some text is returned, and also searches for words
|
||||
solely within that text. However, when no text is returned, it
|
||||
falls back to getTextAfterCursor and getTextBeforeCursor. */
|
||||
if (Build.MANUFACTURER.equalsIgnoreCase ("Samsung")
|
||||
|| Build.MANUFACTURER.equalsIgnoreCase ("Vivo"))
|
||||
extractAbsoluteOffsets = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -2543,6 +2543,7 @@ NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object,
|
|||
event.xkey.state = state;
|
||||
event.xkey.keycode = keycode;
|
||||
event.xkey.unicode_char = unicode_char;
|
||||
event.xkey.counter = 0;
|
||||
|
||||
android_write_event (&event);
|
||||
return event_serial;
|
||||
|
@ -2565,6 +2566,7 @@ NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object,
|
|||
event.xkey.state = state;
|
||||
event.xkey.keycode = keycode;
|
||||
event.xkey.unicode_char = unicode_char;
|
||||
event.xkey.counter = 0;
|
||||
|
||||
android_write_event (&event);
|
||||
return event_serial;
|
||||
|
|
|
@ -277,6 +277,10 @@ struct android_key_event
|
|||
/* If this field is -1, then android_lookup_string should be called
|
||||
to retrieve the associated individual characters. */
|
||||
unsigned int unicode_char;
|
||||
|
||||
/* If this field is non-zero, a text conversion barrier should be
|
||||
generated with its value as the counter. */
|
||||
unsigned long counter;
|
||||
};
|
||||
|
||||
typedef struct android_key_event android_key_pressed_event;
|
||||
|
|
|
@ -885,6 +885,11 @@ handle_one_android_event (struct android_display_info *dpyinfo,
|
|||
if (!f)
|
||||
goto OTHER;
|
||||
|
||||
if (event->xkey.counter)
|
||||
/* This event was generated by `performEditorAction'. Make
|
||||
sure it is processed before any subsequent edits. */
|
||||
textconv_barrier (f, event->xkey.counter);
|
||||
|
||||
wchar_t copy_buffer[129];
|
||||
wchar_t *copy_bufptr = copy_buffer;
|
||||
int copy_bufsiz = 128 * sizeof (wchar_t);
|
||||
|
@ -5178,7 +5183,10 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
|
|||
|
||||
android_write_event (&event);
|
||||
|
||||
/* Finally, send the return key press. */
|
||||
/* Finally, send the return key press. `counter' is set; this means
|
||||
that a text conversion barrier will be generated once the event
|
||||
is read, which will cause subsequent edits to wait until the
|
||||
edits associated with this key press complete. */
|
||||
|
||||
event.xkey.type = ANDROID_KEY_PRESS;
|
||||
event.xkey.serial = ++event_serial;
|
||||
|
@ -5187,6 +5195,7 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
|
|||
event.xkey.state = 0;
|
||||
event.xkey.keycode = 66;
|
||||
event.xkey.unicode_char = 0;
|
||||
event.xkey.counter = ++edit_counter;
|
||||
|
||||
android_write_event (&event);
|
||||
}
|
||||
|
@ -5234,6 +5243,7 @@ NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object,
|
|||
event.xkey.state = 0;
|
||||
event.xkey.keycode = 66;
|
||||
event.xkey.unicode_char = 0;
|
||||
event.xkey.counter = ++edit_counter;
|
||||
|
||||
android_write_event (&event);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ enum text_conversion_operation
|
|||
TEXTCONV_SET_POINT_AND_MARK,
|
||||
TEXTCONV_DELETE_SURROUNDING_TEXT,
|
||||
TEXTCONV_REQUEST_POINT_UPDATE,
|
||||
TEXTCONV_BARRIER,
|
||||
};
|
||||
|
||||
/* Structure describing a single edit being performed by the input
|
||||
|
|
|
@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "buffer.h"
|
||||
#include "syntax.h"
|
||||
#include "blockinput.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
|
||||
|
||||
|
@ -522,7 +523,11 @@ detect_conversion_events (void)
|
|||
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
if (XFRAME (frame)->conversion.actions)
|
||||
/* See if there's a pending edit on this frame. */
|
||||
if (XFRAME (frame)->conversion.actions
|
||||
&& ((XFRAME (frame)->conversion.actions->operation
|
||||
!= TEXTCONV_BARRIER)
|
||||
|| (kbd_fetch_ptr == kbd_store_ptr)))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -740,7 +745,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t position,
|
|||
Fset_marker_insertion_type (f->conversion.compose_region_end,
|
||||
Qt);
|
||||
|
||||
start = position;
|
||||
start = PT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -762,7 +767,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t position,
|
|||
record_buffer_change (start, PT, Qnil);
|
||||
|
||||
/* Now move point to an appropriate location. */
|
||||
if (position < 0)
|
||||
if (position <= 0)
|
||||
{
|
||||
wanted = start;
|
||||
|
||||
|
@ -1198,6 +1203,19 @@ handle_pending_conversion_events_1 (struct frame *f,
|
|||
case TEXTCONV_REQUEST_POINT_UPDATE:
|
||||
really_request_point_update (f);
|
||||
break;
|
||||
|
||||
case TEXTCONV_BARRIER:
|
||||
if (kbd_fetch_ptr != kbd_store_ptr)
|
||||
emacs_abort ();
|
||||
|
||||
/* Once a barrier is hit, synchronize F's selected window's
|
||||
`ephemeral_last_point' with its current point. The reason
|
||||
for this is because otherwise a previous keyboard event may
|
||||
have taken place without redisplay happening in between. */
|
||||
|
||||
if (w)
|
||||
w->ephemeral_last_point = window_point (w);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Signal success. */
|
||||
|
@ -1231,7 +1249,7 @@ handle_pending_conversion_events (void)
|
|||
static int inside;
|
||||
specpdl_ref count;
|
||||
ptrdiff_t last_point;
|
||||
struct window *w;
|
||||
struct window *w, *w1;
|
||||
|
||||
handled = false;
|
||||
|
||||
|
@ -1242,8 +1260,6 @@ handle_pending_conversion_events (void)
|
|||
Vtext_conversion_edits = Qnil;
|
||||
|
||||
inside++;
|
||||
last_point = -1;
|
||||
w = NULL;
|
||||
|
||||
count = SPECPDL_INDEX ();
|
||||
record_unwind_protect_ptr (decrement_inside, &inside);
|
||||
|
@ -1251,6 +1267,8 @@ handle_pending_conversion_events (void)
|
|||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
f = XFRAME (frame);
|
||||
last_point = -1;
|
||||
w = NULL;
|
||||
|
||||
/* Test if F has any outstanding conversion events. Then
|
||||
process them in bottom to up order. */
|
||||
|
@ -1283,6 +1301,13 @@ handle_pending_conversion_events (void)
|
|||
if (!action)
|
||||
break;
|
||||
|
||||
/* If action is a barrier event and the keyboard buffer is
|
||||
not yet empty, break out of the loop. */
|
||||
|
||||
if (action->operation == TEXTCONV_BARRIER
|
||||
&& kbd_store_ptr != kbd_fetch_ptr)
|
||||
break;
|
||||
|
||||
/* Unlink this action. */
|
||||
next = action->next;
|
||||
f->conversion.actions = next;
|
||||
|
@ -1515,6 +1540,29 @@ request_point_update (struct frame *f, unsigned long counter)
|
|||
input_pending = true;
|
||||
}
|
||||
|
||||
/* Request that text conversion on F pause until the keyboard buffer
|
||||
becomes empty.
|
||||
|
||||
Use this function to ensure that edits associated with a keyboard
|
||||
event complete before the text conversion edits after the barrier
|
||||
take place. */
|
||||
|
||||
void
|
||||
textconv_barrier (struct frame *f, unsigned long counter)
|
||||
{
|
||||
struct text_conversion_action *action, **last;
|
||||
|
||||
action = xmalloc (sizeof *action);
|
||||
action->operation = TEXTCONV_BARRIER;
|
||||
action->data = Qnil;
|
||||
action->next = NULL;
|
||||
action->counter = counter;
|
||||
for (last = &f->conversion.actions; *last; last = &(*last)->next)
|
||||
;;
|
||||
*last = action;
|
||||
input_pending = true;
|
||||
}
|
||||
|
||||
/* Return N characters of text around point in F's old selected
|
||||
window.
|
||||
|
||||
|
|
|
@ -139,6 +139,7 @@ extern void textconv_set_point_and_mark (struct frame *, ptrdiff_t,
|
|||
extern void delete_surrounding_text (struct frame *, ptrdiff_t,
|
||||
ptrdiff_t, unsigned long);
|
||||
extern void request_point_update (struct frame *, unsigned long);
|
||||
extern void textconv_barrier (struct frame *, unsigned long);
|
||||
extern char *get_extracted_text (struct frame *, ptrdiff_t, ptrdiff_t *,
|
||||
ptrdiff_t *, ptrdiff_t *, ptrdiff_t *,
|
||||
ptrdiff_t *);
|
||||
|
|
Loading…
Add table
Reference in a new issue