diff options
| author | Po Lu | 2023-01-19 22:19:06 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-19 22:19:06 +0800 |
| commit | a496509cedb17109d0e6297a74e2ff8ed526333c (patch) | |
| tree | 46f3db2be263de7074675a5188796e25f21d4888 /java | |
| parent | 6253e7e74249c7cdfa86723f0b91a1d207cb143e (diff) | |
| download | emacs-a496509cedb17109d0e6297a74e2ff8ed526333c.tar.gz emacs-a496509cedb17109d0e6297a74e2ff8ed526333c.zip | |
Update Android port
* .gitignore: Add new files.
* INSTALL.android: Explain how to build Emacs for ancient
versions of Android.
* admin/merge-gnulib (GNULIB_MODULES): Add getdelim.
* build-aux/config.guess (timestamp, version):
* build-aux/config.sub (timestamp, version): Autoupdate.
* configure.ac (BUILD_DETAILS, ANDROID_MIN_SDK):
(ANDROID_STUBIFY): Allow specifying CFLAGS via ANDROID_CFLAGS.
Add new configure tests for Android API version when not
explicitly specified.
* doc/emacs/android.texi (Android): Add reference to ``Other
Input Devices''.
(Android File System): Remove restrictions on directory-files on
the assets directory.
* doc/emacs/emacs.texi (Top): Add Other Input Devices to menu.
* doc/emacs/input.texi (Other Input Devices): New node.
* doc/lispref/commands.texi (Touchscreen Events): Document
changes to touchscreen input events.
* doc/lispref/frames.texi (Pop-Up Menus): Likewise.
* etc/NEWS: Announce changes.
* java/Makefile.in: Use lib-src/asset-directory-tool to generate
an `directory-tree' file placed in /assets.
* java/debug.sh: Large adjustments to support Android 2.2 and
later.
* java/org/gnu/emacs/EmacsContextMenu.java (inflateMenuItems):
* java/org/gnu/emacs/EmacsCopyArea.java (perform):
* java/org/gnu/emacs/EmacsDialog.java (toAlertDialog):
* java/org/gnu/emacs/EmacsDrawLine.java (perform):
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform):
* java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable):
* java/org/gnu/emacs/EmacsFillPolygon.java (perform):
* java/org/gnu/emacs/EmacsFillRectangle.java (perform):
* java/org/gnu/emacs/EmacsGC.java (EmacsGC):
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap):
(destroyHandle):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java (draw): Avoid
redundant canvas saves and restores.
* java/org/gnu/emacs/EmacsService.java (run):
* java/org/gnu/emacs/EmacsView.java (EmacsView):
(handleDirtyBitmap):
* java/org/gnu/emacs/EmacsWindow.java (changeWindowBackground)
(EmacsWindow): Make compatible with Android 2.2 and later.
* lib-src/Makefile.in (DONT_INSTALL): Add asset-directory-tool
on Android.:(asset-directory-tool{EXEEXT}): New target.
* lib-src/asset-directory-tool.c (struct directory_tree, xmalloc)
(main_1, main_2, main): New file.
* lib, m4: Merge from gnulib. This will be reverted before
merging to master.
* lisp/button.el (button-map):
(push-button):
* lisp/frame.el (display-popup-menus-p): Improve touchscreen
support.
* lisp/subr.el (event-start):
(event-end): Handle touchscreen events.
* lisp/touch-screen.el (touch-screen-handle-timeout):
(touch-screen-handle-point-update):
(touch-screen-handle-point-up):
(touch-screen-track-tap):
(touch-screen-track-drag):
(touch-screen-drag-mode-line-1):
(touch-screen-drag-mode-line): New functions.
([mode-line touchscreen-begin]):
([bottom-divider touchscreen-begin]): Bind new events.
* lisp/wid-edit.el (widget-event-point):
(widget-keymap):
(widget-event-start):
(widget-button--check-and-call-button):
(widget-button-click): Improve touchscreen support.
* src/alloc.c (make_lisp_symbol): Avoid ICE on Android NDK GCC.
(mark_pinned_symbols): Likewise.
* src/android.c (struct android_emacs_window): New struct.
(window_class): New variable.
(android_run_select_thread): Add workaround for Android platform
bug.
(android_extract_long, android_scan_directory_tree): New
functions.
(android_file_access_p): Use those functions instead.
(android_init_emacs_window): New function.
(android_init_emacs_gc_class): Update signature of `markDirty'.
(android_change_gc, android_set_clip_rectangles): Tell the GC
whether or not clip rects were dirtied.
(android_swap_buffers): Do not look up method every time.
(struct android_dir): Adjust for new directory tree lookup.
(android_opendir, android_readdir, android_closedir): Likewise.
(android_four_corners_bilinear): Fix coding style.
(android_ftruncate): New function.
* src/android.h: Update prototypes. Replace ftruncate with
android_ftruncate when necessary.
* src/androidterm.c (handle_one_android_event): Pacify GCC. Fix
touch screen tool bar bug.
* src/emacs.c (using_utf8): Fix compilation error.
* src/fileio.c (Ffile_system_info): Return Qnil when fsusage.o
is not built.
* src/filelock.c (BOOT_TIME_FILE): Fix definition for Android.
* src/frame.c (Fx_parse_geometry): Fix uninitialized variable
uses.
* src/keyboard.c (lispy_function_keys): Fix `back'.
* src/menu.c (x_popup_menu_1): Handle touch screen events.
(Fx_popup_menu): Document changes.
* src/sfnt.c (main): Improve tests.
* src/sfntfont-android.c (sfntfont_android_put_glyphs): Fix
minor problem.
(init_sfntfont_android): Check for
HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL.
* src/sfntfont.c (struct sfnt_font_desc): New fields `adstyle'
and `languages'.
(sfnt_parse_style): Append tokens to adstyle.
(sfnt_parse_languages): New function.
(sfnt_enum_font_1): Parse supported languages and adstyle.
(sfntfont_list_1): Handle new fields.
(sfntfont_text_extents): Fix uninitialized variable use.
(syms_of_sfntfont, mark_sfntfont): Adjust accordingly.
Diffstat (limited to 'java')
| -rw-r--r-- | java/Makefile.in | 37 | ||||
| -rwxr-xr-x | java/debug.sh | 155 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsContextMenu.java | 20 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsCopyArea.java | 11 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDialog.java | 3 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawLine.java | 11 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawRectangle.java | 45 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawable.java | 2 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFillPolygon.java | 11 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFillRectangle.java | 12 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsGC.java | 33 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsPixmap.java | 77 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSdk7FontDriver.java | 11 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 7 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsView.java | 34 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 80 |
16 files changed, 343 insertions, 206 deletions
diff --git a/java/Makefile.in b/java/Makefile.in index c539fb0f1fb..22c912fdce5 100644 --- a/java/Makefile.in +++ b/java/Makefile.in | |||
| @@ -21,6 +21,10 @@ top_builddir = @top_builddir@ | |||
| 21 | top_srcdir = @top_srcdir@ | 21 | top_srcdir = @top_srcdir@ |
| 22 | version = @version@ | 22 | version = @version@ |
| 23 | 23 | ||
| 24 | # This is the host lib-src and lib, not the cross compiler's lib-src. | ||
| 25 | libsrc = ../lib-src | ||
| 26 | EXEEXT = @EXEEXT@ | ||
| 27 | |||
| 24 | -include ${top_builddir}/src/verbose.mk | 28 | -include ${top_builddir}/src/verbose.mk |
| 25 | 29 | ||
| 26 | SHELL = @SHELL@ | 30 | SHELL = @SHELL@ |
| @@ -29,14 +33,25 @@ AAPT = @AAPT@ | |||
| 29 | D8 = @D8@ | 33 | D8 = @D8@ |
| 30 | ZIPALIGN = @ZIPALIGN@ | 34 | ZIPALIGN = @ZIPALIGN@ |
| 31 | JARSIGNER = @JARSIGNER@ | 35 | JARSIGNER = @JARSIGNER@ |
| 36 | JARSIGNER_FLAGS = | ||
| 32 | ANDROID_JAR = @ANDROID_JAR@ | 37 | ANDROID_JAR = @ANDROID_JAR@ |
| 33 | ANDROID_ABI = @ANDROID_ABI@ | 38 | ANDROID_ABI = @ANDROID_ABI@ |
| 39 | ANDROID_SDK_18_OR_EARLIER = @ANDROID_SDK_18_OR_EARLIER@ | ||
| 34 | 40 | ||
| 35 | WARN_JAVAFLAGS = -Xlint:deprecation | 41 | WARN_JAVAFLAGS = -Xlint:deprecation |
| 36 | JAVAFLAGS = -classpath "$(ANDROID_JAR):." -target 1.7 -source 1.7 \ | 42 | JAVAFLAGS = -classpath "$(ANDROID_JAR):." -target 1.7 -source 1.7 \ |
| 37 | $(WARN_JAVAFLAGS) | 43 | $(WARN_JAVAFLAGS) |
| 38 | 44 | ||
| 39 | SIGN_EMACS = -keystore emacs.keystore -storepass emacs1 | 45 | # Android 4.3 and earlier require Emacs to be signed with a different |
| 46 | # digital signature algorithm. | ||
| 47 | |||
| 48 | ifneq (,$(ANDROID_SDK_18_OR_EARLIER)) | ||
| 49 | JARSIGNER_FLAGS = -sigalg MD5withRSA -digestalg SHA1 | ||
| 50 | else | ||
| 51 | JARSIGNER_FLAGS = | ||
| 52 | endif | ||
| 53 | |||
| 54 | SIGN_EMACS = -keystore emacs.keystore -storepass emacs1 $(JARSIGNER_FLAGS) | ||
| 40 | 55 | ||
| 41 | JAVA_FILES = $(shell find . -type f -name *.java) | 56 | JAVA_FILES = $(shell find . -type f -name *.java) |
| 42 | CLASS_FILES = $(foreach file,$(JAVA_FILES),$(basename $(file)).class) | 57 | CLASS_FILES = $(foreach file,$(JAVA_FILES),$(basename $(file)).class) |
| @@ -82,7 +97,14 @@ CROSS_LIBS = ../xcompile/src/libemacs.so | |||
| 82 | ../xcompile/lib-src/ctags ../xcompile/lib-src/ebrowse &: | 97 | ../xcompile/lib-src/ctags ../xcompile/lib-src/ebrowse &: |
| 83 | make -C ../xcompile lib-src/$(notdir $@) | 98 | make -C ../xcompile lib-src/$(notdir $@) |
| 84 | 99 | ||
| 85 | emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) AndroidManifest.xml | 100 | # This is needed to generate the ``.directory-tree'' file used by the |
| 101 | # Android emulations of readdir and faccessat. | ||
| 102 | |||
| 103 | $(libsrc)/asset-directory-tool: | ||
| 104 | $(MAKE) -C $(libsrc) $(notdir $@) | ||
| 105 | |||
| 106 | emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \ | ||
| 107 | AndroidManifest.xml | ||
| 86 | # Make the working directory for this stuff | 108 | # Make the working directory for this stuff |
| 87 | rm -rf install_temp | 109 | rm -rf install_temp |
| 88 | mkdir -p install_temp/lib/$(ANDROID_ABI) | 110 | mkdir -p install_temp/lib/$(ANDROID_ABI) |
| @@ -106,6 +128,9 @@ emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) AndroidManifest.xml | |||
| 106 | rm -rf $${subdir}/[mM]akefile*[.-]in ; \ | 128 | rm -rf $${subdir}/[mM]akefile*[.-]in ; \ |
| 107 | rm -rf $${subdir}/Makefile; \ | 129 | rm -rf $${subdir}/Makefile; \ |
| 108 | done | 130 | done |
| 131 | # Generate the directory tree for those directories. | ||
| 132 | $(libsrc)/asset-directory-tool install_temp/assets \ | ||
| 133 | install_temp/assets/directory-tree | ||
| 109 | # Install architecture dependents to lib/$(ANDROID_ABI). This | 134 | # Install architecture dependents to lib/$(ANDROID_ABI). This |
| 110 | # perculiar naming scheme is required to make Android preserve these | 135 | # perculiar naming scheme is required to make Android preserve these |
| 111 | # binaries upon installation. | 136 | # binaries upon installation. |
| @@ -120,10 +145,12 @@ emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) AndroidManifest.xml | |||
| 120 | cp -f $$file install_temp/lib/$(ANDROID_ABI); \ | 145 | cp -f $$file install_temp/lib/$(ANDROID_ABI); \ |
| 121 | fi \ | 146 | fi \ |
| 122 | done | 147 | done |
| 123 | # Package everything. | 148 | # Package everything. Specifying the assets on this command line is |
| 124 | $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f -M AndroidManifest.xml | 149 | # necessary for AAssetManager_getNextFileName to work on old versions |
| 150 | # of Android. | ||
| 151 | $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f -M AndroidManifest.xml \ | ||
| 152 | -A install_temp/assets | ||
| 125 | pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd | 153 | pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd |
| 126 | pushd install_temp; $(AAPT) add ../$@ `find assets -type f`; popd | ||
| 127 | rm -rf install_temp | 154 | rm -rf install_temp |
| 128 | 155 | ||
| 129 | # Makefile itself. | 156 | # Makefile itself. |
diff --git a/java/debug.sh b/java/debug.sh index aa80aeeebcd..7008664c049 100755 --- a/java/debug.sh +++ b/java/debug.sh | |||
| @@ -93,7 +93,7 @@ while [ $# -gt 0 ]; do | |||
| 93 | shift | 93 | shift |
| 94 | done | 94 | done |
| 95 | 95 | ||
| 96 | if [ -z $devices ]; then | 96 | if [ -z "$devices" ]; then |
| 97 | echo "No devices are available." | 97 | echo "No devices are available." |
| 98 | exit 1 | 98 | exit 1 |
| 99 | fi | 99 | fi |
| @@ -117,25 +117,43 @@ if [ -z $app_data_dir ]; then | |||
| 117 | echo "Is it installed?" | 117 | echo "Is it installed?" |
| 118 | fi | 118 | fi |
| 119 | 119 | ||
| 120 | echo "Found application data directory at $app_data_dir..." | 120 | echo "Found application data directory at" "$app_data_dir" |
| 121 | 121 | ||
| 122 | # Find which PIDs are associated with org.gnu.emacs | 122 | # Generate an awk script to extract PIDs from Android ps output. It |
| 123 | package_uid=`adb -s $device shell run-as $package id -u` | 123 | # is enough to run `ps' as the package user on newer versions of |
| 124 | 124 | # Android, but that doesn't work on Android 2.3. | |
| 125 | if [ -z $package_uid ]; then | 125 | cat << EOF > tmp.awk |
| 126 | echo "Failed to obtain UID of packages named $package" | 126 | BEGIN { |
| 127 | exit 1 | 127 | pid = 0; |
| 128 | fi | 128 | pid_column = 2; |
| 129 | 129 | } | |
| 130 | # First, run ps -u $package_uid -o PID,CMD to fetch the list of | 130 | |
| 131 | # process IDs. | 131 | { |
| 132 | package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD` | 132 | # Remove any trailing carriage return from the input line. |
| 133 | 133 | gsub ("\r", "", \$NF) | |
| 134 | # Next, remove lines matching "ps" itself. | 134 | |
| 135 | package_pids=`awk -- '{ | 135 | # If this is line 1, figure out which column contains the PID. |
| 136 | if (!match ($0, /(PID|ps)/)) | 136 | if (NR == 1) |
| 137 | print $1 | 137 | { |
| 138 | }' <<< $package_pids` | 138 | for (n = 1; n <= NF; ++n) |
| 139 | { | ||
| 140 | if (\$n == "PID") | ||
| 141 | pid_column=n; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | else if (\$NF == "$package") | ||
| 145 | print \$pid_column | ||
| 146 | } | ||
| 147 | EOF | ||
| 148 | |||
| 149 | # Make sure that file disappears once this script exits. | ||
| 150 | trap "rm -f $(pwd)/tmp.awk" 0 | ||
| 151 | |||
| 152 | # First, run ps to fetch the list of process IDs. | ||
| 153 | package_pids=`adb -s $device shell ps` | ||
| 154 | |||
| 155 | # Next, extract the list of PIDs currently running. | ||
| 156 | package_pids=`awk -f tmp.awk <<< $package_pids` | ||
| 139 | 157 | ||
| 140 | if [ "$attach_existing" != "yes" ]; then | 158 | if [ "$attach_existing" != "yes" ]; then |
| 141 | # Finally, kill each existing process. | 159 | # Finally, kill each existing process. |
| @@ -149,19 +167,20 @@ if [ "$attach_existing" != "yes" ]; then | |||
| 149 | echo "Starting activity $activity and attaching debugger" | 167 | echo "Starting activity $activity and attaching debugger" |
| 150 | 168 | ||
| 151 | # Exit if the activity could not be started. | 169 | # Exit if the activity could not be started. |
| 152 | adb -s $device shell am start -D "$package/$activity" | 170 | adb -s $device shell am start -D -n "$package/$activity" |
| 153 | if [ ! $? ]; then | 171 | if [ ! $? ]; then |
| 154 | exit 1; | 172 | exit 1; |
| 155 | fi | 173 | fi |
| 156 | 174 | ||
| 175 | # Sleep for a bit. Otherwise, the process may not have started | ||
| 176 | # yet. | ||
| 177 | sleep 1 | ||
| 178 | |||
| 157 | # Now look for processes matching the package again. | 179 | # Now look for processes matching the package again. |
| 158 | package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD` | 180 | package_pids=`adb -s $device shell ps` |
| 159 | 181 | ||
| 160 | # Next, remove lines matching "ps" itself. | 182 | # Next, remove lines matching "ps" itself. |
| 161 | package_pids=`awk -- '{ | 183 | package_pids=`awk -f tmp.awk <<< $package_pids` |
| 162 | if (!match ($0, /(PID|ps)/)) | ||
| 163 | print $1 | ||
| 164 | }' <<< $package_pids` | ||
| 165 | fi | 184 | fi |
| 166 | 185 | ||
| 167 | pid=$package_pids | 186 | pid=$package_pids |
| @@ -170,10 +189,10 @@ num_pids=`wc -w <<< "$package_pids"` | |||
| 170 | if [ $num_pids -gt 1 ]; then | 189 | if [ $num_pids -gt 1 ]; then |
| 171 | echo "More than one process was started:" | 190 | echo "More than one process was started:" |
| 172 | echo "" | 191 | echo "" |
| 173 | adb -s $device shell run-as $package ps -u $package_uid | awk -- '{ | 192 | adb -s $device shell run-as $package ps | awk -- "{ |
| 174 | if (!match ($0, /ps/)) | 193 | if (!match (\$0, /ps/) && match (\$0, /$package/)) |
| 175 | print $0 | 194 | print \$0 |
| 176 | }' | 195 | }" |
| 177 | echo "" | 196 | echo "" |
| 178 | printf "Which one do you want to attach to? " | 197 | printf "Which one do you want to attach to? " |
| 179 | read pid | 198 | read pid |
| @@ -182,10 +201,12 @@ elif [ -z $package_pids ]; then | |||
| 182 | exit 1 | 201 | exit 1 |
| 183 | fi | 202 | fi |
| 184 | 203 | ||
| 185 | # This isn't necessary when attaching gdb to an existing process. | 204 | # If either --jdb was specified or debug.sh is not connecting to an |
| 205 | # existing process, then store a suitable JDB invocation in | ||
| 206 | # jdb_command. GDB will then run JDB to unblock the application from | ||
| 207 | # the wait dialog after startup. | ||
| 208 | |||
| 186 | if [ "$jdb" = "yes" ] || [ "$attach_existing" != yes ]; then | 209 | if [ "$jdb" = "yes" ] || [ "$attach_existing" != yes ]; then |
| 187 | # Start JDB to make the wait dialog disappear. | ||
| 188 | echo "Attaching JDB to unblock the application." | ||
| 189 | adb -s $device forward --remove-all | 210 | adb -s $device forward --remove-all |
| 190 | adb -s $device forward "tcp:$jdb_port" "jdwp:$pid" | 211 | adb -s $device forward "tcp:$jdb_port" "jdwp:$pid" |
| 191 | 212 | ||
| @@ -203,20 +224,42 @@ if [ "$jdb" = "yes" ] || [ "$attach_existing" != yes ]; then | |||
| 203 | $jdb_command | 224 | $jdb_command |
| 204 | exit 1 | 225 | exit 1 |
| 205 | fi | 226 | fi |
| 227 | fi | ||
| 206 | 228 | ||
| 207 | exec 4<> /tmp/file-descriptor-stamp | 229 | if [ -n "$jdb_command" ]; then |
| 230 | echo "Starting JDB to unblock application." | ||
| 208 | 231 | ||
| 209 | # Now run JDB with IO redirected to file descriptor 4 in a subprocess. | 232 | # Start JDB to unblock the application. |
| 210 | $jdb_command <&4 >&4 & | 233 | coproc JDB { $jdb_command; } |
| 211 | 234 | ||
| 212 | character= | 235 | # Tell JDB to first suspend all threads. |
| 213 | # Next, wait until the prompt is found. | 236 | echo "suspend" >&${JDB[1]} |
| 214 | while read -n1 -u 4 character; do | 237 | |
| 215 | if [ "$character" = ">" ]; then | 238 | # Tell JDB to print a magic string once the program is |
| 216 | echo "JDB attached successfully" | 239 | # initialized. |
| 217 | break; | 240 | echo "print \"__verify_jdb_has_started__\"" >&${JDB[1]} |
| 241 | |||
| 242 | # Now wait for JDB to give the string back. | ||
| 243 | line= | ||
| 244 | while :; do | ||
| 245 | read -u ${JDB[0]} line | ||
| 246 | if [ ! $? ]; then | ||
| 247 | echo "Failed to read JDB output" | ||
| 248 | exit 1 | ||
| 218 | fi | 249 | fi |
| 250 | |||
| 251 | case "$line" in | ||
| 252 | *__verify_jdb_has_started__*) | ||
| 253 | # Android only polls for a Java debugger every 200ms, so | ||
| 254 | # the debugger must be connected for at least that long. | ||
| 255 | echo "Pausing 1 second for the program to continue." | ||
| 256 | sleep 1 | ||
| 257 | break | ||
| 258 | ;; | ||
| 259 | esac | ||
| 219 | done | 260 | done |
| 261 | |||
| 262 | # Note that JDB does not exit until GDB is fully attached! | ||
| 220 | fi | 263 | fi |
| 221 | 264 | ||
| 222 | # See if gdbserver has to be uploaded | 265 | # See if gdbserver has to be uploaded |
| @@ -234,18 +277,19 @@ fi | |||
| 234 | 277 | ||
| 235 | echo "Attaching gdbserver to $pid on $device..." | 278 | echo "Attaching gdbserver to $pid on $device..." |
| 236 | exec 5<> /tmp/file-descriptor-stamp | 279 | exec 5<> /tmp/file-descriptor-stamp |
| 280 | rm -f /tmp/file-descriptor-stamp | ||
| 237 | 281 | ||
| 238 | if [ -z "$gdbserver" ]; then | 282 | if [ -z "$gdbserver" ]; then |
| 239 | adb -s $device shell run-as $package $gdbserver_bin --once \ | 283 | adb -s $device shell run-as $package $gdbserver_bin --once \ |
| 240 | "+debug.$package_uid.socket" --attach $pid >&5 & | 284 | "+debug.$package.socket" --attach $pid >&5 & |
| 241 | gdb_socket="localfilesystem:$app_data_dir/debug.$package_uid.socket" | 285 | gdb_socket="localfilesystem:$app_data_dir/debug.$package.socket" |
| 242 | else | 286 | else |
| 243 | # Normally the program cannot access $gdbserver_bin when it is | 287 | # Normally the program cannot access $gdbserver_bin when it is |
| 244 | # placed in /data/local/tmp. | 288 | # placed in /data/local/tmp. |
| 245 | adb -s $device shell $gdbserver_bin --once \ | 289 | adb -s $device shell $gdbserver_bin --once \ |
| 246 | "+/data/local/tmp/debug.$package_uid.socket" \ | 290 | "+/data/local/tmp/debug.$package.socket" \ |
| 247 | --attach $pid >&5 & | 291 | --attach $pid >&5 & |
| 248 | gdb_socket="localfilesystem:/data/local/tmp/debug.$package_uid.socket" | 292 | gdb_socket="localfilesystem:/data/local/tmp/debug.$package.socket" |
| 249 | fi | 293 | fi |
| 250 | 294 | ||
| 251 | # Wait until gdbserver successfully runs. | 295 | # Wait until gdbserver successfully runs. |
| @@ -256,7 +300,7 @@ while read -u 5 line; do | |||
| 256 | break; | 300 | break; |
| 257 | ;; | 301 | ;; |
| 258 | *error* | *Error* | failed ) | 302 | *error* | *Error* | failed ) |
| 259 | echo $line | 303 | echo "GDB error:" $line |
| 260 | exit 1 | 304 | exit 1 |
| 261 | ;; | 305 | ;; |
| 262 | * ) | 306 | * ) |
| @@ -264,19 +308,18 @@ while read -u 5 line; do | |||
| 264 | esac | 308 | esac |
| 265 | done | 309 | done |
| 266 | 310 | ||
| 267 | if [ "$attach_existing" != "yes" ]; then | 311 | # Now that GDB is attached, tell the Java debugger to resume execution |
| 268 | # Send EOF to JDB to make it go away. This will also cause | 312 | # and then exit. |
| 269 | # Android to allow Emacs to continue executing. | 313 | |
| 270 | echo "Making JDB go away..." | 314 | if [ -n "$jdb_command" ]; then |
| 271 | echo "exit" >&4 | 315 | echo "resume" >&${JDB[1]} |
| 272 | read -u 4 line | 316 | echo "exit" >&${JDB[1]} |
| 273 | echo "JDB has gone away with $line" | ||
| 274 | fi | 317 | fi |
| 275 | 318 | ||
| 276 | # Forward the gdb server port here. | 319 | # Forward the gdb server port here. |
| 277 | adb -s $device forward "tcp:$gdb_port" $gdb_socket | 320 | adb -s $device forward "tcp:$gdb_port" $gdb_socket |
| 278 | if [ ! $? ]; then | 321 | if [ ! $? ]; then |
| 279 | echo "Failed to forward $app_data_dir/debug.$package_uid.socket" | 322 | echo "Failed to forward $app_data_dir/debug.$package.socket" |
| 280 | echo "to $gdb_port! Perhaps you need to specify a different port" | 323 | echo "to $gdb_port! Perhaps you need to specify a different port" |
| 281 | echo "with --port?" | 324 | echo "with --port?" |
| 282 | exit 1; | 325 | exit 1; |
| @@ -284,4 +327,4 @@ fi | |||
| 284 | 327 | ||
| 285 | # Finally, start gdb with any extra arguments needed. | 328 | # Finally, start gdb with any extra arguments needed. |
| 286 | cd "$oldpwd" | 329 | cd "$oldpwd" |
| 287 | gdb --eval-command "" --eval-command "target remote localhost:$gdb_port" $gdbargs | 330 | gdb --eval-command "target remote localhost:$gdb_port" $gdbargs |
diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java index 00e204c9949..ac67ebe4aa0 100644 --- a/java/org/gnu/emacs/EmacsContextMenu.java +++ b/java/org/gnu/emacs/EmacsContextMenu.java | |||
| @@ -168,10 +168,22 @@ public class EmacsContextMenu | |||
| 168 | { | 168 | { |
| 169 | if (item.subMenu != null) | 169 | if (item.subMenu != null) |
| 170 | { | 170 | { |
| 171 | /* This is a submenu. Create the submenu and add the | 171 | try |
| 172 | contents of the menu to it. */ | 172 | { |
| 173 | submenu = menu.addSubMenu (item.itemName); | 173 | /* This is a submenu. On versions of Android which |
| 174 | item.subMenu.inflateMenuItems (submenu); | 174 | support doing so, create the submenu and add the |
| 175 | contents of the menu to it. */ | ||
| 176 | submenu = menu.addSubMenu (item.itemName); | ||
| 177 | } | ||
| 178 | catch (UnsupportedOperationException exception) | ||
| 179 | { | ||
| 180 | /* This version of Android has a restriction | ||
| 181 | preventing submenus from being added to submenus. | ||
| 182 | Inflate everything into the parent menu | ||
| 183 | instead. */ | ||
| 184 | item.subMenu.inflateMenuItems (menu); | ||
| 185 | continue; | ||
| 186 | } | ||
| 175 | 187 | ||
| 176 | /* This is still needed to set wasSubmenuSelected. */ | 188 | /* This is still needed to set wasSubmenuSelected. */ |
| 177 | menuItem = submenu.getItem (); | 189 | menuItem = submenu.getItem (); |
diff --git a/java/org/gnu/emacs/EmacsCopyArea.java b/java/org/gnu/emacs/EmacsCopyArea.java index 5d72a7860c8..7a97d706794 100644 --- a/java/org/gnu/emacs/EmacsCopyArea.java +++ b/java/org/gnu/emacs/EmacsCopyArea.java | |||
| @@ -66,19 +66,11 @@ public class EmacsCopyArea | |||
| 66 | 66 | ||
| 67 | paint = gc.gcPaint; | 67 | paint = gc.gcPaint; |
| 68 | 68 | ||
| 69 | canvas = destination.lockCanvas (); | 69 | canvas = destination.lockCanvas (gc); |
| 70 | 70 | ||
| 71 | if (canvas == null) | 71 | if (canvas == null) |
| 72 | return; | 72 | return; |
| 73 | 73 | ||
| 74 | canvas.save (); | ||
| 75 | |||
| 76 | if (gc.real_clip_rects != null) | ||
| 77 | { | ||
| 78 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 79 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* A copy must be created or drawBitmap could end up overwriting | 74 | /* A copy must be created or drawBitmap could end up overwriting |
| 83 | itself. */ | 75 | itself. */ |
| 84 | srcBitmap = source.getBitmap (); | 76 | srcBitmap = source.getBitmap (); |
| @@ -189,7 +181,6 @@ public class EmacsCopyArea | |||
| 189 | maskBitmap.recycle (); | 181 | maskBitmap.recycle (); |
| 190 | } | 182 | } |
| 191 | 183 | ||
| 192 | canvas.restore (); | ||
| 193 | destination.damageRect (rect); | 184 | destination.damageRect (rect); |
| 194 | } | 185 | } |
| 195 | } | 186 | } |
diff --git a/java/org/gnu/emacs/EmacsDialog.java b/java/org/gnu/emacs/EmacsDialog.java index 5bc8efa5978..7d88a23c58f 100644 --- a/java/org/gnu/emacs/EmacsDialog.java +++ b/java/org/gnu/emacs/EmacsDialog.java | |||
| @@ -168,9 +168,6 @@ public class EmacsDialog implements DialogInterface.OnDismissListener | |||
| 168 | button = buttons.get (1); | 168 | button = buttons.get (1); |
| 169 | dialog.setButton (DialogInterface.BUTTON_NEUTRAL, | 169 | dialog.setButton (DialogInterface.BUTTON_NEUTRAL, |
| 170 | button.name, button); | 170 | button.name, button); |
| 171 | buttonView | ||
| 172 | = dialog.getButton (DialogInterface.BUTTON_NEUTRAL); | ||
| 173 | buttonView.setEnabled (button.enabled); | ||
| 174 | } | 171 | } |
| 175 | 172 | ||
| 176 | if (size >= 3) | 173 | if (size >= 3) |
diff --git a/java/org/gnu/emacs/EmacsDrawLine.java b/java/org/gnu/emacs/EmacsDrawLine.java index 8941d4c217f..827feb96dfb 100644 --- a/java/org/gnu/emacs/EmacsDrawLine.java +++ b/java/org/gnu/emacs/EmacsDrawLine.java | |||
| @@ -49,19 +49,11 @@ public class EmacsDrawLine | |||
| 49 | Math.min (y, y2 + 1), | 49 | Math.min (y, y2 + 1), |
| 50 | Math.max (x2 + 1, x), | 50 | Math.max (x2 + 1, x), |
| 51 | Math.max (y2 + 1, y)); | 51 | Math.max (y2 + 1, y)); |
| 52 | canvas = drawable.lockCanvas (); | 52 | canvas = drawable.lockCanvas (gc); |
| 53 | 53 | ||
| 54 | if (canvas == null) | 54 | if (canvas == null) |
| 55 | return; | 55 | return; |
| 56 | 56 | ||
| 57 | canvas.save (); | ||
| 58 | |||
| 59 | if (gc.real_clip_rects != null) | ||
| 60 | { | ||
| 61 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 62 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 63 | } | ||
| 64 | |||
| 65 | paint.setStyle (Paint.Style.STROKE); | 57 | paint.setStyle (Paint.Style.STROKE); |
| 66 | 58 | ||
| 67 | if (gc.clip_mask == null) | 59 | if (gc.clip_mask == null) |
| @@ -71,7 +63,6 @@ public class EmacsDrawLine | |||
| 71 | 63 | ||
| 72 | /* DrawLine with clip mask not implemented; it is not used by | 64 | /* DrawLine with clip mask not implemented; it is not used by |
| 73 | Emacs. */ | 65 | Emacs. */ |
| 74 | canvas.restore (); | ||
| 75 | drawable.damageRect (rect); | 66 | drawable.damageRect (rect); |
| 76 | } | 67 | } |
| 77 | } | 68 | } |
diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java b/java/org/gnu/emacs/EmacsDrawRectangle.java index c29d413f66e..695a8c6ea44 100644 --- a/java/org/gnu/emacs/EmacsDrawRectangle.java +++ b/java/org/gnu/emacs/EmacsDrawRectangle.java | |||
| @@ -23,6 +23,7 @@ import android.graphics.Bitmap; | |||
| 23 | import android.graphics.Canvas; | 23 | import android.graphics.Canvas; |
| 24 | import android.graphics.Paint; | 24 | import android.graphics.Paint; |
| 25 | import android.graphics.Rect; | 25 | import android.graphics.Rect; |
| 26 | import android.graphics.RectF; | ||
| 26 | 27 | ||
| 27 | import android.util.Log; | 28 | import android.util.Log; |
| 28 | 29 | ||
| @@ -36,51 +37,31 @@ public class EmacsDrawRectangle | |||
| 36 | Paint maskPaint, paint; | 37 | Paint maskPaint, paint; |
| 37 | Canvas maskCanvas; | 38 | Canvas maskCanvas; |
| 38 | Bitmap maskBitmap; | 39 | Bitmap maskBitmap; |
| 40 | Rect rect; | ||
| 39 | Rect maskRect, dstRect; | 41 | Rect maskRect, dstRect; |
| 40 | Canvas canvas; | 42 | Canvas canvas; |
| 41 | Bitmap clipBitmap; | 43 | Bitmap clipBitmap; |
| 42 | Rect clipRect; | ||
| 43 | 44 | ||
| 44 | /* TODO implement stippling. */ | 45 | /* TODO implement stippling. */ |
| 45 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 46 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 46 | return; | 47 | return; |
| 47 | 48 | ||
| 48 | canvas = drawable.lockCanvas (); | 49 | canvas = drawable.lockCanvas (gc); |
| 49 | 50 | ||
| 50 | if (canvas == null) | 51 | if (canvas == null) |
| 51 | return; | 52 | return; |
| 52 | 53 | ||
| 53 | canvas.save (); | ||
| 54 | |||
| 55 | if (gc.real_clip_rects != null) | ||
| 56 | { | ||
| 57 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 58 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 59 | } | ||
| 60 | |||
| 61 | /* Clip to the clipRect because some versions of Android draw an | ||
| 62 | overly wide line. */ | ||
| 63 | clipRect = new Rect (x, y, x + width + 1, | ||
| 64 | y + height + 1); | ||
| 65 | canvas.clipRect (clipRect); | ||
| 66 | |||
| 67 | paint = gc.gcPaint; | 54 | paint = gc.gcPaint; |
| 55 | paint.setStyle (Paint.Style.STROKE); | ||
| 56 | rect = new Rect (x, y, x + width, y + height); | ||
| 68 | 57 | ||
| 69 | if (gc.clip_mask == null) | 58 | if (gc.clip_mask == null) |
| 70 | { | 59 | /* Use canvas.drawRect with a RectF. That seems to reliably |
| 71 | /* canvas.drawRect just doesn't work on Android, producing | 60 | get PostScript behavior. */ |
| 72 | different results on various devices. Do a 5 point | 61 | canvas.drawRect (new RectF (x + 0.5f, y + 0.5f, |
| 73 | PolyLine instead. */ | 62 | x + width + 0.5f, |
| 74 | canvas.drawLine ((float) x, (float) y, (float) x + width, | 63 | y + height + 0.5f), |
| 75 | (float) y, paint); | 64 | paint); |
| 76 | canvas.drawLine ((float) x + width, (float) y, | ||
| 77 | (float) x + width, (float) y + height, | ||
| 78 | paint); | ||
| 79 | canvas.drawLine ((float) x + width, (float) y + height, | ||
| 80 | (float) x, (float) y + height, paint); | ||
| 81 | canvas.drawLine ((float) x, (float) y + height, | ||
| 82 | (float) x, (float) y, paint); | ||
| 83 | } | ||
| 84 | else | 65 | else |
| 85 | { | 66 | { |
| 86 | /* Drawing with a clip mask involves calculating the | 67 | /* Drawing with a clip mask involves calculating the |
| @@ -137,7 +118,7 @@ public class EmacsDrawRectangle | |||
| 137 | maskBitmap.recycle (); | 118 | maskBitmap.recycle (); |
| 138 | } | 119 | } |
| 139 | 120 | ||
| 140 | canvas.restore (); | 121 | drawable.damageRect (new Rect (x, y, x + width + 1, |
| 141 | drawable.damageRect (clipRect); | 122 | y + height + 1)); |
| 142 | } | 123 | } |
| 143 | } | 124 | } |
diff --git a/java/org/gnu/emacs/EmacsDrawable.java b/java/org/gnu/emacs/EmacsDrawable.java index 6a6199ff214..f2f8885e976 100644 --- a/java/org/gnu/emacs/EmacsDrawable.java +++ b/java/org/gnu/emacs/EmacsDrawable.java | |||
| @@ -25,7 +25,7 @@ import android.graphics.Canvas; | |||
| 25 | 25 | ||
| 26 | public interface EmacsDrawable | 26 | public interface EmacsDrawable |
| 27 | { | 27 | { |
| 28 | public Canvas lockCanvas (); | 28 | public Canvas lockCanvas (EmacsGC gc); |
| 29 | public void damageRect (Rect damageRect); | 29 | public void damageRect (Rect damageRect); |
| 30 | public Bitmap getBitmap (); | 30 | public Bitmap getBitmap (); |
| 31 | public boolean isDestroyed (); | 31 | public boolean isDestroyed (); |
diff --git a/java/org/gnu/emacs/EmacsFillPolygon.java b/java/org/gnu/emacs/EmacsFillPolygon.java index 42b73886dff..22e2dd0d8a9 100644 --- a/java/org/gnu/emacs/EmacsFillPolygon.java +++ b/java/org/gnu/emacs/EmacsFillPolygon.java | |||
| @@ -41,21 +41,13 @@ public class EmacsFillPolygon | |||
| 41 | RectF rectF; | 41 | RectF rectF; |
| 42 | int i; | 42 | int i; |
| 43 | 43 | ||
| 44 | canvas = drawable.lockCanvas (); | 44 | canvas = drawable.lockCanvas (gc); |
| 45 | 45 | ||
| 46 | if (canvas == null) | 46 | if (canvas == null) |
| 47 | return; | 47 | return; |
| 48 | 48 | ||
| 49 | paint = gc.gcPaint; | 49 | paint = gc.gcPaint; |
| 50 | 50 | ||
| 51 | canvas.save (); | ||
| 52 | |||
| 53 | if (gc.real_clip_rects != null) | ||
| 54 | { | ||
| 55 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 56 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 57 | } | ||
| 58 | |||
| 59 | /* Build the path from the given array of points. */ | 51 | /* Build the path from the given array of points. */ |
| 60 | path = new Path (); | 52 | path = new Path (); |
| 61 | 53 | ||
| @@ -83,7 +75,6 @@ public class EmacsFillPolygon | |||
| 83 | if (gc.clip_mask == null) | 75 | if (gc.clip_mask == null) |
| 84 | canvas.drawPath (path, paint); | 76 | canvas.drawPath (path, paint); |
| 85 | 77 | ||
| 86 | canvas.restore (); | ||
| 87 | drawable.damageRect (rect); | 78 | drawable.damageRect (rect); |
| 88 | 79 | ||
| 89 | /* FillPolygon with clip mask not implemented; it is not used by | 80 | /* FillPolygon with clip mask not implemented; it is not used by |
diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java b/java/org/gnu/emacs/EmacsFillRectangle.java index 7cc55d3db96..aed0a540c8f 100644 --- a/java/org/gnu/emacs/EmacsFillRectangle.java +++ b/java/org/gnu/emacs/EmacsFillRectangle.java | |||
| @@ -32,7 +32,6 @@ public class EmacsFillRectangle | |||
| 32 | perform (EmacsDrawable drawable, EmacsGC gc, | 32 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 33 | int x, int y, int width, int height) | 33 | int x, int y, int width, int height) |
| 34 | { | 34 | { |
| 35 | int i; | ||
| 36 | Paint maskPaint, paint; | 35 | Paint maskPaint, paint; |
| 37 | Canvas maskCanvas; | 36 | Canvas maskCanvas; |
| 38 | Bitmap maskBitmap; | 37 | Bitmap maskBitmap; |
| @@ -45,19 +44,11 @@ public class EmacsFillRectangle | |||
| 45 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 44 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 46 | return; | 45 | return; |
| 47 | 46 | ||
| 48 | canvas = drawable.lockCanvas (); | 47 | canvas = drawable.lockCanvas (gc); |
| 49 | 48 | ||
| 50 | if (canvas == null) | 49 | if (canvas == null) |
| 51 | return; | 50 | return; |
| 52 | 51 | ||
| 53 | canvas.save (); | ||
| 54 | |||
| 55 | if (gc.real_clip_rects != null) | ||
| 56 | { | ||
| 57 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 58 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 59 | } | ||
| 60 | |||
| 61 | paint = gc.gcPaint; | 52 | paint = gc.gcPaint; |
| 62 | rect = new Rect (x, y, x + width, y + height); | 53 | rect = new Rect (x, y, x + width, y + height); |
| 63 | 54 | ||
| @@ -120,7 +111,6 @@ public class EmacsFillRectangle | |||
| 120 | maskBitmap.recycle (); | 111 | maskBitmap.recycle (); |
| 121 | } | 112 | } |
| 122 | 113 | ||
| 123 | canvas.restore (); | ||
| 124 | drawable.damageRect (rect); | 114 | drawable.damageRect (rect); |
| 125 | } | 115 | } |
| 126 | } | 116 | } |
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index c579625f3f7..bdc27a1ca5b 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java | |||
| @@ -47,6 +47,14 @@ public class EmacsGC extends EmacsHandleObject | |||
| 47 | public EmacsPixmap clip_mask, stipple; | 47 | public EmacsPixmap clip_mask, stipple; |
| 48 | public Paint gcPaint; | 48 | public Paint gcPaint; |
| 49 | 49 | ||
| 50 | /* ID incremented every time the clipping rectangles of any GC | ||
| 51 | changes. */ | ||
| 52 | private static long clip_serial; | ||
| 53 | |||
| 54 | /* The value of clipRectID after the last time this GCs clip | ||
| 55 | rectangles changed. 0 if there are no clip rectangles. */ | ||
| 56 | public long clipRectID; | ||
| 57 | |||
| 50 | static | 58 | static |
| 51 | { | 59 | { |
| 52 | xorAlu = new PorterDuffXfermode (Mode.XOR); | 60 | xorAlu = new PorterDuffXfermode (Mode.XOR); |
| @@ -75,23 +83,28 @@ public class EmacsGC extends EmacsHandleObject | |||
| 75 | recompute real_clip_rects. */ | 83 | recompute real_clip_rects. */ |
| 76 | 84 | ||
| 77 | public void | 85 | public void |
| 78 | markDirty () | 86 | markDirty (boolean clipRectsChanged) |
| 79 | { | 87 | { |
| 80 | int i; | 88 | int i; |
| 81 | 89 | ||
| 82 | if ((ts_origin_x != 0 || ts_origin_y != 0) | 90 | if (clipRectsChanged) |
| 83 | && clip_rects != null) | ||
| 84 | { | 91 | { |
| 85 | real_clip_rects = new Rect[clip_rects.length]; | 92 | if ((ts_origin_x != 0 || ts_origin_y != 0) |
| 86 | 93 | && clip_rects != null) | |
| 87 | for (i = 0; i < clip_rects.length; ++i) | ||
| 88 | { | 94 | { |
| 89 | real_clip_rects[i] = new Rect (clip_rects[i]); | 95 | real_clip_rects = new Rect[clip_rects.length]; |
| 90 | real_clip_rects[i].offset (ts_origin_x, ts_origin_y); | 96 | |
| 97 | for (i = 0; i < clip_rects.length; ++i) | ||
| 98 | { | ||
| 99 | real_clip_rects[i] = new Rect (clip_rects[i]); | ||
| 100 | real_clip_rects[i].offset (ts_origin_x, ts_origin_y); | ||
| 101 | } | ||
| 91 | } | 102 | } |
| 103 | else | ||
| 104 | real_clip_rects = clip_rects; | ||
| 105 | |||
| 106 | clipRectID = ++clip_serial; | ||
| 92 | } | 107 | } |
| 93 | else | ||
| 94 | real_clip_rects = clip_rects; | ||
| 95 | 108 | ||
| 96 | gcPaint.setStrokeWidth (1f); | 109 | gcPaint.setStrokeWidth (1f); |
| 97 | gcPaint.setColor (foreground | 0xff000000); | 110 | gcPaint.setColor (foreground | 0xff000000); |
diff --git a/java/org/gnu/emacs/EmacsPixmap.java b/java/org/gnu/emacs/EmacsPixmap.java index 85931c2abd4..a83d8f25542 100644 --- a/java/org/gnu/emacs/EmacsPixmap.java +++ b/java/org/gnu/emacs/EmacsPixmap.java | |||
| @@ -42,6 +42,14 @@ public class EmacsPixmap extends EmacsHandleObject | |||
| 42 | /* The canvas used to draw to BITMAP. */ | 42 | /* The canvas used to draw to BITMAP. */ |
| 43 | public Canvas canvas; | 43 | public Canvas canvas; |
| 44 | 44 | ||
| 45 | /* Whether or not GC should be explicitly triggered upon | ||
| 46 | release. */ | ||
| 47 | private boolean needCollect; | ||
| 48 | |||
| 49 | /* ID used to determine whether or not the GC clip rects | ||
| 50 | changed. */ | ||
| 51 | private long gcClipRectID; | ||
| 52 | |||
| 45 | public | 53 | public |
| 46 | EmacsPixmap (short handle, int colors[], int width, | 54 | EmacsPixmap (short handle, int colors[], int width, |
| 47 | int height, int depth) | 55 | int height, int depth) |
| @@ -83,18 +91,41 @@ public class EmacsPixmap extends EmacsHandleObject | |||
| 83 | switch (depth) | 91 | switch (depth) |
| 84 | { | 92 | { |
| 85 | case 1: | 93 | case 1: |
| 86 | bitmap = Bitmap.createBitmap (width, height, | 94 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) |
| 87 | Bitmap.Config.ALPHA_8, | 95 | bitmap = Bitmap.createBitmap (width, height, |
| 88 | false); | 96 | Bitmap.Config.ALPHA_8, |
| 97 | false); | ||
| 98 | else | ||
| 99 | bitmap = Bitmap.createBitmap (width, height, | ||
| 100 | Bitmap.Config.ALPHA_8); | ||
| 89 | break; | 101 | break; |
| 90 | 102 | ||
| 91 | case 24: | 103 | case 24: |
| 92 | bitmap = Bitmap.createBitmap (width, height, | 104 | |
| 93 | Bitmap.Config.ARGB_8888, | 105 | /* Emacs doesn't just use the first kind of `createBitmap' |
| 94 | false); | 106 | because the latter allows specifying that the pixmap is |
| 107 | always opaque, which really increases efficiency. */ | ||
| 108 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) | ||
| 109 | bitmap = Bitmap.createBitmap (width, height, | ||
| 110 | Bitmap.Config.ARGB_8888); | ||
| 111 | else | ||
| 112 | bitmap = Bitmap.createBitmap (width, height, | ||
| 113 | Bitmap.Config.ARGB_8888, | ||
| 114 | false); | ||
| 95 | break; | 115 | break; |
| 96 | } | 116 | } |
| 97 | 117 | ||
| 118 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) | ||
| 119 | /* On these old versions of Android, Bitmap.recycle frees bitmap | ||
| 120 | contents immediately. */ | ||
| 121 | needCollect = false; | ||
| 122 | else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) | ||
| 123 | needCollect = (bitmap.getByteCount () | ||
| 124 | >= 1024 * 512); | ||
| 125 | else | ||
| 126 | needCollect = (bitmap.getAllocationByteCount () | ||
| 127 | >= 1024 * 512); | ||
| 128 | |||
| 98 | bitmap.eraseColor (0xff000000); | 129 | bitmap.eraseColor (0xff000000); |
| 99 | 130 | ||
| 100 | this.width = width; | 131 | this.width = width; |
| @@ -104,11 +135,32 @@ public class EmacsPixmap extends EmacsHandleObject | |||
| 104 | 135 | ||
| 105 | @Override | 136 | @Override |
| 106 | public Canvas | 137 | public Canvas |
| 107 | lockCanvas () | 138 | lockCanvas (EmacsGC gc) |
| 108 | { | 139 | { |
| 140 | int i; | ||
| 141 | |||
| 109 | if (canvas == null) | 142 | if (canvas == null) |
| 110 | canvas = new Canvas (bitmap); | 143 | { |
| 144 | canvas = new Canvas (bitmap); | ||
| 145 | canvas.save (); | ||
| 146 | } | ||
| 111 | 147 | ||
| 148 | /* Now see if clipping has to be redone. */ | ||
| 149 | if (gc.clipRectID == gcClipRectID) | ||
| 150 | return canvas; | ||
| 151 | |||
| 152 | /* It does have to be redone. Reapply gc.real_clip_rects. */ | ||
| 153 | canvas.restore (); | ||
| 154 | canvas.save (); | ||
| 155 | |||
| 156 | if (gc.real_clip_rects != null) | ||
| 157 | { | ||
| 158 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 159 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 160 | } | ||
| 161 | |||
| 162 | /* Save the clip rect ID again. */ | ||
| 163 | gcClipRectID = gc.clipRectID; | ||
| 112 | return canvas; | 164 | return canvas; |
| 113 | } | 165 | } |
| 114 | 166 | ||
| @@ -130,15 +182,6 @@ public class EmacsPixmap extends EmacsHandleObject | |||
| 130 | public void | 182 | public void |
| 131 | destroyHandle () | 183 | destroyHandle () |
| 132 | { | 184 | { |
| 133 | boolean needCollect; | ||
| 134 | |||
| 135 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) | ||
| 136 | needCollect = (bitmap.getByteCount () | ||
| 137 | >= 1024 * 512); | ||
| 138 | else | ||
| 139 | needCollect = (bitmap.getAllocationByteCount () | ||
| 140 | >= 1024 * 512); | ||
| 141 | |||
| 142 | bitmap.recycle (); | 185 | bitmap.recycle (); |
| 143 | bitmap = null; | 186 | bitmap = null; |
| 144 | 187 | ||
diff --git a/java/org/gnu/emacs/EmacsSdk7FontDriver.java b/java/org/gnu/emacs/EmacsSdk7FontDriver.java index c0f24c7433a..a964cadb74c 100644 --- a/java/org/gnu/emacs/EmacsSdk7FontDriver.java +++ b/java/org/gnu/emacs/EmacsSdk7FontDriver.java | |||
| @@ -510,20 +510,12 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 510 | backgroundRect.right = x + backgroundWidth; | 510 | backgroundRect.right = x + backgroundWidth; |
| 511 | backgroundRect.bottom = y + sdk7FontObject.descent; | 511 | backgroundRect.bottom = y + sdk7FontObject.descent; |
| 512 | 512 | ||
| 513 | canvas = drawable.lockCanvas (); | 513 | canvas = drawable.lockCanvas (gc); |
| 514 | 514 | ||
| 515 | if (canvas == null) | 515 | if (canvas == null) |
| 516 | return 0; | 516 | return 0; |
| 517 | 517 | ||
| 518 | canvas.save (); | ||
| 519 | paint = gc.gcPaint; | 518 | paint = gc.gcPaint; |
| 520 | |||
| 521 | if (gc.real_clip_rects != null) | ||
| 522 | { | ||
| 523 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 524 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 525 | } | ||
| 526 | |||
| 527 | paint.setStyle (Paint.Style.FILL); | 519 | paint.setStyle (Paint.Style.FILL); |
| 528 | 520 | ||
| 529 | if (withBackground) | 521 | if (withBackground) |
| @@ -538,7 +530,6 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 538 | paint.setAntiAlias (true); | 530 | paint.setAntiAlias (true); |
| 539 | canvas.drawText (charsArray, 0, chars.length, x, y, paint); | 531 | canvas.drawText (charsArray, 0, chars.length, x, y, paint); |
| 540 | 532 | ||
| 541 | canvas.restore (); | ||
| 542 | bounds = new Rect (); | 533 | bounds = new Rect (); |
| 543 | paint.getTextBounds (charsArray, 0, chars.length, bounds); | 534 | paint.getTextBounds (charsArray, 0, chars.length, bounds); |
| 544 | bounds.offset (x, y); | 535 | bounds.offset (x, y); |
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index ca38f93dc98..bcf8d9ff6e8 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -175,7 +175,12 @@ public class EmacsService extends Service | |||
| 175 | { | 175 | { |
| 176 | view.thing = new EmacsView (window); | 176 | view.thing = new EmacsView (window); |
| 177 | view.thing.setVisibility (visibility); | 177 | view.thing.setVisibility (visibility); |
| 178 | view.thing.setFocusedByDefault (isFocusedByDefault); | 178 | |
| 179 | /* The following function is only present on Android 26 | ||
| 180 | or later. */ | ||
| 181 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) | ||
| 182 | view.thing.setFocusedByDefault (isFocusedByDefault); | ||
| 183 | |||
| 179 | notify (); | 184 | notify (); |
| 180 | } | 185 | } |
| 181 | } | 186 | } |
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 6137fd74a7f..82f44acaebe 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java | |||
| @@ -83,6 +83,9 @@ public class EmacsView extends ViewGroup | |||
| 83 | /* The last measured width and height. */ | 83 | /* The last measured width and height. */ |
| 84 | private int measuredWidth, measuredHeight; | 84 | private int measuredWidth, measuredHeight; |
| 85 | 85 | ||
| 86 | /* The serial of the last clip rectangle change. */ | ||
| 87 | private long lastClipSerial; | ||
| 88 | |||
| 86 | public | 89 | public |
| 87 | EmacsView (EmacsWindow window) | 90 | EmacsView (EmacsWindow window) |
| 88 | { | 91 | { |
| @@ -105,10 +108,6 @@ public class EmacsView extends ViewGroup | |||
| 105 | on Android? */ | 108 | on Android? */ |
| 106 | setChildrenDrawingOrderEnabled (true); | 109 | setChildrenDrawingOrderEnabled (true); |
| 107 | 110 | ||
| 108 | /* Get rid of the foreground and background tint. */ | ||
| 109 | setBackgroundTintList (null); | ||
| 110 | setForegroundTintList (null); | ||
| 111 | |||
| 112 | /* Get rid of the default focus highlight. */ | 111 | /* Get rid of the default focus highlight. */ |
| 113 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) | 112 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) |
| 114 | setDefaultFocusHighlightEnabled (false); | 113 | setDefaultFocusHighlightEnabled (false); |
| @@ -145,6 +144,11 @@ public class EmacsView extends ViewGroup | |||
| 145 | 144 | ||
| 146 | /* And canvases. */ | 145 | /* And canvases. */ |
| 147 | canvas = new Canvas (bitmap); | 146 | canvas = new Canvas (bitmap); |
| 147 | canvas.save (); | ||
| 148 | |||
| 149 | /* Since the clip rectangles have been cleared, clear the clip | ||
| 150 | rectangle ID. */ | ||
| 151 | lastClipSerial = 0; | ||
| 148 | 152 | ||
| 149 | /* Copy over the contents of the old bitmap. */ | 153 | /* Copy over the contents of the old bitmap. */ |
| 150 | if (oldBitmap != null) | 154 | if (oldBitmap != null) |
| @@ -177,11 +181,31 @@ public class EmacsView extends ViewGroup | |||
| 177 | } | 181 | } |
| 178 | 182 | ||
| 179 | public synchronized Canvas | 183 | public synchronized Canvas |
| 180 | getCanvas () | 184 | getCanvas (EmacsGC gc) |
| 181 | { | 185 | { |
| 186 | int i; | ||
| 187 | |||
| 182 | if (bitmapDirty || bitmap == null) | 188 | if (bitmapDirty || bitmap == null) |
| 183 | handleDirtyBitmap (); | 189 | handleDirtyBitmap (); |
| 184 | 190 | ||
| 191 | if (canvas == null) | ||
| 192 | return null; | ||
| 193 | |||
| 194 | /* Update clip rectangles if necessary. */ | ||
| 195 | if (gc.clipRectID != lastClipSerial) | ||
| 196 | { | ||
| 197 | canvas.restore (); | ||
| 198 | canvas.save (); | ||
| 199 | |||
| 200 | if (gc.real_clip_rects != null) | ||
| 201 | { | ||
| 202 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 203 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 204 | } | ||
| 205 | |||
| 206 | lastClipSerial = gc.clipRectID; | ||
| 207 | } | ||
| 208 | |||
| 185 | return canvas; | 209 | return canvas; |
| 186 | } | 210 | } |
| 187 | 211 | ||
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index f5b50f11f14..c5b1522086c 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java | |||
| @@ -164,7 +164,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 164 | { | 164 | { |
| 165 | /* scratchGC is used as the argument to a FillRectangles req. */ | 165 | /* scratchGC is used as the argument to a FillRectangles req. */ |
| 166 | scratchGC.foreground = pixel; | 166 | scratchGC.foreground = pixel; |
| 167 | scratchGC.markDirty (); | 167 | scratchGC.markDirty (false); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | public Rect | 170 | public Rect |
| @@ -466,9 +466,9 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 466 | 466 | ||
| 467 | @Override | 467 | @Override |
| 468 | public Canvas | 468 | public Canvas |
| 469 | lockCanvas () | 469 | lockCanvas (EmacsGC gc) |
| 470 | { | 470 | { |
| 471 | return view.getCanvas (); | 471 | return view.getCanvas (gc); |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | @Override | 474 | @Override |
| @@ -512,37 +512,75 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 512 | public void | 512 | public void |
| 513 | onKeyDown (int keyCode, KeyEvent event) | 513 | onKeyDown (int keyCode, KeyEvent event) |
| 514 | { | 514 | { |
| 515 | int state; | 515 | int state, state_1; |
| 516 | 516 | ||
| 517 | state = event.getModifiers (); | 517 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) |
| 518 | state &= ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); | 518 | state = event.getModifiers (); |
| 519 | else | ||
| 520 | { | ||
| 521 | /* Replace this with getMetaState and manual | ||
| 522 | normalization. */ | ||
| 523 | state = event.getMetaState (); | ||
| 524 | |||
| 525 | /* Normalize the state by setting the generic modifier bit if | ||
| 526 | either a left or right modifier is pressed. */ | ||
| 527 | |||
| 528 | if ((state & KeyEvent.META_ALT_LEFT_ON) != 0 | ||
| 529 | || (state & KeyEvent.META_ALT_RIGHT_ON) != 0) | ||
| 530 | state |= KeyEvent.META_ALT_MASK; | ||
| 531 | |||
| 532 | if ((state & KeyEvent.META_CTRL_LEFT_ON) != 0 | ||
| 533 | || (state & KeyEvent.META_CTRL_RIGHT_ON) != 0) | ||
| 534 | state |= KeyEvent.META_CTRL_MASK; | ||
| 535 | } | ||
| 536 | |||
| 537 | /* Ignore meta-state understood by Emacs for now, or Ctrl+C will | ||
| 538 | not be recognized as an ASCII key press event. */ | ||
| 539 | state_1 | ||
| 540 | = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); | ||
| 519 | 541 | ||
| 520 | EmacsNative.sendKeyPress (this.handle, | 542 | EmacsNative.sendKeyPress (this.handle, |
| 521 | event.getEventTime (), | 543 | event.getEventTime (), |
| 522 | event.getModifiers (), | 544 | state, keyCode, |
| 523 | keyCode, | 545 | event.getUnicodeChar (state_1)); |
| 524 | /* Ignore meta-state understood by Emacs | 546 | lastModifiers = state; |
| 525 | for now, or Ctrl+C will not be | ||
| 526 | recognized as an ASCII key press | ||
| 527 | event. */ | ||
| 528 | event.getUnicodeChar (state)); | ||
| 529 | lastModifiers = event.getModifiers (); | ||
| 530 | } | 547 | } |
| 531 | 548 | ||
| 532 | public void | 549 | public void |
| 533 | onKeyUp (int keyCode, KeyEvent event) | 550 | onKeyUp (int keyCode, KeyEvent event) |
| 534 | { | 551 | { |
| 535 | int state; | 552 | int state, state_1; |
| 553 | |||
| 554 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) | ||
| 555 | state = event.getModifiers (); | ||
| 556 | else | ||
| 557 | { | ||
| 558 | /* Replace this with getMetaState and manual | ||
| 559 | normalization. */ | ||
| 560 | state = event.getMetaState (); | ||
| 561 | |||
| 562 | /* Normalize the state by setting the generic modifier bit if | ||
| 563 | either a left or right modifier is pressed. */ | ||
| 564 | |||
| 565 | if ((state & KeyEvent.META_ALT_LEFT_ON) != 0 | ||
| 566 | || (state & KeyEvent.META_ALT_RIGHT_ON) != 0) | ||
| 567 | state |= KeyEvent.META_ALT_MASK; | ||
| 568 | |||
| 569 | if ((state & KeyEvent.META_CTRL_LEFT_ON) != 0 | ||
| 570 | || (state & KeyEvent.META_CTRL_RIGHT_ON) != 0) | ||
| 571 | state |= KeyEvent.META_CTRL_MASK; | ||
| 572 | } | ||
| 536 | 573 | ||
| 537 | state = event.getModifiers (); | 574 | /* Ignore meta-state understood by Emacs for now, or Ctrl+C will |
| 538 | state &= ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); | 575 | not be recognized as an ASCII key press event. */ |
| 576 | state_1 | ||
| 577 | = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); | ||
| 539 | 578 | ||
| 540 | EmacsNative.sendKeyRelease (this.handle, | 579 | EmacsNative.sendKeyRelease (this.handle, |
| 541 | event.getEventTime (), | 580 | event.getEventTime (), |
| 542 | event.getModifiers (), | 581 | state, keyCode, |
| 543 | keyCode, | 582 | event.getUnicodeChar (state_1)); |
| 544 | event.getUnicodeChar (state)); | 583 | lastModifiers = state; |
| 545 | lastModifiers = event.getModifiers (); | ||
| 546 | } | 584 | } |
| 547 | 585 | ||
| 548 | public void | 586 | public void |