aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2023-06-02 13:31:40 +0800
committerPo Lu2023-06-02 13:31:40 +0800
commit189a91bfb699babd936dae48b96d71a332cac8d2 (patch)
tree73ccb99dfebc3c2bb0770781c120a37338bcf76a
parentc3c2289b29df2b723b9db93d9ea4cd5d04fc89a0 (diff)
downloademacs-189a91bfb699babd936dae48b96d71a332cac8d2.tar.gz
emacs-189a91bfb699babd936dae48b96d71a332cac8d2.zip
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.
-rw-r--r--java/org/gnu/emacs/EmacsInputConnection.java11
-rw-r--r--src/android.c2
-rw-r--r--src/androidgui.h4
-rw-r--r--src/androidterm.c12
-rw-r--r--src/frame.h1
-rw-r--r--src/textconv.c60
-rw-r--r--src/textconv.h1
7 files changed, 79 insertions, 12 deletions
diff --git a/java/org/gnu/emacs/EmacsInputConnection.java b/java/org/gnu/emacs/EmacsInputConnection.java
index eb6fd5f2763..9ced7cb7aaf 100644
--- a/java/org/gnu/emacs/EmacsInputConnection.java
+++ b/java/org/gnu/emacs/EmacsInputConnection.java
@@ -66,11 +66,12 @@ public final class EmacsInputConnection extends BaseInputConnection
66 || Build.MANUFACTURER.equalsIgnoreCase ("Honor")) 66 || Build.MANUFACTURER.equalsIgnoreCase ("Honor"))
67 extractAbsoluteOffsets = syncAfterCommit = true; 67 extractAbsoluteOffsets = syncAfterCommit = true;
68 68
69 /* The Samsung keyboard takes `selectionStart' at face value if 69 /* The Samsung and Vivo keyboards take `selectionStart' at face
70 some text is returned, and also searches for words solely 70 value if some text is returned, and also searches for words
71 within that text. However, when no text is returned, it falls 71 solely within that text. However, when no text is returned, it
72 back to getTextAfterCursor and getTextBeforeCursor. */ 72 falls back to getTextAfterCursor and getTextBeforeCursor. */
73 if (Build.MANUFACTURER.equalsIgnoreCase ("Samsung")) 73 if (Build.MANUFACTURER.equalsIgnoreCase ("Samsung")
74 || Build.MANUFACTURER.equalsIgnoreCase ("Vivo"))
74 extractAbsoluteOffsets = true; 75 extractAbsoluteOffsets = true;
75 }; 76 };
76 77
diff --git a/src/android.c b/src/android.c
index 94587344eb5..e74d40a0cdb 100644
--- a/src/android.c
+++ b/src/android.c
@@ -2543,6 +2543,7 @@ NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object,
2543 event.xkey.state = state; 2543 event.xkey.state = state;
2544 event.xkey.keycode = keycode; 2544 event.xkey.keycode = keycode;
2545 event.xkey.unicode_char = unicode_char; 2545 event.xkey.unicode_char = unicode_char;
2546 event.xkey.counter = 0;
2546 2547
2547 android_write_event (&event); 2548 android_write_event (&event);
2548 return event_serial; 2549 return event_serial;
@@ -2565,6 +2566,7 @@ NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object,
2565 event.xkey.state = state; 2566 event.xkey.state = state;
2566 event.xkey.keycode = keycode; 2567 event.xkey.keycode = keycode;
2567 event.xkey.unicode_char = unicode_char; 2568 event.xkey.unicode_char = unicode_char;
2569 event.xkey.counter = 0;
2568 2570
2569 android_write_event (&event); 2571 android_write_event (&event);
2570 return event_serial; 2572 return event_serial;
diff --git a/src/androidgui.h b/src/androidgui.h
index 02cc73809b9..9e604cdcb8c 100644
--- a/src/androidgui.h
+++ b/src/androidgui.h
@@ -277,6 +277,10 @@ struct android_key_event
277 /* If this field is -1, then android_lookup_string should be called 277 /* If this field is -1, then android_lookup_string should be called
278 to retrieve the associated individual characters. */ 278 to retrieve the associated individual characters. */
279 unsigned int unicode_char; 279 unsigned int unicode_char;
280
281 /* If this field is non-zero, a text conversion barrier should be
282 generated with its value as the counter. */
283 unsigned long counter;
280}; 284};
281 285
282typedef struct android_key_event android_key_pressed_event; 286typedef struct android_key_event android_key_pressed_event;
diff --git a/src/androidterm.c b/src/androidterm.c
index c302e3f2877..211faabf5c2 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -885,6 +885,11 @@ handle_one_android_event (struct android_display_info *dpyinfo,
885 if (!f) 885 if (!f)
886 goto OTHER; 886 goto OTHER;
887 887
888 if (event->xkey.counter)
889 /* This event was generated by `performEditorAction'. Make
890 sure it is processed before any subsequent edits. */
891 textconv_barrier (f, event->xkey.counter);
892
888 wchar_t copy_buffer[129]; 893 wchar_t copy_buffer[129];
889 wchar_t *copy_bufptr = copy_buffer; 894 wchar_t *copy_bufptr = copy_buffer;
890 int copy_bufsiz = 128 * sizeof (wchar_t); 895 int copy_bufsiz = 128 * sizeof (wchar_t);
@@ -5178,7 +5183,10 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
5178 5183
5179 android_write_event (&event); 5184 android_write_event (&event);
5180 5185
5181 /* Finally, send the return key press. */ 5186 /* Finally, send the return key press. `counter' is set; this means
5187 that a text conversion barrier will be generated once the event
5188 is read, which will cause subsequent edits to wait until the
5189 edits associated with this key press complete. */
5182 5190
5183 event.xkey.type = ANDROID_KEY_PRESS; 5191 event.xkey.type = ANDROID_KEY_PRESS;
5184 event.xkey.serial = ++event_serial; 5192 event.xkey.serial = ++event_serial;
@@ -5187,6 +5195,7 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
5187 event.xkey.state = 0; 5195 event.xkey.state = 0;
5188 event.xkey.keycode = 66; 5196 event.xkey.keycode = 66;
5189 event.xkey.unicode_char = 0; 5197 event.xkey.unicode_char = 0;
5198 event.xkey.counter = ++edit_counter;
5190 5199
5191 android_write_event (&event); 5200 android_write_event (&event);
5192} 5201}
@@ -5234,6 +5243,7 @@ NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object,
5234 event.xkey.state = 0; 5243 event.xkey.state = 0;
5235 event.xkey.keycode = 66; 5244 event.xkey.keycode = 66;
5236 event.xkey.unicode_char = 0; 5245 event.xkey.unicode_char = 0;
5246 event.xkey.counter = ++edit_counter;
5237 5247
5238 android_write_event (&event); 5248 android_write_event (&event);
5239} 5249}
diff --git a/src/frame.h b/src/frame.h
index e2900d1c15b..41b4cd444f6 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -89,6 +89,7 @@ enum text_conversion_operation
89 TEXTCONV_SET_POINT_AND_MARK, 89 TEXTCONV_SET_POINT_AND_MARK,
90 TEXTCONV_DELETE_SURROUNDING_TEXT, 90 TEXTCONV_DELETE_SURROUNDING_TEXT,
91 TEXTCONV_REQUEST_POINT_UPDATE, 91 TEXTCONV_REQUEST_POINT_UPDATE,
92 TEXTCONV_BARRIER,
92 }; 93 };
93 94
94/* Structure describing a single edit being performed by the input 95/* Structure describing a single edit being performed by the input
diff --git a/src/textconv.c b/src/textconv.c
index d8166bcfd03..9003816e191 100644
--- a/src/textconv.c
+++ b/src/textconv.c
@@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
36#include "buffer.h" 36#include "buffer.h"
37#include "syntax.h" 37#include "syntax.h"
38#include "blockinput.h" 38#include "blockinput.h"
39#include "keyboard.h"
39 40
40 41
41 42
@@ -522,7 +523,11 @@ detect_conversion_events (void)
522 523
523 FOR_EACH_FRAME (tail, frame) 524 FOR_EACH_FRAME (tail, frame)
524 { 525 {
525 if (XFRAME (frame)->conversion.actions) 526 /* See if there's a pending edit on this frame. */
527 if (XFRAME (frame)->conversion.actions
528 && ((XFRAME (frame)->conversion.actions->operation
529 != TEXTCONV_BARRIER)
530 || (kbd_fetch_ptr == kbd_store_ptr)))
526 return true; 531 return true;
527 } 532 }
528 533
@@ -740,7 +745,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t position,
740 Fset_marker_insertion_type (f->conversion.compose_region_end, 745 Fset_marker_insertion_type (f->conversion.compose_region_end,
741 Qt); 746 Qt);
742 747
743 start = position; 748 start = PT;
744 } 749 }
745 else 750 else
746 { 751 {
@@ -762,7 +767,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t position,
762 record_buffer_change (start, PT, Qnil); 767 record_buffer_change (start, PT, Qnil);
763 768
764 /* Now move point to an appropriate location. */ 769 /* Now move point to an appropriate location. */
765 if (position < 0) 770 if (position <= 0)
766 { 771 {
767 wanted = start; 772 wanted = start;
768 773
@@ -1198,6 +1203,19 @@ handle_pending_conversion_events_1 (struct frame *f,
1198 case TEXTCONV_REQUEST_POINT_UPDATE: 1203 case TEXTCONV_REQUEST_POINT_UPDATE:
1199 really_request_point_update (f); 1204 really_request_point_update (f);
1200 break; 1205 break;
1206
1207 case TEXTCONV_BARRIER:
1208 if (kbd_fetch_ptr != kbd_store_ptr)
1209 emacs_abort ();
1210
1211 /* Once a barrier is hit, synchronize F's selected window's
1212 `ephemeral_last_point' with its current point. The reason
1213 for this is because otherwise a previous keyboard event may
1214 have taken place without redisplay happening in between. */
1215
1216 if (w)
1217 w->ephemeral_last_point = window_point (w);
1218 break;
1201 } 1219 }
1202 1220
1203 /* Signal success. */ 1221 /* Signal success. */
@@ -1231,7 +1249,7 @@ handle_pending_conversion_events (void)
1231 static int inside; 1249 static int inside;
1232 specpdl_ref count; 1250 specpdl_ref count;
1233 ptrdiff_t last_point; 1251 ptrdiff_t last_point;
1234 struct window *w; 1252 struct window *w, *w1;
1235 1253
1236 handled = false; 1254 handled = false;
1237 1255
@@ -1242,8 +1260,6 @@ handle_pending_conversion_events (void)
1242 Vtext_conversion_edits = Qnil; 1260 Vtext_conversion_edits = Qnil;
1243 1261
1244 inside++; 1262 inside++;
1245 last_point = -1;
1246 w = NULL;
1247 1263
1248 count = SPECPDL_INDEX (); 1264 count = SPECPDL_INDEX ();
1249 record_unwind_protect_ptr (decrement_inside, &inside); 1265 record_unwind_protect_ptr (decrement_inside, &inside);
@@ -1251,6 +1267,8 @@ handle_pending_conversion_events (void)
1251 FOR_EACH_FRAME (tail, frame) 1267 FOR_EACH_FRAME (tail, frame)
1252 { 1268 {
1253 f = XFRAME (frame); 1269 f = XFRAME (frame);
1270 last_point = -1;
1271 w = NULL;
1254 1272
1255 /* Test if F has any outstanding conversion events. Then 1273 /* Test if F has any outstanding conversion events. Then
1256 process them in bottom to up order. */ 1274 process them in bottom to up order. */
@@ -1283,6 +1301,13 @@ handle_pending_conversion_events (void)
1283 if (!action) 1301 if (!action)
1284 break; 1302 break;
1285 1303
1304 /* If action is a barrier event and the keyboard buffer is
1305 not yet empty, break out of the loop. */
1306
1307 if (action->operation == TEXTCONV_BARRIER
1308 && kbd_store_ptr != kbd_fetch_ptr)
1309 break;
1310
1286 /* Unlink this action. */ 1311 /* Unlink this action. */
1287 next = action->next; 1312 next = action->next;
1288 f->conversion.actions = next; 1313 f->conversion.actions = next;
@@ -1515,6 +1540,29 @@ request_point_update (struct frame *f, unsigned long counter)
1515 input_pending = true; 1540 input_pending = true;
1516} 1541}
1517 1542
1543/* Request that text conversion on F pause until the keyboard buffer
1544 becomes empty.
1545
1546 Use this function to ensure that edits associated with a keyboard
1547 event complete before the text conversion edits after the barrier
1548 take place. */
1549
1550void
1551textconv_barrier (struct frame *f, unsigned long counter)
1552{
1553 struct text_conversion_action *action, **last;
1554
1555 action = xmalloc (sizeof *action);
1556 action->operation = TEXTCONV_BARRIER;
1557 action->data = Qnil;
1558 action->next = NULL;
1559 action->counter = counter;
1560 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1561 ;;
1562 *last = action;
1563 input_pending = true;
1564}
1565
1518/* Return N characters of text around point in F's old selected 1566/* Return N characters of text around point in F's old selected
1519 window. 1567 window.
1520 1568
diff --git a/src/textconv.h b/src/textconv.h
index e632a9dddcf..d4d0e9d7227 100644
--- a/src/textconv.h
+++ b/src/textconv.h
@@ -139,6 +139,7 @@ extern void textconv_set_point_and_mark (struct frame *, ptrdiff_t,
139extern void delete_surrounding_text (struct frame *, ptrdiff_t, 139extern void delete_surrounding_text (struct frame *, ptrdiff_t,
140 ptrdiff_t, unsigned long); 140 ptrdiff_t, unsigned long);
141extern void request_point_update (struct frame *, unsigned long); 141extern void request_point_update (struct frame *, unsigned long);
142extern void textconv_barrier (struct frame *, unsigned long);
142extern char *get_extracted_text (struct frame *, ptrdiff_t, ptrdiff_t *, 143extern char *get_extracted_text (struct frame *, ptrdiff_t, ptrdiff_t *,
143 ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, 144 ptrdiff_t *, ptrdiff_t *, ptrdiff_t *,
144 ptrdiff_t *); 145 ptrdiff_t *);