diff options
| author | Po Lu | 2023-01-02 21:38:19 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-02 21:38:19 +0800 |
| commit | a32963e11f9f8e5d22b0d754d34a867f3b178ed2 (patch) | |
| tree | 898f12248beb2feb63ed4295f9de40c89053ae19 /src | |
| parent | fd074f3133a348dd1d3b7ee569f0fc046223efb9 (diff) | |
| download | emacs-a32963e11f9f8e5d22b0d754d34a867f3b178ed2.tar.gz emacs-a32963e11f9f8e5d22b0d754d34a867f3b178ed2.zip | |
Update Android port
* Makefile.in (java): Depend on info.
(MAKEFILE_NAME):
(config.status): Remove unneeded changes.
* configure.ac (BUILD_DETAILS, ANDROID_STUBIFY): Don't require a
C++ compiler on Android.
* java/AndroidManifest.xml: <EmacsActivity>: Set launchMode
appropriately. <EmacsMultitaskActivity>: New activity.
* java/Makefile.in (CROSS_BINS): Add EmacsClient.
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity)
(onCreate): Use the window attachment manager.
* java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea)
(paintTo): Implement clip masks correctly.
* java/org/gnu/emacs/EmacsDrawRectangle.java (getRect, paintTo):
Fix damage tracking rectangles.
* java/org/gnu/emacs/EmacsFontDriver.java (FontSpec, toString):
New function.
(FontMetrics, EmacsFontDriver): Fix signature of textExtents.
* java/org/gnu/emacs/EmacsMultitaskActivity.java
(EmacsMultitaskActivity): New file.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
functions sendFocusIn, sendFocusOut, sendWindowAction.
* java/org/gnu/emacs/EmacsPaintQueue.java (run): Fix clipping
handling.
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): Add
constructor for mutable pixmaps.
* java/org/gnu/emacs/EmacsSdk23FontDriver.java
(EmacsSdk23FontDriver): New file.
* java/org/gnu/emacs/EmacsSdk7FontDriver.java
(EmacsSdk7FontDriver, Sdk7Typeface, Sdk7FontEntity, Sdk7FontObject)
(checkMatch, hasChar, encodeChar): Implement text display and
fix font metrics semantics.
* java/org/gnu/emacs/EmacsService.java (EmacsService): Remove
availableChildren.
(getLibraryDirectory, onCreate): Pass pixel density to Emacs.
(clearArea): Fix arguments. Switch to using the window
attachment manager.
* java/org/gnu/emacs/EmacsSurfaceView.java (surfaceChanged)
(surfaceCreated): Flip buffers on surface attachment.
* java/org/gnu/emacs/EmacsView.java (EmacsView, swapBuffers):
New argument FORCE. Always swap if it is true.
(onKeyMultiple, onFocusChanged): New functions.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, destroyHandle)
(run): Switch to using the window attachment manager.
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(EmacsWindowAttachmentManager): New file.
* lisp/cus-edit.el (custom-button, custom-button-mouse)
(custom-button-pressed):
* lisp/faces.el (tool-bar): Define faces correctly on Android.
* src/android.c (struct android_emacs_pixmap): Add mutable
constructor.
(struct android_emacs_drawable): New structure.
(android_write_event): Check if event queue hasn't yet been
initialized.
(android_select): Set errno to EINTR if pselect fails.
(android_close): Remove unused debugging code.
(android_get_home_directory): New function.
(Java_org_gnu_emacs_EmacsNative_setEmacsParams): Set pixel
density and compute game path.
(android_init_emacs_drawable): New function.
(Java_org_gnu_emacs_EmacsNative_sendKeyPress): New argument
`unicode_char'. Pass it in events.
(Java_org_gnu_emacs_EmacsNative_sendKeyRelease): Likewise.
(Java_org_gnu_emacs_EmacsNative_sendFocusIn)
(Java_org_gnu_emacs_EmacsNative_sendFocusOut)
(Java_org_gnu_emacs_EmacsNative_sendWindowAction): New
functions.
(android_resolve_handle): Export function.
(android_change_gc): Clear clip rects under the right
circumstances. Set right clip mask field.
(android_create_pixmap_from_bitmap_data): Use correct alpha
channels.
(android_create_pixmap): Create mutable pixmap and avoid
redundant color array allocation.
(android_create_bitmap_from_data, android_create_image)
(android_destroy_image, android_put_pixel, android_get_pixel)
(android_get_image, android_put_image, faccessat): New
functions.
* src/android.h: Update prototypes.
* src/androidfns.c (android_default_font_parameter): Prefer
monospace to Droid Sans Mono.
* src/androidfont.c (struct android_emacs_font_driver): New
method `draw'.
(struct android_emacs_font_spec): New field `dpi'.
(struct androidfont_info): Add font metrics cache.
(android_init_font_driver, android_init_font_spec): Adjust
accordingly.
(androidfont_from_lisp, androidfont_from_java): Handle new
fields.
(androidfont_draw): Implement function.
(androidfont_open_font): Set pixel size correctly.
(androidfont_close_font): Free metrics cache.
(androidfont_cache_text_extents)
(androidfont_check_cached_extents): New functions.
(androidfont_text_extents): Cache glyph metrics somewhere for
future use.
(androidfont_list_family): Implement function.
* src/androidgui.h (enum android_event_type): New focus and
window action events.
(enum android_modifier_mask): New masks.
(struct android_key_event): New field `unicode_char'.
(ANDROID_IS_MODIFIER_KEY): Newmacro.
(struct android_focus_event, struct
android_window_action_event): New structs.
(union android_event): Add new fields.
(enum android_image_format, struct android_image): New enums and
structs.
* src/androidterm.c (android_android_to_emacs_modifiers)
(android_emacs_to_android_modifiers, android_lower_frame)
(android_raise_frame, android_new_focus_frame)
(android_focus_changed, android_detect_focus_change): New
functions.
(handle_one_android_event): Implement focus and key event
handling.
(android_frame_rehighlight): New function.
(android_frame_raise_lower): Implement accordingly.
(android_make_frame_invisible): Clear highlight_frame if
required.
(android_free_frame_resources): Clear x_focus_event_frame if
required.
(android_draw_fringe_bitmap, android_draw_image_foreground)
(android_draw_image_foreground_1)
(android_draw_image_glyph_string): Remove unnecessary code.
(android_create_terminal, android_term_init): Set the baud rate
to something sensible.
* src/androidterm.h (struct android_bitmap_record): Make
structure the same as on X.
(struct android_display_info): New focus tracking fields.
(struct android_output): Likewise.
* src/dispextern.h (struct image): Add ximg and mask_img on
Android.
* src/emacs.c (android_emacs_init): Fix argc sorting iteration.
* src/fileio.c (user_homedir):
(get_homedir): Implement correctly on Android.
* src/font.h (PT_PER_INCH): Define correctly on Android.
* src/fringe.c (X, swap_nibble, init_fringe_bitmap): Swap fringe
bitmaps correctly on Android.
* src/image.c (GET_PIXEL, image_create_bitmap_from_data)
(image_create_bitmap_from_file, free_bitmap_record)
(image_unget_x_image_or_dc, struct image_type)
(prepare_image_for_display, image_clear_image_1)
(image_size_in_bytes, x_check_image_size)
(x_create_x_image_and_pixmap, x_destroy_x_image)
(image_check_image_size, image_create_x_image_and_pixmap_1)
(image_destroy_x_image, gui_put_x_image, image_put_x_image)
(image_get_x_image, image_unget_x_image)
(Create_Pixmap_From_Bitmap_Data, image_pixmap_draw_cross)
(MaskForeground, image_types, syms_of_image): Implement all of
the above on Android in terms of an API very similar to X.
* src/keyboard.c (FUNCTION_KEY_OFFSET, lispy_function_keys):
Define on Android to something sensible.
* src/lread.c (build_load_history): Fix problem.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android.c | 627 | ||||
| -rw-r--r-- | src/android.h | 15 | ||||
| -rw-r--r-- | src/androidfns.c | 5 | ||||
| -rw-r--r-- | src/androidfont.c | 270 | ||||
| -rw-r--r-- | src/androidgui.h | 81 | ||||
| -rw-r--r-- | src/androidterm.c | 544 | ||||
| -rw-r--r-- | src/androidterm.h | 30 | ||||
| -rw-r--r-- | src/dispextern.h | 11 | ||||
| -rw-r--r-- | src/emacs.c | 5 | ||||
| -rw-r--r-- | src/fileio.c | 9 | ||||
| -rw-r--r-- | src/font.h | 6 | ||||
| -rw-r--r-- | src/fringe.c | 23 | ||||
| -rw-r--r-- | src/image.c | 249 | ||||
| -rw-r--r-- | src/keyboard.c | 53 | ||||
| -rw-r--r-- | src/lread.c | 20 |
15 files changed, 1518 insertions, 430 deletions
diff --git a/src/android.c b/src/android.c index dd841cf383a..db12e244275 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 24 | #include <limits.h> | 24 | #include <limits.h> |
| 25 | #include <signal.h> | 25 | #include <signal.h> |
| 26 | #include <semaphore.h> | 26 | #include <semaphore.h> |
| 27 | #include <dlfcn.h> | ||
| 27 | 28 | ||
| 28 | #include <sys/stat.h> | 29 | #include <sys/stat.h> |
| 29 | #include <sys/mman.h> | 30 | #include <sys/mman.h> |
| @@ -46,6 +47,7 @@ bool android_init_gui; | |||
| 46 | 47 | ||
| 47 | #include <android/asset_manager.h> | 48 | #include <android/asset_manager.h> |
| 48 | #include <android/asset_manager_jni.h> | 49 | #include <android/asset_manager_jni.h> |
| 50 | #include <android/bitmap.h> | ||
| 49 | #include <android/log.h> | 51 | #include <android/log.h> |
| 50 | 52 | ||
| 51 | #include <linux/ashmem.h> | 53 | #include <linux/ashmem.h> |
| @@ -86,6 +88,7 @@ struct android_emacs_pixmap | |||
| 86 | { | 88 | { |
| 87 | jclass class; | 89 | jclass class; |
| 88 | jmethodID constructor; | 90 | jmethodID constructor; |
| 91 | jmethodID constructor_mutable; | ||
| 89 | }; | 92 | }; |
| 90 | 93 | ||
| 91 | struct android_graphics_point | 94 | struct android_graphics_point |
| @@ -94,6 +97,12 @@ struct android_graphics_point | |||
| 94 | jmethodID constructor; | 97 | jmethodID constructor; |
| 95 | }; | 98 | }; |
| 96 | 99 | ||
| 100 | struct android_emacs_drawable | ||
| 101 | { | ||
| 102 | jclass class; | ||
| 103 | jmethodID get_bitmap; | ||
| 104 | }; | ||
| 105 | |||
| 97 | /* The asset manager being used. */ | 106 | /* The asset manager being used. */ |
| 98 | static AAssetManager *asset_manager; | 107 | static AAssetManager *asset_manager; |
| 99 | 108 | ||
| @@ -106,6 +115,12 @@ char *android_site_load_path; | |||
| 106 | /* The path used to store native libraries. */ | 115 | /* The path used to store native libraries. */ |
| 107 | char *android_lib_dir; | 116 | char *android_lib_dir; |
| 108 | 117 | ||
| 118 | /* The path used to store game files. */ | ||
| 119 | char *android_game_path; | ||
| 120 | |||
| 121 | /* The display's pixel densities. */ | ||
| 122 | double android_pixel_density_x, android_pixel_density_y; | ||
| 123 | |||
| 109 | /* The Android application data directory. */ | 124 | /* The Android application data directory. */ |
| 110 | static char *android_files_dir; | 125 | static char *android_files_dir; |
| 111 | 126 | ||
| @@ -149,6 +164,9 @@ static struct android_emacs_pixmap pixmap_class; | |||
| 149 | /* Various methods associated with the Point class. */ | 164 | /* Various methods associated with the Point class. */ |
| 150 | static struct android_graphics_point point_class; | 165 | static struct android_graphics_point point_class; |
| 151 | 166 | ||
| 167 | /* Various methods associated with the EmacsDrawable class. */ | ||
| 168 | static struct android_emacs_drawable drawable_class; | ||
| 169 | |||
| 152 | 170 | ||
| 153 | 171 | ||
| 154 | /* Event handling functions. Events are stored on a (circular) queue | 172 | /* Event handling functions. Events are stored on a (circular) queue |
| @@ -383,6 +401,10 @@ android_write_event (union android_event *event) | |||
| 383 | if (!container) | 401 | if (!container) |
| 384 | return; | 402 | return; |
| 385 | 403 | ||
| 404 | /* If the event queue hasn't been initialized yet, return false. */ | ||
| 405 | if (!event_queue.events.next) | ||
| 406 | return; | ||
| 407 | |||
| 386 | pthread_mutex_lock (&event_queue.mutex); | 408 | pthread_mutex_lock (&event_queue.mutex); |
| 387 | 409 | ||
| 388 | /* The event queue is full, wait for events to be read. */ | 410 | /* The event queue is full, wait for events to be read. */ |
| @@ -451,6 +473,10 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 451 | /* Unlock the event queue mutex. */ | 473 | /* Unlock the event queue mutex. */ |
| 452 | pthread_mutex_unlock (&event_queue.mutex); | 474 | pthread_mutex_unlock (&event_queue.mutex); |
| 453 | 475 | ||
| 476 | /* This is to shut up process.c when pselect gets EINTR. */ | ||
| 477 | if (nfds_return < 0) | ||
| 478 | errno = EINTR; | ||
| 479 | |||
| 454 | return nfds_return; | 480 | return nfds_return; |
| 455 | } | 481 | } |
| 456 | 482 | ||
| @@ -793,16 +819,20 @@ android_close (int fd) | |||
| 793 | { | 819 | { |
| 794 | if (fd < ANDROID_MAX_ASSET_FD | 820 | if (fd < ANDROID_MAX_ASSET_FD |
| 795 | && (android_table[fd].flags & ANDROID_FD_TABLE_ENTRY_IS_VALID)) | 821 | && (android_table[fd].flags & ANDROID_FD_TABLE_ENTRY_IS_VALID)) |
| 796 | { | 822 | android_table[fd].flags = 0; |
| 797 | __android_log_print (ANDROID_LOG_INFO, __func__, | ||
| 798 | "closing android file descriptor %d", | ||
| 799 | fd); | ||
| 800 | android_table[fd].flags = 0; | ||
| 801 | } | ||
| 802 | 823 | ||
| 803 | return close (fd); | 824 | return close (fd); |
| 804 | } | 825 | } |
| 805 | 826 | ||
| 827 | /* Return the current user's ``home'' directory, which is actually the | ||
| 828 | app data directory on Android. */ | ||
| 829 | |||
| 830 | const char * | ||
| 831 | android_get_home_directory (void) | ||
| 832 | { | ||
| 833 | return android_files_dir; | ||
| 834 | } | ||
| 835 | |||
| 806 | 836 | ||
| 807 | 837 | ||
| 808 | /* JNI functions called by Java. */ | 838 | /* JNI functions called by Java. */ |
| @@ -814,6 +844,8 @@ JNIEXPORT void JNICALL | |||
| 814 | NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | 844 | NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, |
| 815 | jobject local_asset_manager, | 845 | jobject local_asset_manager, |
| 816 | jobject files_dir, jobject libs_dir, | 846 | jobject files_dir, jobject libs_dir, |
| 847 | jfloat pixel_density_x, | ||
| 848 | jfloat pixel_density_y, | ||
| 817 | jobject emacs_service_object) | 849 | jobject emacs_service_object) |
| 818 | { | 850 | { |
| 819 | int pipefd[2]; | 851 | int pipefd[2]; |
| @@ -829,6 +861,9 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | |||
| 829 | return; | 861 | return; |
| 830 | } | 862 | } |
| 831 | 863 | ||
| 864 | android_pixel_density_x = pixel_density_x; | ||
| 865 | android_pixel_density_y = pixel_density_y; | ||
| 866 | |||
| 832 | __android_log_print (ANDROID_LOG_INFO, __func__, | 867 | __android_log_print (ANDROID_LOG_INFO, __func__, |
| 833 | "Initializing "PACKAGE_STRING"...\nPlease report bugs to " | 868 | "Initializing "PACKAGE_STRING"...\nPlease report bugs to " |
| 834 | PACKAGE_BUGREPORT". Thanks.\n"); | 869 | PACKAGE_BUGREPORT". Thanks.\n"); |
| @@ -891,15 +926,23 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | |||
| 891 | if (!android_site_load_path) | 926 | if (!android_site_load_path) |
| 892 | emacs_abort (); | 927 | emacs_abort (); |
| 893 | 928 | ||
| 929 | android_game_path = malloc (PATH_MAX + 1); | ||
| 930 | |||
| 931 | if (!android_game_path) | ||
| 932 | emacs_abort (); | ||
| 933 | |||
| 894 | snprintf (android_site_load_path, PATH_MAX, "%s/site-lisp", | 934 | snprintf (android_site_load_path, PATH_MAX, "%s/site-lisp", |
| 895 | android_files_dir); | 935 | android_files_dir); |
| 936 | snprintf (android_game_path, PATH_MAX, "%s/scores", android_files_dir); | ||
| 937 | |||
| 896 | __android_log_print (ANDROID_LOG_INFO, __func__, | 938 | __android_log_print (ANDROID_LOG_INFO, __func__, |
| 897 | "Site-lisp directory: %s\n" | 939 | "Site-lisp directory: %s\n" |
| 898 | "Files directory: %s\n" | 940 | "Files directory: %s\n" |
| 899 | "Native code directory: %s", | 941 | "Native code directory: %s\n" |
| 942 | "Game score path: %s\n", | ||
| 900 | android_site_load_path, | 943 | android_site_load_path, |
| 901 | android_files_dir, | 944 | android_files_dir, |
| 902 | android_lib_dir); | 945 | android_lib_dir, android_game_path); |
| 903 | 946 | ||
| 904 | /* Make a reference to the Emacs service. */ | 947 | /* Make a reference to the Emacs service. */ |
| 905 | emacs_service = (*env)->NewGlobalRef (env, emacs_service_object); | 948 | emacs_service = (*env)->NewGlobalRef (env, emacs_service_object); |
| @@ -997,6 +1040,7 @@ android_init_emacs_pixmap (void) | |||
| 997 | assert (pixmap_class.c_name); | 1040 | assert (pixmap_class.c_name); |
| 998 | 1041 | ||
| 999 | FIND_METHOD (constructor, "<init>", "(S[IIII)V"); | 1042 | FIND_METHOD (constructor, "<init>", "(S[IIII)V"); |
| 1043 | FIND_METHOD (constructor_mutable, "<init>", "(SIII)V"); | ||
| 1000 | 1044 | ||
| 1001 | #undef FIND_METHOD | 1045 | #undef FIND_METHOD |
| 1002 | } | 1046 | } |
| @@ -1031,6 +1075,36 @@ android_init_graphics_point (void) | |||
| 1031 | #undef FIND_METHOD | 1075 | #undef FIND_METHOD |
| 1032 | } | 1076 | } |
| 1033 | 1077 | ||
| 1078 | static void | ||
| 1079 | android_init_emacs_drawable (void) | ||
| 1080 | { | ||
| 1081 | jclass old; | ||
| 1082 | |||
| 1083 | drawable_class.class | ||
| 1084 | = (*android_java_env)->FindClass (android_java_env, | ||
| 1085 | "org/gnu/emacs/EmacsDrawable"); | ||
| 1086 | eassert (drawable_class.class); | ||
| 1087 | |||
| 1088 | old = drawable_class.class; | ||
| 1089 | drawable_class.class | ||
| 1090 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, | ||
| 1091 | (jobject) old); | ||
| 1092 | ANDROID_DELETE_LOCAL_REF (old); | ||
| 1093 | |||
| 1094 | if (!drawable_class.class) | ||
| 1095 | emacs_abort (); | ||
| 1096 | |||
| 1097 | #define FIND_METHOD(c_name, name, signature) \ | ||
| 1098 | drawable_class.c_name \ | ||
| 1099 | = (*android_java_env)->GetMethodID (android_java_env, \ | ||
| 1100 | drawable_class.class, \ | ||
| 1101 | name, signature); \ | ||
| 1102 | assert (drawable_class.c_name); | ||
| 1103 | |||
| 1104 | FIND_METHOD (get_bitmap, "getBitmap", "()Landroid/graphics/Bitmap;"); | ||
| 1105 | #undef FIND_METHOD | ||
| 1106 | } | ||
| 1107 | |||
| 1034 | extern JNIEXPORT void JNICALL | 1108 | extern JNIEXPORT void JNICALL |
| 1035 | NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv) | 1109 | NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv) |
| 1036 | { | 1110 | { |
| @@ -1063,6 +1137,15 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv) | |||
| 1063 | android_init_emacs_service (); | 1137 | android_init_emacs_service (); |
| 1064 | android_init_emacs_pixmap (); | 1138 | android_init_emacs_pixmap (); |
| 1065 | android_init_graphics_point (); | 1139 | android_init_graphics_point (); |
| 1140 | android_init_emacs_drawable (); | ||
| 1141 | |||
| 1142 | /* Set HOME to the app data directory. */ | ||
| 1143 | setenv ("HOME", android_files_dir, 1); | ||
| 1144 | |||
| 1145 | /* Set the cwd to that directory as well. */ | ||
| 1146 | if (chdir (android_files_dir)) | ||
| 1147 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 1148 | "chdir: %s", strerror (errno)); | ||
| 1066 | 1149 | ||
| 1067 | /* Initialize the Android GUI. */ | 1150 | /* Initialize the Android GUI. */ |
| 1068 | android_init_gui = true; | 1151 | android_init_gui = true; |
| @@ -1099,7 +1182,8 @@ NATIVE_NAME (sendConfigureNotify) (JNIEnv *env, jobject object, | |||
| 1099 | extern JNIEXPORT void JNICALL | 1182 | extern JNIEXPORT void JNICALL |
| 1100 | NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object, | 1183 | NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object, |
| 1101 | jshort window, jlong time, | 1184 | jshort window, jlong time, |
| 1102 | jint state, jint keycode) | 1185 | jint state, jint keycode, |
| 1186 | jint unicode_char) | ||
| 1103 | { | 1187 | { |
| 1104 | union android_event event; | 1188 | union android_event event; |
| 1105 | 1189 | ||
| @@ -1108,6 +1192,7 @@ NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object, | |||
| 1108 | event.xkey.time = time; | 1192 | event.xkey.time = time; |
| 1109 | event.xkey.state = state; | 1193 | event.xkey.state = state; |
| 1110 | event.xkey.keycode = keycode; | 1194 | event.xkey.keycode = keycode; |
| 1195 | event.xkey.unicode_char = unicode_char; | ||
| 1111 | 1196 | ||
| 1112 | android_write_event (&event); | 1197 | android_write_event (&event); |
| 1113 | } | 1198 | } |
| @@ -1115,7 +1200,8 @@ NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object, | |||
| 1115 | extern JNIEXPORT void JNICALL | 1200 | extern JNIEXPORT void JNICALL |
| 1116 | NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object, | 1201 | NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object, |
| 1117 | jshort window, jlong time, | 1202 | jshort window, jlong time, |
| 1118 | jint state, jint keycode) | 1203 | jint state, jint keycode, |
| 1204 | jint unicode_char) | ||
| 1119 | { | 1205 | { |
| 1120 | union android_event event; | 1206 | union android_event event; |
| 1121 | 1207 | ||
| @@ -1124,6 +1210,46 @@ NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object, | |||
| 1124 | event.xkey.time = time; | 1210 | event.xkey.time = time; |
| 1125 | event.xkey.state = state; | 1211 | event.xkey.state = state; |
| 1126 | event.xkey.keycode = keycode; | 1212 | event.xkey.keycode = keycode; |
| 1213 | event.xkey.unicode_char = unicode_char; | ||
| 1214 | |||
| 1215 | android_write_event (&event); | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | extern JNIEXPORT void JNICALL | ||
| 1219 | NATIVE_NAME (sendFocusIn) (JNIEnv *env, jobject object, | ||
| 1220 | jshort window, jlong time) | ||
| 1221 | { | ||
| 1222 | union android_event event; | ||
| 1223 | |||
| 1224 | event.xkey.type = ANDROID_FOCUS_IN; | ||
| 1225 | event.xkey.window = window; | ||
| 1226 | event.xkey.time = time; | ||
| 1227 | |||
| 1228 | android_write_event (&event); | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | extern JNIEXPORT void JNICALL | ||
| 1232 | NATIVE_NAME (sendFocusOut) (JNIEnv *env, jobject object, | ||
| 1233 | jshort window, jlong time) | ||
| 1234 | { | ||
| 1235 | union android_event event; | ||
| 1236 | |||
| 1237 | event.xkey.type = ANDROID_FOCUS_OUT; | ||
| 1238 | event.xkey.window = window; | ||
| 1239 | event.xkey.time = time; | ||
| 1240 | |||
| 1241 | android_write_event (&event); | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | extern JNIEXPORT void JNICALL | ||
| 1245 | NATIVE_NAME (sendWindowAction) (JNIEnv *env, jobject object, | ||
| 1246 | jshort window, jint action) | ||
| 1247 | { | ||
| 1248 | union android_event event; | ||
| 1249 | |||
| 1250 | event.xaction.type = ANDROID_WINDOW_ACTION; | ||
| 1251 | event.xaction.window = window; | ||
| 1252 | event.xaction.action = action; | ||
| 1127 | 1253 | ||
| 1128 | android_write_event (&event); | 1254 | android_write_event (&event); |
| 1129 | } | 1255 | } |
| @@ -1142,13 +1268,6 @@ NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object, | |||
| 1142 | 1268 | ||
| 1143 | #define MAX_HANDLE 65535 | 1269 | #define MAX_HANDLE 65535 |
| 1144 | 1270 | ||
| 1145 | enum android_handle_type | ||
| 1146 | { | ||
| 1147 | ANDROID_HANDLE_WINDOW, | ||
| 1148 | ANDROID_HANDLE_GCONTEXT, | ||
| 1149 | ANDROID_HANDLE_PIXMAP, | ||
| 1150 | }; | ||
| 1151 | |||
| 1152 | struct android_handle_entry | 1271 | struct android_handle_entry |
| 1153 | { | 1272 | { |
| 1154 | /* The type. */ | 1273 | /* The type. */ |
| @@ -1245,7 +1364,7 @@ android_destroy_handle (android_handle handle) | |||
| 1245 | android_handles[handle].handle = NULL; | 1364 | android_handles[handle].handle = NULL; |
| 1246 | } | 1365 | } |
| 1247 | 1366 | ||
| 1248 | static jobject | 1367 | jobject |
| 1249 | android_resolve_handle (android_handle handle, | 1368 | android_resolve_handle (android_handle handle, |
| 1250 | enum android_handle_type type) | 1369 | enum android_handle_type type) |
| 1251 | { | 1370 | { |
| @@ -1625,14 +1744,15 @@ android_change_gc (struct android_gc *gc, | |||
| 1625 | ANDROID_HANDLE_PIXMAP); | 1744 | ANDROID_HANDLE_PIXMAP); |
| 1626 | (*android_java_env)->SetObjectField (android_java_env, | 1745 | (*android_java_env)->SetObjectField (android_java_env, |
| 1627 | gcontext, | 1746 | gcontext, |
| 1628 | emacs_gc_stipple, | 1747 | emacs_gc_clip_mask, |
| 1629 | what); | 1748 | what); |
| 1630 | 1749 | ||
| 1631 | /* Clearing GCClipMask also clears the clip rectangles. */ | 1750 | /* Clearing GCClipMask also clears the clip rectangles. */ |
| 1632 | (*android_java_env)->SetObjectField (android_java_env, | 1751 | if (!what) |
| 1633 | gcontext, | 1752 | (*android_java_env)->SetObjectField (android_java_env, |
| 1634 | emacs_gc_clip_rects, | 1753 | gcontext, |
| 1635 | NULL); | 1754 | emacs_gc_clip_rects, |
| 1755 | NULL); | ||
| 1636 | } | 1756 | } |
| 1637 | 1757 | ||
| 1638 | if (mask & ANDROID_GC_STIPPLE) | 1758 | if (mask & ANDROID_GC_STIPPLE) |
| @@ -2008,10 +2128,23 @@ android_create_pixmap_from_bitmap_data (char *data, unsigned int width, | |||
| 2008 | { | 2128 | { |
| 2009 | for (x = 0; x < width; ++x) | 2129 | for (x = 0; x < width; ++x) |
| 2010 | { | 2130 | { |
| 2011 | if (data[y / 8] & (1 << (x % 8))) | 2131 | if (depth == 24) |
| 2012 | region[x] = foreground; | 2132 | { |
| 2133 | /* The alpha channels must be set, or otherwise, the | ||
| 2134 | pixmap will be created entirely transparent. */ | ||
| 2135 | |||
| 2136 | if (data[y * (width + 7) / 8 + x / 8] & (1 << (x % 8))) | ||
| 2137 | region[x] = foreground | 0xff000000; | ||
| 2138 | else | ||
| 2139 | region[x] = background | 0xff000000; | ||
| 2140 | } | ||
| 2013 | else | 2141 | else |
| 2014 | region[x] = background; | 2142 | { |
| 2143 | if (data[y * (width + 7) / 8 + x / 8] & (1 << (x % 8))) | ||
| 2144 | region[x] = foreground; | ||
| 2145 | else | ||
| 2146 | region[x] = background; | ||
| 2147 | } | ||
| 2015 | } | 2148 | } |
| 2016 | 2149 | ||
| 2017 | (*android_java_env)->SetIntArrayRegion (android_java_env, | 2150 | (*android_java_env)->SetIntArrayRegion (android_java_env, |
| @@ -2236,36 +2369,21 @@ android_create_pixmap (unsigned int width, unsigned int height, | |||
| 2236 | { | 2369 | { |
| 2237 | android_handle prev_max_handle; | 2370 | android_handle prev_max_handle; |
| 2238 | jobject object; | 2371 | jobject object; |
| 2239 | jintArray colors; | ||
| 2240 | android_pixmap pixmap; | 2372 | android_pixmap pixmap; |
| 2241 | 2373 | ||
| 2242 | /* Create the color array holding the data. */ | ||
| 2243 | colors = (*android_java_env)->NewIntArray (android_java_env, | ||
| 2244 | width * height); | ||
| 2245 | |||
| 2246 | if (!colors) | ||
| 2247 | { | ||
| 2248 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 2249 | memory_full (0); | ||
| 2250 | } | ||
| 2251 | |||
| 2252 | /* First, allocate the pixmap handle. */ | 2374 | /* First, allocate the pixmap handle. */ |
| 2253 | prev_max_handle = max_handle; | 2375 | prev_max_handle = max_handle; |
| 2254 | pixmap = android_alloc_id (); | 2376 | pixmap = android_alloc_id (); |
| 2255 | 2377 | ||
| 2256 | if (!pixmap) | 2378 | if (!pixmap) |
| 2257 | { | 2379 | error ("Out of pixmap handles!"); |
| 2258 | ANDROID_DELETE_LOCAL_REF ((jobject) colors); | ||
| 2259 | error ("Out of pixmap handles!"); | ||
| 2260 | } | ||
| 2261 | 2380 | ||
| 2262 | object = (*android_java_env)->NewObject (android_java_env, | 2381 | object = (*android_java_env)->NewObject (android_java_env, |
| 2263 | pixmap_class.class, | 2382 | pixmap_class.class, |
| 2264 | pixmap_class.constructor, | 2383 | pixmap_class.constructor_mutable, |
| 2265 | (jshort) pixmap, colors, | 2384 | (jshort) pixmap, |
| 2266 | (jint) width, (jint) height, | 2385 | (jint) width, (jint) height, |
| 2267 | (jint) depth); | 2386 | (jint) depth); |
| 2268 | ANDROID_DELETE_LOCAL_REF ((jobject) colors); | ||
| 2269 | 2387 | ||
| 2270 | if (!object) | 2388 | if (!object) |
| 2271 | { | 2389 | { |
| @@ -2313,6 +2431,387 @@ android_clear_area (android_window handle, int x, int y, | |||
| 2313 | (jint) width, (jint) height); | 2431 | (jint) width, (jint) height); |
| 2314 | } | 2432 | } |
| 2315 | 2433 | ||
| 2434 | android_pixmap | ||
| 2435 | android_create_bitmap_from_data (char *bits, unsigned int width, | ||
| 2436 | unsigned int height) | ||
| 2437 | { | ||
| 2438 | return android_create_pixmap_from_bitmap_data (bits, 1, 0, | ||
| 2439 | width, height, 1); | ||
| 2440 | } | ||
| 2441 | |||
| 2442 | struct android_image * | ||
| 2443 | android_create_image (unsigned int depth, enum android_image_format format, | ||
| 2444 | char *data, unsigned int width, unsigned int height) | ||
| 2445 | { | ||
| 2446 | struct android_image *image; | ||
| 2447 | |||
| 2448 | image = xmalloc (sizeof *image); | ||
| 2449 | |||
| 2450 | /* Fill in the fields required by image.c. N.B. that | ||
| 2451 | android_destroy_image ostensibly will free data, but image.c | ||
| 2452 | mostly sets and frees data itself. */ | ||
| 2453 | image->width = width; | ||
| 2454 | image->height = height; | ||
| 2455 | image->data = data; | ||
| 2456 | image->depth = depth; | ||
| 2457 | image->format = format; | ||
| 2458 | |||
| 2459 | /* Now fill in the image dimensions. There are only two depths | ||
| 2460 | supported by this function. */ | ||
| 2461 | |||
| 2462 | if (depth == 1) | ||
| 2463 | { | ||
| 2464 | image->bytes_per_line = (width + 7) / 8; | ||
| 2465 | image->bits_per_pixel = 1; | ||
| 2466 | } | ||
| 2467 | else if (depth == 24) | ||
| 2468 | { | ||
| 2469 | image->bytes_per_line = width * 4; | ||
| 2470 | image->bits_per_pixel = 32; | ||
| 2471 | } | ||
| 2472 | else | ||
| 2473 | emacs_abort (); | ||
| 2474 | |||
| 2475 | return image; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | void | ||
| 2479 | android_destroy_image (struct android_image *ximg) | ||
| 2480 | { | ||
| 2481 | /* If XIMG->data is NULL, then it has already been freed by | ||
| 2482 | image.c. */ | ||
| 2483 | |||
| 2484 | if (ximg->data) | ||
| 2485 | xfree (ximg->data); | ||
| 2486 | xfree (ximg); | ||
| 2487 | } | ||
| 2488 | |||
| 2489 | void | ||
| 2490 | android_put_pixel (struct android_image *ximg, int x, int y, | ||
| 2491 | unsigned long pixel) | ||
| 2492 | { | ||
| 2493 | char *byte, *word; | ||
| 2494 | unsigned int r, g, b; | ||
| 2495 | |||
| 2496 | /* Ignore out-of-bounds accesses. */ | ||
| 2497 | |||
| 2498 | if (x >= ximg->width || y >= ximg->height || x < 0 || y < 0) | ||
| 2499 | return; | ||
| 2500 | |||
| 2501 | switch (ximg->depth) | ||
| 2502 | { | ||
| 2503 | case 1: | ||
| 2504 | byte = ximg->data + y * ximg->bytes_per_line + x / 8; | ||
| 2505 | |||
| 2506 | if (pixel) | ||
| 2507 | *byte |= (1 << x % 8); | ||
| 2508 | else | ||
| 2509 | *byte &= ~(1 << x % 8); | ||
| 2510 | break; | ||
| 2511 | |||
| 2512 | case 24: | ||
| 2513 | /* Unaligned accesses are problematic on Android devices. */ | ||
| 2514 | word = ximg->data + y * ximg->bytes_per_line + x * 4; | ||
| 2515 | |||
| 2516 | /* Swizzle the pixel into ABGR format. Android uses Skia's | ||
| 2517 | ``native color type'', which is ABGR. This is despite the | ||
| 2518 | format being named ``ARGB'', and more confusingly | ||
| 2519 | `ANDROID_BITMAP_FORMAT_RGBA_8888' in bitmap.h. */ | ||
| 2520 | r = pixel & 0x00ff0000; | ||
| 2521 | g = pixel & 0x0000ff00; | ||
| 2522 | b = pixel & 0x000000ff; | ||
| 2523 | pixel = (r >> 16) | g | (b << 16) | 0xff000000; | ||
| 2524 | |||
| 2525 | memcpy (word, &pixel, sizeof pixel); | ||
| 2526 | break; | ||
| 2527 | } | ||
| 2528 | } | ||
| 2529 | |||
| 2530 | unsigned long | ||
| 2531 | android_get_pixel (struct android_image *ximg, int x, int y) | ||
| 2532 | { | ||
| 2533 | char *byte, *word; | ||
| 2534 | unsigned int pixel, r, g, b; | ||
| 2535 | |||
| 2536 | if (x >= ximg->width || y >= ximg->height | ||
| 2537 | || x < 0 || y < 0) | ||
| 2538 | return 0; | ||
| 2539 | |||
| 2540 | switch (ximg->depth) | ||
| 2541 | { | ||
| 2542 | case 1: | ||
| 2543 | byte = ximg->data + y * ximg->bytes_per_line + x / 8; | ||
| 2544 | return (*byte & (1 << x % 8)) ? 1 : 0; | ||
| 2545 | |||
| 2546 | case 24: | ||
| 2547 | word = ximg->data + y * ximg->bytes_per_line + x * 4; | ||
| 2548 | memcpy (&pixel, word, sizeof pixel); | ||
| 2549 | |||
| 2550 | /* Convert the pixel back to RGB. */ | ||
| 2551 | b = pixel & 0x00ff0000; | ||
| 2552 | g = pixel & 0x0000ff00; | ||
| 2553 | r = pixel & 0x000000ff; | ||
| 2554 | pixel = ((r << 16) | g | (b >> 16)) & ~0xff000000; | ||
| 2555 | |||
| 2556 | return pixel; | ||
| 2557 | } | ||
| 2558 | |||
| 2559 | emacs_abort (); | ||
| 2560 | } | ||
| 2561 | |||
| 2562 | struct android_image * | ||
| 2563 | android_get_image (android_drawable handle, | ||
| 2564 | enum android_image_format format) | ||
| 2565 | { | ||
| 2566 | jobject drawable, bitmap; | ||
| 2567 | AndroidBitmapInfo bitmap_info; | ||
| 2568 | size_t byte_size; | ||
| 2569 | void *data; | ||
| 2570 | struct android_image *image; | ||
| 2571 | unsigned char *data1, *data2; | ||
| 2572 | int i, x; | ||
| 2573 | |||
| 2574 | /* N.B. that supporting windows requires some more work to make | ||
| 2575 | EmacsDrawable.getBitmap thread safe. */ | ||
| 2576 | drawable = android_resolve_handle2 (handle, ANDROID_HANDLE_WINDOW, | ||
| 2577 | ANDROID_HANDLE_PIXMAP); | ||
| 2578 | |||
| 2579 | /* Look up the drawable and get the bitmap corresponding to it. | ||
| 2580 | Then, lock the bitmap's bits. */ | ||
| 2581 | bitmap = (*android_java_env)->CallObjectMethod (android_java_env, | ||
| 2582 | drawable, | ||
| 2583 | drawable_class.get_bitmap); | ||
| 2584 | if (!bitmap) | ||
| 2585 | { | ||
| 2586 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 2587 | memory_full (0); | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | memset (&bitmap_info, 0, sizeof bitmap_info); | ||
| 2591 | |||
| 2592 | /* The NDK doc seems to imply this function can fail but doesn't say | ||
| 2593 | what value it gives when it does! */ | ||
| 2594 | AndroidBitmap_getInfo (android_java_env, bitmap, &bitmap_info); | ||
| 2595 | |||
| 2596 | if (!bitmap_info.stride) | ||
| 2597 | { | ||
| 2598 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2599 | memory_full (0); | ||
| 2600 | } | ||
| 2601 | |||
| 2602 | /* Compute how big the image data will be. Fail if it would be too | ||
| 2603 | big. */ | ||
| 2604 | |||
| 2605 | if (bitmap_info.format != ANDROID_BITMAP_FORMAT_A_8) | ||
| 2606 | { | ||
| 2607 | if (INT_MULTIPLY_WRAPV ((size_t) bitmap_info.stride, | ||
| 2608 | (size_t) bitmap_info.height, | ||
| 2609 | &byte_size)) | ||
| 2610 | { | ||
| 2611 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2612 | memory_full (0); | ||
| 2613 | } | ||
| 2614 | } | ||
| 2615 | else | ||
| 2616 | /* This A8 image will be packed into A1 later on. */ | ||
| 2617 | byte_size = (bitmap_info.width + 7) / 8; | ||
| 2618 | |||
| 2619 | /* Lock the image data. Once again, the NDK documentation says the | ||
| 2620 | call can fail, but does not say how to determine whether or not | ||
| 2621 | it has failed, nor how the address is aligned. */ | ||
| 2622 | data = NULL; | ||
| 2623 | AndroidBitmap_lockPixels (android_java_env, bitmap, &data); | ||
| 2624 | |||
| 2625 | if (!data) | ||
| 2626 | { | ||
| 2627 | /* Take a NULL pointer to mean that AndroidBitmap_lockPixels | ||
| 2628 | failed. */ | ||
| 2629 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2630 | memory_full (0); | ||
| 2631 | } | ||
| 2632 | |||
| 2633 | /* Copy the data into a new struct android_image. */ | ||
| 2634 | image = xmalloc (sizeof *image); | ||
| 2635 | image->width = bitmap_info.width; | ||
| 2636 | image->height = bitmap_info.height; | ||
| 2637 | image->data = malloc (byte_size); | ||
| 2638 | |||
| 2639 | if (!image->data) | ||
| 2640 | { | ||
| 2641 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2642 | xfree (image); | ||
| 2643 | memory_full (byte_size); | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | /* Use the format of the bitmap to determine the image depth. */ | ||
| 2647 | switch (bitmap_info.format) | ||
| 2648 | { | ||
| 2649 | case ANDROID_BITMAP_FORMAT_RGBA_8888: | ||
| 2650 | image->depth = 24; | ||
| 2651 | image->bits_per_pixel = 32; | ||
| 2652 | break; | ||
| 2653 | |||
| 2654 | /* A8 images are used by Emacs to represent bitmaps. They have | ||
| 2655 | to be packed manually. */ | ||
| 2656 | case ANDROID_BITMAP_FORMAT_A_8: | ||
| 2657 | image->depth = 1; | ||
| 2658 | image->bits_per_pixel = 1; | ||
| 2659 | break; | ||
| 2660 | |||
| 2661 | /* Other formats are currently not supported. */ | ||
| 2662 | default: | ||
| 2663 | emacs_abort (); | ||
| 2664 | } | ||
| 2665 | |||
| 2666 | image->format = format; | ||
| 2667 | |||
| 2668 | if (image->depth == 24) | ||
| 2669 | { | ||
| 2670 | image->bytes_per_line = bitmap_info.stride; | ||
| 2671 | |||
| 2672 | /* Copy the bitmap data over. */ | ||
| 2673 | memcpy (image->data, data, byte_size); | ||
| 2674 | } | ||
| 2675 | else | ||
| 2676 | { | ||
| 2677 | /* Pack the A8 image data into bits manually. */ | ||
| 2678 | image->bytes_per_line = (image->width + 7) / 8; | ||
| 2679 | |||
| 2680 | data1 = (unsigned char *) image->data; | ||
| 2681 | data2 = data; | ||
| 2682 | |||
| 2683 | for (i = 0; i < image->height; ++i) | ||
| 2684 | { | ||
| 2685 | for (x = 0; x < image->width; ++x) | ||
| 2686 | /* Some bits in data1 might be initialized at this point, | ||
| 2687 | but they will all be set properly later. */ | ||
| 2688 | data1[x / 8] = (data2[x] | ||
| 2689 | ? (data1[x / 8] | (1 << (x % 8))) | ||
| 2690 | : (data1[x / 8] & ~(1 << (x % 8)))); | ||
| 2691 | |||
| 2692 | data1 += image->bytes_per_line; | ||
| 2693 | data2 += bitmap_info.stride; | ||
| 2694 | } | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | /* Unlock the bitmap pixels. */ | ||
| 2698 | AndroidBitmap_unlockPixels (android_java_env, bitmap); | ||
| 2699 | |||
| 2700 | /* Delete the bitmap reference. */ | ||
| 2701 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2702 | return image; | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | void | ||
| 2706 | android_put_image (android_pixmap handle, struct android_image *image) | ||
| 2707 | { | ||
| 2708 | jobject drawable, bitmap; | ||
| 2709 | AndroidBitmapInfo bitmap_info; | ||
| 2710 | void *data; | ||
| 2711 | unsigned char *data_1, *data_2; | ||
| 2712 | int i, x; | ||
| 2713 | |||
| 2714 | drawable = android_resolve_handle (handle, ANDROID_HANDLE_PIXMAP); | ||
| 2715 | |||
| 2716 | /* Look up the drawable and get the bitmap corresponding to it. | ||
| 2717 | Then, lock the bitmap's bits. */ | ||
| 2718 | bitmap = (*android_java_env)->CallObjectMethod (android_java_env, | ||
| 2719 | drawable, | ||
| 2720 | drawable_class.get_bitmap); | ||
| 2721 | if (!bitmap) | ||
| 2722 | { | ||
| 2723 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 2724 | memory_full (0); | ||
| 2725 | } | ||
| 2726 | |||
| 2727 | memset (&bitmap_info, 0, sizeof bitmap_info); | ||
| 2728 | |||
| 2729 | /* The NDK doc seems to imply this function can fail but doesn't say | ||
| 2730 | what value it gives when it does! */ | ||
| 2731 | AndroidBitmap_getInfo (android_java_env, bitmap, &bitmap_info); | ||
| 2732 | |||
| 2733 | if (!bitmap_info.stride) | ||
| 2734 | { | ||
| 2735 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2736 | memory_full (0); | ||
| 2737 | } | ||
| 2738 | |||
| 2739 | if (bitmap_info.width != image->width | ||
| 2740 | || bitmap_info.height != image->height) | ||
| 2741 | /* This is not yet supported. */ | ||
| 2742 | emacs_abort (); | ||
| 2743 | |||
| 2744 | /* Make sure the bitmap formats are compatible with each other. */ | ||
| 2745 | |||
| 2746 | if ((image->depth == 24 | ||
| 2747 | && bitmap_info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) | ||
| 2748 | || (image->depth == 1 | ||
| 2749 | && bitmap_info.format != ANDROID_BITMAP_FORMAT_A_8)) | ||
| 2750 | emacs_abort (); | ||
| 2751 | |||
| 2752 | /* Lock the image data. Once again, the NDK documentation says the | ||
| 2753 | call can fail, but does not say how to determine whether or not | ||
| 2754 | it has failed, nor how the address is aligned. */ | ||
| 2755 | data = NULL; | ||
| 2756 | AndroidBitmap_lockPixels (android_java_env, bitmap, &data); | ||
| 2757 | |||
| 2758 | if (!data) | ||
| 2759 | { | ||
| 2760 | /* Take a NULL pointer to mean that AndroidBitmap_lockPixels | ||
| 2761 | failed. */ | ||
| 2762 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2763 | memory_full (0); | ||
| 2764 | } | ||
| 2765 | |||
| 2766 | data_1 = data; | ||
| 2767 | data_2 = (unsigned char *) image->data; | ||
| 2768 | |||
| 2769 | /* Copy the bitmap data over scanline-by-scanline. */ | ||
| 2770 | for (i = 0; i < image->height; ++i) | ||
| 2771 | { | ||
| 2772 | if (image->depth != 1) | ||
| 2773 | memcpy (data_1, data_2, | ||
| 2774 | image->width * (image->bits_per_pixel / 8)); | ||
| 2775 | else | ||
| 2776 | { | ||
| 2777 | /* Android internally uses a 1 byte-per-pixel format for | ||
| 2778 | ALPHA_8 images. Expand the image from the 1 | ||
| 2779 | bit-per-pixel X format correctly. */ | ||
| 2780 | |||
| 2781 | for (x = 0; x < image->width; ++x) | ||
| 2782 | data_1[x] = (data_2[x / 8] & (1 << x % 8)) ? 0xff : 0; | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | data_1 += bitmap_info.stride; | ||
| 2786 | data_2 += image->bytes_per_line; | ||
| 2787 | } | ||
| 2788 | |||
| 2789 | /* Unlock the bitmap pixels. */ | ||
| 2790 | AndroidBitmap_unlockPixels (android_java_env, bitmap); | ||
| 2791 | |||
| 2792 | /* Delete the bitmap reference. */ | ||
| 2793 | ANDROID_DELETE_LOCAL_REF (bitmap); | ||
| 2794 | } | ||
| 2795 | |||
| 2796 | |||
| 2797 | |||
| 2798 | #undef faccessat | ||
| 2799 | |||
| 2800 | /* Replace the system faccessat with one which understands AT_EACCESS. | ||
| 2801 | Android's faccessat simply fails upon using AT_EACCESS, so repalce | ||
| 2802 | it with zero here. This isn't caught during configuration. */ | ||
| 2803 | |||
| 2804 | int | ||
| 2805 | faccessat (int dirfd, const char *pathname, int mode, int flags) | ||
| 2806 | { | ||
| 2807 | static int (*real_faccessat) (int, const char *, int, int); | ||
| 2808 | |||
| 2809 | if (!real_faccessat) | ||
| 2810 | real_faccessat = dlsym (RTLD_NEXT, "faccessat"); | ||
| 2811 | |||
| 2812 | return real_faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS); | ||
| 2813 | } | ||
| 2814 | |||
| 2316 | #else /* ANDROID_STUBIFY */ | 2815 | #else /* ANDROID_STUBIFY */ |
| 2317 | 2816 | ||
| 2318 | /* X emulation functions for Android. */ | 2817 | /* X emulation functions for Android. */ |
| @@ -2332,4 +2831,44 @@ android_free_gc (struct android_gc *gc) | |||
| 2332 | emacs_abort (); | 2831 | emacs_abort (); |
| 2333 | } | 2832 | } |
| 2334 | 2833 | ||
| 2834 | struct android_image * | ||
| 2835 | android_create_image (unsigned int depth, enum android_image_format format, | ||
| 2836 | char *data, unsigned int width, unsigned int height) | ||
| 2837 | { | ||
| 2838 | emacs_abort (); | ||
| 2839 | } | ||
| 2840 | |||
| 2841 | void | ||
| 2842 | android_destroy_image (struct android_image *ximg) | ||
| 2843 | { | ||
| 2844 | emacs_abort (); | ||
| 2845 | } | ||
| 2846 | |||
| 2847 | void | ||
| 2848 | android_put_pixel (struct android_image *ximg, int x, int y, | ||
| 2849 | unsigned long pixel) | ||
| 2850 | { | ||
| 2851 | emacs_abort (); | ||
| 2852 | } | ||
| 2853 | |||
| 2854 | unsigned long | ||
| 2855 | android_get_pixel (struct android_image *ximg, int x, int y) | ||
| 2856 | { | ||
| 2857 | emacs_abort (); | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | struct android_image * | ||
| 2861 | android_get_image (android_drawable drawable, | ||
| 2862 | enum android_image_format format) | ||
| 2863 | { | ||
| 2864 | emacs_abort (); | ||
| 2865 | } | ||
| 2866 | |||
| 2867 | void | ||
| 2868 | android_put_image (android_pixmap pixmap, | ||
| 2869 | struct android_image *image) | ||
| 2870 | { | ||
| 2871 | emacs_abort (); | ||
| 2872 | } | ||
| 2873 | |||
| 2335 | #endif | 2874 | #endif |
diff --git a/src/android.h b/src/android.h index 6bdcd38ed68..4d702fe2079 100644 --- a/src/android.h +++ b/src/android.h | |||
| @@ -28,6 +28,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | #include <jni.h> | 28 | #include <jni.h> |
| 29 | #include <pwd.h> | 29 | #include <pwd.h> |
| 30 | #include <sys/stat.h> | 30 | #include <sys/stat.h> |
| 31 | |||
| 32 | #include "androidgui.h" | ||
| 31 | #endif | 33 | #endif |
| 32 | 34 | ||
| 33 | /* This must be used in every symbol declaration to export it to the | 35 | /* This must be used in every symbol declaration to export it to the |
| @@ -49,6 +51,19 @@ extern int android_fstat (int, struct stat *); | |||
| 49 | extern int android_fstatat (int, const char *restrict, | 51 | extern int android_fstatat (int, const char *restrict, |
| 50 | struct stat *restrict, int); | 52 | struct stat *restrict, int); |
| 51 | extern int android_close (int); | 53 | extern int android_close (int); |
| 54 | extern const char *android_get_home_directory (void); | ||
| 55 | |||
| 56 | extern double android_pixel_density_x, android_pixel_density_y; | ||
| 57 | |||
| 58 | enum android_handle_type | ||
| 59 | { | ||
| 60 | ANDROID_HANDLE_WINDOW, | ||
| 61 | ANDROID_HANDLE_GCONTEXT, | ||
| 62 | ANDROID_HANDLE_PIXMAP, | ||
| 63 | }; | ||
| 64 | |||
| 65 | extern jobject android_resolve_handle (android_handle, | ||
| 66 | enum android_handle_type); | ||
| 52 | 67 | ||
| 53 | #endif | 68 | #endif |
| 54 | 69 | ||
diff --git a/src/androidfns.c b/src/androidfns.c index e9e1ae3d52e..a78b35fc8ff 100644 --- a/src/androidfns.c +++ b/src/androidfns.c | |||
| @@ -531,9 +531,10 @@ android_default_font_parameter (struct frame *f, Lisp_Object parms) | |||
| 531 | if (! FONTP (font) && ! STRINGP (font)) | 531 | if (! FONTP (font) && ! STRINGP (font)) |
| 532 | { | 532 | { |
| 533 | const char *names[] = { | 533 | const char *names[] = { |
| 534 | /* This will find the normal font. */ | 534 | /* This will find the normal font. The default font size on |
| 535 | "DroidSansMono", | 535 | Android is 8. */ |
| 536 | "monospace", | 536 | "monospace", |
| 537 | "DroidSansMono", | ||
| 537 | NULL | 538 | NULL |
| 538 | }; | 539 | }; |
| 539 | int i; | 540 | int i; |
diff --git a/src/androidfont.c b/src/androidfont.c index e312e55c54a..b2c83201b06 100644 --- a/src/androidfont.c +++ b/src/androidfont.c | |||
| @@ -49,6 +49,7 @@ struct android_emacs_font_driver | |||
| 49 | jmethodID has_char; | 49 | jmethodID has_char; |
| 50 | jmethodID text_extents; | 50 | jmethodID text_extents; |
| 51 | jmethodID encode_char; | 51 | jmethodID encode_char; |
| 52 | jmethodID draw; | ||
| 52 | 53 | ||
| 53 | /* Static methods. */ | 54 | /* Static methods. */ |
| 54 | jmethodID create_font_driver; | 55 | jmethodID create_font_driver; |
| @@ -67,6 +68,7 @@ struct android_emacs_font_spec | |||
| 67 | jfieldID size; | 68 | jfieldID size; |
| 68 | jfieldID spacing; | 69 | jfieldID spacing; |
| 69 | jfieldID avgwidth; | 70 | jfieldID avgwidth; |
| 71 | jfieldID dpi; | ||
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 72 | struct android_emacs_font_metrics | 74 | struct android_emacs_font_metrics |
| @@ -113,6 +115,9 @@ struct androidfont_info | |||
| 113 | 115 | ||
| 114 | /* The Java-side font. */ | 116 | /* The Java-side font. */ |
| 115 | jobject object; | 117 | jobject object; |
| 118 | |||
| 119 | /* Cached glyph metrics arranged in a two dimensional array. */ | ||
| 120 | struct font_metrics **metrics; | ||
| 116 | }; | 121 | }; |
| 117 | 122 | ||
| 118 | struct androidfont_entity | 123 | struct androidfont_entity |
| @@ -197,9 +202,11 @@ android_init_font_driver (void) | |||
| 197 | FIND_METHOD (has_char, "hasChar", "(Lorg/gnu/emacs/EmacsFontDriver$Font" | 202 | FIND_METHOD (has_char, "hasChar", "(Lorg/gnu/emacs/EmacsFontDriver$Font" |
| 198 | "Spec;C)I"); | 203 | "Spec;C)I"); |
| 199 | FIND_METHOD (text_extents, "textExtents", "(Lorg/gnu/emacs/EmacsFontDriver" | 204 | FIND_METHOD (text_extents, "textExtents", "(Lorg/gnu/emacs/EmacsFontDriver" |
| 200 | "$FontObject;[I[Lorg/gnu/emacs/EmacsFontDriver$FontMetrics;)V"); | 205 | "$FontObject;[ILorg/gnu/emacs/EmacsFontDriver$FontMetrics;)V"); |
| 201 | FIND_METHOD (encode_char, "encodeChar", "(Lorg/gnu/emacs/EmacsFontDriver" | 206 | FIND_METHOD (encode_char, "encodeChar", "(Lorg/gnu/emacs/EmacsFontDriver" |
| 202 | "$FontObject;C)I"); | 207 | "$FontObject;C)I"); |
| 208 | FIND_METHOD (draw, "draw", "(Lorg/gnu/emacs/EmacsFontDriver$FontObject;" | ||
| 209 | "Lorg/gnu/emacs/EmacsGC;Lorg/gnu/emacs/EmacsDrawable;[IIIIZ)I"); | ||
| 203 | 210 | ||
| 204 | font_driver_class.create_font_driver | 211 | font_driver_class.create_font_driver |
| 205 | = (*android_java_env)->GetStaticMethodID (android_java_env, | 212 | = (*android_java_env)->GetStaticMethodID (android_java_env, |
| @@ -252,6 +259,7 @@ android_init_font_spec (void) | |||
| 252 | FIND_FIELD (size, "size", "Ljava/lang/Integer;"); | 259 | FIND_FIELD (size, "size", "Ljava/lang/Integer;"); |
| 253 | FIND_FIELD (spacing, "spacing", "Ljava/lang/Integer;"); | 260 | FIND_FIELD (spacing, "spacing", "Ljava/lang/Integer;"); |
| 254 | FIND_FIELD (avgwidth, "avgwidth", "Ljava/lang/Integer;"); | 261 | FIND_FIELD (avgwidth, "avgwidth", "Ljava/lang/Integer;"); |
| 262 | FIND_FIELD (dpi, "dpi", "Ljava/lang/Integer;"); | ||
| 255 | #undef FIND_FIELD | 263 | #undef FIND_FIELD |
| 256 | } | 264 | } |
| 257 | 265 | ||
| @@ -449,6 +457,9 @@ androidfont_from_lisp (Lisp_Object font) | |||
| 449 | DO_CARDINAL_FIELD (avgwidth, (FIXNUMP (AREF (font, FONT_AVGWIDTH_INDEX)) | 457 | DO_CARDINAL_FIELD (avgwidth, (FIXNUMP (AREF (font, FONT_AVGWIDTH_INDEX)) |
| 450 | ? XFIXNUM (AREF (font, FONT_AVGWIDTH_INDEX)) | 458 | ? XFIXNUM (AREF (font, FONT_AVGWIDTH_INDEX)) |
| 451 | : -1)); | 459 | : -1)); |
| 460 | DO_CARDINAL_FIELD (dpi, (FIXNUMP (AREF (font, FONT_DPI_INDEX)) | ||
| 461 | ? XFIXNUM (AREF (font, FONT_DPI_INDEX)) | ||
| 462 | : -1)); | ||
| 452 | 463 | ||
| 453 | #undef DO_CARDINAL_FIELD | 464 | #undef DO_CARDINAL_FIELD |
| 454 | 465 | ||
| @@ -507,6 +518,8 @@ androidfont_from_java (jobject spec, Lisp_Object entity) | |||
| 507 | DO_CARDINAL_FIELD (size, FONT_SIZE_INDEX, false); | 518 | DO_CARDINAL_FIELD (size, FONT_SIZE_INDEX, false); |
| 508 | DO_CARDINAL_FIELD (spacing, FONT_SPACING_INDEX, false); | 519 | DO_CARDINAL_FIELD (spacing, FONT_SPACING_INDEX, false); |
| 509 | DO_CARDINAL_FIELD (avgwidth, FONT_AVGWIDTH_INDEX, false); | 520 | DO_CARDINAL_FIELD (avgwidth, FONT_AVGWIDTH_INDEX, false); |
| 521 | DO_CARDINAL_FIELD (dpi, FONT_DPI_INDEX, false); | ||
| 522 | |||
| 510 | #undef DO_CARDINAL_FIELD | 523 | #undef DO_CARDINAL_FIELD |
| 511 | } | 524 | } |
| 512 | 525 | ||
| @@ -613,49 +626,98 @@ static int | |||
| 613 | androidfont_draw (struct glyph_string *s, int from, int to, | 626 | androidfont_draw (struct glyph_string *s, int from, int to, |
| 614 | int x, int y, bool with_background) | 627 | int x, int y, bool with_background) |
| 615 | { | 628 | { |
| 616 | return 0; | 629 | struct androidfont_info *info; |
| 630 | jarray chars; | ||
| 631 | int rc; | ||
| 632 | jobject gcontext, drawable; | ||
| 633 | |||
| 634 | verify (sizeof (unsigned int) == sizeof (jint)); | ||
| 635 | info = (struct androidfont_info *) s->font; | ||
| 636 | |||
| 637 | gcontext = android_resolve_handle (s->gc->gcontext, | ||
| 638 | ANDROID_HANDLE_GCONTEXT); | ||
| 639 | drawable = android_resolve_handle (FRAME_ANDROID_WINDOW (s->f), | ||
| 640 | ANDROID_HANDLE_WINDOW); | ||
| 641 | chars = (*android_java_env)->NewIntArray (android_java_env, | ||
| 642 | to - from); | ||
| 643 | |||
| 644 | if (!chars) | ||
| 645 | { | ||
| 646 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 647 | memory_full (0); | ||
| 648 | } | ||
| 649 | |||
| 650 | (*android_java_env)->SetIntArrayRegion (android_java_env, chars, | ||
| 651 | 0, to - from, | ||
| 652 | (jint *) s->char2b + from); | ||
| 653 | |||
| 654 | info = (struct androidfont_info *) s->font; | ||
| 655 | prepare_face_for_display (s->f, s->face); | ||
| 656 | |||
| 657 | rc = (*android_java_env)->CallIntMethod (android_java_env, | ||
| 658 | font_driver, | ||
| 659 | font_driver_class.draw, | ||
| 660 | info->object, | ||
| 661 | gcontext, drawable, | ||
| 662 | chars, (jint) x, (jint) y, | ||
| 663 | (jint) s->width, | ||
| 664 | (jboolean) with_background); | ||
| 665 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 666 | ANDROID_DELETE_LOCAL_REF (chars); | ||
| 667 | |||
| 668 | return rc; | ||
| 617 | } | 669 | } |
| 618 | 670 | ||
| 619 | static Lisp_Object | 671 | static Lisp_Object |
| 620 | androidfont_open_font (struct frame *f, Lisp_Object font_entity, int x) | 672 | androidfont_open_font (struct frame *f, Lisp_Object font_entity, |
| 673 | int pixel_size) | ||
| 621 | { | 674 | { |
| 622 | struct androidfont_info *font_info; | 675 | struct androidfont_info *font_info; |
| 623 | struct androidfont_entity *entity; | 676 | struct androidfont_entity *entity; |
| 624 | struct font *font; | 677 | struct font *font; |
| 625 | Lisp_Object font_object, tem; | 678 | Lisp_Object font_object; |
| 626 | jobject old; | 679 | jobject old; |
| 627 | jint value; | 680 | jint value; |
| 628 | 681 | ||
| 629 | if (x <= 0) | 682 | if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0) |
| 683 | pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)); | ||
| 684 | else if (pixel_size == 0) | ||
| 630 | { | 685 | { |
| 631 | /* Get pixel size from frame instead. */ | 686 | /* This bit was copied from xfont.c. The values might need |
| 632 | tem = get_frame_param (f, Qfontsize); | 687 | adjustment. */ |
| 633 | x = NILP (tem) ? 0 : XFIXNAT (tem); | 688 | |
| 689 | if (FRAME_FONT (f)) | ||
| 690 | pixel_size = FRAME_FONT (f)->pixel_size; | ||
| 691 | else | ||
| 692 | pixel_size = 12; | ||
| 634 | } | 693 | } |
| 635 | 694 | ||
| 636 | __android_log_print (ANDROID_LOG_DEBUG, __func__, | 695 | __android_log_print (ANDROID_LOG_DEBUG, __func__, |
| 637 | "opening font entity %"pI"x:%d", | 696 | "opening font entity %"pI"x:%d", |
| 638 | (EMACS_INT) font_entity, x); | 697 | (EMACS_INT) font_entity, pixel_size); |
| 639 | 698 | ||
| 640 | entity = (struct androidfont_entity *) XFONT_ENTITY (font_entity); | 699 | entity = (struct androidfont_entity *) XFONT_ENTITY (font_entity); |
| 641 | 700 | ||
| 642 | block_input (); | 701 | block_input (); |
| 643 | font_object = font_make_object (VECSIZE (struct androidfont_info), | 702 | font_object = font_make_object (VECSIZE (struct androidfont_info), |
| 644 | font_entity, x); | 703 | font_entity, pixel_size); |
| 645 | ASET (font_object, FONT_TYPE_INDEX, Qandroid); | 704 | ASET (font_object, FONT_TYPE_INDEX, Qandroid); |
| 646 | font_info = (struct androidfont_info *) XFONT_OBJECT (font_object); | 705 | font_info = (struct androidfont_info *) XFONT_OBJECT (font_object); |
| 647 | font = &font_info->font; | 706 | font = &font_info->font; |
| 648 | font->driver = &androidfont_driver; | 707 | font->driver = &androidfont_driver; |
| 649 | 708 | ||
| 650 | /* Clear font_info->object early in case GC happens later on! */ | 709 | /* Clear font_info->object and font_info->metrics early in case GC |
| 710 | happens later on! */ | ||
| 651 | font_info->object = NULL; | 711 | font_info->object = NULL; |
| 712 | font_info->metrics = NULL; | ||
| 652 | unblock_input (); | 713 | unblock_input (); |
| 653 | 714 | ||
| 654 | font_info->object | 715 | font_info->object |
| 655 | = (*android_java_env)->CallObjectMethod (android_java_env, | 716 | = (*android_java_env)->CallObjectMethod (android_java_env, |
| 656 | font_driver, | 717 | font_driver, |
| 657 | font_driver_class.open_font, | 718 | font_driver_class.open_font, |
| 658 | entity->object, (jint) x); | 719 | entity->object, |
| 720 | (jint) pixel_size); | ||
| 659 | if (!font_info->object) | 721 | if (!font_info->object) |
| 660 | { | 722 | { |
| 661 | (*android_java_env)->ExceptionClear (android_java_env); | 723 | (*android_java_env)->ExceptionClear (android_java_env); |
| @@ -710,9 +772,19 @@ static void | |||
| 710 | androidfont_close_font (struct font *font) | 772 | androidfont_close_font (struct font *font) |
| 711 | { | 773 | { |
| 712 | struct androidfont_info *info; | 774 | struct androidfont_info *info; |
| 775 | int i; | ||
| 713 | 776 | ||
| 714 | info = (struct androidfont_info *) font; | 777 | info = (struct androidfont_info *) font; |
| 715 | 778 | ||
| 779 | /* Free the font metrics cache if it exists. */ | ||
| 780 | |||
| 781 | if (info->metrics) | ||
| 782 | { | ||
| 783 | for (i = 0; i < 256; ++i) | ||
| 784 | xfree (info->metrics[i]); | ||
| 785 | xfree (info->metrics); | ||
| 786 | } | ||
| 787 | |||
| 716 | /* If info->object is NULL, then FONT was unsuccessfully created, | 788 | /* If info->object is NULL, then FONT was unsuccessfully created, |
| 717 | and there is no global reference that has to be deleted. */ | 789 | and there is no global reference that has to be deleted. */ |
| 718 | 790 | ||
| @@ -763,17 +835,64 @@ androidfont_encode_char (struct font *font, int c) | |||
| 763 | } | 835 | } |
| 764 | 836 | ||
| 765 | static void | 837 | static void |
| 838 | androidfont_cache_text_extents (struct androidfont_info *info, | ||
| 839 | unsigned int glyph, | ||
| 840 | struct font_metrics *metrics) | ||
| 841 | { | ||
| 842 | int i; | ||
| 843 | |||
| 844 | /* Glyphs larger than 65535 can't be cached. */ | ||
| 845 | if (glyph >= 256 * 256) | ||
| 846 | return; | ||
| 847 | |||
| 848 | if (!info->metrics) | ||
| 849 | info->metrics = xzalloc (256 * sizeof *info->metrics); | ||
| 850 | |||
| 851 | if (!info->metrics[glyph / 256]) | ||
| 852 | { | ||
| 853 | info->metrics[glyph / 256] | ||
| 854 | = xnmalloc (256, sizeof **info->metrics); | ||
| 855 | |||
| 856 | /* Now, all the metrics in that array as invalid by setting | ||
| 857 | lbearing to SHRT_MAX. */ | ||
| 858 | for (i = 0; i < 256; ++i) | ||
| 859 | info->metrics[glyph / 256][i].lbearing = SHRT_MAX; | ||
| 860 | } | ||
| 861 | |||
| 862 | /* Finally, cache the glyph. */ | ||
| 863 | info->metrics[glyph / 256][glyph % 256] = *metrics; | ||
| 864 | } | ||
| 865 | |||
| 866 | static bool | ||
| 867 | androidfont_check_cached_extents (struct androidfont_info *info, | ||
| 868 | unsigned int glyph, | ||
| 869 | struct font_metrics *metrics) | ||
| 870 | { | ||
| 871 | if (info->metrics && info->metrics[glyph / 256] | ||
| 872 | && info->metrics[glyph / 256][glyph % 256].lbearing != SHRT_MAX) | ||
| 873 | { | ||
| 874 | *metrics = info->metrics[glyph / 256][glyph % 256]; | ||
| 875 | return true; | ||
| 876 | } | ||
| 877 | |||
| 878 | return false; | ||
| 879 | } | ||
| 880 | |||
| 881 | static void | ||
| 766 | androidfont_text_extents (struct font *font, const unsigned int *code, | 882 | androidfont_text_extents (struct font *font, const unsigned int *code, |
| 767 | int nglyphs, struct font_metrics *metrics) | 883 | int nglyphs, struct font_metrics *metrics) |
| 768 | { | 884 | { |
| 769 | struct androidfont_info *info; | 885 | struct androidfont_info *info; |
| 770 | jarray codepoint_array, metrics_array; | 886 | jarray codepoint_array; |
| 771 | jobject metrics_object; | 887 | jobject metrics_object; |
| 772 | int i; | ||
| 773 | short value; | 888 | short value; |
| 774 | 889 | ||
| 775 | info = (struct androidfont_info *) font; | 890 | info = (struct androidfont_info *) font; |
| 776 | 891 | ||
| 892 | if (nglyphs == 1 | ||
| 893 | && androidfont_check_cached_extents (info, *code, metrics)) | ||
| 894 | return; | ||
| 895 | |||
| 777 | /* Allocate the arrays of code points and font metrics. */ | 896 | /* Allocate the arrays of code points and font metrics. */ |
| 778 | codepoint_array | 897 | codepoint_array |
| 779 | = (*android_java_env)->NewIntArray (android_java_env, | 898 | = (*android_java_env)->NewIntArray (android_java_env, |
| @@ -784,92 +903,103 @@ androidfont_text_extents (struct font *font, const unsigned int *code, | |||
| 784 | memory_full (0); | 903 | memory_full (0); |
| 785 | } | 904 | } |
| 786 | 905 | ||
| 787 | metrics_array | 906 | verify (sizeof (unsigned int) == sizeof (jint)); |
| 788 | = (*android_java_env)->NewObjectArray (android_java_env, | ||
| 789 | nglyphs, | ||
| 790 | font_metrics_class.class, | ||
| 791 | NULL); | ||
| 792 | if (!metrics_array) | ||
| 793 | { | ||
| 794 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 795 | ANDROID_DELETE_LOCAL_REF (metrics_array); | ||
| 796 | memory_full (0); | ||
| 797 | } | ||
| 798 | |||
| 799 | if (sizeof (unsigned int) == sizeof (jint)) | ||
| 800 | /* Always true on every Android device. */ | ||
| 801 | (*android_java_env)->SetIntArrayRegion (android_java_env, | ||
| 802 | codepoint_array, | ||
| 803 | 0, nglyphs, | ||
| 804 | (jint *) code); | ||
| 805 | else | ||
| 806 | emacs_abort (); | ||
| 807 | |||
| 808 | for (i = 0; i < nglyphs; ++i) | ||
| 809 | { | ||
| 810 | metrics_object | ||
| 811 | = (*android_java_env)->AllocObject (android_java_env, | ||
| 812 | font_metrics_class.class); | ||
| 813 | 907 | ||
| 814 | if (!metrics_object) | 908 | /* Always true on every Android device. */ |
| 815 | { | 909 | (*android_java_env)->SetIntArrayRegion (android_java_env, |
| 816 | (*android_java_env)->ExceptionClear (android_java_env); | 910 | codepoint_array, |
| 817 | ANDROID_DELETE_LOCAL_REF (metrics_array); | 911 | 0, nglyphs, |
| 818 | ANDROID_DELETE_LOCAL_REF (codepoint_array); | 912 | (jint *) code); |
| 819 | memory_full (0); | ||
| 820 | } | ||
| 821 | 913 | ||
| 822 | (*android_java_env)->SetObjectArrayElement (android_java_env, | 914 | metrics_object |
| 823 | metrics_array, i, | 915 | = (*android_java_env)->AllocObject (android_java_env, |
| 824 | metrics_object); | 916 | font_metrics_class.class); |
| 825 | ANDROID_DELETE_LOCAL_REF (metrics_object); | ||
| 826 | } | ||
| 827 | 917 | ||
| 828 | (*android_java_env)->CallVoidMethod (android_java_env, | 918 | (*android_java_env)->CallVoidMethod (android_java_env, |
| 829 | font_driver, | 919 | font_driver, |
| 830 | font_driver_class.text_extents, | 920 | font_driver_class.text_extents, |
| 831 | info->object, codepoint_array, | 921 | info->object, codepoint_array, |
| 832 | metrics_array); | 922 | metrics_object); |
| 833 | 923 | ||
| 834 | if ((*android_java_env)->ExceptionCheck (android_java_env)) | 924 | if ((*android_java_env)->ExceptionCheck (android_java_env)) |
| 835 | { | 925 | { |
| 836 | (*android_java_env)->ExceptionClear (android_java_env); | 926 | (*android_java_env)->ExceptionClear (android_java_env); |
| 837 | ANDROID_DELETE_LOCAL_REF (metrics_array); | 927 | ANDROID_DELETE_LOCAL_REF (metrics_object); |
| 838 | ANDROID_DELETE_LOCAL_REF (codepoint_array); | 928 | ANDROID_DELETE_LOCAL_REF (codepoint_array); |
| 839 | memory_full (0); | 929 | memory_full (0); |
| 840 | } | 930 | } |
| 841 | 931 | ||
| 842 | for (i = 0; i < nglyphs; ++i) | ||
| 843 | { | ||
| 844 | metrics_object | ||
| 845 | = (*android_java_env)->GetObjectArrayElement (android_java_env, | ||
| 846 | metrics_array, i); | ||
| 847 | #define DO_CARDINAL_FIELD(field) \ | 932 | #define DO_CARDINAL_FIELD(field) \ |
| 848 | value \ | 933 | value \ |
| 849 | = (*android_java_env)->GetShortField (android_java_env, \ | 934 | = (*android_java_env)->GetShortField (android_java_env, \ |
| 850 | metrics_object, \ | 935 | metrics_object, \ |
| 851 | font_metrics_class.field); \ | 936 | font_metrics_class.field); \ |
| 852 | metrics[i].field = value; | 937 | metrics->field = value; |
| 853 | 938 | ||
| 854 | DO_CARDINAL_FIELD (lbearing); | 939 | DO_CARDINAL_FIELD (lbearing); |
| 855 | DO_CARDINAL_FIELD (rbearing); | 940 | DO_CARDINAL_FIELD (rbearing); |
| 856 | DO_CARDINAL_FIELD (width); | 941 | DO_CARDINAL_FIELD (width); |
| 857 | DO_CARDINAL_FIELD (ascent); | 942 | DO_CARDINAL_FIELD (ascent); |
| 858 | DO_CARDINAL_FIELD (descent); | 943 | DO_CARDINAL_FIELD (descent); |
| 859 | 944 | ||
| 860 | #undef DO_CARDINAL_FIELD | 945 | #undef DO_CARDINAL_FIELD |
| 861 | 946 | ||
| 862 | ANDROID_DELETE_LOCAL_REF (metrics_object); | 947 | ANDROID_DELETE_LOCAL_REF (metrics_object); |
| 863 | } | ||
| 864 | |||
| 865 | ANDROID_DELETE_LOCAL_REF (metrics_array); | ||
| 866 | ANDROID_DELETE_LOCAL_REF (codepoint_array); | 948 | ANDROID_DELETE_LOCAL_REF (codepoint_array); |
| 949 | |||
| 950 | /* Emacs spends a lot of time in androidfont_text_extents, which | ||
| 951 | makes calling JNI too slow. Cache the metrics for this single | ||
| 952 | glyph. */ | ||
| 953 | |||
| 954 | if (nglyphs == 1) | ||
| 955 | androidfont_cache_text_extents (info, *code, metrics); | ||
| 867 | } | 956 | } |
| 868 | 957 | ||
| 869 | static Lisp_Object | 958 | static Lisp_Object |
| 870 | androidfont_list_family (struct frame *f) | 959 | androidfont_list_family (struct frame *f) |
| 871 | { | 960 | { |
| 872 | return Qnil; | 961 | Lisp_Object families; |
| 962 | jarray family_array; | ||
| 963 | jobject string; | ||
| 964 | jsize i, length; | ||
| 965 | const char *family; | ||
| 966 | |||
| 967 | family_array | ||
| 968 | = (*android_java_env)->CallObjectMethod (android_java_env, | ||
| 969 | font_driver, | ||
| 970 | font_driver_class.list_families); | ||
| 971 | if (!family_array) | ||
| 972 | { | ||
| 973 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 974 | memory_full (0); | ||
| 975 | } | ||
| 976 | |||
| 977 | length = (*android_java_env)->GetArrayLength (android_java_env, | ||
| 978 | family_array); | ||
| 979 | families = Qnil; | ||
| 980 | |||
| 981 | for (i = 0; i < length; ++i) | ||
| 982 | { | ||
| 983 | string = (*android_java_env)->GetObjectArrayElement (android_java_env, | ||
| 984 | family_array, i); | ||
| 985 | family = (*android_java_env)->GetStringUTFChars (android_java_env, | ||
| 986 | (jstring) string, NULL); | ||
| 987 | |||
| 988 | if (!family) | ||
| 989 | { | ||
| 990 | ANDROID_DELETE_LOCAL_REF (string); | ||
| 991 | ANDROID_DELETE_LOCAL_REF (family_array); | ||
| 992 | } | ||
| 993 | |||
| 994 | families = Fcons (build_string_from_utf8 (string), families); | ||
| 995 | (*android_java_env)->ReleaseStringUTFChars (android_java_env, | ||
| 996 | (jstring) string, | ||
| 997 | family); | ||
| 998 | ANDROID_DELETE_LOCAL_REF (string); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | ANDROID_DELETE_LOCAL_REF (family_array); | ||
| 1002 | return Fnreverse (families); | ||
| 873 | } | 1003 | } |
| 874 | 1004 | ||
| 875 | struct font_driver androidfont_driver = | 1005 | struct font_driver androidfont_driver = |
diff --git a/src/androidgui.h b/src/androidgui.h index 43ccc86e5c7..b0ea820cfdf 100644 --- a/src/androidgui.h +++ b/src/androidgui.h | |||
| @@ -201,6 +201,9 @@ enum android_event_type | |||
| 201 | ANDROID_KEY_PRESS, | 201 | ANDROID_KEY_PRESS, |
| 202 | ANDROID_KEY_RELEASE, | 202 | ANDROID_KEY_RELEASE, |
| 203 | ANDROID_CONFIGURE_NOTIFY, | 203 | ANDROID_CONFIGURE_NOTIFY, |
| 204 | ANDROID_FOCUS_IN, | ||
| 205 | ANDROID_FOCUS_OUT, | ||
| 206 | ANDROID_WINDOW_ACTION, | ||
| 204 | }; | 207 | }; |
| 205 | 208 | ||
| 206 | struct android_any_event | 209 | struct android_any_event |
| @@ -209,6 +212,13 @@ struct android_any_event | |||
| 209 | android_window window; | 212 | android_window window; |
| 210 | }; | 213 | }; |
| 211 | 214 | ||
| 215 | enum android_modifier_mask | ||
| 216 | { | ||
| 217 | ANDROID_SHIFT_MASK = 193, | ||
| 218 | ANDROID_CONTROL_MASK = 4096, | ||
| 219 | ANDROID_ALT_MASK = 2, | ||
| 220 | }; | ||
| 221 | |||
| 212 | struct android_key_event | 222 | struct android_key_event |
| 213 | { | 223 | { |
| 214 | enum android_event_type type; | 224 | enum android_event_type type; |
| @@ -216,8 +226,18 @@ struct android_key_event | |||
| 216 | android_time time; | 226 | android_time time; |
| 217 | unsigned int state; | 227 | unsigned int state; |
| 218 | unsigned int keycode; | 228 | unsigned int keycode; |
| 229 | unsigned int unicode_char; | ||
| 219 | }; | 230 | }; |
| 220 | 231 | ||
| 232 | /* These hard coded values are Android modifier keycodes derived | ||
| 233 | through experimentation. */ | ||
| 234 | |||
| 235 | #define ANDROID_IS_MODIFIER_KEY(key) \ | ||
| 236 | ((key) == 57 || (key) == 58 || (key) == 113 || (key) == 114 \ | ||
| 237 | || (key) == 119 || (key) == 117 || (key) == 118 || (key) == 78 \ | ||
| 238 | || (key) == 94 || (key) == 59 || (key) == 60 || (key) == 95 \ | ||
| 239 | || (key) == 63) | ||
| 240 | |||
| 221 | struct android_configure_event | 241 | struct android_configure_event |
| 222 | { | 242 | { |
| 223 | enum android_event_type type; | 243 | enum android_event_type type; |
| @@ -227,12 +247,35 @@ struct android_configure_event | |||
| 227 | int width, height; | 247 | int width, height; |
| 228 | }; | 248 | }; |
| 229 | 249 | ||
| 250 | struct android_focus_event | ||
| 251 | { | ||
| 252 | enum android_event_type type; | ||
| 253 | android_window window; | ||
| 254 | android_time time; | ||
| 255 | }; | ||
| 256 | |||
| 257 | struct android_window_action_event | ||
| 258 | { | ||
| 259 | enum android_event_type type; | ||
| 260 | |||
| 261 | /* The window handle. This can be ANDROID_NONE. */ | ||
| 262 | android_window window; | ||
| 263 | |||
| 264 | /* Numerical identifier for this action. If 0 and WINDOW is set, | ||
| 265 | then it means the frame associated with that window has been | ||
| 266 | destroyed. Otherwise, it means Emacs should create a new | ||
| 267 | frame. */ | ||
| 268 | unsigned int action; | ||
| 269 | }; | ||
| 270 | |||
| 230 | union android_event | 271 | union android_event |
| 231 | { | 272 | { |
| 232 | enum android_event_type type; | 273 | enum android_event_type type; |
| 233 | struct android_any_event xany; | 274 | struct android_any_event xany; |
| 234 | struct android_key_event xkey; | 275 | struct android_key_event xkey; |
| 235 | struct android_configure_event xconfigure; | 276 | struct android_configure_event xconfigure; |
| 277 | struct android_focus_event xfocus; | ||
| 278 | struct android_window_action_event xaction; | ||
| 236 | }; | 279 | }; |
| 237 | 280 | ||
| 238 | extern int android_pending (void); | 281 | extern int android_pending (void); |
| @@ -303,9 +346,47 @@ extern android_pixmap android_create_pixmap (unsigned int, unsigned int, | |||
| 303 | extern void android_set_ts_origin (struct android_gc *, int, int); | 346 | extern void android_set_ts_origin (struct android_gc *, int, int); |
| 304 | extern void android_clear_area (android_window, int, int, unsigned int, | 347 | extern void android_clear_area (android_window, int, int, unsigned int, |
| 305 | unsigned int); | 348 | unsigned int); |
| 349 | extern android_pixmap android_create_bitmap_from_data (char *, unsigned int, | ||
| 350 | unsigned int); | ||
| 306 | 351 | ||
| 307 | #endif | 352 | #endif |
| 308 | 353 | ||
| 354 | |||
| 355 | |||
| 356 | /* Image support. Keep the API as similar to XImage as possible. To | ||
| 357 | avoid leaving a huge mess of "#ifndef ANDROID_STUBIFY" in image.c, | ||
| 358 | stubs should be defined for all functions. */ | ||
| 359 | |||
| 360 | enum android_image_format | ||
| 361 | { | ||
| 362 | ANDROID_Z_PIXMAP, | ||
| 363 | }; | ||
| 364 | |||
| 365 | struct android_image | ||
| 366 | { | ||
| 367 | int width, height; | ||
| 368 | enum android_image_format format; | ||
| 369 | char *data; | ||
| 370 | int depth; | ||
| 371 | int bytes_per_line; | ||
| 372 | int bits_per_pixel; | ||
| 373 | }; | ||
| 374 | |||
| 375 | extern struct android_image *android_create_image (unsigned int, | ||
| 376 | enum android_image_format, | ||
| 377 | char *, unsigned int, | ||
| 378 | unsigned int); | ||
| 379 | extern void android_destroy_image (struct android_image *); | ||
| 380 | |||
| 381 | extern void android_put_pixel (struct android_image *, int, int, | ||
| 382 | unsigned long); | ||
| 383 | extern unsigned long android_get_pixel (struct android_image *, int, int); | ||
| 384 | extern struct android_image *android_get_image (android_drawable, | ||
| 385 | enum android_image_format); | ||
| 386 | extern void android_put_image (android_pixmap, struct android_image *); | ||
| 387 | |||
| 388 | |||
| 389 | |||
| 309 | /* X emulation stuff also needed while building stubs. */ | 390 | /* X emulation stuff also needed while building stubs. */ |
| 310 | 391 | ||
| 311 | extern struct android_gc *android_create_gc (enum android_gc_value_mask, | 392 | extern struct android_gc *android_create_gc (enum android_gc_value_mask, |
diff --git a/src/androidterm.c b/src/androidterm.c index bb3c2a29737..0279da4f58d 100644 --- a/src/androidterm.c +++ b/src/androidterm.c | |||
| @@ -39,6 +39,8 @@ struct android_display_info *x_display_list; | |||
| 39 | 39 | ||
| 40 | #ifndef ANDROID_STUBIFY | 40 | #ifndef ANDROID_STUBIFY |
| 41 | 41 | ||
| 42 | #include <android/log.h> | ||
| 43 | |||
| 42 | enum | 44 | enum |
| 43 | { | 45 | { |
| 44 | ANDROID_EVENT_NORMAL, | 46 | ANDROID_EVENT_NORMAL, |
| @@ -141,6 +143,124 @@ android_flush_dirty_back_buffer_on (struct frame *f) | |||
| 141 | show_back_buffer (f); | 143 | show_back_buffer (f); |
| 142 | } | 144 | } |
| 143 | 145 | ||
| 146 | /* Convert between the modifier bits Android uses and the modifier | ||
| 147 | bits Emacs uses. */ | ||
| 148 | |||
| 149 | static int | ||
| 150 | android_android_to_emacs_modifiers (struct android_display_info *dpyinfo, | ||
| 151 | int state) | ||
| 152 | { | ||
| 153 | return ((state & ANDROID_CONTROL_MASK) ? ctrl_modifier : 0 | ||
| 154 | | (state & ANDROID_SHIFT_MASK) ? shift_modifier : 0 | ||
| 155 | | (state & ANDROID_ALT_MASK) ? meta_modifier : 0); | ||
| 156 | } | ||
| 157 | |||
| 158 | static int | ||
| 159 | android_emacs_to_android_modifiers (struct android_display_info *dpyinfo, | ||
| 160 | intmax_t state) | ||
| 161 | { | ||
| 162 | return ((state & ctrl_modifier) ? ANDROID_CONTROL_MASK : 0 | ||
| 163 | | (state & shift_modifier) ? ANDROID_SHIFT_MASK : 0 | ||
| 164 | | (state & meta_modifier) ? ANDROID_ALT_MASK : 0); | ||
| 165 | } | ||
| 166 | |||
| 167 | static void android_frame_rehighlight (struct android_display_info *); | ||
| 168 | |||
| 169 | static void | ||
| 170 | android_lower_frame (struct frame *f) | ||
| 171 | { | ||
| 172 | /* TODO. */ | ||
| 173 | } | ||
| 174 | |||
| 175 | static void | ||
| 176 | android_raise_frame (struct frame *f) | ||
| 177 | { | ||
| 178 | /* TODO. */ | ||
| 179 | } | ||
| 180 | |||
| 181 | static void | ||
| 182 | android_new_focus_frame (struct android_display_info *dpyinfo, | ||
| 183 | struct frame *frame) | ||
| 184 | { | ||
| 185 | struct frame *old_focus; | ||
| 186 | |||
| 187 | old_focus = dpyinfo->focus_frame; | ||
| 188 | |||
| 189 | if (frame != dpyinfo->focus_frame) | ||
| 190 | { | ||
| 191 | /* Set this before calling other routines, so that they see | ||
| 192 | the correct value of x_focus_frame. */ | ||
| 193 | dpyinfo->focus_frame = frame; | ||
| 194 | |||
| 195 | if (old_focus && old_focus->auto_lower) | ||
| 196 | android_lower_frame (old_focus); | ||
| 197 | |||
| 198 | if (dpyinfo->focus_frame && dpyinfo->focus_frame->auto_raise) | ||
| 199 | dpyinfo->pending_autoraise_frame = dpyinfo->focus_frame; | ||
| 200 | else | ||
| 201 | dpyinfo->pending_autoraise_frame = NULL; | ||
| 202 | } | ||
| 203 | |||
| 204 | android_frame_rehighlight (dpyinfo); | ||
| 205 | } | ||
| 206 | |||
| 207 | static void | ||
| 208 | android_focus_changed (int type, int state, | ||
| 209 | struct android_display_info *dpyinfo, | ||
| 210 | struct frame *frame, struct input_event *bufp) | ||
| 211 | { | ||
| 212 | if (type == ANDROID_FOCUS_IN) | ||
| 213 | { | ||
| 214 | if (dpyinfo->x_focus_event_frame != frame) | ||
| 215 | { | ||
| 216 | android_new_focus_frame (dpyinfo, frame); | ||
| 217 | dpyinfo->x_focus_event_frame = frame; | ||
| 218 | bufp->kind = FOCUS_IN_EVENT; | ||
| 219 | XSETFRAME (bufp->frame_or_window, frame); | ||
| 220 | } | ||
| 221 | |||
| 222 | frame->output_data.android->focus_state |= state; | ||
| 223 | } | ||
| 224 | else if (type == ANDROID_FOCUS_OUT) | ||
| 225 | { | ||
| 226 | frame->output_data.android->focus_state &= ~state; | ||
| 227 | |||
| 228 | if (dpyinfo->x_focus_event_frame == frame) | ||
| 229 | { | ||
| 230 | dpyinfo->x_focus_event_frame = 0; | ||
| 231 | android_new_focus_frame (dpyinfo, 0); | ||
| 232 | |||
| 233 | bufp->kind = FOCUS_OUT_EVENT; | ||
| 234 | XSETFRAME (bufp->frame_or_window, frame); | ||
| 235 | } | ||
| 236 | |||
| 237 | if (frame->pointer_invisible) | ||
| 238 | android_toggle_invisible_pointer (frame, false); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | static void | ||
| 243 | android_detect_focus_change (struct android_display_info *dpyinfo, | ||
| 244 | struct frame *frame, | ||
| 245 | union android_event *event, | ||
| 246 | struct input_event *bufp) | ||
| 247 | { | ||
| 248 | if (!frame) | ||
| 249 | return; | ||
| 250 | |||
| 251 | switch (event->type) | ||
| 252 | { | ||
| 253 | case ANDROID_FOCUS_IN: | ||
| 254 | case ANDROID_FOCUS_OUT: | ||
| 255 | android_focus_changed (event->type, FOCUS_EXPLICIT, | ||
| 256 | dpyinfo, frame, bufp); | ||
| 257 | break; | ||
| 258 | |||
| 259 | default: | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 144 | static int | 264 | static int |
| 145 | handle_one_android_event (struct android_display_info *dpyinfo, | 265 | handle_one_android_event (struct android_display_info *dpyinfo, |
| 146 | union android_event *event, int *finish, | 266 | union android_event *event, int *finish, |
| @@ -149,11 +269,20 @@ handle_one_android_event (struct android_display_info *dpyinfo, | |||
| 149 | union android_event configureEvent; | 269 | union android_event configureEvent; |
| 150 | struct frame *f, *any, *mouse_frame; | 270 | struct frame *f, *any, *mouse_frame; |
| 151 | Mouse_HLInfo *hlinfo; | 271 | Mouse_HLInfo *hlinfo; |
| 272 | union buffered_input_event inev; | ||
| 273 | int modifiers, count; | ||
| 274 | |||
| 275 | /* It is okay for this to not resemble handle_one_xevent so much. | ||
| 276 | Differences in event handling code are much less nasty than | ||
| 277 | stuble differences in the graphics code. */ | ||
| 152 | 278 | ||
| 279 | count = 0; | ||
| 153 | hlinfo = &dpyinfo->mouse_highlight; | 280 | hlinfo = &dpyinfo->mouse_highlight; |
| 154 | *finish = ANDROID_EVENT_NORMAL; | 281 | *finish = ANDROID_EVENT_NORMAL; |
| 155 | any = android_window_to_frame (dpyinfo, event->xany.window); | 282 | any = android_window_to_frame (dpyinfo, event->xany.window); |
| 156 | 283 | ||
| 284 | EVENT_INIT (inev.ie); | ||
| 285 | |||
| 157 | switch (event->type) | 286 | switch (event->type) |
| 158 | { | 287 | { |
| 159 | case ANDROID_CONFIGURE_NOTIFY: | 288 | case ANDROID_CONFIGURE_NOTIFY: |
| @@ -192,12 +321,15 @@ handle_one_android_event (struct android_display_info *dpyinfo, | |||
| 192 | 321 | ||
| 193 | case ANDROID_KEY_PRESS: | 322 | case ANDROID_KEY_PRESS: |
| 194 | 323 | ||
| 324 | /* Set f to any. There are no ``outer windows'' on Android. */ | ||
| 325 | f = any; | ||
| 326 | |||
| 195 | /* If mouse-highlight is an integer, input clears out | 327 | /* If mouse-highlight is an integer, input clears out |
| 196 | mouse highlighting. */ | 328 | mouse highlighting. */ |
| 197 | if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight) | 329 | if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight) |
| 198 | && (any == 0 | 330 | && (any == 0 |
| 199 | || !EQ (f->tool_bar_window, hlinfo->mouse_face_window) | 331 | || !EQ (any->tool_bar_window, hlinfo->mouse_face_window) |
| 200 | || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))) | 332 | || !EQ (any->tab_bar_window, hlinfo->mouse_face_window))) |
| 201 | { | 333 | { |
| 202 | mouse_frame = hlinfo->mouse_face_mouse_frame; | 334 | mouse_frame = hlinfo->mouse_face_mouse_frame; |
| 203 | 335 | ||
| @@ -208,13 +340,90 @@ handle_one_android_event (struct android_display_info *dpyinfo, | |||
| 208 | android_flush_dirty_back_buffer_on (mouse_frame); | 340 | android_flush_dirty_back_buffer_on (mouse_frame); |
| 209 | } | 341 | } |
| 210 | 342 | ||
| 343 | event->xkey.state | ||
| 344 | |= android_emacs_to_android_modifiers (dpyinfo, | ||
| 345 | extra_keyboard_modifiers); | ||
| 346 | modifiers = event->xkey.state; | ||
| 347 | |||
| 348 | /* Common for all keysym input events. */ | ||
| 349 | XSETFRAME (inev.ie.frame_or_window, any); | ||
| 350 | inev.ie.modifiers | ||
| 351 | = android_android_to_emacs_modifiers (dpyinfo, modifiers); | ||
| 352 | inev.ie.timestamp = event->xkey.time; | ||
| 353 | |||
| 354 | /* First deal with keysyms which have defined translations to | ||
| 355 | characters. */ | ||
| 356 | |||
| 357 | if (event->xkey.unicode_char >= 32 | ||
| 358 | && event->xkey.unicode_char < 128) | ||
| 359 | { | ||
| 360 | inev.ie.kind = ASCII_KEYSTROKE_EVENT; | ||
| 361 | inev.ie.code = event->xkey.unicode_char; | ||
| 362 | } | ||
| 363 | else if (event->xkey.unicode_char < 32) | ||
| 364 | { | ||
| 365 | /* If the key is a modifier key, just return. */ | ||
| 366 | if (ANDROID_IS_MODIFIER_KEY (event->xkey.keycode)) | ||
| 367 | goto done_keysym; | ||
| 368 | |||
| 369 | /* Next, deal with special ``characters'' by giving the | ||
| 370 | keycode to keyboard.c. */ | ||
| 371 | inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT; | ||
| 372 | inev.ie.code = event->xkey.keycode; | ||
| 373 | } | ||
| 374 | else | ||
| 375 | { | ||
| 376 | /* Finally, deal with Unicode characters. */ | ||
| 377 | inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; | ||
| 378 | inev.ie.code = event->xkey.unicode_char; | ||
| 379 | } | ||
| 380 | |||
| 381 | goto done_keysym; | ||
| 382 | |||
| 383 | done_keysym: | ||
| 384 | goto OTHER; | ||
| 385 | |||
| 386 | case ANDROID_FOCUS_IN: | ||
| 387 | case ANDROID_FOCUS_OUT: | ||
| 388 | android_detect_focus_change (dpyinfo, any, event, &inev.ie); | ||
| 389 | goto OTHER; | ||
| 390 | |||
| 391 | case ANDROID_WINDOW_ACTION: | ||
| 392 | |||
| 393 | f = any; | ||
| 394 | |||
| 395 | if (event->xaction.action == 0) | ||
| 396 | { | ||
| 397 | /* Action 0 either means to destroy a frame or to create a | ||
| 398 | new frame, depending on whether or not | ||
| 399 | event->xaction.window exists. */ | ||
| 400 | |||
| 401 | if (event->xaction.window) | ||
| 402 | { | ||
| 403 | if (!f) | ||
| 404 | goto OTHER; | ||
| 405 | |||
| 406 | inev.ie.kind = DELETE_WINDOW_EVENT; | ||
| 407 | XSETFRAME (inev.ie.frame_or_window, f); | ||
| 408 | } | ||
| 409 | else | ||
| 410 | /* A new frame must be created. */; | ||
| 411 | } | ||
| 412 | |||
| 413 | goto OTHER; | ||
| 414 | |||
| 211 | default: | 415 | default: |
| 212 | goto OTHER; | 416 | goto OTHER; |
| 213 | } | 417 | } |
| 214 | 418 | ||
| 215 | OTHER: | 419 | OTHER: |
| 420 | if (inev.ie.kind != NO_EVENT) | ||
| 421 | { | ||
| 422 | kbd_buffer_store_buffered_event (&inev, hold_quit); | ||
| 423 | count++; | ||
| 424 | } | ||
| 216 | 425 | ||
| 217 | return 0; | 426 | return count; |
| 218 | } | 427 | } |
| 219 | 428 | ||
| 220 | static int | 429 | static int |
| @@ -378,15 +587,52 @@ android_focus_frame (struct frame *f, bool noactivate) | |||
| 378 | } | 587 | } |
| 379 | 588 | ||
| 380 | static void | 589 | static void |
| 381 | android_frame_rehighlight (struct frame *f) | 590 | android_frame_rehighlight (struct android_display_info *dpyinfo) |
| 382 | { | 591 | { |
| 383 | /* TODO */ | 592 | struct frame *old_highlight; |
| 593 | |||
| 594 | old_highlight = dpyinfo->highlight_frame; | ||
| 595 | |||
| 596 | if (dpyinfo->focus_frame) | ||
| 597 | { | ||
| 598 | dpyinfo->highlight_frame | ||
| 599 | = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->focus_frame))) | ||
| 600 | ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->focus_frame)) | ||
| 601 | : dpyinfo->focus_frame); | ||
| 602 | if (!FRAME_LIVE_P (dpyinfo->highlight_frame)) | ||
| 603 | { | ||
| 604 | fset_focus_frame (dpyinfo->focus_frame, Qnil); | ||
| 605 | dpyinfo->highlight_frame = dpyinfo->focus_frame; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | else | ||
| 609 | dpyinfo->highlight_frame = 0; | ||
| 610 | |||
| 611 | if (dpyinfo->highlight_frame != old_highlight) | ||
| 612 | { | ||
| 613 | /* This is not yet required on Android. */ | ||
| 614 | #if 0 | ||
| 615 | if (old_highlight) | ||
| 616 | android_frame_unhighlight (old_highlight); | ||
| 617 | if (dpyinfo->highlight_frame) | ||
| 618 | android_frame_highlight (dpyinfo->highlight_frame); | ||
| 619 | #endif | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | static void | ||
| 624 | android_frame_rehighlight_hook (struct frame *f) | ||
| 625 | { | ||
| 626 | android_frame_rehighlight (FRAME_DISPLAY_INFO (f)); | ||
| 384 | } | 627 | } |
| 385 | 628 | ||
| 386 | static void | 629 | static void |
| 387 | android_frame_raise_lower (struct frame *f, bool raise_flag) | 630 | android_frame_raise_lower (struct frame *f, bool raise_flag) |
| 388 | { | 631 | { |
| 389 | /* TODO */ | 632 | if (raise_flag) |
| 633 | android_raise_frame (f); | ||
| 634 | else | ||
| 635 | android_lower_frame (f); | ||
| 390 | } | 636 | } |
| 391 | 637 | ||
| 392 | void | 638 | void |
| @@ -401,6 +647,10 @@ android_make_frame_visible (struct frame *f) | |||
| 401 | void | 647 | void |
| 402 | android_make_frame_invisible (struct frame *f) | 648 | android_make_frame_invisible (struct frame *f) |
| 403 | { | 649 | { |
| 650 | /* Don't keep the highlight on an invisible frame. */ | ||
| 651 | if (FRAME_DISPLAY_INFO (f)->highlight_frame == f) | ||
| 652 | FRAME_DISPLAY_INFO (f)->highlight_frame = 0; | ||
| 653 | |||
| 404 | android_unmap_window (FRAME_ANDROID_WINDOW (f)); | 654 | android_unmap_window (FRAME_ANDROID_WINDOW (f)); |
| 405 | 655 | ||
| 406 | SET_FRAME_VISIBLE (f, false); | 656 | SET_FRAME_VISIBLE (f, false); |
| @@ -584,6 +834,8 @@ android_free_frame_resources (struct frame *f) | |||
| 584 | 834 | ||
| 585 | if (f == dpyinfo->focus_frame) | 835 | if (f == dpyinfo->focus_frame) |
| 586 | dpyinfo->focus_frame = 0; | 836 | dpyinfo->focus_frame = 0; |
| 837 | if (f == dpyinfo->x_focus_event_frame) | ||
| 838 | dpyinfo->x_focus_event_frame = 0; | ||
| 587 | if (f == dpyinfo->highlight_frame) | 839 | if (f == dpyinfo->highlight_frame) |
| 588 | dpyinfo->highlight_frame = 0; | 840 | dpyinfo->highlight_frame = 0; |
| 589 | if (f == hlinfo->mouse_face_mouse_frame) | 841 | if (f == hlinfo->mouse_face_mouse_frame) |
| @@ -783,7 +1035,7 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 783 | if (p->overlay_p) | 1035 | if (p->overlay_p) |
| 784 | { | 1036 | { |
| 785 | clipmask = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h, | 1037 | clipmask = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h, |
| 786 | 1, 0, 0); | 1038 | 1, 0, 1); |
| 787 | 1039 | ||
| 788 | gcv.clip_mask = clipmask; | 1040 | gcv.clip_mask = clipmask; |
| 789 | gcv.clip_x_origin = p->x; | 1041 | gcv.clip_x_origin = p->x; |
| @@ -1606,158 +1858,47 @@ android_draw_image_foreground (struct glyph_string *s) | |||
| 1606 | 1858 | ||
| 1607 | if (s->img->pixmap) | 1859 | if (s->img->pixmap) |
| 1608 | { | 1860 | { |
| 1609 | if (s->img->mask) | 1861 | unsigned long mask = (ANDROID_GC_CLIP_MASK |
| 1610 | { | 1862 | | ANDROID_GC_CLIP_X_ORIGIN |
| 1611 | unsigned long mask = (ANDROID_GC_CLIP_MASK | 1863 | | ANDROID_GC_CLIP_Y_ORIGIN |
| 1612 | | ANDROID_GC_CLIP_X_ORIGIN | 1864 | | ANDROID_GC_FUNCTION); |
| 1613 | | ANDROID_GC_CLIP_Y_ORIGIN | 1865 | struct android_gc_values xgcv; |
| 1614 | | ANDROID_GC_FUNCTION); | 1866 | struct android_rectangle clip_rect, image_rect, r; |
| 1615 | struct android_gc_values xgcv; | 1867 | |
| 1616 | struct android_rectangle clip_rect, image_rect, r; | 1868 | xgcv.clip_mask = s->img->mask; |
| 1617 | 1869 | xgcv.clip_x_origin = x - s->slice.x; | |
| 1618 | xgcv.clip_mask = s->img->mask; | 1870 | xgcv.clip_y_origin = y - s->slice.y; |
| 1619 | xgcv.clip_x_origin = x - s->slice.x; | 1871 | xgcv.function = ANDROID_GC_COPY; |
| 1620 | xgcv.clip_y_origin = y - s->slice.y; | 1872 | android_change_gc (s->gc, mask, &xgcv); |
| 1621 | xgcv.function = ANDROID_GC_COPY; | 1873 | |
| 1622 | android_change_gc (s->gc, mask, &xgcv); | 1874 | get_glyph_string_clip_rect (s, &clip_rect); |
| 1623 | 1875 | image_rect.x = x; | |
| 1624 | get_glyph_string_clip_rect (s, &clip_rect); | 1876 | image_rect.y = y; |
| 1625 | image_rect.x = x; | 1877 | image_rect.width = s->slice.width; |
| 1626 | image_rect.y = y; | 1878 | image_rect.height = s->slice.height; |
| 1627 | image_rect.width = s->slice.width; | 1879 | |
| 1628 | image_rect.height = s->slice.height; | 1880 | if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) |
| 1629 | 1881 | android_copy_area (s->img->pixmap, | |
| 1630 | if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) | 1882 | FRAME_ANDROID_WINDOW (s->f), |
| 1631 | android_copy_area (s->img->pixmap, FRAME_ANDROID_WINDOW (s->f), | 1883 | s->gc, s->slice.x + r.x - x, |
| 1632 | s->gc, s->slice.x + r.x - x, | 1884 | s->slice.y + r.y - y, |
| 1633 | s->slice.y + r.y - y, | 1885 | r.width, r.height, r.x, r.y); |
| 1634 | r.x, r.y, r.width, r.height); | 1886 | |
| 1635 | } | 1887 | /* When the image has a mask, we can expect that at least part |
| 1636 | else | 1888 | of a mouse highlight or a block cursor will be visible. If |
| 1889 | the image doesn't have a mask, make a block cursor visible by | ||
| 1890 | drawing a rectangle around the image. I believe it's looking | ||
| 1891 | better if we do nothing here for mouse-face. */ | ||
| 1892 | if (s->hl == DRAW_CURSOR && !s->img->mask) | ||
| 1637 | { | 1893 | { |
| 1638 | unsigned long mask = (ANDROID_GC_CLIP_MASK | 1894 | int relief = eabs (s->img->relief); |
| 1639 | | ANDROID_GC_CLIP_X_ORIGIN | 1895 | android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, |
| 1640 | | ANDROID_GC_CLIP_Y_ORIGIN | 1896 | x - relief, y - relief, |
| 1641 | | ANDROID_GC_FUNCTION); | 1897 | s->slice.width + relief*2 - 1, |
| 1642 | struct android_gc_values xgcv; | 1898 | s->slice.height + relief*2 - 1); |
| 1643 | struct android_rectangle clip_rect, image_rect, r; | ||
| 1644 | |||
| 1645 | xgcv.clip_mask = s->img->mask; | ||
| 1646 | xgcv.clip_x_origin = x - s->slice.x; | ||
| 1647 | xgcv.clip_y_origin = y - s->slice.y; | ||
| 1648 | xgcv.function = ANDROID_GC_COPY; | ||
| 1649 | android_change_gc (s->gc, mask, &xgcv); | ||
| 1650 | |||
| 1651 | get_glyph_string_clip_rect (s, &clip_rect); | ||
| 1652 | image_rect.x = x; | ||
| 1653 | image_rect.y = y; | ||
| 1654 | image_rect.width = s->slice.width; | ||
| 1655 | image_rect.height = s->slice.height; | ||
| 1656 | |||
| 1657 | if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) | ||
| 1658 | android_copy_area (s->img->pixmap, | ||
| 1659 | FRAME_ANDROID_WINDOW (s->f), | ||
| 1660 | s->gc, s->slice.x + r.x - x, | ||
| 1661 | s->slice.y + r.y - y, | ||
| 1662 | r.x, r.y, r.width, r.height); | ||
| 1663 | |||
| 1664 | /* When the image has a mask, we can expect that at | ||
| 1665 | least part of a mouse highlight or a block cursor will | ||
| 1666 | be visible. If the image doesn't have a mask, make | ||
| 1667 | a block cursor visible by drawing a rectangle around | ||
| 1668 | the image. I believe it's looking better if we do | ||
| 1669 | nothing here for mouse-face. */ | ||
| 1670 | if (s->hl == DRAW_CURSOR) | ||
| 1671 | { | ||
| 1672 | int relief = eabs (s->img->relief); | ||
| 1673 | android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, | ||
| 1674 | x - relief, y - relief, | ||
| 1675 | s->slice.width + relief*2 - 1, | ||
| 1676 | s->slice.height + relief*2 - 1); | ||
| 1677 | } | ||
| 1678 | } | 1899 | } |
| 1679 | } | ||
| 1680 | else | ||
| 1681 | /* Draw a rectangle if image could not be loaded. */ | ||
| 1682 | android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, x, y, | ||
| 1683 | s->slice.width - 1, s->slice.height - 1); | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | /* Draw the foreground of image glyph string S to PIXMAP. */ | ||
| 1687 | |||
| 1688 | static void | ||
| 1689 | android_draw_image_foreground_1 (struct glyph_string *s, | ||
| 1690 | android_pixmap pixmap) | ||
| 1691 | { | ||
| 1692 | int x = 0; | ||
| 1693 | int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice); | ||
| 1694 | |||
| 1695 | /* If first glyph of S has a left box line, start drawing it to the | ||
| 1696 | right of that line. */ | ||
| 1697 | if (s->face->box != FACE_NO_BOX | ||
| 1698 | && s->first_glyph->left_box_line_p | ||
| 1699 | && s->slice.x == 0) | ||
| 1700 | x += max (s->face->box_vertical_line_width, 0); | ||
| 1701 | |||
| 1702 | /* If there is a margin around the image, adjust x- and y-position | ||
| 1703 | by that margin. */ | ||
| 1704 | if (s->slice.x == 0) | ||
| 1705 | x += s->img->hmargin; | ||
| 1706 | if (s->slice.y == 0) | ||
| 1707 | y += s->img->vmargin; | ||
| 1708 | 1900 | ||
| 1709 | if (s->img->pixmap) | 1901 | android_set_clip_mask (s->gc, ANDROID_NONE); |
| 1710 | { | ||
| 1711 | if (s->img->mask) | ||
| 1712 | { | ||
| 1713 | unsigned long mask = (ANDROID_GC_CLIP_MASK | ||
| 1714 | | ANDROID_GC_CLIP_X_ORIGIN | ||
| 1715 | | ANDROID_GC_CLIP_Y_ORIGIN | ||
| 1716 | | ANDROID_GC_FUNCTION); | ||
| 1717 | struct android_gc_values xgcv; | ||
| 1718 | struct android_rectangle clip_rect, image_rect, r; | ||
| 1719 | |||
| 1720 | xgcv.clip_mask = s->img->mask; | ||
| 1721 | xgcv.clip_x_origin = x - s->slice.x; | ||
| 1722 | xgcv.clip_y_origin = y - s->slice.y; | ||
| 1723 | xgcv.function = ANDROID_GC_COPY; | ||
| 1724 | android_change_gc (s->gc, mask, &xgcv); | ||
| 1725 | |||
| 1726 | get_glyph_string_clip_rect (s, &clip_rect); | ||
| 1727 | image_rect.x = x; | ||
| 1728 | image_rect.y = y; | ||
| 1729 | image_rect.width = s->slice.width; | ||
| 1730 | image_rect.height = s->slice.height; | ||
| 1731 | |||
| 1732 | if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) | ||
| 1733 | android_copy_area (s->img->pixmap, pixmap, s->gc, | ||
| 1734 | s->slice.x + r.x - x, | ||
| 1735 | s->slice.y + r.y - y, | ||
| 1736 | r.x, r.y, r.width, r.height); | ||
| 1737 | |||
| 1738 | android_set_clip_mask (s->gc, ANDROID_NONE); | ||
| 1739 | } | ||
| 1740 | else | ||
| 1741 | { | ||
| 1742 | android_copy_area (s->img->pixmap, pixmap, s->gc, | ||
| 1743 | s->slice.x, s->slice.y, | ||
| 1744 | s->slice.width, s->slice.height, x, y); | ||
| 1745 | |||
| 1746 | /* When the image has a mask, we can expect that at | ||
| 1747 | least part of a mouse highlight or a block cursor will | ||
| 1748 | be visible. If the image doesn't have a mask, make | ||
| 1749 | a block cursor visible by drawing a rectangle around | ||
| 1750 | the image. I believe it's looking better if we do | ||
| 1751 | nothing here for mouse-face. */ | ||
| 1752 | if (s->hl == DRAW_CURSOR) | ||
| 1753 | { | ||
| 1754 | int r = eabs (s->img->relief); | ||
| 1755 | android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), | ||
| 1756 | s->gc, x - r, y - r, | ||
| 1757 | s->slice.width + r*2 - 1, | ||
| 1758 | s->slice.height + r*2 - 1); | ||
| 1759 | } | ||
| 1760 | } | ||
| 1761 | } | 1902 | } |
| 1762 | else | 1903 | else |
| 1763 | /* Draw a rectangle if image could not be loaded. */ | 1904 | /* Draw a rectangle if image could not be loaded. */ |
| @@ -1771,7 +1912,6 @@ android_draw_image_glyph_string (struct glyph_string *s) | |||
| 1771 | int box_line_hwidth = max (s->face->box_vertical_line_width, 0); | 1912 | int box_line_hwidth = max (s->face->box_vertical_line_width, 0); |
| 1772 | int box_line_vwidth = max (s->face->box_horizontal_line_width, 0); | 1913 | int box_line_vwidth = max (s->face->box_horizontal_line_width, 0); |
| 1773 | int height; | 1914 | int height; |
| 1774 | android_pixmap pixmap = ANDROID_NONE; | ||
| 1775 | 1915 | ||
| 1776 | height = s->height; | 1916 | height = s->height; |
| 1777 | if (s->slice.y == 0) | 1917 | if (s->slice.y == 0) |
| @@ -1793,79 +1933,27 @@ android_draw_image_glyph_string (struct glyph_string *s) | |||
| 1793 | if (s->stippled_p) | 1933 | if (s->stippled_p) |
| 1794 | s->row->stipple_p = true; | 1934 | s->row->stipple_p = true; |
| 1795 | 1935 | ||
| 1796 | if (s->img->mask) | 1936 | int x = s->x; |
| 1797 | { | 1937 | int y = s->y; |
| 1798 | /* Create a pixmap as large as the glyph string. Fill it | 1938 | int width = s->background_width; |
| 1799 | with the background color. Copy the image to it, using | ||
| 1800 | its mask. Copy the temporary pixmap to the display. */ | ||
| 1801 | int depth = FRAME_DISPLAY_INFO (s->f)->n_planes; | ||
| 1802 | |||
| 1803 | /* Create a pixmap as large as the glyph string. */ | ||
| 1804 | pixmap = android_create_pixmap (s->background_width, | ||
| 1805 | s->height, depth); | ||
| 1806 | |||
| 1807 | /* Don't clip in the following because we're working on the | ||
| 1808 | pixmap. */ | ||
| 1809 | android_set_clip_mask (s->gc, ANDROID_NONE); | ||
| 1810 | |||
| 1811 | /* Fill the pixmap with the background color/stipple. */ | ||
| 1812 | if (s->stippled_p) | ||
| 1813 | { | ||
| 1814 | /* Fill background with a stipple pattern. */ | ||
| 1815 | android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED); | ||
| 1816 | android_set_ts_origin (s->gc, - s->x, - s->y); | ||
| 1817 | android_fill_rectangle (pixmap, s->gc, | ||
| 1818 | 0, 0, s->background_width, s->height); | ||
| 1819 | android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED); | ||
| 1820 | android_set_ts_origin (s->gc, 0, 0); | ||
| 1821 | } | ||
| 1822 | else | ||
| 1823 | { | ||
| 1824 | struct android_gc_values xgcv; | ||
| 1825 | 1939 | ||
| 1826 | android_get_gc_values (s->gc, (ANDROID_GC_FOREGROUND | 1940 | if (s->first_glyph->left_box_line_p |
| 1827 | | ANDROID_GC_BACKGROUND), | 1941 | && s->slice.x == 0) |
| 1828 | &xgcv); | ||
| 1829 | android_set_foreground (s->gc, xgcv.background); | ||
| 1830 | android_fill_rectangle (pixmap, s->gc, | ||
| 1831 | 0, 0, s->background_width, s->height); | ||
| 1832 | android_set_background (s->gc, xgcv.foreground); | ||
| 1833 | } | ||
| 1834 | } | ||
| 1835 | else | ||
| 1836 | { | 1942 | { |
| 1837 | int x = s->x; | 1943 | x += box_line_hwidth; |
| 1838 | int y = s->y; | 1944 | width -= box_line_hwidth; |
| 1839 | int width = s->background_width; | 1945 | } |
| 1840 | 1946 | ||
| 1841 | if (s->first_glyph->left_box_line_p | 1947 | if (s->slice.y == 0) |
| 1842 | && s->slice.x == 0) | 1948 | y += box_line_vwidth; |
| 1843 | { | ||
| 1844 | x += box_line_hwidth; | ||
| 1845 | width -= box_line_hwidth; | ||
| 1846 | } | ||
| 1847 | 1949 | ||
| 1848 | if (s->slice.y == 0) | 1950 | android_draw_glyph_string_bg_rect (s, x, y, width, height); |
| 1849 | y += box_line_vwidth; | ||
| 1850 | |||
| 1851 | android_draw_glyph_string_bg_rect (s, x, y, width, height); | ||
| 1852 | } | ||
| 1853 | 1951 | ||
| 1854 | s->background_filled_p = true; | 1952 | s->background_filled_p = true; |
| 1855 | } | 1953 | } |
| 1856 | 1954 | ||
| 1857 | /* Draw the foreground. */ | 1955 | /* Draw the foreground. */ |
| 1858 | if (pixmap != ANDROID_NONE) | 1956 | android_draw_image_foreground (s); |
| 1859 | { | ||
| 1860 | android_draw_image_foreground_1 (s, pixmap); | ||
| 1861 | android_set_glyph_string_clipping (s); | ||
| 1862 | android_copy_area (pixmap, FRAME_ANDROID_WINDOW (s->f), s->gc, | ||
| 1863 | 0, 0, s->background_width, s->height, s->x, | ||
| 1864 | s->y); | ||
| 1865 | android_free_pixmap (pixmap); | ||
| 1866 | } | ||
| 1867 | else | ||
| 1868 | android_draw_image_foreground (s); | ||
| 1869 | 1957 | ||
| 1870 | /* If we must draw a relief around the image, do it. */ | 1958 | /* If we must draw a relief around the image, do it. */ |
| 1871 | if (s->img->relief | 1959 | if (s->img->relief |
| @@ -3047,7 +3135,7 @@ android_create_terminal (struct android_display_info *dpyinfo) | |||
| 3047 | terminal->mouse_position_hook = android_mouse_position; | 3135 | terminal->mouse_position_hook = android_mouse_position; |
| 3048 | terminal->get_focus_frame = android_get_focus_frame; | 3136 | terminal->get_focus_frame = android_get_focus_frame; |
| 3049 | terminal->focus_frame_hook = android_focus_frame; | 3137 | terminal->focus_frame_hook = android_focus_frame; |
| 3050 | terminal->frame_rehighlight_hook = android_frame_rehighlight; | 3138 | terminal->frame_rehighlight_hook = android_frame_rehighlight_hook; |
| 3051 | terminal->frame_raise_lower_hook = android_frame_raise_lower; | 3139 | terminal->frame_raise_lower_hook = android_frame_raise_lower; |
| 3052 | terminal->frame_visible_invisible_hook | 3140 | terminal->frame_visible_invisible_hook |
| 3053 | = android_make_frame_visible_invisible; | 3141 | = android_make_frame_visible_invisible; |
| @@ -3117,9 +3205,12 @@ android_term_init (void) | |||
| 3117 | 3205 | ||
| 3118 | dpyinfo->color_map = color_map; | 3206 | dpyinfo->color_map = color_map; |
| 3119 | 3207 | ||
| 3120 | /* TODO! */ | 3208 | #ifndef ANDROID_STUBIFY |
| 3121 | dpyinfo->resx = 96.0; | 3209 | |
| 3122 | dpyinfo->resy = 96.0; | 3210 | dpyinfo->resx = android_pixel_density_x; |
| 3211 | dpyinfo->resy = android_pixel_density_y; | ||
| 3212 | |||
| 3213 | #endif | ||
| 3123 | 3214 | ||
| 3124 | /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */ | 3215 | /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */ |
| 3125 | dpyinfo->smallest_font_height = 1; | 3216 | dpyinfo->smallest_font_height = 1; |
| @@ -3130,6 +3221,9 @@ android_term_init (void) | |||
| 3130 | /* The display "connection" is now set up, and it must never go | 3221 | /* The display "connection" is now set up, and it must never go |
| 3131 | away. */ | 3222 | away. */ |
| 3132 | terminal->reference_count = 30000; | 3223 | terminal->reference_count = 30000; |
| 3224 | |||
| 3225 | /* Set the baud rate to the same value it gets set to on X. */ | ||
| 3226 | baud_rate = 19200; | ||
| 3133 | } | 3227 | } |
| 3134 | 3228 | ||
| 3135 | 3229 | ||
diff --git a/src/androidterm.h b/src/androidterm.h index 3a0c9f60555..c834ffb70e5 100644 --- a/src/androidterm.h +++ b/src/androidterm.h | |||
| @@ -28,8 +28,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | 28 | ||
| 29 | struct android_bitmap_record | 29 | struct android_bitmap_record |
| 30 | { | 30 | { |
| 31 | /* The image backing the bitmap. */ | 31 | /* The image backing the bitmap and its mask. */ |
| 32 | Emacs_Pixmap img; | 32 | android_pixmap pixmap, mask; |
| 33 | 33 | ||
| 34 | /* The file from which it comes. */ | 34 | /* The file from which it comes. */ |
| 35 | char *file; | 35 | char *file; |
| @@ -37,8 +37,11 @@ struct android_bitmap_record | |||
| 37 | /* The number of references to it. */ | 37 | /* The number of references to it. */ |
| 38 | int refcount; | 38 | int refcount; |
| 39 | 39 | ||
| 40 | /* The height and width. */ | 40 | /* The height and width and the depth. */ |
| 41 | int height, width; | 41 | int height, width, depth; |
| 42 | |||
| 43 | /* Whether or not there is a mask. */ | ||
| 44 | bool have_mask; | ||
| 42 | }; | 45 | }; |
| 43 | 46 | ||
| 44 | struct android_display_info | 47 | struct android_display_info |
| @@ -95,6 +98,9 @@ struct android_display_info | |||
| 95 | /* The frame currently with the input focus. */ | 98 | /* The frame currently with the input focus. */ |
| 96 | struct frame *focus_frame; | 99 | struct frame *focus_frame; |
| 97 | 100 | ||
| 101 | /* The last frame mentioned in a focus event. */ | ||
| 102 | struct frame *x_focus_event_frame; | ||
| 103 | |||
| 98 | /* The frame which currently has the visual highlight, and should | 104 | /* The frame which currently has the visual highlight, and should |
| 99 | get keyboard input. It points to the focus frame's selected | 105 | get keyboard input. It points to the focus frame's selected |
| 100 | window's frame, but can differ. */ | 106 | window's frame, but can differ. */ |
| @@ -206,8 +212,24 @@ struct android_output | |||
| 206 | /* The background for which the above relief GCs were set up. | 212 | /* The background for which the above relief GCs were set up. |
| 207 | They are changed only when a different background is involved. */ | 213 | They are changed only when a different background is involved. */ |
| 208 | unsigned long relief_background; | 214 | unsigned long relief_background; |
| 215 | |||
| 216 | /* Focus state. Only present for consistency with X; it is actually | ||
| 217 | a boolean. */ | ||
| 218 | int focus_state; | ||
| 209 | }; | 219 | }; |
| 210 | 220 | ||
| 221 | enum | ||
| 222 | { | ||
| 223 | /* Values for focus_state, used as bit mask. EXPLICIT means we | ||
| 224 | received a FocusIn for the frame and know it has the focus. | ||
| 225 | IMPLICIT means we received an EnterNotify and the frame may | ||
| 226 | have the focus if no window manager is running. FocusOut and | ||
| 227 | LeaveNotify clears EXPLICIT/IMPLICIT. */ | ||
| 228 | FOCUS_NONE = 0, | ||
| 229 | FOCUS_IMPLICIT = 1, | ||
| 230 | FOCUS_EXPLICIT = 2 | ||
| 231 | }; | ||
| 232 | |||
| 211 | /* Return the Android output data for frame F. */ | 233 | /* Return the Android output data for frame F. */ |
| 212 | #define FRAME_ANDROID_OUTPUT(f) ((f)->output_data.android) | 234 | #define FRAME_ANDROID_OUTPUT(f) ((f)->output_data.android) |
| 213 | #define FRAME_OUTPUT_DATA(f) ((f)->output_data.android) | 235 | #define FRAME_OUTPUT_DATA(f) ((f)->output_data.android) |
diff --git a/src/dispextern.h b/src/dispextern.h index e521dffc37c..c9b3495934b 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -160,8 +160,8 @@ typedef Emacs_Pixmap Emacs_Pix_Context; | |||
| 160 | #ifdef HAVE_ANDROID | 160 | #ifdef HAVE_ANDROID |
| 161 | #include "androidgui.h" | 161 | #include "androidgui.h" |
| 162 | typedef struct android_display_info Display_Info; | 162 | typedef struct android_display_info Display_Info; |
| 163 | typedef Emacs_Pixmap Emacs_Pix_Container; | 163 | typedef struct android_image *Emacs_Pix_Container; |
| 164 | typedef Emacs_Pixmap Emacs_Pix_Context; | 164 | typedef struct android_image *Emacs_Pix_Context; |
| 165 | #endif | 165 | #endif |
| 166 | 166 | ||
| 167 | #ifdef HAVE_WINDOW_SYSTEM | 167 | #ifdef HAVE_WINDOW_SYSTEM |
| @@ -3119,6 +3119,13 @@ struct image | |||
| 3119 | int original_width, original_height; | 3119 | int original_width, original_height; |
| 3120 | # endif | 3120 | # endif |
| 3121 | #endif /* HAVE_X_WINDOWS */ | 3121 | #endif /* HAVE_X_WINDOWS */ |
| 3122 | #ifdef HAVE_ANDROID | ||
| 3123 | /* Android images of the image, corresponding to the above Pixmaps. | ||
| 3124 | Non-NULL means it and its Pixmap counterpart may be out of sync | ||
| 3125 | and the latter is outdated. NULL means the X image has been | ||
| 3126 | synchronized to Pixmap. */ | ||
| 3127 | struct android_image *ximg, *mask_img; | ||
| 3128 | #endif /* HAVE_ANDROID */ | ||
| 3122 | #ifdef HAVE_NTGUI | 3129 | #ifdef HAVE_NTGUI |
| 3123 | XFORM xform; | 3130 | XFORM xform; |
| 3124 | #endif | 3131 | #endif |
diff --git a/src/emacs.c b/src/emacs.c index 9ef58ca412e..d3c53dd8051 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1440,9 +1440,8 @@ main (int argc, char **argv) | |||
| 1440 | bool only_version = false; | 1440 | bool only_version = false; |
| 1441 | sort_args (argc, argv); | 1441 | sort_args (argc, argv); |
| 1442 | old_argc = argc, argc = 0; | 1442 | old_argc = argc, argc = 0; |
| 1443 | while (argv[argc] | 1443 | /* Don't allow going past argv. */ |
| 1444 | /* Don't allow going past argv. */ | 1444 | while (argc < old_argc && argv[argc]) argc++; |
| 1445 | && argc < old_argc) argc++; | ||
| 1446 | 1445 | ||
| 1447 | skip_args = 0; | 1446 | skip_args = 0; |
| 1448 | if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args)) | 1447 | if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args)) |
diff --git a/src/fileio.c b/src/fileio.c index 1d22c51ebaa..0f205283d7e 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -898,6 +898,10 @@ user_homedir (char const *name) | |||
| 898 | p[length] = 0; | 898 | p[length] = 0; |
| 899 | struct passwd *pw = getpwnam (p); | 899 | struct passwd *pw = getpwnam (p); |
| 900 | SAFE_FREE (); | 900 | SAFE_FREE (); |
| 901 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 902 | if (pw && !pw->pw_dir && pw->pw_uid == getuid ()) | ||
| 903 | return (char *) android_get_home_directory (); | ||
| 904 | #endif | ||
| 901 | if (!pw || (pw->pw_dir && !IS_ABSOLUTE_FILE_NAME (pw->pw_dir))) | 905 | if (!pw || (pw->pw_dir && !IS_ABSOLUTE_FILE_NAME (pw->pw_dir))) |
| 902 | return NULL; | 906 | return NULL; |
| 903 | return pw->pw_dir; | 907 | return pw->pw_dir; |
| @@ -1888,6 +1892,11 @@ get_homedir (void) | |||
| 1888 | pw = getpwuid (getuid ()); | 1892 | pw = getpwuid (getuid ()); |
| 1889 | if (pw) | 1893 | if (pw) |
| 1890 | home = pw->pw_dir; | 1894 | home = pw->pw_dir; |
| 1895 | |||
| 1896 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 1897 | if (!home && pw && pw->pw_uid == getuid ()) | ||
| 1898 | return android_get_home_directory (); | ||
| 1899 | #endif | ||
| 1891 | if (!home) | 1900 | if (!home) |
| 1892 | return ""; | 1901 | return ""; |
| 1893 | } | 1902 | } |
diff --git a/src/font.h b/src/font.h index c1ab26b87cb..1db94a9f3f8 100644 --- a/src/font.h +++ b/src/font.h | |||
| @@ -547,8 +547,14 @@ CHECK_FONT_GET_OBJECT (Lisp_Object x) | |||
| 547 | return XFONT_OBJECT (x); | 547 | return XFONT_OBJECT (x); |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | #ifndef HAVE_ANDROID | ||
| 550 | /* Number of pt per inch (from the TeXbook). */ | 551 | /* Number of pt per inch (from the TeXbook). */ |
| 551 | #define PT_PER_INCH 72.27 | 552 | #define PT_PER_INCH 72.27 |
| 553 | #else | ||
| 554 | /* Android uses this value instead to compensate for different device | ||
| 555 | dimensions. */ | ||
| 556 | #define PT_PER_INCH 160.00 | ||
| 557 | #endif | ||
| 552 | 558 | ||
| 553 | /* Return a pixel size (integer) corresponding to POINT size (double) | 559 | /* Return a pixel size (integer) corresponding to POINT size (double) |
| 554 | on resolution DPI. */ | 560 | on resolution DPI. */ |
diff --git a/src/fringe.c b/src/fringe.c index 5d7c8dca998..f10bc424239 100644 --- a/src/fringe.c +++ b/src/fringe.c | |||
| @@ -1422,25 +1422,30 @@ If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. | |||
| 1422 | On X, we bit-swap the built-in bitmaps and reduce bitmap | 1422 | On X, we bit-swap the built-in bitmaps and reduce bitmap |
| 1423 | from short to char array if width is <= 8 bits. | 1423 | from short to char array if width is <= 8 bits. |
| 1424 | 1424 | ||
| 1425 | The Android port tries to follow X as closely as possible, so do | ||
| 1426 | that there too. | ||
| 1427 | |||
| 1425 | On MAC with big-endian CPU, we need to byte-swap each short. | 1428 | On MAC with big-endian CPU, we need to byte-swap each short. |
| 1426 | 1429 | ||
| 1427 | On W32 and MAC (little endian), there's no need to do this. | 1430 | On W32 and MAC (little endian), there's no need to do this. |
| 1428 | */ | 1431 | */ |
| 1429 | 1432 | ||
| 1430 | #if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) | 1433 | #if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) || defined (HAVE_ANDROID) |
| 1431 | static const unsigned char swap_nibble[16] = { | 1434 | static const unsigned char swap_nibble[16] = |
| 1432 | 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */ | 1435 | { |
| 1433 | 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */ | 1436 | 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */ |
| 1434 | 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */ | 1437 | 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */ |
| 1435 | 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */ | 1438 | 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */ |
| 1436 | #endif /* HAVE_X_WINDOWS */ | 1439 | 0x3, 0xb, 0x7, 0xf, /* 0011 1011 0111 1111 */ |
| 1440 | }; | ||
| 1441 | #endif | ||
| 1437 | 1442 | ||
| 1438 | static void | 1443 | static void |
| 1439 | init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p) | 1444 | init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p) |
| 1440 | { | 1445 | { |
| 1441 | if (once_p || fb->dynamic) | 1446 | if (once_p || fb->dynamic) |
| 1442 | { | 1447 | { |
| 1443 | #if defined (HAVE_X_WINDOWS) | 1448 | #if defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID) |
| 1444 | unsigned short *bits = fb->bits; | 1449 | unsigned short *bits = fb->bits; |
| 1445 | int j; | 1450 | int j; |
| 1446 | 1451 | ||
| @@ -1488,7 +1493,7 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p) | |||
| 1488 | } | 1493 | } |
| 1489 | } | 1494 | } |
| 1490 | #endif /* not USE_CAIRO */ | 1495 | #endif /* not USE_CAIRO */ |
| 1491 | #endif /* HAVE_X_WINDOWS */ | 1496 | #endif /* HAVE_X_WINDOWS || HAVE_ANDROID */ |
| 1492 | 1497 | ||
| 1493 | #if !defined(HAVE_X_WINDOWS) && defined (HAVE_PGTK) | 1498 | #if !defined(HAVE_X_WINDOWS) && defined (HAVE_PGTK) |
| 1494 | unsigned short *bits = fb->bits; | 1499 | unsigned short *bits = fb->bits; |
diff --git a/src/image.c b/src/image.c index 986dd7aada4..08d092e2c6e 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -177,11 +177,14 @@ typedef struct haiku_bitmap_record Bitmap_Record; | |||
| 177 | 177 | ||
| 178 | #ifdef HAVE_ANDROID | 178 | #ifdef HAVE_ANDROID |
| 179 | #include "androidterm.h" | 179 | #include "androidterm.h" |
| 180 | |||
| 180 | typedef struct android_bitmap_record Bitmap_Record; | 181 | typedef struct android_bitmap_record Bitmap_Record; |
| 181 | 182 | ||
| 182 | /* TODO: implement images on Android. */ | 183 | typedef struct android_image XImage; |
| 183 | #define GET_PIXEL(ximg, x, y) 0 | 184 | typedef android_pixmap Pixmap; |
| 184 | #define PUT_PIXEL(ximg, x, y, pixel) ((void) (pixel)) | 185 | |
| 186 | #define GET_PIXEL(ximg, x, y) android_get_pixel (ximg, x, y) | ||
| 187 | #define PUT_PIXEL(ximg, x, y, pixel) android_put_pixel (ximg, x, y, pixel) | ||
| 185 | #define NO_PIXMAP 0 | 188 | #define NO_PIXMAP 0 |
| 186 | 189 | ||
| 187 | #define PIX_MASK_RETAIN 0 | 190 | #define PIX_MASK_RETAIN 0 |
| @@ -507,6 +510,18 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 507 | return -1; | 510 | return -1; |
| 508 | #endif /* HAVE_X_WINDOWS */ | 511 | #endif /* HAVE_X_WINDOWS */ |
| 509 | 512 | ||
| 513 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 514 | android_pixmap bitmap; | ||
| 515 | |||
| 516 | bitmap = android_create_bitmap_from_data (bits, width, height); | ||
| 517 | |||
| 518 | if (!bitmap) | ||
| 519 | return -1; | ||
| 520 | #else | ||
| 521 | ((void) dpyinfo); | ||
| 522 | emacs_abort (); | ||
| 523 | #endif | ||
| 524 | |||
| 510 | #ifdef HAVE_NTGUI | 525 | #ifdef HAVE_NTGUI |
| 511 | Lisp_Object frame UNINIT; /* The value is not used. */ | 526 | Lisp_Object frame UNINIT; /* The value is not used. */ |
| 512 | Emacs_Pixmap bitmap; | 527 | Emacs_Pixmap bitmap; |
| @@ -619,14 +634,14 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 619 | dpyinfo->bitmaps[id - 1].width = width; | 634 | dpyinfo->bitmaps[id - 1].width = width; |
| 620 | dpyinfo->bitmaps[id - 1].refcount = 1; | 635 | dpyinfo->bitmaps[id - 1].refcount = 1; |
| 621 | 636 | ||
| 622 | #ifdef HAVE_X_WINDOWS | 637 | #if defined HAVE_X_WINDOWS && defined HAVE_ANDROID |
| 623 | dpyinfo->bitmaps[id - 1].pixmap = bitmap; | 638 | dpyinfo->bitmaps[id - 1].pixmap = bitmap; |
| 624 | dpyinfo->bitmaps[id - 1].have_mask = false; | 639 | dpyinfo->bitmaps[id - 1].have_mask = false; |
| 625 | dpyinfo->bitmaps[id - 1].depth = 1; | 640 | dpyinfo->bitmaps[id - 1].depth = 1; |
| 626 | #ifdef USE_CAIRO | 641 | #ifdef USE_CAIRO |
| 627 | dpyinfo->bitmaps[id - 1].stipple = NULL; | 642 | dpyinfo->bitmaps[id - 1].stipple = NULL; |
| 628 | #endif /* USE_CAIRO */ | 643 | #endif /* USE_CAIRO */ |
| 629 | #endif /* HAVE_X_WINDOWS */ | 644 | #endif /* HAVE_X_WINDOWS || HAVE_ANDROID */ |
| 630 | 645 | ||
| 631 | #ifdef HAVE_NTGUI | 646 | #ifdef HAVE_NTGUI |
| 632 | dpyinfo->bitmaps[id - 1].pixmap = bitmap; | 647 | dpyinfo->bitmaps[id - 1].pixmap = bitmap; |
| @@ -637,7 +652,7 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 637 | return id; | 652 | return id; |
| 638 | } | 653 | } |
| 639 | 654 | ||
| 640 | #if defined HAVE_HAIKU || defined HAVE_NS | 655 | #if defined HAVE_HAIKU || defined HAVE_NS || defined HAVE_ANDROID |
| 641 | static char *slurp_file (int, ptrdiff_t *); | 656 | static char *slurp_file (int, ptrdiff_t *); |
| 642 | static Lisp_Object image_find_image_fd (Lisp_Object, int *); | 657 | static Lisp_Object image_find_image_fd (Lisp_Object, int *); |
| 643 | static bool xbm_read_bitmap_data (struct frame *, char *, char *, | 658 | static bool xbm_read_bitmap_data (struct frame *, char *, char *, |
| @@ -861,8 +876,62 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 861 | /* This function should never be called when building stubs. */ | 876 | /* This function should never be called when building stubs. */ |
| 862 | emacs_abort (); | 877 | emacs_abort (); |
| 863 | #else | 878 | #else |
| 864 | /* you lose, not yet implemented TODO */ | 879 | ptrdiff_t id, size; |
| 865 | return 0; | 880 | int fd, width, height, rc; |
| 881 | char *contents, *data; | ||
| 882 | Lisp_Object found; | ||
| 883 | android_pixmap bitmap; | ||
| 884 | |||
| 885 | /* Look for an existing bitmap with the same name. */ | ||
| 886 | for (id = 0; id < dpyinfo->bitmaps_last; ++id) | ||
| 887 | { | ||
| 888 | if (dpyinfo->bitmaps[id].refcount | ||
| 889 | && dpyinfo->bitmaps[id].file | ||
| 890 | && !strcmp (dpyinfo->bitmaps[id].file, SSDATA (file))) | ||
| 891 | { | ||
| 892 | ++dpyinfo->bitmaps[id].refcount; | ||
| 893 | return id + 1; | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | /* Search bitmap-file-path for the file, if appropriate. */ | ||
| 898 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, | ||
| 899 | make_fixnum (R_OK), false, false) | ||
| 900 | < 0) | ||
| 901 | return -1; | ||
| 902 | |||
| 903 | if (!STRINGP (image_find_image_fd (file, &fd)) | ||
| 904 | && !STRINGP (image_find_image_fd (found, &fd))) | ||
| 905 | return -1; | ||
| 906 | |||
| 907 | contents = slurp_file (fd, &size); | ||
| 908 | |||
| 909 | if (!contents) | ||
| 910 | return -1; | ||
| 911 | |||
| 912 | rc = xbm_read_bitmap_data (f, contents, contents + size, | ||
| 913 | &width, &height, &data, 0); | ||
| 914 | |||
| 915 | if (!rc) | ||
| 916 | { | ||
| 917 | xfree (contents); | ||
| 918 | return -1; | ||
| 919 | } | ||
| 920 | |||
| 921 | xfree (contents); | ||
| 922 | bitmap = android_create_bitmap_from_data (data, width, height); | ||
| 923 | xfree (data); | ||
| 924 | |||
| 925 | id = image_allocate_bitmap_record (f); | ||
| 926 | dpyinfo->bitmaps[id - 1].pixmap = bitmap; | ||
| 927 | dpyinfo->bitmaps[id - 1].have_mask = false; | ||
| 928 | dpyinfo->bitmaps[id - 1].refcount = 1; | ||
| 929 | dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); | ||
| 930 | dpyinfo->bitmaps[id - 1].depth = 1; | ||
| 931 | dpyinfo->bitmaps[id - 1].height = height; | ||
| 932 | dpyinfo->bitmaps[id - 1].width = width; | ||
| 933 | |||
| 934 | return id; | ||
| 866 | #endif | 935 | #endif |
| 867 | #endif | 936 | #endif |
| 868 | } | 937 | } |
| @@ -882,6 +951,13 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) | |||
| 882 | #endif /* USE_CAIRO */ | 951 | #endif /* USE_CAIRO */ |
| 883 | #endif /* HAVE_X_WINDOWS */ | 952 | #endif /* HAVE_X_WINDOWS */ |
| 884 | 953 | ||
| 954 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 955 | android_free_pixmap (bm->pixmap); | ||
| 956 | |||
| 957 | if (bm->have_mask) | ||
| 958 | android_free_pixmap (bm->pixmap); | ||
| 959 | #endif | ||
| 960 | |||
| 885 | #ifdef HAVE_NTGUI | 961 | #ifdef HAVE_NTGUI |
| 886 | DeleteObject (bm->pixmap); | 962 | DeleteObject (bm->pixmap); |
| 887 | #endif /* HAVE_NTGUI */ | 963 | #endif /* HAVE_NTGUI */ |
| @@ -969,7 +1045,7 @@ static void image_unget_x_image (struct image *, bool, Emacs_Pix_Container); | |||
| 969 | image_unget_x_image (img, mask_p, ximg) | 1045 | image_unget_x_image (img, mask_p, ximg) |
| 970 | #endif | 1046 | #endif |
| 971 | 1047 | ||
| 972 | #ifdef HAVE_X_WINDOWS | 1048 | #if defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 973 | 1049 | ||
| 974 | #ifndef USE_CAIRO | 1050 | #ifndef USE_CAIRO |
| 975 | static void image_sync_to_pixmaps (struct frame *, struct image *); | 1051 | static void image_sync_to_pixmaps (struct frame *, struct image *); |
| @@ -983,6 +1059,8 @@ static bool x_create_x_image_and_pixmap (struct frame *, int, int, int, | |||
| 983 | XImage **, Pixmap *); | 1059 | XImage **, Pixmap *); |
| 984 | static void x_destroy_x_image (XImage *); | 1060 | static void x_destroy_x_image (XImage *); |
| 985 | 1061 | ||
| 1062 | #if defined HAVE_X_WINDOWS | ||
| 1063 | |||
| 986 | /* Create a mask of a bitmap. Note is this not a perfect mask. | 1064 | /* Create a mask of a bitmap. Note is this not a perfect mask. |
| 987 | It's nicer with some borders in this context */ | 1065 | It's nicer with some borders in this context */ |
| 988 | 1066 | ||
| @@ -1079,7 +1157,9 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) | |||
| 1079 | x_destroy_x_image (mask_img); | 1157 | x_destroy_x_image (mask_img); |
| 1080 | } | 1158 | } |
| 1081 | 1159 | ||
| 1082 | #endif /* HAVE_X_WINDOWS */ | 1160 | #endif |
| 1161 | |||
| 1162 | #endif /* HAVE_X_WINDOWS || defined HAVE_ANDROID*/ | ||
| 1083 | 1163 | ||
| 1084 | /*********************************************************************** | 1164 | /*********************************************************************** |
| 1085 | Image types | 1165 | Image types |
| @@ -1113,7 +1193,7 @@ struct image_type | |||
| 1113 | #if defined HAVE_RSVG || defined HAVE_PNG || defined HAVE_GIF || \ | 1193 | #if defined HAVE_RSVG || defined HAVE_PNG || defined HAVE_GIF || \ |
| 1114 | defined HAVE_TIFF || defined HAVE_JPEG || defined HAVE_XPM || \ | 1194 | defined HAVE_TIFF || defined HAVE_JPEG || defined HAVE_XPM || \ |
| 1115 | defined HAVE_NS || defined HAVE_HAIKU || defined HAVE_PGTK || \ | 1195 | defined HAVE_NS || defined HAVE_HAIKU || defined HAVE_PGTK || \ |
| 1116 | defined HAVE_WEBP | 1196 | defined HAVE_WEBP || defined HAVE_ANDROID |
| 1117 | # ifdef WINDOWSNT | 1197 | # ifdef WINDOWSNT |
| 1118 | # define IMAGE_TYPE_INIT(f) f | 1198 | # define IMAGE_TYPE_INIT(f) f |
| 1119 | # else | 1199 | # else |
| @@ -1615,7 +1695,7 @@ prepare_image_for_display (struct frame *f, struct image *img) | |||
| 1615 | } | 1695 | } |
| 1616 | unblock_input (); | 1696 | unblock_input (); |
| 1617 | } | 1697 | } |
| 1618 | #elif defined HAVE_X_WINDOWS | 1698 | #elif defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 1619 | if (!img->load_failed_p) | 1699 | if (!img->load_failed_p) |
| 1620 | { | 1700 | { |
| 1621 | block_input (); | 1701 | block_input (); |
| @@ -1822,7 +1902,7 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) | |||
| 1822 | /* NOTE (HAVE_NS): background color is NOT an indexed color! */ | 1902 | /* NOTE (HAVE_NS): background color is NOT an indexed color! */ |
| 1823 | img->background_valid = 0; | 1903 | img->background_valid = 0; |
| 1824 | } | 1904 | } |
| 1825 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | 1905 | #if (defined HAVE_X_WINDOWS || defined HAVE_ANDROID) && !defined USE_CAIRO |
| 1826 | if (img->ximg) | 1906 | if (img->ximg) |
| 1827 | { | 1907 | { |
| 1828 | image_destroy_x_image (img->ximg); | 1908 | image_destroy_x_image (img->ximg); |
| @@ -1840,7 +1920,7 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) | |||
| 1840 | img->mask = NO_PIXMAP; | 1920 | img->mask = NO_PIXMAP; |
| 1841 | img->background_transparent_valid = 0; | 1921 | img->background_transparent_valid = 0; |
| 1842 | } | 1922 | } |
| 1843 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | 1923 | #if (defined HAVE_X_WINDOWS || defined HAVE_ANDROID) && !defined USE_CAIRO |
| 1844 | if (img->mask_img) | 1924 | if (img->mask_img) |
| 1845 | { | 1925 | { |
| 1846 | image_destroy_x_image (img->mask_img); | 1926 | image_destroy_x_image (img->mask_img); |
| @@ -2212,11 +2292,11 @@ image_size_in_bytes (struct image *img) | |||
| 2212 | if (msk) | 2292 | if (msk) |
| 2213 | size += msk->height * msk->bytes_per_line; | 2293 | size += msk->height * msk->bytes_per_line; |
| 2214 | 2294 | ||
| 2215 | #elif defined HAVE_X_WINDOWS | 2295 | #elif defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 2216 | /* Use a nominal depth of 24 bpp for pixmap and 1 bpp for mask, | 2296 | /* Use a nominal depth of 24 and a bpp of 32 for pixmap and 1 bpp |
| 2217 | to avoid having to query the server. */ | 2297 | for mask, to avoid having to query the server. */ |
| 2218 | if (img->pixmap != NO_PIXMAP) | 2298 | if (img->pixmap != NO_PIXMAP) |
| 2219 | size += img->width * img->height * 3; | 2299 | size += img->width * img->height * 4; |
| 2220 | if (img->mask != NO_PIXMAP) | 2300 | if (img->mask != NO_PIXMAP) |
| 2221 | size += img->width * img->height / 8; | 2301 | size += img->width * img->height / 8; |
| 2222 | 2302 | ||
| @@ -3195,9 +3275,12 @@ mark_image_cache (struct image_cache *c) | |||
| 3195 | 3275 | ||
| 3196 | /*********************************************************************** | 3276 | /*********************************************************************** |
| 3197 | X / NS / W32 support code | 3277 | X / NS / W32 support code |
| 3278 | Most of this code is shared with Android to make | ||
| 3279 | it easier to maintain. | ||
| 3198 | ***********************************************************************/ | 3280 | ***********************************************************************/ |
| 3199 | 3281 | ||
| 3200 | #ifdef HAVE_X_WINDOWS | 3282 | #if defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 3283 | |||
| 3201 | static bool | 3284 | static bool |
| 3202 | x_check_image_size (XImage *ximg, int width, int height) | 3285 | x_check_image_size (XImage *ximg, int width, int height) |
| 3203 | { | 3286 | { |
| @@ -3213,7 +3296,11 @@ x_check_image_size (XImage *ximg, int width, int height) | |||
| 3213 | int bitmap_pad, depth, bytes_per_line; | 3296 | int bitmap_pad, depth, bytes_per_line; |
| 3214 | if (ximg) | 3297 | if (ximg) |
| 3215 | { | 3298 | { |
| 3299 | #ifndef HAVE_ANDROID | ||
| 3216 | bitmap_pad = ximg->bitmap_pad; | 3300 | bitmap_pad = ximg->bitmap_pad; |
| 3301 | #else | ||
| 3302 | bitmap_pad = (ximg->depth == 1 ? 8 : 32); | ||
| 3303 | #endif | ||
| 3217 | depth = ximg->depth; | 3304 | depth = ximg->depth; |
| 3218 | bytes_per_line = ximg->bytes_per_line; | 3305 | bytes_per_line = ximg->bytes_per_line; |
| 3219 | } | 3306 | } |
| @@ -3231,16 +3318,23 @@ static bool | |||
| 3231 | x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | 3318 | x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, |
| 3232 | XImage **ximg, Pixmap *pixmap) | 3319 | XImage **ximg, Pixmap *pixmap) |
| 3233 | { | 3320 | { |
| 3321 | #ifndef HAVE_ANDROID | ||
| 3234 | Display *display = FRAME_X_DISPLAY (f); | 3322 | Display *display = FRAME_X_DISPLAY (f); |
| 3235 | Drawable drawable = FRAME_X_DRAWABLE (f); | 3323 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 3324 | #endif | ||
| 3236 | 3325 | ||
| 3237 | eassert (input_blocked_p ()); | 3326 | eassert (input_blocked_p ()); |
| 3238 | 3327 | ||
| 3239 | if (depth <= 0) | 3328 | if (depth <= 0) |
| 3240 | depth = FRAME_DISPLAY_INFO (f)->n_planes; | 3329 | depth = FRAME_DISPLAY_INFO (f)->n_planes; |
| 3330 | #ifndef HAVE_ANDROID | ||
| 3241 | *ximg = XCreateImage (display, FRAME_X_VISUAL (f), | 3331 | *ximg = XCreateImage (display, FRAME_X_VISUAL (f), |
| 3242 | depth, ZPixmap, 0, NULL, width, height, | 3332 | depth, ZPixmap, 0, NULL, width, height, |
| 3243 | depth > 16 ? 32 : depth > 8 ? 16 : 8, 0); | 3333 | depth > 16 ? 32 : depth > 8 ? 16 : 8, 0); |
| 3334 | #else | ||
| 3335 | *ximg = android_create_image (depth, ANDROID_Z_PIXMAP, NULL, width, | ||
| 3336 | height); | ||
| 3337 | #endif | ||
| 3244 | if (*ximg == NULL) | 3338 | if (*ximg == NULL) |
| 3245 | { | 3339 | { |
| 3246 | image_error ("Unable to allocate X image"); | 3340 | image_error ("Unable to allocate X image"); |
| @@ -3260,7 +3354,15 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 3260 | (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); | 3354 | (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height); |
| 3261 | 3355 | ||
| 3262 | /* Allocate a pixmap of the same size. */ | 3356 | /* Allocate a pixmap of the same size. */ |
| 3357 | #ifndef HAVE_ANDROID | ||
| 3263 | *pixmap = XCreatePixmap (display, drawable, width, height, depth); | 3358 | *pixmap = XCreatePixmap (display, drawable, width, height, depth); |
| 3359 | #else | ||
| 3360 | #ifndef ANDROID_STUBIFY | ||
| 3361 | *pixmap = android_create_pixmap (width, height, depth); | ||
| 3362 | #else | ||
| 3363 | emacs_abort (); | ||
| 3364 | #endif | ||
| 3365 | #endif | ||
| 3264 | if (*pixmap == NO_PIXMAP) | 3366 | if (*pixmap == NO_PIXMAP) |
| 3265 | { | 3367 | { |
| 3266 | x_destroy_x_image (*ximg); | 3368 | x_destroy_x_image (*ximg); |
| @@ -3281,7 +3383,11 @@ x_destroy_x_image (XImage *ximg) | |||
| 3281 | ximg->data = NULL; | 3383 | ximg->data = NULL; |
| 3282 | } | 3384 | } |
| 3283 | 3385 | ||
| 3386 | #ifndef HAVE_ANDROID | ||
| 3284 | XDestroyImage (ximg); | 3387 | XDestroyImage (ximg); |
| 3388 | #else | ||
| 3389 | android_destroy_image (ximg); | ||
| 3390 | #endif | ||
| 3285 | } | 3391 | } |
| 3286 | 3392 | ||
| 3287 | # if !defined USE_CAIRO && defined HAVE_XRENDER | 3393 | # if !defined USE_CAIRO && defined HAVE_XRENDER |
| @@ -3348,7 +3454,7 @@ x_create_xrender_picture (struct frame *f, Emacs_Pixmap pixmap, int depth) | |||
| 3348 | static bool | 3454 | static bool |
| 3349 | image_check_image_size (Emacs_Pix_Container ximg, int width, int height) | 3455 | image_check_image_size (Emacs_Pix_Container ximg, int width, int height) |
| 3350 | { | 3456 | { |
| 3351 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | 3457 | #if (defined HAVE_X_WINDOWS || defined HAVE_ANDROID) && !defined USE_CAIRO |
| 3352 | return x_check_image_size (ximg, width, height); | 3458 | return x_check_image_size (ximg, width, height); |
| 3353 | #else | 3459 | #else |
| 3354 | /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases. | 3460 | /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases. |
| @@ -3372,16 +3478,6 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d | |||
| 3372 | Emacs_Pix_Container *pimg, | 3478 | Emacs_Pix_Container *pimg, |
| 3373 | Emacs_Pixmap *pixmap, Picture *picture) | 3479 | Emacs_Pixmap *pixmap, Picture *picture) |
| 3374 | { | 3480 | { |
| 3375 | #ifdef HAVE_ANDROID | ||
| 3376 | #ifdef ANDROID_STUBIFY | ||
| 3377 | /* This function should never be called when building stubs. */ | ||
| 3378 | emacs_abort (); | ||
| 3379 | #else | ||
| 3380 | /* you lose, not yet implemented TODO */ | ||
| 3381 | return false; | ||
| 3382 | #endif | ||
| 3383 | #endif | ||
| 3384 | |||
| 3385 | #ifdef USE_CAIRO | 3481 | #ifdef USE_CAIRO |
| 3386 | eassert (input_blocked_p ()); | 3482 | eassert (input_blocked_p ()); |
| 3387 | 3483 | ||
| @@ -3396,7 +3492,7 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d | |||
| 3396 | 3492 | ||
| 3397 | *pimg = *pixmap; | 3493 | *pimg = *pixmap; |
| 3398 | return 1; | 3494 | return 1; |
| 3399 | #elif defined HAVE_X_WINDOWS | 3495 | #elif defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 3400 | if (!x_create_x_image_and_pixmap (f, width, height, depth, pimg, pixmap)) | 3496 | if (!x_create_x_image_and_pixmap (f, width, height, depth, pimg, pixmap)) |
| 3401 | return 0; | 3497 | return 0; |
| 3402 | # ifdef HAVE_XRENDER | 3498 | # ifdef HAVE_XRENDER |
| @@ -3542,7 +3638,7 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d | |||
| 3542 | static void | 3638 | static void |
| 3543 | image_destroy_x_image (Emacs_Pix_Container pimg) | 3639 | image_destroy_x_image (Emacs_Pix_Container pimg) |
| 3544 | { | 3640 | { |
| 3545 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | 3641 | #if (defined HAVE_X_WINDOWS || defined HAVE_ANDROID) && !defined USE_CAIRO |
| 3546 | x_destroy_x_image (pimg); | 3642 | x_destroy_x_image (pimg); |
| 3547 | #else | 3643 | #else |
| 3548 | eassert (input_blocked_p ()); | 3644 | eassert (input_blocked_p ()); |
| @@ -3581,7 +3677,9 @@ gui_put_x_image (struct frame *f, Emacs_Pix_Container pimg, | |||
| 3581 | XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, pimg, 0, 0, 0, 0, | 3677 | XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, pimg, 0, 0, 0, 0, |
| 3582 | pimg->width, pimg->height); | 3678 | pimg->width, pimg->height); |
| 3583 | XFreeGC (FRAME_X_DISPLAY (f), gc); | 3679 | XFreeGC (FRAME_X_DISPLAY (f), gc); |
| 3584 | #endif /* HAVE_X_WINDOWS */ | 3680 | #elif defined HAVE_ANDROID |
| 3681 | android_put_image (pixmap, pimg); | ||
| 3682 | #endif | ||
| 3585 | 3683 | ||
| 3586 | #ifdef HAVE_NS | 3684 | #ifdef HAVE_NS |
| 3587 | eassert (pimg == pixmap); | 3685 | eassert (pimg == pixmap); |
| @@ -3618,7 +3716,7 @@ static void | |||
| 3618 | image_put_x_image (struct frame *f, struct image *img, Emacs_Pix_Container ximg, | 3716 | image_put_x_image (struct frame *f, struct image *img, Emacs_Pix_Container ximg, |
| 3619 | bool mask_p) | 3717 | bool mask_p) |
| 3620 | { | 3718 | { |
| 3621 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | 3719 | #if (defined HAVE_X_WINDOWS || defined HAVE_ANDROID) && !defined USE_CAIRO |
| 3622 | if (!mask_p) | 3720 | if (!mask_p) |
| 3623 | { | 3721 | { |
| 3624 | eassert (img->ximg == NULL); | 3722 | eassert (img->ximg == NULL); |
| @@ -3636,7 +3734,7 @@ image_put_x_image (struct frame *f, struct image *img, Emacs_Pix_Container ximg, | |||
| 3636 | #endif | 3734 | #endif |
| 3637 | } | 3735 | } |
| 3638 | 3736 | ||
| 3639 | #if defined HAVE_X_WINDOWS && !defined USE_CAIRO | 3737 | #if (defined HAVE_X_WINDOWS || defined HAVE_ANDROID) && !defined USE_CAIRO |
| 3640 | /* Put the X images recorded in IMG on frame F into pixmaps, then free | 3738 | /* Put the X images recorded in IMG on frame F into pixmaps, then free |
| 3641 | the X images and their buffers. */ | 3739 | the X images and their buffers. */ |
| 3642 | 3740 | ||
| @@ -3690,19 +3788,9 @@ image_unget_x_image_or_dc (struct image *img, bool mask_p, | |||
| 3690 | static Emacs_Pix_Container | 3788 | static Emacs_Pix_Container |
| 3691 | image_get_x_image (struct frame *f, struct image *img, bool mask_p) | 3789 | image_get_x_image (struct frame *f, struct image *img, bool mask_p) |
| 3692 | { | 3790 | { |
| 3693 | #ifdef HAVE_ANDROID | ||
| 3694 | #ifdef ANDROID_STUBIFY | ||
| 3695 | /* This function should never be called when building stubs. */ | ||
| 3696 | emacs_abort (); | ||
| 3697 | #else | ||
| 3698 | /* you lose, not yet implemented TODO */ | ||
| 3699 | return 0; | ||
| 3700 | #endif | ||
| 3701 | #endif | ||
| 3702 | |||
| 3703 | #if defined USE_CAIRO || defined (HAVE_HAIKU) | 3791 | #if defined USE_CAIRO || defined (HAVE_HAIKU) |
| 3704 | return !mask_p ? img->pixmap : img->mask; | 3792 | return !mask_p ? img->pixmap : img->mask; |
| 3705 | #elif defined HAVE_X_WINDOWS | 3793 | #elif defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 3706 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; | 3794 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; |
| 3707 | 3795 | ||
| 3708 | if (ximg_in_img) | 3796 | if (ximg_in_img) |
| @@ -3712,9 +3800,15 @@ image_get_x_image (struct frame *f, struct image *img, bool mask_p) | |||
| 3712 | return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask, | 3800 | return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask, |
| 3713 | 0, 0, img->original_width, img->original_height, ~0, ZPixmap); | 3801 | 0, 0, img->original_width, img->original_height, ~0, ZPixmap); |
| 3714 | #endif | 3802 | #endif |
| 3803 | #ifndef HAVE_ANDROID | ||
| 3715 | else | 3804 | else |
| 3716 | return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask, | 3805 | return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask, |
| 3717 | 0, 0, img->width, img->height, ~0, ZPixmap); | 3806 | 0, 0, img->width, img->height, ~0, ZPixmap); |
| 3807 | #else | ||
| 3808 | else | ||
| 3809 | return android_get_image (!mask_p ? img->pixmap : img->mask, | ||
| 3810 | ANDROID_Z_PIXMAP); | ||
| 3811 | #endif | ||
| 3718 | #elif defined (HAVE_NS) | 3812 | #elif defined (HAVE_NS) |
| 3719 | Emacs_Pix_Container pixmap = !mask_p ? img->pixmap : img->mask; | 3813 | Emacs_Pix_Container pixmap = !mask_p ? img->pixmap : img->mask; |
| 3720 | 3814 | ||
| @@ -3727,13 +3821,18 @@ static void | |||
| 3727 | image_unget_x_image (struct image *img, bool mask_p, Emacs_Pix_Container ximg) | 3821 | image_unget_x_image (struct image *img, bool mask_p, Emacs_Pix_Container ximg) |
| 3728 | { | 3822 | { |
| 3729 | #ifdef USE_CAIRO | 3823 | #ifdef USE_CAIRO |
| 3730 | #elif defined HAVE_X_WINDOWS | 3824 | #elif defined HAVE_X_WINDOWS || defined HAVE_ANDROID |
| 3731 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; | 3825 | XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img; |
| 3732 | 3826 | ||
| 3733 | if (ximg_in_img) | 3827 | if (ximg_in_img) |
| 3734 | eassert (ximg == ximg_in_img); | 3828 | eassert (ximg == ximg_in_img); |
| 3829 | #ifdef HAVE_ANDROID | ||
| 3830 | else | ||
| 3831 | android_destroy_image (ximg); | ||
| 3832 | #else | ||
| 3735 | else | 3833 | else |
| 3736 | XDestroyImage (ximg); | 3834 | XDestroyImage (ximg); |
| 3835 | #endif | ||
| 3737 | #elif defined (HAVE_NS) | 3836 | #elif defined (HAVE_NS) |
| 3738 | ns_release_object (ximg); | 3837 | ns_release_object (ximg); |
| 3739 | #endif | 3838 | #endif |
| @@ -4256,6 +4355,15 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, | |||
| 4256 | img->picture = x_create_xrender_picture (f, img->pixmap, 0); | 4355 | img->picture = x_create_xrender_picture (f, img->pixmap, 0); |
| 4257 | # endif | 4356 | # endif |
| 4258 | 4357 | ||
| 4358 | #elif defined HAVE_ANDROID | ||
| 4359 | #ifndef ANDROID_STUBIFY | ||
| 4360 | img->pixmap | ||
| 4361 | = android_create_pixmap_from_bitmap_data (data, img->width, img->height, | ||
| 4362 | fg, bg, | ||
| 4363 | FRAME_DISPLAY_INFO (f)->n_planes); | ||
| 4364 | #else | ||
| 4365 | emacs_abort (); | ||
| 4366 | #endif | ||
| 4259 | #elif defined HAVE_NTGUI | 4367 | #elif defined HAVE_NTGUI |
| 4260 | img->pixmap | 4368 | img->pixmap |
| 4261 | = w32_create_pixmap_from_bitmap_data (img->width, img->height, data); | 4369 | = w32_create_pixmap_from_bitmap_data (img->width, img->height, data); |
| @@ -4686,7 +4794,8 @@ xbm_load (struct frame *f, struct image *img) | |||
| 4686 | XPM images | 4794 | XPM images |
| 4687 | ***********************************************************************/ | 4795 | ***********************************************************************/ |
| 4688 | 4796 | ||
| 4689 | #if defined (HAVE_XPM) || defined (HAVE_NS) || defined (HAVE_PGTK) | 4797 | #if defined (HAVE_XPM) || defined (HAVE_NS) || defined (HAVE_PGTK) \ |
| 4798 | || defined (HAVE_ANDROID) | ||
| 4690 | 4799 | ||
| 4691 | static bool xpm_image_p (Lisp_Object object); | 4800 | static bool xpm_image_p (Lisp_Object object); |
| 4692 | static bool xpm_load (struct frame *f, struct image *img); | 4801 | static bool xpm_load (struct frame *f, struct image *img); |
| @@ -4716,7 +4825,8 @@ static bool xpm_load (struct frame *f, struct image *img); | |||
| 4716 | #endif /* not HAVE_NTGUI */ | 4825 | #endif /* not HAVE_NTGUI */ |
| 4717 | #endif /* HAVE_XPM */ | 4826 | #endif /* HAVE_XPM */ |
| 4718 | 4827 | ||
| 4719 | #if defined HAVE_XPM || defined USE_CAIRO || defined HAVE_NS || defined HAVE_HAIKU | 4828 | #if defined HAVE_XPM || defined USE_CAIRO || defined HAVE_NS \ |
| 4829 | || defined HAVE_HAIKU || defined HAVE_ANDROID | ||
| 4720 | 4830 | ||
| 4721 | /* Indices of image specification fields in xpm_format, below. */ | 4831 | /* Indices of image specification fields in xpm_format, below. */ |
| 4722 | 4832 | ||
| @@ -4736,7 +4846,8 @@ enum xpm_keyword_index | |||
| 4736 | XPM_LAST | 4846 | XPM_LAST |
| 4737 | }; | 4847 | }; |
| 4738 | 4848 | ||
| 4739 | #if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU || defined HAVE_PGTK | 4849 | #if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU \ |
| 4850 | || defined HAVE_PGTK || defined HAVE_ANDROID | ||
| 4740 | /* Vector of image_keyword structures describing the format | 4851 | /* Vector of image_keyword structures describing the format |
| 4741 | of valid XPM image specifications. */ | 4852 | of valid XPM image specifications. */ |
| 4742 | 4853 | ||
| @@ -4978,7 +5089,8 @@ init_xpm_functions (void) | |||
| 4978 | 5089 | ||
| 4979 | #endif /* WINDOWSNT */ | 5090 | #endif /* WINDOWSNT */ |
| 4980 | 5091 | ||
| 4981 | #if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU || defined HAVE_PGTK | 5092 | #if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU \ |
| 5093 | || defined HAVE_PGTK || defined HAVE_ANDROID | ||
| 4982 | /* Value is true if COLOR_SYMBOLS is a valid color symbols list | 5094 | /* Value is true if COLOR_SYMBOLS is a valid color symbols list |
| 4983 | for XPM images. Such a list must consist of conses whose car and | 5095 | for XPM images. Such a list must consist of conses whose car and |
| 4984 | cdr are strings. */ | 5096 | cdr are strings. */ |
| @@ -5014,9 +5126,9 @@ xpm_image_p (Lisp_Object object) | |||
| 5014 | && (! fmt[XPM_COLOR_SYMBOLS].count | 5126 | && (! fmt[XPM_COLOR_SYMBOLS].count |
| 5015 | || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); | 5127 | || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); |
| 5016 | } | 5128 | } |
| 5017 | #endif /* HAVE_XPM || HAVE_NS || HAVE_HAIKU || HAVE_PGTK */ | 5129 | #endif /* HAVE_XPM || HAVE_NS || HAVE_HAIKU || HAVE_PGTK || HAVE_ANDROID */ |
| 5018 | 5130 | ||
| 5019 | #endif /* HAVE_XPM || USE_CAIRO || HAVE_NS || HAVE_HAIKU */ | 5131 | #endif /* HAVE_XPM || USE_CAIRO || HAVE_NS || HAVE_HAIKU || HAVE_ANDROID */ |
| 5020 | 5132 | ||
| 5021 | #if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK | 5133 | #if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK |
| 5022 | ptrdiff_t | 5134 | ptrdiff_t |
| @@ -5389,10 +5501,12 @@ xpm_load (struct frame *f, struct image *img) | |||
| 5389 | #if (defined USE_CAIRO && defined HAVE_XPM) \ | 5501 | #if (defined USE_CAIRO && defined HAVE_XPM) \ |
| 5390 | || (defined HAVE_NS && !defined HAVE_XPM) \ | 5502 | || (defined HAVE_NS && !defined HAVE_XPM) \ |
| 5391 | || (defined HAVE_HAIKU && !defined HAVE_XPM) \ | 5503 | || (defined HAVE_HAIKU && !defined HAVE_XPM) \ |
| 5392 | || (defined HAVE_PGTK && !defined HAVE_XPM) | 5504 | || (defined HAVE_PGTK && !defined HAVE_XPM) \ |
| 5505 | || (defined HAVE_ANDROID && !defined HAVE_XPM) | ||
| 5393 | 5506 | ||
| 5394 | /* XPM support functions for NS and Haiku where libxpm is not available, and for | 5507 | /* XPM support functions for NS, Haiku and Android where libxpm is not |
| 5395 | Cairo. Only XPM version 3 (without any extensions) is supported. */ | 5508 | available, and for Cairo. Only XPM version 3 (without any |
| 5509 | extensions) is supported. */ | ||
| 5396 | 5510 | ||
| 5397 | static void xpm_put_color_table_v (Lisp_Object, const char *, | 5511 | static void xpm_put_color_table_v (Lisp_Object, const char *, |
| 5398 | int, Lisp_Object); | 5512 | int, Lisp_Object); |
| @@ -6492,11 +6606,16 @@ image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap, | |||
| 6492 | #elif HAVE_HAIKU | 6606 | #elif HAVE_HAIKU |
| 6493 | be_draw_cross_on_pixmap (pixmap, x, y, width, height, color); | 6607 | be_draw_cross_on_pixmap (pixmap, x, y, width, height, color); |
| 6494 | #elif HAVE_ANDROID | 6608 | #elif HAVE_ANDROID |
| 6495 | #ifdef ANDROID_STUBIFY | 6609 | #ifndef ANDROID_STUBIFY |
| 6496 | /* This function should never be called when building stubs. */ | 6610 | struct android_gc *gc; |
| 6497 | emacs_abort (); | 6611 | |
| 6612 | gc = android_create_gc (0, NULL); | ||
| 6613 | android_set_foreground (gc, color); | ||
| 6614 | android_draw_line (pixmap, gc, x, y, x + width - 1, y + height - 1); | ||
| 6615 | android_draw_line (pixmap, gc, x, y + height - 1, x + width - 1, y); | ||
| 6616 | android_free_gc (gc); | ||
| 6498 | #else | 6617 | #else |
| 6499 | /* you lose, not yet implemented TODO */ | 6618 | emacs_abort (); |
| 6500 | #endif | 6619 | #endif |
| 6501 | #endif | 6620 | #endif |
| 6502 | } | 6621 | } |
| @@ -6552,7 +6671,7 @@ image_disable_image (struct frame *f, struct image *img) | |||
| 6552 | #define MaskForeground(f) PIX_MASK_DRAW | 6671 | #define MaskForeground(f) PIX_MASK_DRAW |
| 6553 | #endif /* USE_CAIRO || HAVE_HAIKU */ | 6672 | #endif /* USE_CAIRO || HAVE_HAIKU */ |
| 6554 | 6673 | ||
| 6555 | #if !defined USE_CAIRO && !defined HAVE_HAIKU && !defined HAVE_ANDROID | 6674 | #if !defined USE_CAIRO && !defined HAVE_HAIKU |
| 6556 | image_sync_to_pixmaps (f, img); | 6675 | image_sync_to_pixmaps (f, img); |
| 6557 | #endif /* !USE_CAIRO && !HAVE_HAIKU */ | 6676 | #endif /* !USE_CAIRO && !HAVE_HAIKU */ |
| 6558 | image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height, | 6677 | image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height, |
| @@ -12079,7 +12198,8 @@ static struct image_type const image_types[] = | |||
| 12079 | { SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image, | 12198 | { SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image, |
| 12080 | IMAGE_TYPE_INIT (init_jpeg_functions) }, | 12199 | IMAGE_TYPE_INIT (init_jpeg_functions) }, |
| 12081 | #endif | 12200 | #endif |
| 12082 | #if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU || defined HAVE_PGTK | 12201 | #if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU \ |
| 12202 | || defined HAVE_PGTK || defined HAVE_ANDROID | ||
| 12083 | { SYMBOL_INDEX (Qxpm), xpm_image_p, xpm_load, image_clear_image, | 12203 | { SYMBOL_INDEX (Qxpm), xpm_image_p, xpm_load, image_clear_image, |
| 12084 | IMAGE_TYPE_INIT (init_xpm_functions) }, | 12204 | IMAGE_TYPE_INIT (init_xpm_functions) }, |
| 12085 | #endif | 12205 | #endif |
| @@ -12138,7 +12258,7 @@ syms_of_image (void) | |||
| 12138 | DEFVAR_LISP ("image-types", Vimage_types, | 12258 | DEFVAR_LISP ("image-types", Vimage_types, |
| 12139 | doc: /* List of potentially supported image types. | 12259 | doc: /* List of potentially supported image types. |
| 12140 | Each element of the list is a symbol for an image type, like `jpeg' or `png'. | 12260 | Each element of the list is a symbol for an image type, like `jpeg' or `png'. |
| 12141 | To check whether it is really supported, use `image-type-available-p'. */); | 12261 | check whether it is really supported, use `image-type-available-p'. */); |
| 12142 | Vimage_types = Qnil; | 12262 | Vimage_types = Qnil; |
| 12143 | 12263 | ||
| 12144 | DEFVAR_LISP ("max-image-size", Vmax_image_size, | 12264 | DEFVAR_LISP ("max-image-size", Vmax_image_size, |
| @@ -12241,7 +12361,8 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 12241 | add_image_type (Qxbm); | 12361 | add_image_type (Qxbm); |
| 12242 | 12362 | ||
| 12243 | #if defined (HAVE_XPM) || defined (HAVE_NS) \ | 12363 | #if defined (HAVE_XPM) || defined (HAVE_NS) \ |
| 12244 | || defined (HAVE_HAIKU) || defined (HAVE_PGTK) | 12364 | || defined (HAVE_HAIKU) || defined (HAVE_PGTK) \ |
| 12365 | || defined (HAVE_ANDROID) | ||
| 12245 | DEFSYM (Qxpm, "xpm"); | 12366 | DEFSYM (Qxpm, "xpm"); |
| 12246 | add_image_type (Qxpm); | 12367 | add_image_type (Qxpm); |
| 12247 | #endif | 12368 | #endif |
diff --git a/src/keyboard.c b/src/keyboard.c index 7bf89ac7d4b..8eec833a9ca 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -4909,7 +4909,58 @@ static const char *const lispy_accent_keys[] = | |||
| 4909 | "dead-horn", | 4909 | "dead-horn", |
| 4910 | }; | 4910 | }; |
| 4911 | 4911 | ||
| 4912 | #ifdef HAVE_NTGUI | 4912 | #ifdef HAVE_ANDROID |
| 4913 | #define FUNCTION_KEY_OFFSET 0 | ||
| 4914 | |||
| 4915 | const char *const lispy_function_keys[] = | ||
| 4916 | { | ||
| 4917 | /* All elements in this array default to 0, except for the few | ||
| 4918 | function keys that Emacs recognizes. */ | ||
| 4919 | [111] = "escape", | ||
| 4920 | [121] = "break", | ||
| 4921 | [122] = "home", | ||
| 4922 | [123] = "end", | ||
| 4923 | [124] = "insert", | ||
| 4924 | [131] = "f1", | ||
| 4925 | [132] = "f2", | ||
| 4926 | [133] = "f3", | ||
| 4927 | [134] = "f4", | ||
| 4928 | [135] = "f5", | ||
| 4929 | [136] = "f6", | ||
| 4930 | [137] = "f7", | ||
| 4931 | [138] = "f8", | ||
| 4932 | [139] = "f9", | ||
| 4933 | [140] = "f10", | ||
| 4934 | [141] = "f11", | ||
| 4935 | [142] = "f12", | ||
| 4936 | [160] = "kp-ret", | ||
| 4937 | [19] = "up", | ||
| 4938 | [20] = "down", | ||
| 4939 | [213] = "muhenkan", | ||
| 4940 | [214] = "henkan", | ||
| 4941 | [215] = "hiragana-katakana", | ||
| 4942 | [218] = "kana", | ||
| 4943 | [21] = "left", | ||
| 4944 | [22] = "right", | ||
| 4945 | [259] = "help", | ||
| 4946 | [268] = "kp-up-left", | ||
| 4947 | [269] = "kp-down-left", | ||
| 4948 | [270] = "kp-up-right", | ||
| 4949 | [271] = "kp-down-right", | ||
| 4950 | [277] = "cut", | ||
| 4951 | [278] = "copy", | ||
| 4952 | [279] = "paste", | ||
| 4953 | [28] = "clear", | ||
| 4954 | [4] = "back", | ||
| 4955 | [61] = "tab", | ||
| 4956 | [66] = "return", | ||
| 4957 | [67] = "backspace", | ||
| 4958 | [82] = "menu", | ||
| 4959 | [92] = "page-up", | ||
| 4960 | [93] = "page-down", | ||
| 4961 | }; | ||
| 4962 | |||
| 4963 | #elif defined HAVE_NTGUI | ||
| 4913 | #define FUNCTION_KEY_OFFSET 0x0 | 4964 | #define FUNCTION_KEY_OFFSET 0x0 |
| 4914 | 4965 | ||
| 4915 | const char *const lispy_function_keys[] = | 4966 | const char *const lispy_function_keys[] = |
diff --git a/src/lread.c b/src/lread.c index eb029f01623..15273ad34fa 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -2073,7 +2073,7 @@ static void | |||
| 2073 | build_load_history (Lisp_Object filename, bool entire) | 2073 | build_load_history (Lisp_Object filename, bool entire) |
| 2074 | { | 2074 | { |
| 2075 | Lisp_Object tail, prev, newelt; | 2075 | Lisp_Object tail, prev, newelt; |
| 2076 | Lisp_Object tem, tem2; | 2076 | Lisp_Object tem, tem2, association; |
| 2077 | bool foundit = 0; | 2077 | bool foundit = 0; |
| 2078 | 2078 | ||
| 2079 | tail = Vload_history; | 2079 | tail = Vload_history; |
| @@ -2088,7 +2088,7 @@ build_load_history (Lisp_Object filename, bool entire) | |||
| 2088 | { | 2088 | { |
| 2089 | foundit = 1; | 2089 | foundit = 1; |
| 2090 | 2090 | ||
| 2091 | /* If we're loading the entire file, remove old data. */ | 2091 | /* If we're loading the entire file, remove old data. */ |
| 2092 | if (entire) | 2092 | if (entire) |
| 2093 | { | 2093 | { |
| 2094 | if (NILP (prev)) | 2094 | if (NILP (prev)) |
| @@ -2096,8 +2096,8 @@ build_load_history (Lisp_Object filename, bool entire) | |||
| 2096 | else | 2096 | else |
| 2097 | Fsetcdr (prev, XCDR (tail)); | 2097 | Fsetcdr (prev, XCDR (tail)); |
| 2098 | } | 2098 | } |
| 2099 | 2099 | /* Otherwise, cons on new symbols that are not already | |
| 2100 | /* Otherwise, cons on new symbols that are not already members. */ | 2100 | members. */ |
| 2101 | else | 2101 | else |
| 2102 | { | 2102 | { |
| 2103 | tem2 = Vcurrent_load_list; | 2103 | tem2 = Vcurrent_load_list; |
| @@ -2122,8 +2122,16 @@ build_load_history (Lisp_Object filename, bool entire) | |||
| 2122 | front of load-history, the most-recently-loaded position. Also | 2122 | front of load-history, the most-recently-loaded position. Also |
| 2123 | do this if we didn't find an existing member for the file. */ | 2123 | do this if we didn't find an existing member for the file. */ |
| 2124 | if (entire || !foundit) | 2124 | if (entire || !foundit) |
| 2125 | Vload_history = Fcons (Fnreverse (Vcurrent_load_list), | 2125 | { |
| 2126 | Vload_history); | 2126 | association = Fnreverse (Vcurrent_load_list); |
| 2127 | |||
| 2128 | if (!NILP (association) && STRINGP (XCAR (association))) | ||
| 2129 | /* readevalloop can be called with SOURCENAME set to some | ||
| 2130 | nonsense value, meaning the car of ASSOCIATION will be nil | ||
| 2131 | (or worse something else), leading to an invalid | ||
| 2132 | Vload_history. Ignore such invalid entries. */ | ||
| 2133 | Vload_history = Fcons (association, Vload_history); | ||
| 2134 | } | ||
| 2127 | } | 2135 | } |
| 2128 | 2136 | ||
| 2129 | static void | 2137 | static void |