]> git.eshelyaron.com Git - emacs.git/commitdiff
Update Android port
authorPo Lu <luangruo@yahoo.com>
Fri, 2 Jun 2023 05:31:40 +0000 (13:31 +0800)
committerPo Lu <luangruo@yahoo.com>
Fri, 2 Jun 2023 05:31:40 +0000 (13:31 +0800)
* 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.

java/org/gnu/emacs/EmacsInputConnection.java
src/android.c
src/androidgui.h
src/androidterm.c
src/frame.h
src/textconv.c
src/textconv.h

index eb6fd5f2763916c4d623be644c031da9a6b024f9..9ced7cb7aaf6e2ee8a01818716ee4fad3a16ec81 100644 (file)
@@ -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;
   };
 
index 94587344eb5343b389329fc715a43fe4b665c443..e74d40a0cdbb3945637f7a186d03ddd4dc8361d0 100644 (file)
@@ -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;
index 02cc73809b931ea705882b85fe510ca02d9fac9b..9e604cdcb8cf82002d7c69e3d6b50d0f68dce499 100644 (file)
@@ -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;
index c302e3f287752465643a5f1e502a6c637097e48a..211faabf5c276ee452971ec87183d5440103031f 100644 (file)
@@ -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);
 }
index e2900d1c15b56a652afd6108fb6439933da39702..41b4cd444f6477981b9a6c86490b1db994cc4690 100644 (file)
@@ -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
index d8166bcfd03d85872212ab8ba10a84a8ff4e7987..9003816e1916235a0c99212e0c8dadd9acb58fae 100644 (file)
@@ -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"
 
 \f
 
@@ -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.
 
index e632a9dddcff41056774c214bb79558b62784038..d4d0e9d7227626a84b28be0270c4966f7e7b2978 100644 (file)
@@ -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 *);