From a496509cedb17109d0e6297a74e2ff8ed526333c Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 19 Jan 2023 22:19:06 +0800 Subject: 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. --- java/org/gnu/emacs/EmacsContextMenu.java | 20 ++++++-- java/org/gnu/emacs/EmacsCopyArea.java | 11 +--- java/org/gnu/emacs/EmacsDialog.java | 3 -- java/org/gnu/emacs/EmacsDrawLine.java | 11 +--- java/org/gnu/emacs/EmacsDrawRectangle.java | 45 +++++----------- java/org/gnu/emacs/EmacsDrawable.java | 2 +- java/org/gnu/emacs/EmacsFillPolygon.java | 11 +--- java/org/gnu/emacs/EmacsFillRectangle.java | 12 +---- java/org/gnu/emacs/EmacsGC.java | 33 ++++++++---- java/org/gnu/emacs/EmacsPixmap.java | 77 +++++++++++++++++++++------ java/org/gnu/emacs/EmacsSdk7FontDriver.java | 11 +--- java/org/gnu/emacs/EmacsService.java | 7 ++- java/org/gnu/emacs/EmacsView.java | 34 ++++++++++-- java/org/gnu/emacs/EmacsWindow.java | 80 +++++++++++++++++++++-------- 14 files changed, 212 insertions(+), 145 deletions(-) (limited to 'java/org/gnu') 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 { if (item.subMenu != null) { - /* This is a submenu. Create the submenu and add the - contents of the menu to it. */ - submenu = menu.addSubMenu (item.itemName); - item.subMenu.inflateMenuItems (submenu); + try + { + /* This is a submenu. On versions of Android which + support doing so, create the submenu and add the + contents of the menu to it. */ + submenu = menu.addSubMenu (item.itemName); + } + catch (UnsupportedOperationException exception) + { + /* This version of Android has a restriction + preventing submenus from being added to submenus. + Inflate everything into the parent menu + instead. */ + item.subMenu.inflateMenuItems (menu); + continue; + } /* This is still needed to set wasSubmenuSelected. */ 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 paint = gc.gcPaint; - canvas = destination.lockCanvas (); + canvas = destination.lockCanvas (gc); if (canvas == null) return; - canvas.save (); - - if (gc.real_clip_rects != null) - { - for (i = 0; i < gc.real_clip_rects.length; ++i) - canvas.clipRect (gc.real_clip_rects[i]); - } - /* A copy must be created or drawBitmap could end up overwriting itself. */ srcBitmap = source.getBitmap (); @@ -189,7 +181,6 @@ public class EmacsCopyArea maskBitmap.recycle (); } - canvas.restore (); destination.damageRect (rect); } } 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 button = buttons.get (1); dialog.setButton (DialogInterface.BUTTON_NEUTRAL, button.name, button); - buttonView - = dialog.getButton (DialogInterface.BUTTON_NEUTRAL); - buttonView.setEnabled (button.enabled); } 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 Math.min (y, y2 + 1), Math.max (x2 + 1, x), Math.max (y2 + 1, y)); - canvas = drawable.lockCanvas (); + canvas = drawable.lockCanvas (gc); if (canvas == null) return; - canvas.save (); - - if (gc.real_clip_rects != null) - { - for (i = 0; i < gc.real_clip_rects.length; ++i) - canvas.clipRect (gc.real_clip_rects[i]); - } - paint.setStyle (Paint.Style.STROKE); if (gc.clip_mask == null) @@ -71,7 +63,6 @@ public class EmacsDrawLine /* DrawLine with clip mask not implemented; it is not used by Emacs. */ - canvas.restore (); drawable.damageRect (rect); } } 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; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.RectF; import android.util.Log; @@ -36,51 +37,31 @@ public class EmacsDrawRectangle Paint maskPaint, paint; Canvas maskCanvas; Bitmap maskBitmap; + Rect rect; Rect maskRect, dstRect; Canvas canvas; Bitmap clipBitmap; - Rect clipRect; /* TODO implement stippling. */ if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) return; - canvas = drawable.lockCanvas (); + canvas = drawable.lockCanvas (gc); if (canvas == null) return; - canvas.save (); - - if (gc.real_clip_rects != null) - { - for (i = 0; i < gc.real_clip_rects.length; ++i) - canvas.clipRect (gc.real_clip_rects[i]); - } - - /* Clip to the clipRect because some versions of Android draw an - overly wide line. */ - clipRect = new Rect (x, y, x + width + 1, - y + height + 1); - canvas.clipRect (clipRect); - paint = gc.gcPaint; + paint.setStyle (Paint.Style.STROKE); + rect = new Rect (x, y, x + width, y + height); if (gc.clip_mask == null) - { - /* canvas.drawRect just doesn't work on Android, producing - different results on various devices. Do a 5 point - PolyLine instead. */ - canvas.drawLine ((float) x, (float) y, (float) x + width, - (float) y, paint); - canvas.drawLine ((float) x + width, (float) y, - (float) x + width, (float) y + height, - paint); - canvas.drawLine ((float) x + width, (float) y + height, - (float) x, (float) y + height, paint); - canvas.drawLine ((float) x, (float) y + height, - (float) x, (float) y, paint); - } + /* Use canvas.drawRect with a RectF. That seems to reliably + get PostScript behavior. */ + canvas.drawRect (new RectF (x + 0.5f, y + 0.5f, + x + width + 0.5f, + y + height + 0.5f), + paint); else { /* Drawing with a clip mask involves calculating the @@ -137,7 +118,7 @@ public class EmacsDrawRectangle maskBitmap.recycle (); } - canvas.restore (); - drawable.damageRect (clipRect); + drawable.damageRect (new Rect (x, y, x + width + 1, + y + height + 1)); } } 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; public interface EmacsDrawable { - public Canvas lockCanvas (); + public Canvas lockCanvas (EmacsGC gc); public void damageRect (Rect damageRect); public Bitmap getBitmap (); 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 RectF rectF; int i; - canvas = drawable.lockCanvas (); + canvas = drawable.lockCanvas (gc); if (canvas == null) return; paint = gc.gcPaint; - canvas.save (); - - if (gc.real_clip_rects != null) - { - for (i = 0; i < gc.real_clip_rects.length; ++i) - canvas.clipRect (gc.real_clip_rects[i]); - } - /* Build the path from the given array of points. */ path = new Path (); @@ -83,7 +75,6 @@ public class EmacsFillPolygon if (gc.clip_mask == null) canvas.drawPath (path, paint); - canvas.restore (); drawable.damageRect (rect); /* 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 perform (EmacsDrawable drawable, EmacsGC gc, int x, int y, int width, int height) { - int i; Paint maskPaint, paint; Canvas maskCanvas; Bitmap maskBitmap; @@ -45,19 +44,11 @@ public class EmacsFillRectangle if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) return; - canvas = drawable.lockCanvas (); + canvas = drawable.lockCanvas (gc); if (canvas == null) return; - canvas.save (); - - if (gc.real_clip_rects != null) - { - for (i = 0; i < gc.real_clip_rects.length; ++i) - canvas.clipRect (gc.real_clip_rects[i]); - } - paint = gc.gcPaint; rect = new Rect (x, y, x + width, y + height); @@ -120,7 +111,6 @@ public class EmacsFillRectangle maskBitmap.recycle (); } - canvas.restore (); drawable.damageRect (rect); } } 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 public EmacsPixmap clip_mask, stipple; public Paint gcPaint; + /* ID incremented every time the clipping rectangles of any GC + changes. */ + private static long clip_serial; + + /* The value of clipRectID after the last time this GCs clip + rectangles changed. 0 if there are no clip rectangles. */ + public long clipRectID; + static { xorAlu = new PorterDuffXfermode (Mode.XOR); @@ -75,23 +83,28 @@ public class EmacsGC extends EmacsHandleObject recompute real_clip_rects. */ public void - markDirty () + markDirty (boolean clipRectsChanged) { int i; - if ((ts_origin_x != 0 || ts_origin_y != 0) - && clip_rects != null) + if (clipRectsChanged) { - real_clip_rects = new Rect[clip_rects.length]; - - for (i = 0; i < clip_rects.length; ++i) + if ((ts_origin_x != 0 || ts_origin_y != 0) + && clip_rects != null) { - real_clip_rects[i] = new Rect (clip_rects[i]); - real_clip_rects[i].offset (ts_origin_x, ts_origin_y); + real_clip_rects = new Rect[clip_rects.length]; + + for (i = 0; i < clip_rects.length; ++i) + { + real_clip_rects[i] = new Rect (clip_rects[i]); + real_clip_rects[i].offset (ts_origin_x, ts_origin_y); + } } + else + real_clip_rects = clip_rects; + + clipRectID = ++clip_serial; } - else - real_clip_rects = clip_rects; gcPaint.setStrokeWidth (1f); 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 /* The canvas used to draw to BITMAP. */ public Canvas canvas; + /* Whether or not GC should be explicitly triggered upon + release. */ + private boolean needCollect; + + /* ID used to determine whether or not the GC clip rects + changed. */ + private long gcClipRectID; + public EmacsPixmap (short handle, int colors[], int width, int height, int depth) @@ -83,18 +91,41 @@ public class EmacsPixmap extends EmacsHandleObject switch (depth) { case 1: - bitmap = Bitmap.createBitmap (width, height, - Bitmap.Config.ALPHA_8, - false); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + bitmap = Bitmap.createBitmap (width, height, + Bitmap.Config.ALPHA_8, + false); + else + bitmap = Bitmap.createBitmap (width, height, + Bitmap.Config.ALPHA_8); break; case 24: - bitmap = Bitmap.createBitmap (width, height, - Bitmap.Config.ARGB_8888, - false); + + /* Emacs doesn't just use the first kind of `createBitmap' + because the latter allows specifying that the pixmap is + always opaque, which really increases efficiency. */ + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) + bitmap = Bitmap.createBitmap (width, height, + Bitmap.Config.ARGB_8888); + else + bitmap = Bitmap.createBitmap (width, height, + Bitmap.Config.ARGB_8888, + false); break; } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) + /* On these old versions of Android, Bitmap.recycle frees bitmap + contents immediately. */ + needCollect = false; + else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) + needCollect = (bitmap.getByteCount () + >= 1024 * 512); + else + needCollect = (bitmap.getAllocationByteCount () + >= 1024 * 512); + bitmap.eraseColor (0xff000000); this.width = width; @@ -104,11 +135,32 @@ public class EmacsPixmap extends EmacsHandleObject @Override public Canvas - lockCanvas () + lockCanvas (EmacsGC gc) { + int i; + if (canvas == null) - canvas = new Canvas (bitmap); + { + canvas = new Canvas (bitmap); + canvas.save (); + } + /* Now see if clipping has to be redone. */ + if (gc.clipRectID == gcClipRectID) + return canvas; + + /* It does have to be redone. Reapply gc.real_clip_rects. */ + canvas.restore (); + canvas.save (); + + if (gc.real_clip_rects != null) + { + for (i = 0; i < gc.real_clip_rects.length; ++i) + canvas.clipRect (gc.real_clip_rects[i]); + } + + /* Save the clip rect ID again. */ + gcClipRectID = gc.clipRectID; return canvas; } @@ -130,15 +182,6 @@ public class EmacsPixmap extends EmacsHandleObject public void destroyHandle () { - boolean needCollect; - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) - needCollect = (bitmap.getByteCount () - >= 1024 * 512); - else - needCollect = (bitmap.getAllocationByteCount () - >= 1024 * 512); - bitmap.recycle (); bitmap = null; 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 backgroundRect.right = x + backgroundWidth; backgroundRect.bottom = y + sdk7FontObject.descent; - canvas = drawable.lockCanvas (); + canvas = drawable.lockCanvas (gc); if (canvas == null) return 0; - canvas.save (); paint = gc.gcPaint; - - if (gc.real_clip_rects != null) - { - for (i = 0; i < gc.real_clip_rects.length; ++i) - canvas.clipRect (gc.real_clip_rects[i]); - } - paint.setStyle (Paint.Style.FILL); if (withBackground) @@ -538,7 +530,6 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver paint.setAntiAlias (true); canvas.drawText (charsArray, 0, chars.length, x, y, paint); - canvas.restore (); bounds = new Rect (); paint.getTextBounds (charsArray, 0, chars.length, bounds); 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 { view.thing = new EmacsView (window); view.thing.setVisibility (visibility); - view.thing.setFocusedByDefault (isFocusedByDefault); + + /* The following function is only present on Android 26 + or later. */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + view.thing.setFocusedByDefault (isFocusedByDefault); + notify (); } } 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 /* The last measured width and height. */ private int measuredWidth, measuredHeight; + /* The serial of the last clip rectangle change. */ + private long lastClipSerial; + public EmacsView (EmacsWindow window) { @@ -105,10 +108,6 @@ public class EmacsView extends ViewGroup on Android? */ setChildrenDrawingOrderEnabled (true); - /* Get rid of the foreground and background tint. */ - setBackgroundTintList (null); - setForegroundTintList (null); - /* Get rid of the default focus highlight. */ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) setDefaultFocusHighlightEnabled (false); @@ -145,6 +144,11 @@ public class EmacsView extends ViewGroup /* And canvases. */ canvas = new Canvas (bitmap); + canvas.save (); + + /* Since the clip rectangles have been cleared, clear the clip + rectangle ID. */ + lastClipSerial = 0; /* Copy over the contents of the old bitmap. */ if (oldBitmap != null) @@ -177,11 +181,31 @@ public class EmacsView extends ViewGroup } public synchronized Canvas - getCanvas () + getCanvas (EmacsGC gc) { + int i; + if (bitmapDirty || bitmap == null) handleDirtyBitmap (); + if (canvas == null) + return null; + + /* Update clip rectangles if necessary. */ + if (gc.clipRectID != lastClipSerial) + { + canvas.restore (); + canvas.save (); + + if (gc.real_clip_rects != null) + { + for (i = 0; i < gc.real_clip_rects.length; ++i) + canvas.clipRect (gc.real_clip_rects[i]); + } + + lastClipSerial = gc.clipRectID; + } + return canvas; } 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 { /* scratchGC is used as the argument to a FillRectangles req. */ scratchGC.foreground = pixel; - scratchGC.markDirty (); + scratchGC.markDirty (false); } public Rect @@ -466,9 +466,9 @@ public class EmacsWindow extends EmacsHandleObject @Override public Canvas - lockCanvas () + lockCanvas (EmacsGC gc) { - return view.getCanvas (); + return view.getCanvas (gc); } @Override @@ -512,37 +512,75 @@ public class EmacsWindow extends EmacsHandleObject public void onKeyDown (int keyCode, KeyEvent event) { - int state; + int state, state_1; - state = event.getModifiers (); - state &= ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) + state = event.getModifiers (); + else + { + /* Replace this with getMetaState and manual + normalization. */ + state = event.getMetaState (); + + /* Normalize the state by setting the generic modifier bit if + either a left or right modifier is pressed. */ + + if ((state & KeyEvent.META_ALT_LEFT_ON) != 0 + || (state & KeyEvent.META_ALT_RIGHT_ON) != 0) + state |= KeyEvent.META_ALT_MASK; + + if ((state & KeyEvent.META_CTRL_LEFT_ON) != 0 + || (state & KeyEvent.META_CTRL_RIGHT_ON) != 0) + state |= KeyEvent.META_CTRL_MASK; + } + + /* Ignore meta-state understood by Emacs for now, or Ctrl+C will + not be recognized as an ASCII key press event. */ + state_1 + = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); EmacsNative.sendKeyPress (this.handle, event.getEventTime (), - event.getModifiers (), - keyCode, - /* Ignore meta-state understood by Emacs - for now, or Ctrl+C will not be - recognized as an ASCII key press - event. */ - event.getUnicodeChar (state)); - lastModifiers = event.getModifiers (); + state, keyCode, + event.getUnicodeChar (state_1)); + lastModifiers = state; } public void onKeyUp (int keyCode, KeyEvent event) { - int state; + int state, state_1; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) + state = event.getModifiers (); + else + { + /* Replace this with getMetaState and manual + normalization. */ + state = event.getMetaState (); + + /* Normalize the state by setting the generic modifier bit if + either a left or right modifier is pressed. */ + + if ((state & KeyEvent.META_ALT_LEFT_ON) != 0 + || (state & KeyEvent.META_ALT_RIGHT_ON) != 0) + state |= KeyEvent.META_ALT_MASK; + + if ((state & KeyEvent.META_CTRL_LEFT_ON) != 0 + || (state & KeyEvent.META_CTRL_RIGHT_ON) != 0) + state |= KeyEvent.META_CTRL_MASK; + } - state = event.getModifiers (); - state &= ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); + /* Ignore meta-state understood by Emacs for now, or Ctrl+C will + not be recognized as an ASCII key press event. */ + state_1 + = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK); EmacsNative.sendKeyRelease (this.handle, event.getEventTime (), - event.getModifiers (), - keyCode, - event.getUnicodeChar (state)); - lastModifiers = event.getModifiers (); + state, keyCode, + event.getUnicodeChar (state_1)); + lastModifiers = state; } public void -- cgit v1.2.1