diff options
| author | Po Lu | 2023-06-02 13:31:40 +0800 |
|---|---|---|
| committer | Po Lu | 2023-06-02 13:31:40 +0800 |
| commit | 189a91bfb699babd936dae48b96d71a332cac8d2 (patch) | |
| tree | 73ccb99dfebc3c2bb0770781c120a37338bcf76a /src | |
| parent | c3c2289b29df2b723b9db93d9ea4cd5d04fc89a0 (diff) | |
| download | emacs-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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android.c | 2 | ||||
| -rw-r--r-- | src/androidgui.h | 4 | ||||
| -rw-r--r-- | src/androidterm.c | 12 | ||||
| -rw-r--r-- | src/frame.h | 1 | ||||
| -rw-r--r-- | src/textconv.c | 60 | ||||
| -rw-r--r-- | src/textconv.h | 1 |
6 files changed, 73 insertions, 7 deletions
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 | ||
| 282 | typedef struct android_key_event android_key_pressed_event; | 286 | typedef 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 | |||
| 1550 | void | ||
| 1551 | textconv_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, | |||
| 139 | extern void delete_surrounding_text (struct frame *, ptrdiff_t, | 139 | extern void delete_surrounding_text (struct frame *, ptrdiff_t, |
| 140 | ptrdiff_t, unsigned long); | 140 | ptrdiff_t, unsigned long); |
| 141 | extern void request_point_update (struct frame *, unsigned long); | 141 | extern void request_point_update (struct frame *, unsigned long); |
| 142 | extern void textconv_barrier (struct frame *, unsigned long); | ||
| 142 | extern char *get_extracted_text (struct frame *, ptrdiff_t, ptrdiff_t *, | 143 | extern 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 *); |