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/org | |
| 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/org')
| -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 |
14 files changed, 212 insertions, 145 deletions
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 |