aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-03-08 15:04:49 +0800
committerPo Lu2023-03-08 15:04:49 +0800
commitbb55528c7b58c5f50336ed3f2ff9759559d78680 (patch)
tree6a4422afb19dc4ac9644d62b12d2a8aaf145deb3 /src
parentfdff5442a59fd2387c23e2be2658dafa39466891 (diff)
downloademacs-bb55528c7b58c5f50336ed3f2ff9759559d78680.tar.gz
emacs-bb55528c7b58c5f50336ed3f2ff9759559d78680.zip
Update Android port
* doc/emacs/android.texi (Android File System): Document what `temp~unlinked' means in the temporary files directory. * java/org/gnu/emacs/EmacsService.java (updateExtractedText): New function. * java/org/gnu/emacs/EmacsView.java (onCreateInputConnection): Ask the input method nicely to not display the extracted text UI. * src/android.c (struct android_emacs_service): New method `updateExtractedText'. (android_hack_asset_fd_fallback): Improve naming convention. Fix typo. (android_init_emacs_service): Add new method. (android_update_extracted_text): New function. (android_open_asset): Fix typo. * src/androidgui.h: Update prototypes. * src/androidterm.c (struct android_get_extracted_text_context): New field `flags'. (android_get_extracted_text): Set flags on the frame's output data. (android_build_extracted_text): New function. (getExtractedText): Move out class structures. (android_update_selection): Send updates to extracted text if the input method asked for them. (android_reset_conversion): Clear extracted text flags. * src/androidterm.h (struct android_output): New fields for storing extracted text data.
Diffstat (limited to 'src')
-rw-r--r--src/android.c44
-rw-r--r--src/androidgui.h2
-rw-r--r--src/androidterm.c111
-rw-r--r--src/androidterm.h10
4 files changed, 155 insertions, 12 deletions
diff --git a/src/android.c b/src/android.c
index 11b0fa5e0f3..e620a041348 100644
--- a/src/android.c
+++ b/src/android.c
@@ -112,6 +112,7 @@ struct android_emacs_service
112 jmethodID check_content_uri; 112 jmethodID check_content_uri;
113 jmethodID query_battery; 113 jmethodID query_battery;
114 jmethodID display_toast; 114 jmethodID display_toast;
115 jmethodID update_extracted_text;
115}; 116};
116 117
117struct android_emacs_pixmap 118struct android_emacs_pixmap
@@ -1236,13 +1237,12 @@ android_hack_asset_fd_fallback (AAsset *asset)
1236 Creating an ashmem file descriptor and reading from it doesn't 1237 Creating an ashmem file descriptor and reading from it doesn't
1237 work on these old Android versions. */ 1238 work on these old Android versions. */
1238 1239
1239 snprintf (filename, PATH_MAX, "%s/%s.%d", 1240 snprintf (filename, PATH_MAX, "%s/temp~unlinked.%d",
1240 android_cache_dir, "temp-unlinked", 1241 android_cache_dir, getpid ());
1241 getpid ());
1242 fd = open (filename, O_CREAT | O_RDWR | O_TRUNC, 1242 fd = open (filename, O_CREAT | O_RDWR | O_TRUNC,
1243 S_IRUSR | S_IWUSR); 1243 S_IRUSR | S_IWUSR);
1244 1244
1245 if (fd < 1) 1245 if (fd < 0)
1246 return -1; 1246 return -1;
1247 1247
1248 if (unlink (filename)) 1248 if (unlink (filename))
@@ -2135,6 +2135,9 @@ android_init_emacs_service (void)
2135 FIND_METHOD (query_battery, "queryBattery", "()[J"); 2135 FIND_METHOD (query_battery, "queryBattery", "()[J");
2136 FIND_METHOD (display_toast, "displayToast", 2136 FIND_METHOD (display_toast, "displayToast",
2137 "(Ljava/lang/String;)V"); 2137 "(Ljava/lang/String;)V");
2138 FIND_METHOD (update_extracted_text, "updateExtractedText",
2139 "(Lorg/gnu/emacs/EmacsWindow;"
2140 "Landroid/view/inputmethod/ExtractedText;I)V");
2138#undef FIND_METHOD 2141#undef FIND_METHOD
2139} 2142}
2140 2143
@@ -5991,6 +5994,37 @@ android_reset_ic (android_window window, enum android_ic_mode mode)
5991 android_exception_check (); 5994 android_exception_check ();
5992} 5995}
5993 5996
5997/* Make updates to extracted text known to the input method on
5998 WINDOW. TEXT should be a local reference to the new
5999 extracted text. TOKEN should be the token specified by the
6000 input method. */
6001
6002void
6003android_update_extracted_text (android_window window, void *text,
6004 int token)
6005{
6006 jobject object;
6007 jmethodID method;
6008
6009 object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW);
6010 method = service_class.update_extracted_text;
6011
6012 (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
6013 emacs_service,
6014 service_class.class,
6015 method, object,
6016 /* N.B. that
6017 text is not
6018 jobject,
6019 because that
6020 type is not
6021 available in
6022 androidgui.h. */
6023 (jobject) text,
6024 (jint) token);
6025 android_exception_check_1 (text);
6026}
6027
5994 6028
5995 6029
5996/* Window decoration management functions. */ 6030/* Window decoration management functions. */
@@ -6083,7 +6117,7 @@ android_open_asset (const char *filename, int oflag, mode_t mode)
6083 get a regular file descriptor. */ 6117 get a regular file descriptor. */
6084 6118
6085 fd.fd = android_open (filename, oflag, mode); 6119 fd.fd = android_open (filename, oflag, mode);
6086 if (fd.fd < 1) 6120 if (fd.fd < 0)
6087 return fd; 6121 return fd;
6088 6122
6089 /* Set fd.asset to NULL, signifying that it is a file 6123 /* Set fd.asset to NULL, signifying that it is a file
diff --git a/src/androidgui.h b/src/androidgui.h
index e1c80a71a59..afcaed98cae 100644
--- a/src/androidgui.h
+++ b/src/androidgui.h
@@ -613,6 +613,8 @@ extern int android_wc_lookup_string (android_key_pressed_event *,
613extern void android_update_ic (android_window, ptrdiff_t, ptrdiff_t, 613extern void android_update_ic (android_window, ptrdiff_t, ptrdiff_t,
614 ptrdiff_t, ptrdiff_t); 614 ptrdiff_t, ptrdiff_t);
615extern void android_reset_ic (android_window, enum android_ic_mode); 615extern void android_reset_ic (android_window, enum android_ic_mode);
616extern void android_update_extracted_text (android_window, void *,
617 int);
616extern int android_set_fullscreen (android_window, bool); 618extern int android_set_fullscreen (android_window, bool);
617 619
618#endif 620#endif
diff --git a/src/androidterm.c b/src/androidterm.c
index 0cc2b35099c..f4a535292f2 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -4968,6 +4968,10 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
4968 android_write_event (&event); 4968 android_write_event (&event);
4969} 4969}
4970 4970
4971
4972
4973/* Text extraction. */
4974
4971struct android_get_extracted_text_context 4975struct android_get_extracted_text_context
4972{ 4976{
4973 /* The parameters of the request. */ 4977 /* The parameters of the request. */
@@ -4976,6 +4980,9 @@ struct android_get_extracted_text_context
4976 /* Token for the request. */ 4980 /* Token for the request. */
4977 int token; 4981 int token;
4978 4982
4983 /* Flags associated with the request. */
4984 int flags;
4985
4979 /* The returned text, or NULL. */ 4986 /* The returned text, or NULL. */
4980 char *text; 4987 char *text;
4981 4988
@@ -5011,6 +5018,14 @@ android_get_extracted_text (void *data)
5011 = get_extracted_text (f, min (request->hint_max_chars, 600), 5018 = get_extracted_text (f, min (request->hint_max_chars, 600),
5012 &request->start, &request->offset, 5019 &request->start, &request->offset,
5013 &request->length, &request->bytes); 5020 &request->length, &request->bytes);
5021
5022 /* See if request->flags & GET_EXTRACTED_TEXT_MONITOR. If so, then
5023 the input method has asked to monitor changes to the extracted
5024 text until the next IM context reset. */
5025
5026 FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = request->flags;
5027 FRAME_ANDROID_OUTPUT (f)->extracted_text_token = request->token;
5028 FRAME_ANDROID_OUTPUT (f)->extracted_text_hint = request->hint_max_chars;
5014} 5029}
5015 5030
5016/* Structure describing the `ExtractedTextRequest' class. 5031/* Structure describing the `ExtractedTextRequest' class.
@@ -5038,6 +5053,51 @@ struct android_extracted_text_class
5038 jfieldID text; 5053 jfieldID text;
5039}; 5054};
5040 5055
5056/* Fields and methods associated with the `ExtractedTextRequest'
5057 class. */
5058struct android_extracted_text_request_class request_class;
5059
5060/* Fields and methods associated with the `ExtractedText' class. */
5061struct android_extracted_text_class text_class;
5062
5063/* Return an ExtractedText object corresponding to the extracted text
5064 TEXT. START is a character position describing the offset of the
5065 first character in TEXT. OFFSET is the offset of point relative to
5066 START.
5067
5068 Assume that request_class and text_class have already been
5069 initialized.
5070
5071 Value is NULL if an error occurs; the exception is not cleared,
5072 else a local reference to the ExtractedText object. */
5073
5074static jobject
5075android_build_extracted_text (jstring text, ptrdiff_t start,
5076 ptrdiff_t offset)
5077{
5078 JNIEnv *env;
5079 jobject object;
5080
5081 env = android_java_env;
5082
5083 /* Create an ExtractedText object containing this information. */
5084 object = (*env)->NewObject (env, text_class.class,
5085 text_class.constructor);
5086 if (!object)
5087 return NULL;
5088
5089 (*env)->SetIntField (env, object, text_class.partial_start_offset, -1);
5090 (*env)->SetIntField (env, object, text_class.partial_end_offset, -1);
5091 (*env)->SetIntField (env, object, text_class.selection_start,
5092 min (offset, TYPE_MAXIMUM (jint)));
5093 (*env)->SetIntField (env, object, text_class.selection_end,
5094 min (offset, TYPE_MAXIMUM (jint)));
5095 (*env)->SetIntField (env, object, text_class.start_offset,
5096 min (start, TYPE_MAXIMUM (jint)));
5097 (*env)->SetObjectField (env, object, text_class.text, text);
5098 return object;
5099}
5100
5041JNIEXPORT jobject JNICALL 5101JNIEXPORT jobject JNICALL
5042NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object, 5102NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5043 jshort window, jobject request, 5103 jshort window, jobject request,
@@ -5046,14 +5106,10 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5046 JNI_STACK_ALIGNMENT_PROLOGUE; 5106 JNI_STACK_ALIGNMENT_PROLOGUE;
5047 5107
5048 struct android_get_extracted_text_context context; 5108 struct android_get_extracted_text_context context;
5049 static struct android_extracted_text_request_class request_class;
5050 static struct android_extracted_text_class text_class;
5051 jstring string; 5109 jstring string;
5052 jclass class; 5110 jclass class;
5053 jobject object; 5111 jobject object;
5054 5112
5055 /* TODO: report changes to extracted text. */
5056
5057 /* Initialize both classes if necessary. */ 5113 /* Initialize both classes if necessary. */
5058 5114
5059 if (!request_class.initialized) 5115 if (!request_class.initialized)
@@ -5106,6 +5162,7 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5106 = (*env)->GetIntField (env, request, request_class.hint_max_chars); 5162 = (*env)->GetIntField (env, request, request_class.hint_max_chars);
5107 context.token 5163 context.token
5108 = (*env)->GetIntField (env, request, request_class.token); 5164 = (*env)->GetIntField (env, request, request_class.token);
5165 context.flags = flags;
5109 context.text = NULL; 5166 context.text = NULL;
5110 context.window = window; 5167 context.window = window;
5111 5168
@@ -5126,8 +5183,8 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5126 return NULL; 5183 return NULL;
5127 5184
5128 /* Create an ExtractedText object containing this information. */ 5185 /* Create an ExtractedText object containing this information. */
5129 object = (*android_java_env)->NewObject (env, text_class.class, 5186 object = (*env)->NewObject (env, text_class.class,
5130 text_class.constructor); 5187 text_class.constructor);
5131 if (!object) 5188 if (!object)
5132 return NULL; 5189 return NULL;
5133 5190
@@ -5143,6 +5200,8 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5143 return object; 5200 return object;
5144} 5201}
5145 5202
5203
5204
5146JNIEXPORT jstring JNICALL 5205JNIEXPORT jstring JNICALL
5147NATIVE_NAME (getSelectedText) (JNIEnv *env, jobject object, 5206NATIVE_NAME (getSelectedText) (JNIEnv *env, jobject object,
5148 jshort window) 5207 jshort window)
@@ -5210,8 +5269,12 @@ NATIVE_NAME (requestSelectionUpdate) (JNIEnv *env, jobject object,
5210static void 5269static void
5211android_update_selection (struct frame *f, struct window *w) 5270android_update_selection (struct frame *f, struct window *w)
5212{ 5271{
5213 ptrdiff_t start, end, point, mark; 5272 ptrdiff_t start, end, point, mark, offset, length, bytes;
5214 struct buffer *b; 5273 struct buffer *b;
5274 int hint, token;
5275 char *text;
5276 jobject extracted;
5277 jstring string;
5215 5278
5216 if (MARKERP (f->conversion.compose_region_start)) 5279 if (MARKERP (f->conversion.compose_region_start))
5217 { 5280 {
@@ -5246,6 +5309,36 @@ android_update_selection (struct frame *f, struct window *w)
5246 the selection is less than or equal to the end. */ 5309 the selection is less than or equal to the end. */
5247 android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark), 5310 android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark),
5248 max (point, mark), start, end); 5311 max (point, mark), start, end);
5312
5313 /* Update the extracted text as well, if the input method has asked
5314 for updates. 1 is
5315 InputConnection.GET_EXTRACTED_TEXT_MONITOR. */
5316
5317 if (FRAME_ANDROID_OUTPUT (f)->extracted_text_flags & 1)
5318 {
5319 hint = FRAME_ANDROID_OUTPUT (f)->extracted_text_hint;
5320 token = FRAME_ANDROID_OUTPUT (f)->extracted_text_token;
5321 text = get_extracted_text (f, min (hint, 600), &start,
5322 &offset, &length, &bytes);
5323
5324 /* Make a string out of the extracted text. */
5325 string = android_text_to_string (android_java_env,
5326 text, length, bytes);
5327 xfree (text);
5328 android_exception_check ();
5329
5330 /* Make extracted text out of that string. */
5331 extracted = android_build_extracted_text (string, start,
5332 offset);
5333 android_exception_check_1 (string);
5334 ANDROID_DELETE_LOCAL_REF (string);
5335
5336 /* extracted is now an associated ExtractedText object. Perform
5337 the update. */
5338 android_update_extracted_text (FRAME_ANDROID_WINDOW (f),
5339 extracted, token);
5340 ANDROID_DELETE_LOCAL_REF (extracted);
5341 }
5249} 5342}
5250 5343
5251/* Notice that the input method connection to F should be reset as a 5344/* Notice that the input method connection to F should be reset as a
@@ -5283,6 +5376,10 @@ android_reset_conversion (struct frame *f)
5283 5376
5284 android_reset_ic (FRAME_ANDROID_WINDOW (f), mode); 5377 android_reset_ic (FRAME_ANDROID_WINDOW (f), mode);
5285 5378
5379 /* Clear extracted text flags. Since the IM has been reinitialised,
5380 it should no longer be displaying extracted text. */
5381 FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = 0;
5382
5286 /* Move its selection to the specified position. */ 5383 /* Move its selection to the specified position. */
5287 android_update_selection (f, NULL); 5384 android_update_selection (f, NULL);
5288} 5385}
diff --git a/src/androidterm.h b/src/androidterm.h
index ac845187a66..9bd11bb7853 100644
--- a/src/androidterm.h
+++ b/src/androidterm.h
@@ -241,6 +241,16 @@ struct android_output
241 /* List of all tools (either styluses or fingers) pressed onto the 241 /* List of all tools (either styluses or fingers) pressed onto the
242 frame. */ 242 frame. */
243 struct android_touch_point *touch_points; 243 struct android_touch_point *touch_points;
244
245 /* Flags associated with the last request to obtain ``extracted
246 text''. */
247 int extracted_text_flags;
248
249 /* Token asssociated with that request. */
250 int extracted_text_token;
251
252 /* The number of characters of extracted text wanted by the IM. */
253 int extracted_text_hint;
244}; 254};
245 255
246enum 256enum