From 59f7cea1041558e3550efbbbd5e6a4e0ddcbedb9 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 21 Mar 2024 14:23:40 +0800 Subject: [PATCH] Android compatibility fixes * doc/emacs/android.texi (Android Windowing): Document restrictions on number of windows under Android 4.4 and earlier. * java/AndroidManifest.xml.in : Assign each class of activity a unique task affinity. * java/org/gnu/emacs/EmacsDesktopNotification.java (display1): Remove redundant priority assignment. * java/org/gnu/emacs/EmacsOpenActivity.java (onCreate): Handle file URIs when processing attachments from a mailto URI, and check for KitKat before opening content ones. * java/org/gnu/emacs/EmacsWindow.java (figureChange): Replace coordinate HashMap with a SparseArray. * java/org/gnu/emacs/EmacsWindowAttachmentManager.java (registerWindow): Don't specify FLAG_ACTIVITY_NEW_DOCUMENT on systems where it is absent. (cherry picked from commit ad0492c5a97aaad7f784f7834772400d9af96b69) --- doc/emacs/android.texi | 6 ++++ java/AndroidManifest.xml.in | 4 ++- .../gnu/emacs/EmacsDesktopNotification.java | 35 +++++++++---------- java/org/gnu/emacs/EmacsOpenActivity.java | 34 ++++++++++++++++-- java/org/gnu/emacs/EmacsWindow.java | 12 ++++--- .../emacs/EmacsWindowAttachmentManager.java | 9 +++-- 6 files changed, 70 insertions(+), 30 deletions(-) diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi index 56bfa2591f6..b367515cb35 100644 --- a/doc/emacs/android.texi +++ b/doc/emacs/android.texi @@ -864,6 +864,12 @@ behalf of a specific frame, Emacs deletes the frame displayed within that window. @end itemize + When the system predates Android 5.0, the window manager will not +accept more than one user-created Emacs window. If frame creation gives +rise to windows in excess of this limit, the window manager will +arbitrarily select one of their number to display, with the rest +remaining invisible until that window is destroyed with its frame. + @cindex windowing limitations, android @cindex frame parameters, android Emacs only supports a limited subset of GUI features on Android; the diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in index 4d23c752747..563914fb02c 100644 --- a/java/AndroidManifest.xml.in +++ b/java/AndroidManifest.xml.in @@ -218,6 +218,7 @@ along with GNU Emacs. If not, see . --> @@ -229,7 +230,7 @@ along with GNU Emacs. If not, see . --> @@ -273,6 +274,7 @@ along with GNU Emacs. If not, see . --> diff --git a/java/org/gnu/emacs/EmacsDesktopNotification.java b/java/org/gnu/emacs/EmacsDesktopNotification.java index c80aa21b4fe..72569631a8c 100644 --- a/java/org/gnu/emacs/EmacsDesktopNotification.java +++ b/java/org/gnu/emacs/EmacsDesktopNotification.java @@ -208,22 +208,6 @@ public final class EmacsDesktopNotification distinct categories, but permit an importance to be assigned to each individual notification. */ - switch (importance) - { - case 2: /* IMPORTANCE_LOW */ - default: - priority = Notification.PRIORITY_LOW; - break; - - case 3: /* IMPORTANCE_DEFAULT */ - priority = Notification.PRIORITY_DEFAULT; - break; - - case 4: /* IMPORTANCE_HIGH */ - priority = Notification.PRIORITY_HIGH; - break; - } - builder = new Notification.Builder (context); builder.setContentTitle (title); builder.setContentText (content); @@ -231,15 +215,28 @@ public final class EmacsDesktopNotification if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + switch (importance) + { + case 2: /* IMPORTANCE_LOW */ + default: + priority = Notification.PRIORITY_LOW; + break; + + case 3: /* IMPORTANCE_DEFAULT */ + priority = Notification.PRIORITY_DEFAULT; + break; + + case 4: /* IMPORTANCE_HIGH */ + priority = Notification.PRIORITY_HIGH; + break; + } + builder.setPriority (priority); insertActions (context, builder); notification = builder.build (); } else notification = builder.getNotification (); - - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) - notification.priority = priority; } else { diff --git a/java/org/gnu/emacs/EmacsOpenActivity.java b/java/org/gnu/emacs/EmacsOpenActivity.java index 2cdfa2ec776..327a53bc417 100644 --- a/java/org/gnu/emacs/EmacsOpenActivity.java +++ b/java/org/gnu/emacs/EmacsOpenActivity.java @@ -535,7 +535,9 @@ public final class EmacsOpenActivity extends Activity uri = intent.getParcelableExtra (Intent.EXTRA_STREAM); if ((scheme = uri.getScheme ()) != null - && scheme.equals ("content")) + && scheme.equals ("content") + && (Build.VERSION.SDK_INT + >= Build.VERSION_CODES.KITKAT)) { tem1 = EmacsService.buildContentName (uri, resolver); attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\") @@ -543,6 +545,14 @@ public final class EmacsOpenActivity extends Activity .replace ("$", "\\$")) + "\")"); } + else if (scheme != null && scheme.equals ("file")) + { + tem1 = uri.getPath (); + attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\") + .replace ("\"", "\\\"") + .replace ("$", "\\$")) + + "\")"); + } } else { @@ -567,7 +577,9 @@ public final class EmacsOpenActivity extends Activity if (uri != null && (scheme = uri.getScheme ()) != null - && scheme.equals ("content")) + && scheme.equals ("content") + && (Build.VERSION.SDK_INT + >= Build.VERSION_CODES.KITKAT)) { tem1 = EmacsService.buildContentName (uri, resolver); @@ -577,6 +589,16 @@ public final class EmacsOpenActivity extends Activity .replace ("$", "\\$")); builder.append ("\""); } + else if (scheme != null + && scheme.equals ("file")) + { + tem1 = uri.getPath (); + builder.append ("\""); + builder.append (tem1.replace ("\\", "\\\\") + .replace ("\"", "\\\"") + .replace ("$", "\\$")); + builder.append ("\""); + } } builder.append (")"); @@ -604,7 +626,13 @@ public final class EmacsOpenActivity extends Activity { fileName = null; - if (scheme.equals ("content")) + if (scheme.equals ("content") + /* Retrieving the native file descriptor of a + ParcelFileDescriptor requires Honeycomb, and + proceeding without this capability is pointless on + systems before KitKat, since Emacs doesn't support + opening content files on those. */ + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { /* This is one of the annoying Android ``content'' URIs. Most of the time, there is actually an diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index d81d4106170..06257a69dc5 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -23,7 +23,6 @@ import java.lang.IllegalStateException; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -50,6 +49,7 @@ import android.view.View; import android.view.ViewManager; import android.view.WindowManager; +import android.util.SparseArray; import android.util.Log; import android.os.Build; @@ -109,7 +109,7 @@ public final class EmacsWindow extends EmacsHandleObject /* Map between pointer identifiers and last known position. Used to compute which pointer changed upon a touch event. */ - private HashMap pointerMap; + private SparseArray pointerMap; /* The window consumer currently attached, if it exists. */ private EmacsWindowAttachmentManager.WindowConsumer attached; @@ -166,7 +166,7 @@ public final class EmacsWindow extends EmacsHandleObject super (handle); rect = new Rect (x, y, x + width, y + height); - pointerMap = new HashMap (); + pointerMap = new SparseArray (); /* Create the view from the context's UI thread. The window is unmapped, so the view is GONE. */ @@ -1001,7 +1001,8 @@ public final class EmacsWindow extends EmacsHandleObject case MotionEvent.ACTION_CANCEL: /* Primary pointer released with index 0. */ pointerID = event.getPointerId (0); - coordinate = pointerMap.remove (pointerID); + coordinate = pointerMap.get (pointerID); + pointerMap.delete (pointerID); break; case MotionEvent.ACTION_POINTER_DOWN: @@ -1020,7 +1021,8 @@ public final class EmacsWindow extends EmacsHandleObject /* Pointer removed. Remove it from the map. */ pointerIndex = event.getActionIndex (); pointerID = event.getPointerId (pointerIndex); - coordinate = pointerMap.remove (pointerID); + coordinate = pointerMap.get (pointerID); + pointerMap.delete (pointerID); break; default: diff --git a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java index 18bdb6dbf60..aae4e2ee49b 100644 --- a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java +++ b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java @@ -124,10 +124,15 @@ public final class EmacsWindowAttachmentManager intent = new Intent (EmacsService.SERVICE, EmacsMultitaskActivity.class); - intent.addFlags (Intent.FLAG_ACTIVITY_NEW_DOCUMENT - | Intent.FLAG_ACTIVITY_NEW_TASK + + intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + /* Intent.FLAG_ACTIVITY_NEW_DOCUMENT is lamentably unavailable on + older systems than Lolipop. */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + intent.addFlags (Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) EmacsService.SERVICE.startActivity (intent); else -- 2.39.5