aboutsummaryrefslogtreecommitdiffstats
path: root/src/android.c
diff options
context:
space:
mode:
authorPo Lu2024-03-02 14:04:56 +0800
committerPo Lu2024-03-02 14:04:56 +0800
commit5e20b114ef32d504f4429fd35ecd0d5dcf3bd8db (patch)
tree83215f4df69308e61c490172f4a68ff0fea63452 /src/android.c
parent8b96503b6e8514f1f9f92895a0707c78b1bbd1fd (diff)
downloademacs-5e20b114ef32d504f4429fd35ecd0d5dcf3bd8db.tar.gz
emacs-5e20b114ef32d504f4429fd35ecd0d5dcf3bd8db.zip
Implement dead key combination on Android
* src/android.c (android_init_key_character_map) (android_get_dead_char): New functions. (android_wc_lookup_string): New argument COMPOSE_STATE. Ignore key events with the COMBINING_ACCENT flag set while recording their character values there, and combine such characters with the key event when processing a subsequent key event. * src/androidgui.h (struct android_compose_status): New structure. * src/androidterm.c (handle_one_android_event): Port dead key combination code from X. (bug#69321)
Diffstat (limited to 'src/android.c')
-rw-r--r--src/android.c122
1 files changed, 119 insertions, 3 deletions
diff --git a/src/android.c b/src/android.c
index 41481afa475..eb6981093be 100644
--- a/src/android.c
+++ b/src/android.c
@@ -123,6 +123,12 @@ struct android_emacs_cursor
123 jmethodID constructor; 123 jmethodID constructor;
124}; 124};
125 125
126struct android_key_character_map
127{
128 jclass class;
129 jmethodID get_dead_char;
130};
131
126/* The API level of the current device. */ 132/* The API level of the current device. */
127static int android_api_level; 133static int android_api_level;
128 134
@@ -203,6 +209,9 @@ static struct android_emacs_window window_class;
203/* Various methods associated with the EmacsCursor class. */ 209/* Various methods associated with the EmacsCursor class. */
204static struct android_emacs_cursor cursor_class; 210static struct android_emacs_cursor cursor_class;
205 211
212/* Various methods associated with the KeyCharacterMap class. */
213static struct android_key_character_map key_character_map_class;
214
206/* The time at which Emacs was installed, which also supplies the 215/* The time at which Emacs was installed, which also supplies the
207 mtime of asset files. */ 216 mtime of asset files. */
208struct timespec emacs_installation_time; 217struct timespec emacs_installation_time;
@@ -1865,6 +1874,32 @@ android_init_emacs_cursor (void)
1865#undef FIND_METHOD 1874#undef FIND_METHOD
1866} 1875}
1867 1876
1877static void
1878android_init_key_character_map (void)
1879{
1880 jclass old;
1881
1882 key_character_map_class.class
1883 = (*android_java_env)->FindClass (android_java_env,
1884 "android/view/KeyCharacterMap");
1885 eassert (key_character_map_class.class);
1886
1887 old = key_character_map_class.class;
1888 key_character_map_class.class
1889 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
1890 (jobject) old);
1891 ANDROID_DELETE_LOCAL_REF (old);
1892
1893 if (!key_character_map_class.class)
1894 emacs_abort ();
1895
1896 key_character_map_class.get_dead_char
1897 = (*android_java_env)->GetStaticMethodID (android_java_env,
1898 key_character_map_class.class,
1899 "getDeadChar", "(II)I");
1900 eassert (key_character_map_class.get_dead_char);
1901}
1902
1868JNIEXPORT void JNICALL 1903JNIEXPORT void JNICALL
1869NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, 1904NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv,
1870 jobject dump_file_object) 1905 jobject dump_file_object)
@@ -1913,6 +1948,7 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv,
1913 android_init_emacs_drawable (); 1948 android_init_emacs_drawable ();
1914 android_init_emacs_window (); 1949 android_init_emacs_window ();
1915 android_init_emacs_cursor (); 1950 android_init_emacs_cursor ();
1951 android_init_key_character_map ();
1916 1952
1917 /* Set HOME to the app data directory. */ 1953 /* Set HOME to the app data directory. */
1918 setenv ("HOME", android_files_dir, 1); 1954 setenv ("HOME", android_files_dir, 1);
@@ -5376,11 +5412,51 @@ android_translate_coordinates (android_window src, int x,
5376 ANDROID_DELETE_LOCAL_REF (coordinates); 5412 ANDROID_DELETE_LOCAL_REF (coordinates);
5377} 5413}
5378 5414
5415/* Return the character produced by combining the diacritic character
5416 DCHAR with the key-producing character C in *VALUE. Value is 1 if
5417 there is no character for this combination, 0 otherwise. */
5418
5419static int
5420android_get_dead_char (unsigned int dchar, unsigned int c,
5421 unsigned int *value)
5422{
5423 jmethodID method;
5424 jclass class;
5425 jint result;
5426
5427 /* Call getDeadChar. */
5428 class = key_character_map_class.class;
5429 method = key_character_map_class.get_dead_char;
5430 result = (*android_java_env)->CallStaticIntMethod (android_java_env,
5431 class, method,
5432 (jint) dchar,
5433 (jint) c);
5434
5435 if (result)
5436 {
5437 *value = result;
5438 return 0;
5439 }
5440
5441 return 1;
5442}
5443
5444/* Return a Unicode string in BUFFER_RETURN, a buffer of size
5445 WCHARS_BUFFER, from the key press event EVENT, much like
5446 XmbLookupString. If EVENT represents a key press without a
5447 corresponding Unicode character, return its keysym in *KEYSYM_RETURN.
5448 Return the action taken in *STATUS_RETURN.
5449
5450 COMPOSE_STATUS, if non-NULL, should point to a structure for
5451 temporary information to be stored in during dead key
5452 composition. */
5453
5379int 5454int
5380android_wc_lookup_string (android_key_pressed_event *event, 5455android_wc_lookup_string (android_key_pressed_event *event,
5381 wchar_t *buffer_return, int wchars_buffer, 5456 wchar_t *buffer_return, int wchars_buffer,
5382 int *keysym_return, 5457 int *keysym_return,
5383 enum android_lookup_status *status_return) 5458 enum android_lookup_status *status_return,
5459 struct android_compose_status *compose_status)
5384{ 5460{
5385 enum android_lookup_status status; 5461 enum android_lookup_status status;
5386 int rc; 5462 int rc;
@@ -5389,6 +5465,7 @@ android_wc_lookup_string (android_key_pressed_event *event,
5389 jsize size; 5465 jsize size;
5390 size_t i; 5466 size_t i;
5391 JNIEnv *env; 5467 JNIEnv *env;
5468 unsigned int unicode_char;
5392 5469
5393 env = android_java_env; 5470 env = android_java_env;
5394 status = ANDROID_LOOKUP_NONE; 5471 status = ANDROID_LOOKUP_NONE;
@@ -5402,6 +5479,13 @@ android_wc_lookup_string (android_key_pressed_event *event,
5402 { 5479 {
5403 if (event->unicode_char) 5480 if (event->unicode_char)
5404 { 5481 {
5482 /* KeyCharacterMap.COMBINING_ACCENT. */
5483 if ((event->unicode_char & 0x80000000) && compose_status)
5484 goto dead_key;
5485
5486 /* Remove combining accent bits. */
5487 unicode_char = event->unicode_char & ~0x80000000;
5488
5405 if (wchars_buffer < 1) 5489 if (wchars_buffer < 1)
5406 { 5490 {
5407 *status_return = ANDROID_BUFFER_OVERFLOW; 5491 *status_return = ANDROID_BUFFER_OVERFLOW;
@@ -5409,7 +5493,31 @@ android_wc_lookup_string (android_key_pressed_event *event,
5409 } 5493 }
5410 else 5494 else
5411 { 5495 {
5412 buffer_return[0] = event->unicode_char; 5496 /* If COMPOSE_STATUS holds a diacritic mark unicode_char
5497 ought to be combined with, and this combination is
5498 valid, return the result alone with no keysym. */
5499
5500 if (compose_status
5501 && compose_status->chars_matched
5502 && !android_get_dead_char (compose_status->accent,
5503 unicode_char,
5504 &unicode_char))
5505 {
5506 buffer_return[0] = unicode_char;
5507 *status_return = ANDROID_LOOKUP_CHARS;
5508 compose_status->chars_matched = 0;
5509 return 1;
5510 }
5511 else if (compose_status && compose_status->chars_matched)
5512 {
5513 /* If the combination is valid the compose status must
5514 be reset and no character returned. */
5515 compose_status->chars_matched = 0;
5516 status = ANDROID_LOOKUP_NONE;
5517 return 0;
5518 }
5519
5520 buffer_return[0] = unicode_char;
5413 status = ANDROID_LOOKUP_CHARS; 5521 status = ANDROID_LOOKUP_CHARS;
5414 rc = 1; 5522 rc = 1;
5415 } 5523 }
@@ -5426,7 +5534,6 @@ android_wc_lookup_string (android_key_pressed_event *event,
5426 } 5534 }
5427 5535
5428 *status_return = status; 5536 *status_return = status;
5429
5430 return rc; 5537 return rc;
5431 } 5538 }
5432 5539
@@ -5482,6 +5589,15 @@ android_wc_lookup_string (android_key_pressed_event *event,
5482 5589
5483 *status_return = status; 5590 *status_return = status;
5484 return rc; 5591 return rc;
5592
5593 dead_key:
5594 /* event->unicode_char is a dead key, which are diacritic marks that
5595 should not be directly inserted but instead be combined with a
5596 subsequent character before insertion. */
5597 *status_return = ANDROID_LOOKUP_NONE;
5598 compose_status->chars_matched = 1;
5599 compose_status->accent = event->unicode_char & ~0x80000000;
5600 return 0;
5485} 5601}
5486 5602
5487 5603