From 1b8258a1f2b6a080a4f0e819aa4a86c1ec2da89f Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 17 Jan 2023 22:10:43 +0800 Subject: Update Android port * doc/emacs/android.texi (Android Fonts): Document that TTC format fonts are now supported. * doc/emacs/emacs.texi (Top): Fix menus. * doc/lispref/commands.texi (Touchscreen Events) (Key Sequence Input): Document changes to touchscreen events. * etc/DEBUG: Describe how to debug 64 bit binaries on Android. * java/org/gnu/emacs/EmacsCopyArea.java (perform): Explicitly recycle copy bitmap. * java/org/gnu/emacs/EmacsDialog.java (EmacsDialog): New class. * java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Use 5 point PolyLine like X, because Android behaves like Postscript on some devices and X elsewhere. * java/org/gnu/emacs/EmacsFillRectangle.java (perform): Explicitly recycle copy bitmap. * java/org/gnu/emacs/EmacsPixmap.java (destroyHandle): Explicitly recycle bitmap and GC if it is big. * java/org/gnu/emacs/EmacsView.java (EmacsView): Make `bitmapDirty' a boolean. (handleDirtyBitmap): Reimplement in terms of that boolean. Explicitly recycle old bitmap and GC. (onLayout): Fix lock up. (onDetachedFromWindow): Recycle bitmap and GC. * java/org/gnu/emacs/EmacsWindow.java (requestViewLayout): Update call to explicitlyDirtyBitmap. * src/android.c (android_run_select_thread, android_select): Really fix android_select. (android_build_jstring): New function. * src/android.h: Update prototypes. * src/androidmenu.c (android_process_events_for_menu): Totally unblock input before process_pending_signals. (android_menu_show): Remove redundant unblock_input and debugging code. (struct android_emacs_dialog, android_init_emacs_dialog) (android_dialog_show, android_popup_dialog, init_androidmenu): Implement popup dialogs on Android. * src/androidterm.c (android_update_tools) (handle_one_android_event, android_frame_up_to_date): Allow tapping tool bar items. (android_create_terminal): Add dialog hook. (android_wait_for_event): Adjust call to android_select. * src/androidterm.h (struct android_touch_point): New field `tool_bar_p'. * src/keyboard.c (read_key_sequence, head_table) (syms_of_keyboard): Prefix touchscreen events with posn. * src/keyboard.h (EVENT_HEAD): Handle touchscreen events. * src/process.c (wait_reading_process_output): Adjust call to android_select. * src/sfnt.c (sfnt_read_table_directory): If the first long turns out to be ttcf, return -1. (sfnt_read_ttc_header): New function. (main): Test TTC support. * src/sfnt.h (struct sfnt_ttc_header): New structure. (enum sfnt_ttc_tag): New enum. * src/sfntfont-android.c (struct sfntfont_android_scanline_buffer): New structure. (GET_SCANLINE_BUFFER): New macro. Try to avoid so much malloc upon accessing the scanline buffer. (sfntfont_android_put_glyphs): Do not use SAFE_ALLOCA to allocate the scaline buffer. (Fandroid_enumerate_fonts): Enumerate ttc fonts too. * src/sfntfont.c (struct sfnt_font_desc): New field `offset'. (sfnt_enum_font_1): Split out enumeration code from sfnt_enum_font. (sfnt_enum_font): Read TTC tables and enumerate each font therein. (sfntfont_open): Seek to the offset specified. * xcompile/Makefile.in (maintainer-clean): Fix depends here. --- java/org/gnu/emacs/EmacsView.java | 84 +++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 21 deletions(-) (limited to 'java/org/gnu/emacs/EmacsView.java') diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 445d8ffa023..6137fd74a7f 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -70,9 +70,9 @@ public class EmacsView extends ViewGroup event regardless of what changed. */ public boolean mustReportLayout; - /* If non-null, whether or not bitmaps must be recreated upon the - next call to getBitmap. */ - private Rect bitmapDirty; + /* Whether or not bitmaps must be recreated upon the next call to + getBitmap. */ + private boolean bitmapDirty; /* Whether or not a popup is active. */ private boolean popupActive; @@ -80,6 +80,9 @@ public class EmacsView extends ViewGroup /* The current context menu. */ private EmacsContextMenu contextMenu; + /* The last measured width and height. */ + private int measuredWidth, measuredHeight; + public EmacsView (EmacsWindow window) { @@ -116,13 +119,27 @@ public class EmacsView extends ViewGroup { Bitmap oldBitmap; + if (measuredWidth == 0 || measuredHeight == 0) + return; + + /* If bitmap is the same width and height as the measured width + and height, there is no need to do anything. Avoid allocating + the extra bitmap. */ + if (bitmap != null + && (bitmap.getWidth () == measuredWidth + && bitmap.getHeight () == measuredHeight)) + { + bitmapDirty = false; + return; + } + /* Save the old bitmap. */ oldBitmap = bitmap; /* Recreate the front and back buffer bitmaps. */ bitmap - = Bitmap.createBitmap (bitmapDirty.width (), - bitmapDirty.height (), + = Bitmap.createBitmap (measuredWidth, + measuredHeight, Bitmap.Config.ARGB_8888); bitmap.eraseColor (0xffffffff); @@ -133,23 +150,27 @@ public class EmacsView extends ViewGroup if (oldBitmap != null) canvas.drawBitmap (oldBitmap, 0f, 0f, new Paint ()); - bitmapDirty = null; + bitmapDirty = false; + + /* Explicitly free the old bitmap's memory. */ + if (oldBitmap != null) + oldBitmap.recycle (); + + /* Some Android versions still don't free the bitmap until the + next GC. */ + Runtime.getRuntime ().gc (); } public synchronized void - explicitlyDirtyBitmap (Rect rect) + explicitlyDirtyBitmap () { - if (bitmapDirty == null - && (bitmap == null - || rect.width () != bitmap.getWidth () - || rect.height () != bitmap.getHeight ())) - bitmapDirty = rect; + bitmapDirty = true; } public synchronized Bitmap getBitmap () { - if (bitmapDirty != null) + if (bitmapDirty || bitmap == null) handleDirtyBitmap (); return bitmap; @@ -158,7 +179,7 @@ public class EmacsView extends ViewGroup public synchronized Canvas getCanvas () { - if (bitmapDirty != null) + if (bitmapDirty || bitmap == null) handleDirtyBitmap (); return canvas; @@ -196,8 +217,12 @@ public class EmacsView extends ViewGroup super.setMeasuredDimension (width, height); } + /* Note that the monitor lock for the window must never be held from + within the lock for the view, because the window also locks the + other way around. */ + @Override - protected synchronized void + protected void onLayout (boolean changed, int left, int top, int right, int bottom) { @@ -213,12 +238,13 @@ public class EmacsView extends ViewGroup window.viewLayout (left, top, right, bottom); } - if (changed - /* Check that a change has really happened. */ - && (bitmapDirty == null - || bitmapDirty.width () != right - left - || bitmapDirty.height () != bottom - top)) - bitmapDirty = new Rect (left, top, right, bottom); + measuredWidth = right - left; + measuredHeight = bottom - top; + + /* Dirty the back buffer. */ + + if (changed) + explicitlyDirtyBitmap (); for (i = 0; i < count; ++i) { @@ -472,4 +498,20 @@ public class EmacsView extends ViewGroup contextMenu = null; popupActive = false; } + + @Override + public synchronized void + onDetachedFromWindow () + { + synchronized (this) + { + /* Recycle the bitmap and call GC. */ + bitmap.recycle (); + bitmap = null; + canvas = null; + + /* Collect the bitmap storage; it could be large. */ + Runtime.getRuntime ().gc (); + } + } }; -- cgit v1.3