|| 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;
};
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;
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;
/* 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;
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);
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;
event.xkey.state = 0;
event.xkey.keycode = 66;
event.xkey.unicode_char = 0;
+ event.xkey.counter = ++edit_counter;
android_write_event (&event);
}
event.xkey.state = 0;
event.xkey.keycode = 66;
event.xkey.unicode_char = 0;
+ event.xkey.counter = ++edit_counter;
android_write_event (&event);
}
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
#include "buffer.h"
#include "syntax.h"
#include "blockinput.h"
+#include "keyboard.h"
\f
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;
}
Fset_marker_insertion_type (f->conversion.compose_region_end,
Qt);
- start = position;
+ start = PT;
}
else
{
record_buffer_change (start, PT, Qnil);
/* Now move point to an appropriate location. */
- if (position < 0)
+ if (position <= 0)
{
wanted = start;
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. */
static int inside;
specpdl_ref count;
ptrdiff_t last_point;
- struct window *w;
+ struct window *w, *w1;
handled = false;
Vtext_conversion_edits = Qnil;
inside++;
- last_point = -1;
- w = NULL;
count = SPECPDL_INDEX ();
record_unwind_protect_ptr (decrement_inside, &inside);
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. */
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;
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.
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 *);